source: git/Singular/LIB/linalg.lib @ 6d37e8

fieker-DuValspielwiese
Last change on this file since 6d37e8 was 6d37e8, checked in by Eric Westenberger <westenb@…>, 22 years ago
*westenb: removed static proc abs, call now absValue from general.lib git-svn-id: file:///usr/local/Singular/svn/trunk@6049 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 42.3 KB
Line 
1//GMG last modified: 04/25/2000
2//////////////////////////////////////////////////////////////////////////////
3version="$Id: linalg.lib,v 1.32 2002-04-11 14:48:43 westenb Exp $";
4category="Linear Algebra";
5info="
6LIBRARY:  linalg.lib  Algorithmic Linear Algebra
7AUTHORS:  Ivor Saynisch (ivs@math.tu-cottbus.de)
8@*        Mathias Schulze (mschulze@mathematik.uni-kl.de)
9
10PROCEDURES:
11 inverse(A);          matrix, the inverse of A
12 inverse_B(A);        list(matrix Inv,poly p),Inv*A=p*En ( using busadj(A) )
13 inverse_L(A);        list(matrix Inv,poly p),Inv*A=p*En ( using lift )
14 sym_gauss(A);        symmetric gaussian algorithm
15 orthogonalize(A);    Gram-Schmidt orthogonalization
16 diag_test(A);        test whether A can be diagnolized
17 busadj(A);           coefficients of Adj(E*t-A) and coefficients of det(E*t-A)
18 charpoly(A,v);       characteristic polynomial of A ( using busadj(A) )
19 adjoint(A);          adjoint of A ( using busadj(A) )
20 det_B(A);            determinant of A ( using busadj(A) )
21 gaussred(A);         gaussian reduction: P*A=U*S, S a row reduced form of A
22 gaussred_pivot(A);   gaussian reduction: P*A=U*S, uses row pivoting
23 gauss_nf(A);         gaussian normal form of A
24 mat_rk(A);           rank of constant matrix A
25 U_D_O(A);            P*A=U*D*O, P,D,U,O=permutaion,diag,lower-,upper-triang
26 pos_def(A,i);        test symmetric matrix for positive definiteness
27 hessenberg(M);       Hessenberg form of M
28 evnf(e[,m]);         eigenvalues normal form of (e[,m])
29 eigenvals(M);        eigenvalues with multiplicities of M
30 jordan(M);           Jordan data of M
31 jordanbasis(M);      Jordan basis and weight filtration of M
32 jordanmatrix(e,s,m); Jordan matrix with Jordan data (e,s,m)
33 jordannf(M);         Jordan normal form of M
34";
35
36LIB "matrix.lib";
37LIB "ring.lib";
38LIB "elim.lib";
39LIB "general.lib";
40//////////////////////////////////////////////////////////////////////////////
41// help functions
42//////////////////////////////////////////////////////////////////////////////
43static proc const_mat(matrix A)
44"RETURN:   1 (0) if A is (is not) a constant matrix"
45{
46  int i;
47  int n=ncols(A);
48  def BR=basering;
49  changeord("@R","dp,c",BR);
50  matrix A=fetch(BR,A);
51  for(i=1;i<=n;i=i+1){
52    if(deg(lead(A)[i])>=1){
53      //"input is not a constant matrix";
54      kill @R;
55      setring BR;
56      return(0);
57    }
58  }
59  kill @R;
60  setring BR;
61  return(1);
62}
63//////////////////////////////////////////////////////////////////////////////
64static proc red(matrix A,int i,int j)
65"USAGE:    red(A,i,j);  A = constant matrix
66          reduces column j with respect to A[i,i] and column i
67          reduces row j with respect to A[i,i] and row i
68RETURN:   matrix
69"
70{
71  module m=module(A);
72
73  if(A[i,i]==0){
74    m[i]=m[i]+m[j];
75    m=module(transpose(matrix(m)));
76    m[i]=m[i]+m[j];
77    m=module(transpose(matrix(m)));
78  }
79
80  A=matrix(m);
81  m[j]=m[j]-(A[i,j]/A[i,i])*m[i];
82  m=module(transpose(matrix(m)));
83  m[j]=m[j]-(A[i,j]/A[i,i])*m[i];
84  m=module(transpose(matrix(m)));
85
86  return(matrix(m));
87}
88
89//////////////////////////////////////////////////////////////////////////////
90proc inner_product(vector v1,vector v2)
91"RETURN:   inner product <v1,v2> "
92{
93  int k;
94  if (nrows(v2)>nrows(v1)) { k=nrows(v2); } else { k=nrows(v1); }
95  return ((transpose(matrix(v1,k,1))*matrix(v2,k,1))[1,1]);
96}
97
98/////////////////////////////////////////////////////////////////////////////
99// user functions
100/////////////////////////////////////////////////////////////////////////////
101
102proc inverse(matrix A, list #)
103"USAGE:    inverse(A [,opt]);  A a square matrix, opt integer
104RETURN:
105@format
106          a matrix:
107          - the inverse matrix of A, if A is invertible;
108          - the 1x1 0-matrix if A is not invertible (in the polynomial ring!).
109          There are the following options:
110          - opt=0 or not given: heuristically best option from below
111          - opt=1 : apply std to (transpose(E,A)), ordering (C,dp).
112          - opt=2 : apply interred (transpose(E,A)), ordering (C,dp).
113          - opt=3 : apply lift(A,E), ordering (C,dp).
114@end format
115NOTE:     parameters and minpoly are allowed; opt=2 is only correct for
116          matrices with entries in a field
117SEE ALSO: inverse_B, inverse_L
118EXAMPLE:  example inverse; shows an example
119"
120{
121//--------------------------- initialization and check ------------------------
122   int ii,u,i,opt;
123   matrix invA;
124   int db = printlevel-voice+3;      //used for comments
125   def R=basering;
126   string mp = string(minpoly);
127   int n = nrows(A);
128   module M = A;
129   intvec v = option(get);           //get options to reset it later
130   if ( ncols(A)!=n )
131   {
132     ERROR("// ** no square matrix");
133   }
134//----------------------- choose heurisitically best option ------------------
135// This may change later, depending on improvements of the implemantation
136// at the monent we use if opt=0 or opt not given:
137// opt = 1 (std) for everything
138// opt = 2 (interred) for nothing, NOTE: interred is ok for constant matricea
139// opt = 3 (lift) for nothing
140// NOTE: interred is ok for constant matrices only (Beispiele am Ende der lib)
141   if(size(#) != 0) {opt = #[1];}
142   if(opt == 0)
143   {
144      if(npars(R) == 0)                       //no parameters
145      {
146         if( size(ideal(A-jet(A,0))) == 0 )   //constant matrix
147         {opt = 1;}
148         else
149         {opt = 1;}
150      }
151      else {opt = 1;}
152   }
153//------------------------- change ring if necessary -------------------------
154   if( ordstr(R) != "C,dp(nvars(R))" )
155   {
156     u=1;
157     changeord("@R","C,dp",R);
158     module M = fetch(R,M);
159     execute("minpoly="+mp+";");
160   }
161//----------------------------- opt=3: use lift ------------------------------
162   if( opt==3 )
163   {
164      module D2;
165      D2 = lift(M,freemodule(n));
166      if (size(ideal(D2))==0)
167      {                                               //catch error in lift
168         dbprint(db,"// ** matrix is not invertible");
169         setring R;
170         if (u==1) { kill @R;}
171         return(invA);
172      }
173   }
174//-------------- opt = 1 resp. opt = 2: use std resp. interred --------------
175   if( opt==1 or opt==2 )
176   {
177      option(redSB);
178      module B = freemodule(n),M;
179      if(opt == 2)
180      {
181         module D = interred(transpose(B));
182         D = transpose(simplify(D,1));
183      }
184      if(opt == 1)
185      {
186         module D = std(transpose(B));
187         D = transpose(simplify(D,1));
188      }
189      module D2 = D[1..n];
190      module D1 = D[n+1..2*n];
191//----------------------- check if matrix is invertible ----------------------
192      for (ii=1; ii<=n; ii++)
193      {
194         if ( D1[ii] != gen(ii) )
195         {
196            dbprint(db,"// ** matrix is not invertible");
197            i = 1;
198            break;
199         }
200      }
201   }
202   option(set,v);
203//------------------ return to basering and return result ---------------------
204   if ( u==1 )
205   {
206      setring R;
207      module D2 = fetch(@R,D2);
208      if( opt==1 or opt==2 )
209      { module D1 = fetch(@R,D1);}
210      kill @R;
211   }
212   if( i==1 ) { return(invA); }     //matrix not invetible
213   else { return(matrix(D2)); }     //matrix invertible with inverse D2
214
215}
216example
217{ "EXAMPLE:"; echo = 2;
218  ring r=0,(x,y,z),lp;
219  matrix A[3][3]=
220   1,4,3,
221   1,5,7,
222   0,4,17;
223  print(inverse(A));"";
224  matrix B[3][3]=
225   y+1,  x+y,    y,
226   z,    z+1,    z,
227   y+z+2,x+y+z+2,y+z+1;
228  print(inverse(B));
229  print(B*inverse(B));
230}
231
232//////////////////////////////////////////////////////////////////////////////
233proc sym_gauss(matrix A)
234"USAGE:    sym_gauss(A);  A = symmetric matrix
235RETURN:   matrix, diagonalisation with symmetric gauss algorithm
236EXAMPLE:  example sym_gauss; shows an example"
237{
238  int i,j;
239  int n=nrows(A);
240
241  if (ncols(A)!=n){
242    "// ** input is not a square matrix";;
243    return(A);
244  }
245
246  if(!const_mat(A)){
247    "// ** input is not a constant matrix";
248    return(A);
249  }
250
251  if(deg(std(A-transpose(A))[1])!=-1){
252    "// ** input is not a symmetric matrix";
253    return(A);
254  }
255
256  for(i=1; i<n; i++){
257    for(j=i+1; j<=n; j++){
258      if(A[i,j]!=0){ A=red(A,i,j); }
259    }
260  }
261
262  return(A);
263}
264example
265{"EXAMPLE:"; echo = 2;
266  ring r=0,(x),lp;
267  matrix A[2][2]=1,4,4,15;
268  print(A);
269  print(sym_gauss(A));
270}
271
272//////////////////////////////////////////////////////////////////////////////
273proc orthogonalize(matrix A)
274"USAGE:    orthogonalize(A); A = constant matrix
275RETURN:    matrix, orthogonal basis of the colum space of A
276EXAMPLE:   example orthogonalize; shows an example "
277{
278  int i,j;
279  int n=ncols(A);
280  poly k;
281
282  if(!const_mat(A)){
283    "// ** input is not a constant matrix";
284    matrix B;
285    return(B);
286  }
287
288  module B=module(interred(A));
289
290  for(i=1;i<=n;i=i+1) {
291    for(j=1;j<i;j=j+1) {
292      k=inner_product(B[j],B[j]);
293      if (k==0) { "Error: vector of length zero"; return(matrix(B)); }
294      B[i]=B[i]-(inner_product(B[i],B[j])/k)*B[j];
295    }
296  }
297
298  return(matrix(B));
299}
300example
301{ "EXAMPLE:"; echo = 2;
302  ring r=0,(x),lp;
303  matrix A[4][4]=5,6,12,4,7,3,2,6,12,1,1,2,6,4,2,10;
304  print(A);
305  print(orthogonalize(A));
306}
307
308////////////////////////////////////////////////////////////////////////////
309proc diag_test(matrix A)
310"USAGE:          diag_test(A); A = const square matrix
311RETURN:   int,  1 if A is diagonalisable, 0 if not
312               -1 no statement is possible, since A does not split.
313NOTE:     The test works only for split matrices, i.e if eigenvalues of A
314          are in the ground field.
315          Does not work with parameters (uses factorize,gcd).
316EXAMPLE:  example diag_test; shows an example"
317{
318  int i,j;
319  int n     = nrows(A);
320  string mp = string(minpoly);
321  string cs = charstr(basering);
322  int np=0;
323
324  if(ncols(A) != n) {
325    "// input is not a square matrix";
326    return(-1);
327  }
328
329   if(!const_mat(A)){
330    "// input is not a constant matrix";
331    return(-1);
332  }
333
334  //Parameterring wegen factorize nicht erlaubt
335  for(i=1;i<size(cs);i=i+1){
336    if(cs[i]==","){np=np+1;} //Anzahl der Parameter
337  }
338  if(np>0){
339        "// rings with parameters not allowed";
340        return(-1);
341  }
342
343  //speichern des aktuellen Rings
344  def BR=basering;
345  //setze R[t]
346  execute("ring rt=("+charstr(basering)+"),(@t,"+varstr(basering)+"),lp;");
347  execute("minpoly="+mp+";");
348  matrix A=imap(BR,A);
349
350  intvec z;
351  intvec s;
352  poly X;         //characteristisches Polynom
353  poly dXdt;      //Ableitung von X nach t
354  ideal g;              //ggT(X,dXdt)
355  poly b;              //Komponente der Busadjunkten-Matrix
356  matrix E[n][n]; //Einheitsmatrix
357
358  E=E+1;
359  A=E*@t-A;
360  X=det(A);
361
362  matrix Xfactors=matrix(factorize(X,1));        //zerfaellt die Matrtix ?
363  int nf=ncols(Xfactors);
364
365  for(i=1;i<=nf;i++){
366    if(lead(Xfactors[1,i])>=@t^2){
367      //" matrix does not split";
368      setring BR;
369      return(-1);
370    }
371  }
372
373  dXdt=diff(X,@t);
374  g=std(ideal(gcd(X,dXdt)));
375
376  //Busadjunkte
377  z=2..n;
378  for(i=1;i<=n;i++){
379    s=2..n;
380    for(j=1;j<=n;j++){
381      b=det(submat(A,z,s));
382
383      if(0!=reduce(b,g)){
384        //" matrix not diagonalizable";
385        setring BR;
386        return(0);
387      }
388
389      s[j]=j;
390    }
391    z[i]=i;
392  }
393
394  //"Die Matrix ist diagonalisierbar";
395  setring BR;
396  return(1);
397}
398example
399{ "EXAMPLE:"; echo = 2;
400  ring r=0,(x),dp;
401  matrix A[4][4]=6,0,0,0,0,0,6,0,0,6,0,0,0,0,0,6;
402  print(A);
403  diag_test(A);
404}
405
406//////////////////////////////////////////////////////////////////////////////
407proc busadj(matrix A)
408"USAGE:   busadj(A);  A = square matrix (of size nxn)
409RETURN:  list L:
410@format
411         L[1] contains the (n+1) coefficients of the characteristic
412              polynomial X of A, i.e.
413              X = L[1][1]+..+L[1][k]*t^(k-1)+..+(L[1][n+1])*t^n
414         L[2] contains the n (nxn)-matrices Hk which are the coefficients of
415              the busadjoint bA = adjoint(E*t-A) of A, i.e.
416              bA = (Hn-1)*t^(n-1)+...+Hk*t^k+...+H0,  ( Hk=L[2][k+1] )
417@end format
418EXAMPLE: example busadj; shows an example"
419{
420  int k;
421  int n    = nrows(A);
422  matrix E = unitmat(n);
423  matrix H[n][n];
424  matrix B[n][n];
425  list bA, X, L;
426  poly a;
427
428  if(ncols(A) != n) {
429    "input is not a square matrix";
430    return(L);
431  }
432
433  bA   = E;
434  X[1] = 1;
435  for(k=1; k<n; k++){
436    B  = A*bA[1];              //bA[1] is the last H
437    a  = -trace(B)/k;
438    H  = B+a*E;
439    bA = insert(bA,H);
440    X  = insert(X,a);
441  }
442  B = A*bA[1];
443  a = -trace(B)/n;
444  X = insert(X,a);
445
446  L = insert(L,bA);
447  L = insert(L,X);
448  return(L);
449}
450example
451{ "EXAMPLE"; echo = 2;
452  ring r = 0,(t,x),lp;
453  matrix A[2][2] = 1,x2,x,x2+3x;
454  print(A);
455  list L = busadj(A);
456  poly X = L[1][1]+L[1][2]*t+L[1][3]*t2; X;
457  matrix bA[2][2] = L[2][1]+L[2][2]*t;
458  print(bA);               //the busadjoint of A;
459  print(bA*(t*unitmat(2)-A));
460}
461
462//////////////////////////////////////////////////////////////////////////////
463proc charpoly(matrix A, list #)
464"USAGE:   charpoly(A[,v]); A square matrix, v string, name of a variable
465RETURN:  poly, the characteristic polynomial det(E*v-A)
466         (default: v=name of last variable)
467NOTE:    A must be independent of the variable v. The computation uses det.
468         If printlevel>0, det(E*v-A) is diplayed recursively.
469EXAMPLE: example charpoly; shows an example"
470{
471  int n = nrows(A);
472  int z = nvars(basering);
473  int i,j;
474  string v;
475  poly X;
476  if(ncols(A) != n)
477  {
478    "// input is not a square matrix";
479    return(X);
480  }
481  //---------------------- test for correct variable -------------------------
482  if( size(#)==0 ){
483    #[1] = varstr(z);
484  }
485  if( typeof(#[1]) == "string") { v = #[1]; }
486  else
487  {
488    "// 2nd argument must be a name of a variable not contained in the matrix";
489    return(X);
490  }
491  j=-1;
492  for(i=1; i<=z; i++)
493  {
494    if(varstr(i)==v){j=i;}
495  }
496  if(j==-1)
497  {
498    "// "+v+" is not a variable in the basering";
499    return(X);
500  }
501  if ( size(select1(module(A),j)) != 0 )
502  {
503    "// matrix must not contain the variable "+v;
504    "// change to a ring with an extra variable, if necessary."
505    return(X);
506  }
507  //-------------------------- compute charpoly ------------------------------
508  X = det(var(j)*unitmat(n)-A);
509  if( printlevel-voice+2 >0) { showrecursive(X,var(j));}
510  return(X);
511}
512example
513{ "EXAMPLE"; echo=2;
514  ring r=0,(x,t),dp;
515  matrix A[3][3]=1,x2,x,x2,6,4,x,4,1;
516  print(A);
517  charpoly(A,"t");
518}
519
520//////////////////////////////////////////////////////////////////////////////
521proc charpoly_B(matrix A, list #)
522"USAGE:   charpoly_B(A[,v]); A square matrix, v string, name of a variable
523RETURN:  poly, the characteristic polynomial det(E*v-A)
524         (default: v=name of last variable)
525NOTE:    A must be constant in the variable v. The computation uses busadj(A).
526EXAMPLE: example charpoly_B; shows an example"
527{
528  int i,j;
529  string s,v;
530  list L;
531  int n     = nrows(A);
532  poly X    = 0;
533  def BR    = basering;
534  string mp = string(minpoly);
535
536  if(ncols(A) != n){
537    "// input is not a square matrix";
538    return(X);
539  }
540
541  //test for correct variable
542  if( size(#)==0 ){
543    #[1] = varstr(nvars(BR));
544  }
545  if( typeof(#[1]) == "string"){
546     v = #[1];
547  }
548  else{
549    "// 2nd argument must be a name of a variable not contained in the matrix";
550    return(X);
551  }
552
553  j=-1;
554  for(i=1; i<=nvars(BR); i++){
555    if(varstr(i)==v){j=i;}
556  }
557  if(j==-1){
558    "// "+v+" is not a variable in the basering";
559    return(X);
560  }
561
562  //var can not be in A
563  s="Wp(";
564  for( i=1; i<=nvars(BR); i++ ){
565    if(i!=j){ s=s+"0";}
566    else{ s=s+"1";}
567    if( i<nvars(BR)) {s=s+",";}
568  }
569  s=s+")";
570
571  changeord("@R",s);
572  execute("minpoly="+mp+";");
573  matrix A = imap(BR,A);
574  for(i=1; i<=n; i++){
575    if(deg(lead(A)[i])>=1){
576      "// matrix must not contain the variable "+v;
577      kill @R;
578      setring BR;
579      return(X);
580    }
581  }
582
583  //get coefficients and build the char. poly
584  kill @R;
585  setring BR;
586  L = busadj(A);
587  for(i=1; i<=n+1; i++){
588    execute("X=X+L[1][i]*"+v+"^"+string(i-1)+";");
589  }
590
591  return(X);
592}
593example
594{ "EXAMPLE"; echo=2;
595  ring r=0,(x,t),dp;
596  matrix A[3][3]=1,x2,x,x2,6,4,x,4,1;
597  print(A);
598  charpoly_B(A,"t");
599}
600
601//////////////////////////////////////////////////////////////////////////////
602proc adjoint(matrix A)
603"USAGE:    adjoint(A);  A = square matrix
604RETURN:   adjoint matrix of A, i.e. Adj*A=det(A)*E
605NOTE:     computation uses busadj(A)
606EXAMPLE:  example adjoint; shows an example"
607{
608  int n=nrows(A);
609  matrix Adj[n][n];
610  list L;
611
612  if(ncols(A) != n) {
613    "// input is not a square matrix";
614    return(Adj);
615  }
616
617  L  = busadj(A);
618  Adj= (-1)^(n-1)*L[2][1];
619  return(Adj);
620
621}
622example
623{ "EXAMPLE"; echo=2;
624  ring r=0,(t,x),lp;
625  matrix A[2][2]=1,x2,x,x2+3x;
626  print(A);
627  matrix Adj[2][2]=adjoint(A);
628  print(Adj);                    //Adj*A=det(A)*E
629  print(Adj*A);
630}
631
632//////////////////////////////////////////////////////////////////////////////
633proc inverse_B(matrix A)
634"USAGE:    inverse_B(A);  A = square matrix
635RETURN:   list Inv with
636          - Inv[1] = matrix I and
637          - Inv[2] = poly p
638          such that I*A = unitmat(n)*p;
639NOTE:     p=1 if 1/det(A) is computable and  p=det(A) if not;
640          the computation uses busadj.
641SEE ALSO: inverse, inverse_L
642EXAMPLE:  example inverse_B; shows an example"
643{
644  int i;
645  int n=nrows(A);
646  matrix I[n][n];
647  poly factor;
648  list L;
649  list Inv;
650
651  if(ncols(A) != n) {
652    "input is not a square matrix";
653    return(I);
654  }
655
656  L=busadj(A);
657  I=module(-L[2][1]);        //+-Adj(A)
658
659  if(reduce(1,std(L[1][1]))==0){
660    I=I*lift(L[1][1],1)[1][1];
661    factor=1;
662  }
663  else{ factor=L[1][1];}     //=+-det(A) or 1
664  Inv=insert(Inv,factor);
665  Inv=insert(Inv,matrix(I));
666
667  return(Inv);
668}
669example
670{ "EXAMPLE"; echo=2;
671  ring r=0,(x,y),lp;
672  matrix A[3][3]=x,y,1,1,x2,y,x,6,0;
673  print(A);
674  list Inv=inverse_B(A);
675  print(Inv[1]);
676  print(Inv[2]);
677  print(Inv[1]*A);
678}
679
680//////////////////////////////////////////////////////////////////////////////
681proc det_B(matrix A)
682"USAGE:     det_B(A);  A any matrix
683RETURN:    returns the determinant of A
684NOTE:      the computation uses the busadj algorithm
685EXAMPLE:   example det_B; shows an example"
686{
687  int n=nrows(A);
688  list L;
689
690  if(ncols(A) != n){ return(0);}
691
692  L=busadj(A);
693  return((-1)^n*L[1][1]);
694}
695example
696{ "EXAMPLE"; echo=2;
697  ring r=0,(x),dp;
698  matrix A[10][10]=random(2,10,10)+unitmat(10)*x;
699  print(A);
700  det_B(A);
701}
702
703//////////////////////////////////////////////////////////////////////////////
704proc inverse_L(matrix A)
705"USAGE:     inverse_L(A);  A = square matrix
706RETURN:    list Inv representing a left inverse of A, i.e
707           - Inv[1] = matrix I and
708           - Inv[2] = poly p
709           such that I*A = unitmat(n)*p;
710NOTE:      p=1 if 1/det(A) is computable and p=det(A) if not;
711           the computation computes first det(A) and then uses lift
712SEE ALSO:  inverse, inverse_B
713EXAMPLE:   example inverse_L; shows an example"
714{
715  int n=nrows(A);
716  matrix I;
717  matrix E[n][n]=unitmat(n);
718  poly factor;
719  poly d=1;
720  list Inv;
721
722  if (ncols(A)!=n){
723    "// input is not a square matrix";
724    return(I);
725  }
726
727  d=det(A);
728  if(d==0){
729    "// matrix is not invertible";
730    return(Inv);
731  }
732
733  // test if 1/det(A) exists
734  if(reduce(1,std(d))!=0){ E=E*d;}
735
736  I=lift(A,E);
737  if(I==unitmat(n)-unitmat(n)){ //catch error in lift
738    "// matrix is not invertible";
739    return(Inv);
740  }
741
742  factor=d;      //=det(A) or 1
743  Inv=insert(Inv,factor);
744  Inv=insert(Inv,I);
745
746  return(Inv);
747}
748example
749{ "EXAMPLE"; echo=2;
750  ring r=0,(x,y),lp;
751  matrix A[3][3]=x,y,1,1,x2,y,x,6,0;
752  print(A);
753  list Inv=inverse_L(A);
754  print(Inv[1]);
755  print(Inv[2]);
756  print(Inv[1]*A);
757}
758
759//////////////////////////////////////////////////////////////////////////////
760proc gaussred(matrix A)
761"USAGE:   gaussred(A);   A any constant matrix
762RETURN:  list Z:  Z[1]=P , Z[2]=U , Z[3]=S , Z[4]=rank(A)
763         gives a row reduced matrix S, a permutation matrix P and a
764         normalized lower triangular matrix U, with P*A=U*S
765NOTE:    This procedure is designed for teaching purposes mainly.
766         The straight forward implementation in the interpreted library
767         is not very efficient (no standard basis computation).
768EXAMPLE: example gaussred; shows an example"
769{
770  int i,j,l,k,jp,rang;
771  poly c,pivo;
772  list Z;
773  int n = nrows(A);
774  int m = ncols(A);
775  int mr= n; //max. rang
776  matrix P[n][n] = unitmat(n);
777  matrix U[n][n] = P;
778
779  if(!const_mat(A)){
780    "// input is not a constant matrix";
781    return(Z);
782  }
783
784  if(n>m){mr=m;} //max. rang
785
786  for(i=1;i<=mr;i=i+1){
787    if((i+k)>m){break};
788
789    //Test: Diagonalelement=0
790    if(A[i,i+k]==0){
791      jp=i;pivo=0;
792      for(j=i+1;j<=n;j=j+1){
793        c=absValue(A[j,i+k]);
794        if(pivo<c){ pivo=c;jp=j;}
795      }
796      if(jp != i){       //Zeilentausch
797        for(j=1;j<=m;j=j+1){ //Zeilentausch in A (und U) (i-te mit jp-ter)
798          c=A[i,j];
799          A[i,j]=A[jp,j];
800          A[jp,j]=c;
801        }
802        for(j=1;j<=n;j=j+1){ //Zeilentausch in P
803          c=P[i,j];
804          P[i,j]=P[jp,j];
805          P[jp,j]=c;
806        }
807      }
808      if(pivo==0){k++;continue;} //eine von selbst auftauchende Stufe !
809    }                          //i sollte im naechsten Lauf nicht erhoeht sein
810
811    //Eliminationsschritt
812    for(j=i+1;j<=n;j=j+1){
813      c=A[j,i+k]/A[i,i+k];
814      for(l=i+k+1;l<=m;l=l+1){
815        A[j,l]=A[j,l]-A[i,l]*c;
816      }
817      A[j,i+k]=0;  // nur wichtig falls k>0 ist
818      A[j,i]=c;    // bildet U
819    }
820  rang=i;
821  }
822
823  for(i=1;i<=mr;i=i+1){
824    for(j=i+1;j<=n;j=j+1){
825      U[j,i]=A[j,i];
826      A[j,i]=0;
827    }
828  }
829
830  Z=insert(Z,rang);
831  Z=insert(Z,A);
832  Z=insert(Z,U);
833  Z=insert(Z,P);
834
835  return(Z);
836}
837example
838{ "EXAMPLE";echo=2;
839  ring r=0,(x),dp;
840  matrix A[5][4]=1,3,-1,4,2,5,-1,3,1,3,-1,4,0,4,-3,1,-3,1,-5,-2;
841  print(A);
842  list Z=gaussred(A);   //construct P,U,S s.t. P*A=U*S
843  print(Z[1]);          //P
844  print(Z[2]);          //U
845  print(Z[3]);          //S
846  print(Z[4]);          //rank
847  print(Z[1]*A);        //P*A
848  print(Z[2]*Z[3]);     //U*S
849}
850
851//////////////////////////////////////////////////////////////////////////////
852proc gaussred_pivot(matrix A)
853"USAGE:     gaussred_pivot(A);   A any constant matrix
854RETURN:    list Z:  Z[1]=P , Z[2]=U , Z[3]=S , Z[4]=rank(A)
855           gives n row reduced matrix S, a permutation matrix P and a
856           normalized lower triangular matrix U, with P*A=U*S
857NOTE:      with row pivoting
858EXAMPLE:   example gaussred_pivot; shows an example"
859{
860  int i,j,l,k,jp,rang;
861  poly c,pivo;
862  list Z;
863  int n=nrows(A);
864  int m=ncols(A);
865  int mr=n; //max. rang
866  matrix P[n][n]=unitmat(n);
867  matrix U[n][n]=P;
868
869  if(!const_mat(A)){
870    "// input is not a constant matrix";
871    return(Z);
872  }
873
874  if(n>m){mr=m;} //max. rang
875
876  for(i=1;i<=mr;i=i+1){
877    if((i+k)>m){break};
878
879    //Pivotisierung
880    pivo=absValue(A[i,i+k]);jp=i;
881    for(j=i+1;j<=n;j=j+1){
882      c=absValue(A[j,i+k]);
883      if(pivo<c){ pivo=c;jp=j;}
884    }
885    if(jp != i){ //Zeilentausch
886      for(j=1;j<=m;j=j+1){ //Zeilentausch in A (und U) (i-te mit jp-ter)
887        c=A[i,j];
888        A[i,j]=A[jp,j];
889        A[jp,j]=c;
890      }
891      for(j=1;j<=n;j=j+1){ //Zeilentausch in P
892        c=P[i,j];
893        P[i,j]=P[jp,j];
894        P[jp,j]=c;
895      }
896    }
897    if(pivo==0){k++;continue;} //eine von selbst auftauchende Stufe !
898                               //i sollte im naechsten Lauf nicht erhoeht sein
899    //Eliminationsschritt
900    for(j=i+1;j<=n;j=j+1){
901      c=A[j,i+k]/A[i,i+k];
902      for(l=i+k+1;l<=m;l=l+1){
903        A[j,l]=A[j,l]-A[i,l]*c;
904      }
905      A[j,i+k]=0;  // nur wichtig falls k>0 ist
906      A[j,i]=c;    // bildet U
907    }
908  rang=i;
909  }
910
911  for(i=1;i<=mr;i=i+1){
912    for(j=i+1;j<=n;j=j+1){
913      U[j,i]=A[j,i];
914      A[j,i]=0;
915    }
916  }
917
918  Z=insert(Z,rang);
919  Z=insert(Z,A);
920  Z=insert(Z,U);
921  Z=insert(Z,P);
922
923  return(Z);
924}
925example
926{ "EXAMPLE";echo=2;
927  ring r=0,(x),dp;
928  matrix A[5][4] = 1, 3,-1,4,
929                   2, 5,-1,3,
930                   1, 3,-1,4,
931                   0, 4,-3,1,
932                  -3,1,-5,-2;
933  list Z=gaussred_pivot(A);  //construct P,U,S s.t. P*A=U*S
934  print(Z[1]);               //P
935  print(Z[2]);               //U
936  print(Z[3]);               //S
937  print(Z[4]);               //rank
938  print(Z[1]*A);             //P*A
939  print(Z[2]*Z[3]);          //U*S
940}
941
942//////////////////////////////////////////////////////////////////////////////
943proc gauss_nf(matrix A)
944"USAGE:    gauss_nf(A); A any constant matrix
945RETURN:   matrix; gauss normal form of A (uses gaussred)
946EXAMPLE:  example gauss_nf; shows an example"
947{
948  list Z;
949  if(!const_mat(A)){
950    "// input is not a constant matrix";
951    return(A);
952  }
953  Z = gaussred(A);
954  return(Z[3]);
955}
956example
957{ "EXAMPLE";echo=2;
958  ring r = 0,(x),dp;
959  matrix A[4][4] = 1,4,4,7,2,5,5,4,4,1,1,3,0,2,2,7;
960  print(gauss_nf(A));
961}
962
963//////////////////////////////////////////////////////////////////////////////
964proc mat_rk(matrix A)
965"USAGE:    mat_rk(A); A any constant matrix
966RETURN:   int, rank of A
967EXAMPLE:  example mat_rk; shows an example"
968{
969  list Z;
970  if(!const_mat(A)){
971    "// input is not a constant matrix";
972    return(-1);
973  }
974  Z = gaussred(A);
975  return(Z[4]);
976}
977example
978{ "EXAMPLE";echo=2;
979  ring r = 0,(x),dp;
980  matrix A[4][4] = 1,4,4,7,2,5,5,4,4,1,1,3,0,2,2,7;
981  mat_rk(A);
982}
983
984//////////////////////////////////////////////////////////////////////////////
985proc U_D_O(matrix A)
986"USAGE:     U_D_O(A);   constant invertible matrix A
987RETURN:    list Z:  Z[1]=P , Z[2]=U , Z[3]=D , Z[4]=O
988           gives a permutation matrix P,
989           a normalized lower triangular matrix U ,
990           a diagonal matrix D, and
991           a normalized upper triangular matrix O
992           with P*A=U*D*O
993NOTE:      Z[1]=-1 means that A is not regular (proc uses gaussred)
994EXAMPLE:   example U_D_O; shows an example"
995{
996  int i,j;
997  list Z,L;
998  int n=nrows(A);
999  matrix O[n][n]=unitmat(n);
1000  matrix D[n][n];
1001
1002  if (ncols(A)!=n){
1003    "// input is not a square matrix";
1004    return(Z);
1005  }
1006  if(!const_mat(A)){
1007    "// input is not a constant matrix";
1008    return(Z);
1009  }
1010
1011  L=gaussred(A);
1012
1013  if(L[4]!=n){
1014    "// input is not an invertible matrix";
1015    Z=insert(Z,-1);  //hint for calling procedures
1016    return(Z);
1017  }
1018
1019  D=L[3];
1020
1021  for(i=1; i<=n; i++){
1022    for(j=i+1; j<=n; j++){
1023      O[i,j] = D[i,j]/D[i,i];
1024      D[i,j] = 0;
1025    }
1026  }
1027
1028  Z=insert(Z,O);
1029  Z=insert(Z,D);
1030  Z=insert(Z,L[2]);
1031  Z=insert(Z,L[1]);
1032  return(Z);
1033}
1034example
1035{ "EXAMPLE";echo=2;
1036  ring r = 0,(x),dp;
1037  matrix A[5][5] = 10, 4,  0, -9,  8,
1038                   -3, 6, -6, -4,  9,
1039                    0, 3, -1, -9, -8,
1040                   -4,-2, -6, -10,10,
1041                   -9, 5, -1, -6,  5;
1042  list Z = U_D_O(A);              //construct P,U,D,O s.t. P*A=U*D*O
1043  print(Z[1]);                    //P
1044  print(Z[2]);                    //U
1045  print(Z[3]);                    //D
1046  print(Z[4]);                    //O
1047  print(Z[1]*A);                  //P*A
1048  print(Z[2]*Z[3]*Z[4]);          //U*D*O
1049}
1050
1051//////////////////////////////////////////////////////////////////////////////
1052proc pos_def(matrix A)
1053"USAGE:     pos_def(A); A = constant, symmetric square matrix
1054RETURN:    int:
1055           1  if A is positive definit ,
1056           0  if not,
1057           -1 if unknown
1058EXAMPLE:   example pos_def; shows an example"
1059{
1060  int j;
1061  list Z;
1062  int n = nrows(A);
1063  matrix H[n][n];
1064
1065  if (ncols(A)!=n){
1066    "// input is not a square matrix";
1067    return(0);
1068  }
1069  if(!const_mat(A)){
1070    "// input is not a constant matrix";
1071    return(-1);
1072  }
1073  if(deg(std(A-transpose(A))[1])!=-1){
1074    "// input is not a hermitian (symmetric) matrix";
1075    return(-1);
1076  }
1077
1078  Z=U_D_O(A);
1079
1080  if(Z[1]==-1){
1081    return(0);
1082  }  //A not regular, therefore not pos. definit
1083
1084  H=Z[1];
1085  //es fand Zeilentausch statt: also nicht positiv definit
1086  if(deg(std(H-unitmat(n))[1])!=-1){
1087    return(0);
1088  }
1089
1090  H=Z[3];
1091
1092  for(j=1;j<=n;j=j+1){
1093    if(H[j,j]<=0){
1094      return(0);
1095    } //eigenvalue<=0, not pos.definit
1096  }
1097
1098  return(1); //positiv definit;
1099}
1100example
1101{ "EXAMPLE"; echo=2;
1102  ring r = 0,(x),dp;
1103  matrix A[5][5] = 20,  4,  0, -9,   8,
1104                    4, 12, -6, -4,   9,
1105                    0, -6, -2, -9,  -8,
1106                   -9, -4, -9, -20, 10,
1107                    8,  9, -8,  10, 10;
1108  pos_def(A);
1109  matrix B[3][3] =  3,  2,  0,
1110                    2, 12,  4,
1111                    0,  4,  2;
1112  pos_def(B);
1113}
1114
1115//////////////////////////////////////////////////////////////////////////////
1116proc linsolve(matrix A, matrix b)
1117"USAGE:     linsolve(A,b); A a constant nxm-matrix, b a constant nx1-matrix
1118RETURN:    a 1xm matrix X, solution of inhomogeneous linear system A*X = b
1119           return the 0-matrix if system is not solvable
1120NOTE:      uses gaussred
1121EXAMPLE:   example linsolve; shows an example"
1122{
1123  int i,j,k,rc,r;
1124  poly c;
1125  list Z;
1126  int n  = nrows(A);
1127  int m  = ncols(A);
1128  int n_b= nrows(b);
1129  matrix Ab[n][m+1];
1130  matrix X[m][1];
1131
1132  if(ncols(b)!=1){
1133    "// right hand side b is not a nx1 matrix";
1134    return(X);
1135  }
1136
1137  if(!const_mat(A)){
1138    "// input hand is not a constant matrix";
1139    return(X);
1140  }
1141
1142  if(n_b>n){
1143    for(i=n; i<=n_b; i++){
1144      if(b[i,1]!=0){
1145        "// right hand side b not in Image(A)";
1146        return X;
1147      }
1148    }
1149  }
1150
1151  if(n_b<n){
1152    matrix copy[n_b][1]=b;
1153    matrix b[n][1]=0;
1154    for(i=1;i<=n_b;i=i+1){
1155      b[i,1]=copy[i,1];
1156    }
1157  }
1158
1159  r=mat_rk(A);
1160
1161  //1. b constant vector
1162  if(const_mat(b)){
1163    //extend A with b
1164    for(i=1; i<=n; i++){
1165      for(j=1; j<=m; j++){
1166        Ab[i,j]=A[i,j];
1167      }
1168      Ab[i,m+1]=b[i,1];
1169    }
1170
1171    //Gauss reduction
1172    Z  = gaussred(Ab);
1173    Ab = Z[3];  //normal form
1174    rc = Z[4];  //rank(Ab)
1175    //print(Ab);
1176
1177    if(r<rc){
1178        "// no solution";
1179        return(X);
1180    }
1181    k=m;
1182    for(i=r;i>=1;i=i-1){
1183
1184      j=1;
1185      while(Ab[i,j]==0){j=j+1;}// suche Ecke
1186
1187      for(;k>j;k=k-1){ X[k]=0;}//springe zur Ecke
1188
1189
1190      c=Ab[i,m+1]; //i-te Komponene von b
1191      for(j=m;j>k;j=j-1){
1192        c=c-X[j,1]*Ab[i,j];
1193      }
1194      if(Ab[i,k]==0){
1195        X[k,1]=1; //willkuerlich
1196      }
1197      else{
1198          X[k,1]=c/Ab[i,k];
1199      }
1200      k=k-1;
1201      if(k==0){break;}
1202    }
1203
1204
1205  }//endif (const b)
1206  else{  //b not constant
1207    "// !not implemented!";
1208
1209  }
1210
1211  return(X);
1212}
1213example
1214{ "EXAMPLE";echo=2;
1215  ring r=0,(x),dp;
1216  matrix A[3][2] = -4,-6,
1217                    2, 3,
1218                   -5, 7;
1219  matrix b[3][1] = 10,
1220                   -5,
1221                    2;
1222  matrix X = linsolve(A,b);
1223  print(X);
1224  print(A*X);
1225}
1226//////////////////////////////////////////////////////////////////////////////
1227
1228///////////////////////////////////////////////////////////////////////////////
1229//    PROCEDURES for Jordan normal form
1230//    AUTHOR:  Mathias Schulze, email: mschulze@mathematik.uni-kl.de
1231///////////////////////////////////////////////////////////////////////////////
1232
1233static proc rowcolswap(matrix M,int i,int j)
1234{
1235  if(i==j)
1236  {
1237    return(M);
1238  }
1239  poly p;
1240  for(int k=1;k<=nrows(M);k++)
1241  {
1242    p=M[i,k];
1243    M[i,k]=M[j,k];
1244    M[j,k]=p;
1245  }
1246  for(k=1;k<=ncols(M);k++)
1247  {
1248    p=M[k,i];
1249    M[k,i]=M[k,j];
1250    M[k,j]=p;
1251  }
1252  return(M);
1253}
1254//////////////////////////////////////////////////////////////////////////////
1255
1256static proc rowelim(matrix M,int i,int j,int k)
1257{
1258  if(jet(M[i,k],0)==0||jet(M[j,k],0)==0)
1259  {
1260    return(M);
1261  }
1262  number n=number(jet(M[i,k],0))/number(jet(M[j,k],0));
1263  for(int l=1;l<=ncols(M);l++)
1264  {
1265    M[i,l]=M[i,l]-n*M[j,l];
1266  }
1267  for(l=1;l<=nrows(M);l++)
1268  {
1269    M[l,j]=M[l,j]+n*M[l,i];
1270  }
1271  return(M);
1272}
1273///////////////////////////////////////////////////////////////////////////////
1274
1275static proc colelim(matrix M,int i,int j,int k)
1276{
1277  if(jet(M[k,i],0)==0||jet(M[k,j],0)==0)
1278  {
1279    return(M);
1280  }
1281  number n=number(jet(M[k,i],0))/number(jet(M[k,j],0));
1282  for(int l=1;l<=nrows(M);l++)
1283  {
1284    M[l,i]=M[l,i]-n*M[l,j];
1285  }
1286  for(l=1;l<=ncols(M);l++)
1287  {
1288    M[j,l]=M[j,l]+n*M[i,l];
1289  }
1290  return(M);
1291}
1292///////////////////////////////////////////////////////////////////////////////
1293
1294proc hessenberg(matrix M)
1295"USAGE:   hessenberg(M); matrix M
1296ASSUME:  M constant square matrix
1297RETURN:  matrix H;  Hessenberg form of M
1298EXAMPLE: example hessenberg; shows examples
1299"
1300{
1301  if(system("with","eigenval"))
1302  {
1303   return(system("hessenberg",M));
1304  }
1305
1306  int n=ncols(M);
1307  int i,j;
1308  for(int k=1;k<n-1;k++)
1309  {
1310    j=k+1;
1311    while(j<n&&jet(M[j,k],0)==0)
1312    {
1313      j++;
1314    }
1315    if(jet(M[j,k],0)!=0)
1316    {
1317      M=rowcolswap(M,j,k+1);
1318      for(i=j+1;i<=n;i++)
1319      {
1320        M=rowelim(M,i,k+1,k);
1321      }
1322    }
1323  }
1324  return(M);
1325}
1326example
1327{ "EXAMPLE:"; echo=2;
1328  ring R=0,x,dp;
1329  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1330  print(M);
1331  print(hessenberg(M));
1332}
1333///////////////////////////////////////////////////////////////////////////////
1334
1335proc evnf(ideal e,list #)
1336"USAGE:   evnf(e[,m]); ideal e, intvec m
1337ASSUME:  ncols(e)==size(m)
1338RETURN:  order eigenvalues e with multiplicities m
1339EXAMPLE: example evnf; shows examples
1340"
1341{
1342  int n=ncols(e);
1343  intvec m;
1344  int i,j;
1345  while(i<size(#))
1346  {
1347    i++;
1348    if(typeof(#[i])=="intvec")
1349    {
1350      m=#[i];
1351    }
1352  }
1353  if(m==0)
1354  {
1355    for(i=n;i>=1;i--)
1356    {
1357      m[i]=1;
1358    }
1359  }
1360
1361  int k;
1362  ideal e0;
1363  intvec m0;
1364  number e1;
1365  int m1;
1366  for(i=n;i>=1;i--)
1367  {
1368    if(m[i]!=0)
1369    {
1370      for(j=i-1;j>=1;j--)
1371      {
1372        if(m[j]!=0)
1373        {
1374          if(number(e[i])>number(e[j]))
1375          {
1376            e1=number(e[i]);
1377            e[i]=e[j];
1378            e[j]=e1;
1379            m1=m[i];
1380            m[i]=m[j];
1381            m[j]=m1;
1382          }
1383          if(number(e[i])==number(e[j]))
1384          {
1385            m[i]=m[i]+m[j];
1386            m[j]=0;
1387          }
1388        }
1389      }
1390      k++;
1391      e0[k]=e[i];
1392      m0[k]=m[i];
1393    }
1394  }
1395
1396  list l;
1397  if(k>0)
1398  {
1399    l=e0,m0;
1400  }
1401  return(l);
1402}
1403example
1404{ "EXAMPLE:"; echo=2;
1405}
1406///////////////////////////////////////////////////////////////////////////////
1407
1408proc eigenvals(matrix M)
1409"USAGE:   eigenvals(M); matrix M
1410ASSUME:  eigenvalues of M in basefield
1411RETURN:
1412@format
1413list l;
1414  ideal l[1];
1415    number l[1][i];  i-th eigenvalue of M
1416  intvec l[2];
1417    int l[2][i];  multiplicity of i-th eigenvalue of M
1418@end format
1419EXAMPLE: example eigenvals; shows examples
1420"
1421{
1422  if(system("with","eigenval"))
1423  {
1424   return(system("eigenvals",jet(M,0)));
1425  }
1426
1427  M=jet(hessenberg(M),0);
1428  int n=ncols(M);
1429  int k;
1430  ideal e;
1431  intvec m;
1432  number e0;
1433  intvec v;
1434  list l;
1435  int i,j;
1436  j=1;
1437  while(j<=n)
1438  {
1439    v=j;
1440    j++;
1441    if(j<=n)
1442    {
1443      while(j<n&&M[j,j-1]!=0)
1444      {
1445        v=v,j;
1446        j++;
1447      }
1448      if(M[j,j-1]!=0)
1449      {
1450        v=v,j;
1451        j++;
1452      }
1453    }
1454    if(size(v)==1)
1455    {
1456      k++;
1457      e[k]=M[v,v];
1458      m[k]=1;
1459    }
1460    else
1461    {
1462      l=factorize(det(submat(M,v,v)-var(1)));
1463      for(i=size(l[1]);i>=1;i--)
1464      {
1465        e0=number(jet(l[1][i]/var(1),0));
1466        if(e0!=0)
1467        {
1468          k++;
1469          e[k]=(e0*var(1)-l[1][i])/e0;
1470          m[k]=l[2][i];
1471        }
1472      }
1473    }
1474  }
1475  return(evnf(e,m));
1476}
1477example
1478{ "EXAMPLE:"; echo=2;
1479  ring R=0,x,dp;
1480  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1481  print(M);
1482  eigenvals(M);
1483}
1484///////////////////////////////////////////////////////////////////////////////
1485
1486proc jordan(matrix M,list #)
1487"USAGE:   jordan(M); matrix M
1488ASSUME:  eigenvalues of M in basefield
1489RETURN:
1490@format
1491list l;  Jordan data of M
1492  ideal l[1];
1493    number l[1][i];  eigenvalue of i-th Jordan block of M
1494  intvec l[2];
1495    int l[2][i];  size of i-th Jordan block of M
1496  intvec l[3];
1497    int l[3][i];  multiplicity of i-th Jordan block of M
1498@end format
1499EXAMPLE: example jordan; shows examples
1500"
1501{
1502  if(nrows(M)==0)
1503  {
1504    ERROR("non empty expected");
1505  }
1506  if(ncols(M)!=nrows(M))
1507  {
1508    ERROR("square matrix expected");
1509  }
1510
1511  M=jet(M,0);
1512
1513  if(size(#)==0)
1514  {
1515    #=eigenvals(M);
1516  }
1517  def e0,m0=#[1..2];
1518
1519  int i;
1520  for(i=1;i<=ncols(e0);i++)
1521  {
1522    if(deg(e0[i])>0)
1523    {
1524
1525      ERROR("eigenvalues in coefficient field expected");
1526      return(list());
1527    }
1528  }
1529
1530  int j,k;
1531  matrix N0,N1;
1532  module K0;
1533  list K;
1534  ideal e;
1535  intvec s,m;
1536
1537  for(i=1;i<=ncols(e0);i++)
1538  {
1539    N0=M-e0[i]*matrix(freemodule(ncols(M)));
1540
1541    N1=N0;
1542    K0=0;
1543    K=module();
1544    while(size(K0)<m0[i])
1545    {
1546      K0=syz(N1);
1547      K=K+list(K0);
1548      N1=N1*N0;
1549    }
1550
1551    for(j=2;j<size(K);j++)
1552    {
1553      if(2*size(K[j])-size(K[j-1])-size(K[j+1])>0)
1554      {
1555        k++;
1556        e[k]=e0[i];
1557        s[k]=j-1;
1558        m[k]=2*size(K[j])-size(K[j-1])-size(K[j+1]);
1559      }
1560    }
1561    if(size(K[j])-size(K[j-1])>0)
1562    {
1563      k++;
1564      e[k]=e0[i];
1565      s[k]=j-1;
1566      m[k]=size(K[j])-size(K[j-1]);
1567    }
1568  }
1569
1570  return(list(e,s,m));
1571}
1572example
1573{ "EXAMPLE:"; echo=2;
1574  ring R=0,x,dp;
1575  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1576  print(M);
1577  jordan(M);
1578}
1579///////////////////////////////////////////////////////////////////////////////
1580
1581proc jordanbasis(matrix M,list #)
1582"USAGE:   jordanbasis(M); matrix M
1583ASSUME:  eigenvalues of M in basefield
1584RETURN:
1585@format
1586list l:
1587  module l[1];  inverse(l[1])*M*l[1] in Jordan normal form
1588  intvec l[2];
1589    int l[2][i];  weight filtration index of l[1][i]
1590@end format
1591EXAMPLE: example jordanbasis; shows examples
1592"
1593{
1594  if(nrows(M)==0)
1595  {
1596    ERROR("non empty matrix expected");
1597  }
1598  if(ncols(M)!=nrows(M))
1599  {
1600    ERROR("square matrix expected");
1601  }
1602
1603  M=jet(M,0);
1604
1605  if(size(#)==0)
1606  {
1607    #=eigenvals(M);
1608  }
1609  def e,m=#[1..2];
1610
1611  for(int i=1;i<=ncols(e);i++)
1612  {
1613    if(deg(e[i])>0)
1614    {
1615      ERROR("eigenvalues in coefficient field expected");
1616      return(freemodule(ncols(M)));
1617    }
1618  }
1619
1620  int j,k,l,n;
1621  matrix N0,N1;
1622  module K0,K1;
1623  list K;
1624  matrix u[ncols(M)][1];
1625  module U;
1626  intvec w;
1627
1628  for(i=1;i<=ncols(e);i++)
1629  {
1630    N0=M-e[i]*matrix(freemodule(ncols(M)));
1631
1632    N1=N0;
1633    K0=0;
1634    K=list();
1635    while(size(K0)<m[i])
1636    {
1637      K0=syz(N1);
1638      K=K+list(K0);
1639      N1=N1*N0;
1640    }
1641
1642    K1=0;
1643    for(j=1;j<size(K);j++)
1644    {
1645      K0=K[j];
1646      K[j]=interred(reduce(K[j],std(K1+module(N0*K[j+1]))));
1647      K1=K0;
1648    }
1649    K[j]=interred(reduce(K[j],std(K1)));
1650
1651    for(l=size(K);l>=1;l--)
1652    {
1653      for(k=size(K[l]);k>0;k--)
1654      {
1655        u=K[l][k];
1656        for(j=l;j>=1;j--)
1657        {
1658          U=U+module(u);
1659          n++;
1660          w[n]=2*j-l-1;
1661          u=N0*u;
1662        }
1663      }
1664    }
1665  }
1666
1667  return(list(U,w));
1668}
1669example
1670{ "EXAMPLE:"; echo=2;
1671  ring R=0,x,dp;
1672  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1673  print(M);
1674  list l=jordanbasis(M);
1675  print(l[1]);
1676  print(l[2]);
1677  print(inverse(l[1])*M*l[1]);
1678}
1679///////////////////////////////////////////////////////////////////////////////
1680
1681proc jordanmatrix(ideal e,intvec s,intvec m)
1682"USAGE:   jordanmatrix(e,s,m); ideal e, intvec s, intvec m
1683ASSUME:  ncols(e)==size(s)==size(m)
1684RETURN:
1685@format
1686matrix J;  Jordan matrix with list(e,s,m)==jordan(J)
1687@end format
1688EXAMPLE: example jordanmatrix; shows examples
1689"
1690{
1691  if(ncols(e)!=size(s)||size(e)!=size(m))
1692  {
1693    ERROR("arguments of equal size expected");
1694  }
1695
1696  int i,j,k,l;
1697  int n=int((transpose(matrix(s))*matrix(m))[1,1]);
1698  matrix J[n][n];
1699  for(k=1;k<=ncols(e);k++)
1700  {
1701    for(l=1;l<=m[k];l++)
1702    {
1703      j++;
1704      J[j,j]=e[k];
1705      for(i=s[k];i>=2;i--)
1706      {
1707        J[j+1,j]=1;
1708        j++;
1709        J[j,j]=e[k];
1710      }
1711    }
1712  }
1713
1714  return(J);
1715}
1716example
1717{ "EXAMPLE:"; echo=2;
1718  ring R=0,x,dp;
1719  ideal e=ideal(2,3);
1720  intvec s=1,2;
1721  intvec m=1,1;
1722  print(jordanmatrix(e,s,m));
1723}
1724///////////////////////////////////////////////////////////////////////////////
1725
1726proc jordannf(matrix M,list #)
1727"USAGE:   jordannf(M); matrix M
1728ASSUME:  eigenvalues of M in basefield
1729RETURN:  matrix J; Jordan normal form of M
1730EXAMPLE: example jordannf; shows examples
1731"
1732{
1733  list l=jordan(M,#);
1734  return(jordanmatrix(l[1],l[2],l[3]));
1735}
1736example
1737{ "EXAMPLE:"; echo=2;
1738  ring R=0,x,dp;
1739  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1740  print(M);
1741  print(jordannf(M));
1742}
1743
1744///////////////////////////////////////////////////////////////////////////////
1745
1746/*
1747///////////////////////////////////////////////////////////////////////////////
1748//          Auskommentierte zusaetzliche Beispiele
1749//
1750///////////////////////////////////////////////////////////////////////////////
1751// Singular for ix86-Linux version 1-3-10  (2000121517)  Dec 15 2000 17:55:12
1752// Rechnungen auf AMD700 mit 632 MB
1753
1754 LIB "linalg.lib";
1755
17561. Sparse integer Matrizen
1757--------------------------
1758ring r1=0,(x),dp;
1759system("--random", 12345678);
1760int n = 70;
1761matrix m = sparsemat(n,n,50,100);
1762option(prot,mem);
1763
1764int t=timer;
1765matrix im = inverse(m,1)[1];
1766timer-t;
1767print(im*m);
1768//list l0 = watchdog(100,"inverse("+"m"+",3)");
1769//bricht bei 100 sec ab und gibt l0[1]: string Killed zurueck
1770
1771//inverse(m,1): std       5sec 5,5 MB
1772//inverse(m,2): interred  12sec
1773//inverse(m,2): lift      nach 180 sec 13MB abgebrochen
1774//n=60: linalgorig: 3  linalg: 5
1775//n=70: linalgorig: 6,7 linalg: 11,12
1776// aber linalgorig rechnet falsch!
1777
17782. Sparse poly Matrizen
1779-----------------------
1780ring r=(0),(a,b,c),dp;
1781system("--random", 12345678);
1782int n=6;
1783matrix m = sparsematrix(n,n,2,0,50,50,9); //matrix of polys of deg <=2
1784option(prot,mem);
1785
1786int t=timer;
1787matrix im = inverse(m);
1788timer-t;
1789print(im*m);
1790//inverse(m,1): std       0sec 1MB
1791//inverse(m,2): interred  0sec 1MB
1792//inverse(m,2): lift      nach 2000 sec 33MB abgebrochen
1793
17943. Sparse Matrizen mit Parametern
1795---------------------------------
1796//liborig rechnet hier falsch!
1797ring r=(0),(a,b),dp;
1798system("--random", 12345678);
1799int n=7;
1800matrix m = sparsematrix(n,n,1,0,40,50,9);
1801ring r1 = (0,a,b),(x),dp;
1802matrix m = imap(r,m);
1803option(prot,mem);
1804
1805int t=timer;
1806matrix im = inverse(m);
1807timer-t;
1808print(im*m);
1809//inverse(m)=inverse(m,3):15 sec inverse(m,1)=1sec inverse(m,2):>120sec
1810//Bei Parametern vergeht die Zeit beim Normieren!
1811
18123. Sparse Matrizen mit Variablen und Parametern
1813-----------------------------------------------
1814ring r=(0),(a,b),dp;
1815system("--random", 12345678);
1816int n=6;
1817matrix m = sparsematrix(n,n,1,0,35,50,9);
1818ring r1 = (0,a),(b),dp;
1819matrix m = imap(r,m);
1820option(prot,mem);
1821
1822int t=timer;
1823matrix im = inverse(m,3);
1824timer-t;
1825print(im*m);
1826//n=7: inverse(m,3):lange sec inverse(m,1)=1sec inverse(m,2):1sec
1827
18284. Ueber Polynomring invertierbare Matrizen
1829-------------------------------------------
1830LIB"random.lib"; LIB"linalg.lib";
1831system("--random", 12345678);
1832int n =3;
1833ring r= 0,(x,y,z),(C,dp);
1834matrix A=triagmatrix(n,n,1,0,0,50,2);
1835intmat B=sparsetriag(n,n,20,1);
1836matrix M = A*transpose(B);
1837M=M*transpose(M);
1838M[1,1..ncols(M)]=M[1,1..n]+xyz*M[n,1..ncols(M)];
1839print(M);
1840//M hat det=1 nach Konstruktion
1841
1842int t=timer;
1843matrix iM=inverse(M);
1844timer-t;
1845print(iM*M);                      //test
1846
1847//ACHTUNG: Interred liefert i.A. keine Inverse, Gegenbeispiel z.B.
1848//mit n=3
1849//eifacheres Gegenbeispiel:
1850matrix M =
18519yz+3y+3z+2,             9y2+6y+1,
18529xyz+3xy+3xz-9z2+2x-6z-1,9xy2+6xy-9yz+x-3y-3z
1853//det M=1, inverse(M,2); ->// ** matrix is not invertible
1854//lead(M); 9xyz*gen(2) 9xy2*gen(2) nicht teilbar!
1855
18565. charpoly:
1857-----------
1858//ring rp=(0,A,B,C),(x),dp;
1859ring r=0,(A,B,C,x),dp;
1860matrix m[12][12]=
1861AC,BC,-3BC,0,-A2+B2,-3AC+1,B2,   B2,  1,   0, -C2+1,0,
18621, 1, 2C,  0,0,     B,     -A,   -4C, 2A+1,0, 0,    0,
18630, 0, 0,   1,0,     2C+1,  -4C+1,-A,  B+1, 0, B+1,  3B,
1864AB,B2,0,   1,0,     1,     0,    1,   A,   0, 1,    B+1,
18651, 0, 1,   0,0,     1,     0,    -C2, 0,   1, 0,    1,
18660, 0, 2,   1,2A,    1,     0,    0,   0,   0, 1,    1,
18670, 1, 0,   1,1,     2,     A,    3B+1,1,   B2,1,    1,
18680, 1, 0,   1,1,     1,     1,    1,   2,   0, 0,    0,
18691, 0, 1,   0,0,     0,     1,    0,   1,   1, 0,    3,
18701, 3B,B2+1,0,0,     1,     0,    1,   0,   0, 1,    0,
18710, 0, 1,   0,0,     0,     0,    1,   0,   0, 0,    0,
18720, 1, 0,   1,1,     3,     3B+1, 0,   1,   1, 1,    0;
1873option(prot,mem);
1874
1875int t=timer;
1876poly q=charpoly(m,"x");         //1sec, charpoly_B 1sec, 16MB
1877timer-t;
1878//1sec, charpoly_B 1sec, 16MB  (gleich in r und rp)
1879
1880*/
Note: See TracBrowser for help on using the repository browser.