source: git/Singular/LIB/linalg.lib @ 4b6c75

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