source: git/Singular/LIB/linalg.lib @ a0c62d

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