source: git/Singular/LIB/linalg.lib @ 7d56875

spielwiese
Last change on this file since 7d56875 was 979c4c, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: Santiagos changes git-svn-id: file:///usr/local/Singular/svn/trunk@9343 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 44.9 KB
Line 
1//GMG last modified: 04/25/2000
2//////////////////////////////////////////////////////////////////////////////
3version="$Id: linalg.lib,v 1.39 2006-07-24 14:06:05 Singular Exp $";
4category="Linear Algebra";
5info="
6LIBRARY:  linalg.lib  Algorithmic Linear Algebra
7AUTHORS:  Ivor Saynisch (ivs@math.tu-cottbus.de)
8@*        Mathias Schulze (mschulze@mathematik.uni-kl.de)
9
10PROCEDURES:
11 inverse(A);          matrix, the inverse of A
12 inverse_B(A);        list(matrix Inv,poly p),Inv*A=p*En ( using busadj(A) )
13 inverse_L(A);        list(matrix Inv,poly p),Inv*A=p*En ( using lift )
14 sym_gauss(A);        symmetric gaussian algorithm
15 orthogonalize(A);    Gram-Schmidt orthogonalization
16 diag_test(A);        test whether A can be diagnolized
17 busadj(A);           coefficients of Adj(E*t-A) and coefficients of det(E*t-A)
18 charpoly(A,v);       characteristic polynomial of A ( using busadj(A) )
19 adjoint(A);          adjoint of A ( using busadj(A) )
20 det_B(A);            determinant of A ( using busadj(A) )
21 gaussred(A);         gaussian reduction: P*A=U*S, S a row reduced form of A
22 gaussred_pivot(A);   gaussian reduction: P*A=U*S, uses row pivoting
23 gauss_nf(A);         gaussian normal form of A
24 mat_rk(A);           rank of constant matrix A
25 U_D_O(A);            P*A=U*D*O, P,D,U,O=permutaion,diag,lower-,upper-triang
26 pos_def(A,i);        test symmetric matrix for positive definiteness
27 hessenberg(M);       Hessenberg form of M
28 eigenvals(M);        eigenvalues with multiplicities of M
29 minipoly(M);         minimal polynomial of M
30 spnf(sp);            normal form of spectrum sp
31 spprint(sp);         print spectrum sp
32 jordan(M);           Jordan data of M
33 jordanbasis(M);      Jordan basis and weight filtration of M
34 jordanmatrix(jd);    Jordan matrix with Jordan data jd
35 jordannf(M);         Jordan normal form of M
36";
37
38LIB "matrix.lib";
39LIB "ring.lib";
40LIB "elim.lib";
41LIB "general.lib";
42//////////////////////////////////////////////////////////////////////////////
43// help functions
44//////////////////////////////////////////////////////////////////////////////
45static proc const_mat(matrix A)
46"RETURN:   1 (0) if A is (is not) a constant matrix"
47{
48  int i;
49  int n=ncols(A);
50  def BR=basering;
51  def @R=changeord("dp,c",BR);
52  setring @R;
53  matrix A=fetch(BR,A);
54  for(i=1;i<=n;i=i+1){
55    if(deg(lead(A)[i])>=1){
56      //"input is not a constant matrix";
57      kill @R;
58      setring BR;
59      return(0);
60    }
61  }
62  kill @R;
63  setring BR;
64  return(1);
65}
66//////////////////////////////////////////////////////////////////////////////
67static proc red(matrix A,int i,int j)
68"USAGE:    red(A,i,j);  A = constant matrix
69          reduces column j with respect to A[i,i] and column i
70          reduces row j with respect to A[i,i] and row i
71RETURN:   matrix
72"
73{
74  module m=module(A);
75
76  if(A[i,i]==0){
77    m[i]=m[i]+m[j];
78    m=module(transpose(matrix(m)));
79    m[i]=m[i]+m[j];
80    m=module(transpose(matrix(m)));
81  }
82
83  A=matrix(m);
84  m[j]=m[j]-(A[i,j]/A[i,i])*m[i];
85  m=module(transpose(matrix(m)));
86  m[j]=m[j]-(A[i,j]/A[i,i])*m[i];
87  m=module(transpose(matrix(m)));
88
89  return(matrix(m));
90}
91
92//////////////////////////////////////////////////////////////////////////////
93proc inner_product(vector v1,vector v2)
94"RETURN:   inner product <v1,v2> "
95{
96  int k;
97  if (nrows(v2)>nrows(v1)) { k=nrows(v2); } else { k=nrows(v1); }
98  return ((transpose(matrix(v1,k,1))*matrix(v2,k,1))[1,1]);
99}
100
101/////////////////////////////////////////////////////////////////////////////
102// user functions
103/////////////////////////////////////////////////////////////////////////////
104
105proc inverse(matrix A, list #)
106"USAGE:    inverse(A [,opt]);  A a square matrix, opt integer
107RETURN:
108@format
109          a matrix:
110          - the inverse matrix of A, if A is invertible;
111          - the 1x1 0-matrix if A is not invertible (in the polynomial ring!).
112          There are the following options:
113          - opt=0 or not given: heuristically best option from below
114          - opt=1 : apply std to (transpose(E,A)), ordering (C,dp).
115          - opt=2 : apply interred (transpose(E,A)), ordering (C,dp).
116          - opt=3 : apply lift(A,E), ordering (C,dp).
117@end format
118NOTE:     parameters and minpoly are allowed; opt=2 is only correct for
119          matrices with entries in a field
120SEE ALSO: inverse_B, inverse_L
121EXAMPLE:  example inverse; shows an example
122"
123{
124//--------------------------- initialization and check ------------------------
125   int ii,u,i,opt;
126   matrix invA;
127   int db = printlevel-voice+3;      //used for comments
128   def R=basering;
129   string mp = string(minpoly);
130   int n = nrows(A);
131   module M = A;
132   intvec v = option(get);           //get options to reset it later
133   if ( ncols(A)!=n )
134   {
135     ERROR("// ** no square matrix");
136   }
137//----------------------- choose heurisitically best option ------------------
138// This may change later, depending on improvements of the implemantation
139// at the monent we use if opt=0 or opt not given:
140// opt = 1 (std) for everything
141// opt = 2 (interred) for nothing, NOTE: interred is ok for constant matricea
142// opt = 3 (lift) for nothing
143// NOTE: interred is ok for constant matrices only (Beispiele am Ende der lib)
144   if(size(#) != 0) {opt = #[1];}
145   if(opt == 0)
146   {
147      if(npars(R) == 0)                       //no parameters
148      {
149         if( size(ideal(A-jet(A,0))) == 0 )   //constant matrix
150         {opt = 1;}
151         else
152         {opt = 1;}
153      }
154      else {opt = 1;}
155   }
156//------------------------- change ring if necessary -------------------------
157   if( ordstr(R) != "C,dp(nvars(R))" )
158   {
159     u=1;
160     def @R=changeord("C,dp",R);
161     setring @R;
162     module M = fetch(R,M);
163     execute("minpoly="+mp+";");
164   }
165//----------------------------- opt=3: use lift ------------------------------
166   if( opt==3 )
167   {
168      module D2;
169      D2 = lift(M,freemodule(n));
170      if (size(ideal(D2))==0)
171      {                                               //catch error in lift
172         dbprint(db,"// ** matrix is not invertible");
173         setring R;
174         if (u==1) { kill @R;}
175         return(invA);
176      }
177   }
178//-------------- opt = 1 resp. opt = 2: use std resp. interred --------------
179   if( opt==1 or opt==2 )
180   {
181      option(redSB);
182      module B = freemodule(n),M;
183      if(opt == 2)
184      {
185         module D = interred(transpose(B));
186         D = transpose(simplify(D,1));
187      }
188      if(opt == 1)
189      {
190         module D = std(transpose(B));
191         D = transpose(simplify(D,1));
192      }
193      module D2 = D[1..n];
194      module D1 = D[n+1..2*n];
195//----------------------- check if matrix is invertible ----------------------
196      for (ii=1; ii<=n; ii++)
197      {
198         if ( D1[ii] != gen(ii) )
199         {
200            dbprint(db,"// ** matrix is not invertible");
201            i = 1;
202            break;
203         }
204      }
205   }
206   option(set,v);
207//------------------ return to basering and return result ---------------------
208   if ( u==1 )
209   {
210      setring R;
211      module D2 = fetch(@R,D2);
212      if( opt==1 or opt==2 )
213      { module D1 = fetch(@R,D1);}
214      kill @R;
215   }
216   if( i==1 ) { return(invA); }     //matrix not invetible
217   else { return(matrix(D2)); }     //matrix invertible with inverse D2
218
219}
220example
221{ "EXAMPLE:"; echo = 2;
222  ring r=0,(x,y,z),lp;
223  matrix A[3][3]=
224   1,4,3,
225   1,5,7,
226   0,4,17;
227  print(inverse(A));"";
228  matrix B[3][3]=
229   y+1,  x+y,    y,
230   z,    z+1,    z,
231   y+z+2,x+y+z+2,y+z+1;
232  print(inverse(B));
233  print(B*inverse(B));
234}
235
236//////////////////////////////////////////////////////////////////////////////
237proc sym_gauss(matrix A)
238"USAGE:    sym_gauss(A);  A = symmetric matrix
239RETURN:   matrix, diagonalisation of A with symmetric gauss algorithm
240EXAMPLE:  example sym_gauss; shows an example"
241{
242  int i,j;
243  int n=nrows(A);
244
245  if (ncols(A)!=n){
246    "// ** input is not a square matrix";;
247    return(A);
248  }
249
250  if(!const_mat(A)){
251    "// ** input is not a constant matrix";
252    return(A);
253  }
254
255  if(deg(std(A-transpose(A))[1])!=-1){
256    "// ** input is not a symmetric matrix";
257    return(A);
258  }
259
260  for(i=1; i<n; i++){
261    for(j=i+1; j<=n; j++){
262      if(A[i,j]!=0){ A=red(A,i,j); }
263    }
264  }
265
266  return(A);
267}
268example
269{"EXAMPLE:"; echo = 2;
270  ring r=0,(x),lp;
271  matrix A[2][2]=1,4,4,15;
272  print(A);
273  print(sym_gauss(A));
274}
275
276//////////////////////////////////////////////////////////////////////////////
277proc orthogonalize(matrix A)
278"USAGE:    orthogonalize(A); A = matrix of constants
279RETURN:    matrix, orthogonal basis of the colum space of A
280EXAMPLE:   example orthogonalize; shows an example "
281{
282  int i,j;
283  int n=ncols(A);
284  poly k;
285
286  if(!const_mat(A)){
287    "// ** input is not a constant matrix";
288    matrix B;
289    return(B);
290  }
291
292  module B=module(interred(A));
293
294  for(i=1;i<=n;i=i+1) {
295    for(j=1;j<i;j=j+1) {
296      k=inner_product(B[j],B[j]);
297      if (k==0) { "Error: vector of length zero"; return(matrix(B)); }
298      B[i]=B[i]-(inner_product(B[i],B[j])/k)*B[j];
299    }
300  }
301
302  return(matrix(B));
303}
304example
305{ "EXAMPLE:"; echo = 2;
306  ring r=0,(x),lp;
307  matrix A[4][4]=5,6,12,4,7,3,2,6,12,1,1,2,6,4,2,10;
308  print(A);
309  print(orthogonalize(A));
310}
311
312////////////////////////////////////////////////////////////////////////////
313proc diag_test(matrix A)
314"USAGE:          diag_test(A); A = const square matrix
315RETURN:   int,  1 if A is diagonalizable,@*
316                0 if not@*
317               -1 if 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  def @R=changeord(s);
577  setring @R;
578  execute("minpoly="+mp+";");
579  matrix A = imap(BR,A);
580  for(i=1; i<=n; i++){
581    if(deg(lead(A)[i])>=1){
582      "// matrix must not contain the variable "+v;
583      kill @R;
584      setring BR;
585      return(X);
586    }
587  }
588
589  //get coefficients and build the char. poly
590  kill @R;
591  setring BR;
592  L = busadj(A);
593  for(i=1; i<=n+1; i++){
594    execute("X=X+L[1][i]*"+v+"^"+string(i-1)+";");
595  }
596
597  return(X);
598}
599example
600{ "EXAMPLE"; echo=2;
601  ring r=0,(x,t),dp;
602  matrix A[3][3]=1,x2,x,x2,6,4,x,4,1;
603  print(A);
604  charpoly_B(A,"t");
605}
606
607//////////////////////////////////////////////////////////////////////////////
608proc adjoint(matrix A)
609"USAGE:    adjoint(A);  A = square matrix
610RETURN:   adjoint matrix of A, i.e. Adj*A=det(A)*E
611NOTE:     computation uses busadj(A)
612EXAMPLE:  example adjoint; shows an example"
613{
614  int n=nrows(A);
615  matrix Adj[n][n];
616  list L;
617
618  if(ncols(A) != n) {
619    "// input is not a square matrix";
620    return(Adj);
621  }
622
623  L  = busadj(A);
624  Adj= (-1)^(n-1)*L[2][1];
625  return(Adj);
626
627}
628example
629{ "EXAMPLE"; echo=2;
630  ring r=0,(t,x),lp;
631  matrix A[2][2]=1,x2,x,x2+3x;
632  print(A);
633  matrix Adj[2][2]=adjoint(A);
634  print(Adj);                    //Adj*A=det(A)*E
635  print(Adj*A);
636}
637
638//////////////////////////////////////////////////////////////////////////////
639proc inverse_B(matrix A)
640"USAGE:    inverse_B(A);  A = square matrix
641RETURN:   list Inv with
642          - Inv[1] = matrix I and
643          - Inv[2] = poly p
644          such that I*A = unitmat(n)*p;
645NOTE:     p=1 if 1/det(A) is computable and  p=det(A) if not;
646          the computation uses busadj.
647SEE ALSO: inverse, inverse_L
648EXAMPLE:  example inverse_B; shows an example"
649{
650  int i;
651  int n=nrows(A);
652  matrix I[n][n];
653  poly factor;
654  list L;
655  list Inv;
656
657  if(ncols(A) != n) {
658    "input is not a square matrix";
659    return(I);
660  }
661
662  L=busadj(A);
663  I=module(-L[2][1]);        //+-Adj(A)
664
665  if(reduce(1,std(L[1][1]))==0){
666    I=I*lift(L[1][1],1)[1][1];
667    factor=1;
668  }
669  else{ factor=L[1][1];}     //=+-det(A) or 1
670  Inv=insert(Inv,factor);
671  Inv=insert(Inv,matrix(I));
672
673  return(Inv);
674}
675example
676{ "EXAMPLE"; echo=2;
677  ring r=0,(x,y),lp;
678  matrix A[3][3]=x,y,1,1,x2,y,x,6,0;
679  print(A);
680  list Inv=inverse_B(A);
681  print(Inv[1]);
682  print(Inv[2]);
683  print(Inv[1]*A);
684}
685
686//////////////////////////////////////////////////////////////////////////////
687proc det_B(matrix A)
688"USAGE:     det_B(A);  A any matrix
689RETURN:    returns the determinant of A
690NOTE:      the computation uses the busadj algorithm
691EXAMPLE:   example det_B; shows an example"
692{
693  int n=nrows(A);
694  list L;
695
696  if(ncols(A) != n){ return(0);}
697
698  L=busadj(A);
699  return((-1)^n*L[1][1]);
700}
701example
702{ "EXAMPLE"; echo=2;
703  ring r=0,(x),dp;
704  matrix A[10][10]=random(2,10,10)+unitmat(10)*x;
705  print(A);
706  det_B(A);
707}
708
709//////////////////////////////////////////////////////////////////////////////
710proc inverse_L(matrix A)
711"USAGE:     inverse_L(A);  A = square matrix
712RETURN:    list Inv representing a left inverse of A, i.e
713           - Inv[1] = matrix I and
714           - Inv[2] = poly p
715           such that I*A = unitmat(n)*p;
716NOTE:      p=1 if 1/det(A) is computable and p=det(A) if not;
717           the computation computes first det(A) and then uses lift
718SEE ALSO:  inverse, inverse_B
719EXAMPLE:   example inverse_L; shows an example"
720{
721  int n=nrows(A);
722  matrix I;
723  matrix E[n][n]=unitmat(n);
724  poly factor;
725  poly d=1;
726  list Inv;
727
728  if (ncols(A)!=n){
729    "// input is not a square matrix";
730    return(I);
731  }
732
733  d=det(A);
734  if(d==0){
735    "// matrix is not invertible";
736    return(Inv);
737  }
738
739  // test if 1/det(A) exists
740  if(reduce(1,std(d))!=0){ E=E*d;}
741
742  I=lift(A,E);
743  if(I==unitmat(n)-unitmat(n)){ //catch error in lift
744    "// matrix is not invertible";
745    return(Inv);
746  }
747
748  factor=d;      //=det(A) or 1
749  Inv=insert(Inv,factor);
750  Inv=insert(Inv,I);
751
752  return(Inv);
753}
754example
755{ "EXAMPLE"; echo=2;
756  ring r=0,(x,y),lp;
757  matrix A[3][3]=x,y,1,1,x2,y,x,6,0;
758  print(A);
759  list Inv=inverse_L(A);
760  print(Inv[1]);
761  print(Inv[2]);
762  print(Inv[1]*A);
763}
764
765//////////////////////////////////////////////////////////////////////////////
766proc gaussred(matrix A)
767"USAGE:   gaussred(A);   A any constant matrix
768RETURN:  list Z:  Z[1]=P , Z[2]=U , Z[3]=S , Z[4]=rank(A)
769         gives a row reduced matrix S, a permutation matrix P and a
770         normalized lower triangular matrix U, with P*A=U*S
771NOTE:    This procedure is designed for teaching purposes mainly.
772         The straight forward implementation in the interpreted library
773         is not very efficient (no standard basis computation).
774EXAMPLE: example gaussred; shows an example"
775{
776  int i,j,l,k,jp,rang;
777  poly c,pivo;
778  list Z;
779  int n = nrows(A);
780  int m = ncols(A);
781  int mr= n; //max. rang
782  matrix P[n][n] = unitmat(n);
783  matrix U[n][n] = P;
784
785  if(!const_mat(A)){
786    "// input is not a constant matrix";
787    return(Z);
788  }
789
790  if(n>m){mr=m;} //max. rang
791
792  for(i=1;i<=mr;i=i+1){
793    if((i+k)>m){break};
794
795    //Test: Diagonalelement=0
796    if(A[i,i+k]==0){
797      jp=i;pivo=0;
798      for(j=i+1;j<=n;j=j+1){
799        c=absValue(A[j,i+k]);
800        if(pivo<c){ pivo=c;jp=j;}
801      }
802      if(jp != i){       //Zeilentausch
803        for(j=1;j<=m;j=j+1){ //Zeilentausch in A (und U) (i-te mit jp-ter)
804          c=A[i,j];
805          A[i,j]=A[jp,j];
806          A[jp,j]=c;
807        }
808        for(j=1;j<=n;j=j+1){ //Zeilentausch in P
809          c=P[i,j];
810          P[i,j]=P[jp,j];
811          P[jp,j]=c;
812        }
813      }
814      if(pivo==0){k++;continue;} //eine von selbst auftauchende Stufe !
815    }                          //i sollte im naechsten Lauf nicht erhoeht sein
816
817    //Eliminationsschritt
818    for(j=i+1;j<=n;j=j+1){
819      c=A[j,i+k]/A[i,i+k];
820      for(l=i+k+1;l<=m;l=l+1){
821        A[j,l]=A[j,l]-A[i,l]*c;
822      }
823      A[j,i+k]=0;  // nur wichtig falls k>0 ist
824      A[j,i]=c;    // bildet U
825    }
826  rang=i;
827  }
828
829  for(i=1;i<=mr;i=i+1){
830    for(j=i+1;j<=n;j=j+1){
831      U[j,i]=A[j,i];
832      A[j,i]=0;
833    }
834  }
835
836  Z=insert(Z,rang);
837  Z=insert(Z,A);
838  Z=insert(Z,U);
839  Z=insert(Z,P);
840
841  return(Z);
842}
843example
844{ "EXAMPLE";echo=2;
845  ring r=0,(x),dp;
846  matrix A[5][4]=1,3,-1,4,2,5,-1,3,1,3,-1,4,0,4,-3,1,-3,1,-5,-2;
847  print(A);
848  list Z=gaussred(A);   //construct P,U,S s.t. P*A=U*S
849  print(Z[1]);          //P
850  print(Z[2]);          //U
851  print(Z[3]);          //S
852  print(Z[4]);          //rank
853  print(Z[1]*A);        //P*A
854  print(Z[2]*Z[3]);     //U*S
855}
856
857//////////////////////////////////////////////////////////////////////////////
858proc gaussred_pivot(matrix A)
859"USAGE:     gaussred_pivot(A);   A any constant matrix
860RETURN:    list Z:  Z[1]=P , Z[2]=U , Z[3]=S , Z[4]=rank(A)
861           gives a row reduced matrix S, a permutation matrix P and a
862           normalized lower triangular matrix U, with P*A=U*S
863NOTE:      with row pivoting
864EXAMPLE:   example gaussred_pivot; shows an example"
865{
866  int i,j,l,k,jp,rang;
867  poly c,pivo;
868  list Z;
869  int n=nrows(A);
870  int m=ncols(A);
871  int mr=n; //max. rang
872  matrix P[n][n]=unitmat(n);
873  matrix U[n][n]=P;
874
875  if(!const_mat(A)){
876    "// input is not a constant matrix";
877    return(Z);
878  }
879
880  if(n>m){mr=m;} //max. rang
881
882  for(i=1;i<=mr;i=i+1){
883    if((i+k)>m){break};
884
885    //Pivotisierung
886    pivo=absValue(A[i,i+k]);jp=i;
887    for(j=i+1;j<=n;j=j+1){
888      c=absValue(A[j,i+k]);
889      if(pivo<c){ pivo=c;jp=j;}
890    }
891    if(jp != i){ //Zeilentausch
892      for(j=1;j<=m;j=j+1){ //Zeilentausch in A (und U) (i-te mit jp-ter)
893        c=A[i,j];
894        A[i,j]=A[jp,j];
895        A[jp,j]=c;
896      }
897      for(j=1;j<=n;j=j+1){ //Zeilentausch in P
898        c=P[i,j];
899        P[i,j]=P[jp,j];
900        P[jp,j]=c;
901      }
902    }
903    if(pivo==0){k++;continue;} //eine von selbst auftauchende Stufe !
904                               //i sollte im naechsten Lauf nicht erhoeht sein
905    //Eliminationsschritt
906    for(j=i+1;j<=n;j=j+1){
907      c=A[j,i+k]/A[i,i+k];
908      for(l=i+k+1;l<=m;l=l+1){
909        A[j,l]=A[j,l]-A[i,l]*c;
910      }
911      A[j,i+k]=0;  // nur wichtig falls k>0 ist
912      A[j,i]=c;    // bildet U
913    }
914  rang=i;
915  }
916
917  for(i=1;i<=mr;i=i+1){
918    for(j=i+1;j<=n;j=j+1){
919      U[j,i]=A[j,i];
920      A[j,i]=0;
921    }
922  }
923
924  Z=insert(Z,rang);
925  Z=insert(Z,A);
926  Z=insert(Z,U);
927  Z=insert(Z,P);
928
929  return(Z);
930}
931example
932{ "EXAMPLE";echo=2;
933  ring r=0,(x),dp;
934  matrix A[5][4] = 1, 3,-1,4,
935                   2, 5,-1,3,
936                   1, 3,-1,4,
937                   0, 4,-3,1,
938                  -3,1,-5,-2;
939  list Z=gaussred_pivot(A);  //construct P,U,S s.t. P*A=U*S
940  print(Z[1]);               //P
941  print(Z[2]);               //U
942  print(Z[3]);               //S
943  print(Z[4]);               //rank
944  print(Z[1]*A);             //P*A
945  print(Z[2]*Z[3]);          //U*S
946}
947
948//////////////////////////////////////////////////////////////////////////////
949proc gauss_nf(matrix A)
950"USAGE:    gauss_nf(A); A any constant matrix
951RETURN:   matrix; gauss normal form of A (uses gaussred)
952EXAMPLE:  example gauss_nf; shows an example"
953{
954  list Z;
955  if(!const_mat(A)){
956    "// input is not a constant matrix";
957    return(A);
958  }
959  Z = gaussred(A);
960  return(Z[3]);
961}
962example
963{ "EXAMPLE";echo=2;
964  ring r = 0,(x),dp;
965  matrix A[4][4] = 1,4,4,7,2,5,5,4,4,1,1,3,0,2,2,7;
966  print(gauss_nf(A));
967}
968
969//////////////////////////////////////////////////////////////////////////////
970proc mat_rk(matrix A)
971"USAGE:    mat_rk(A); A any constant matrix
972RETURN:   int, rank of A
973EXAMPLE:  example mat_rk; shows an example"
974{
975  list Z;
976  if(!const_mat(A)){
977    "// input is not a constant matrix";
978    return(-1);
979  }
980  Z = gaussred(A);
981  return(Z[4]);
982}
983example
984{ "EXAMPLE";echo=2;
985  ring r = 0,(x),dp;
986  matrix A[4][4] = 1,4,4,7,2,5,5,4,4,1,1,3,0,2,2,7;
987  mat_rk(A);
988}
989
990//////////////////////////////////////////////////////////////////////////////
991proc U_D_O(matrix A)
992"USAGE:     U_D_O(A);   constant invertible matrix A
993RETURN:    list Z:  Z[1]=P , Z[2]=U , Z[3]=D , Z[4]=O
994           gives a permutation matrix P,
995           a normalized lower triangular matrix U ,
996           a diagonal matrix D, and
997           a normalized upper triangular matrix O
998           with P*A=U*D*O
999NOTE:      Z[1]=-1 means that A is not regular (proc uses gaussred)
1000EXAMPLE:   example U_D_O; shows an example"
1001{
1002  int i,j;
1003  list Z,L;
1004  int n=nrows(A);
1005  matrix O[n][n]=unitmat(n);
1006  matrix D[n][n];
1007
1008  if (ncols(A)!=n){
1009    "// input is not a square matrix";
1010    return(Z);
1011  }
1012  if(!const_mat(A)){
1013    "// input is not a constant matrix";
1014    return(Z);
1015  }
1016
1017  L=gaussred(A);
1018
1019  if(L[4]!=n){
1020    "// input is not an invertible matrix";
1021    Z=insert(Z,-1);  //hint for calling procedures
1022    return(Z);
1023  }
1024
1025  D=L[3];
1026
1027  for(i=1; i<=n; i++){
1028    for(j=i+1; j<=n; j++){
1029      O[i,j] = D[i,j]/D[i,i];
1030      D[i,j] = 0;
1031    }
1032  }
1033
1034  Z=insert(Z,O);
1035  Z=insert(Z,D);
1036  Z=insert(Z,L[2]);
1037  Z=insert(Z,L[1]);
1038  return(Z);
1039}
1040example
1041{ "EXAMPLE";echo=2;
1042  ring r = 0,(x),dp;
1043  matrix A[5][5] = 10, 4,  0, -9,  8,
1044                   -3, 6, -6, -4,  9,
1045                    0, 3, -1, -9, -8,
1046                   -4,-2, -6, -10,10,
1047                   -9, 5, -1, -6,  5;
1048  list Z = U_D_O(A);              //construct P,U,D,O s.t. P*A=U*D*O
1049  print(Z[1]);                    //P
1050  print(Z[2]);                    //U
1051  print(Z[3]);                    //D
1052  print(Z[4]);                    //O
1053  print(Z[1]*A);                  //P*A
1054  print(Z[2]*Z[3]*Z[4]);          //U*D*O
1055}
1056
1057//////////////////////////////////////////////////////////////////////////////
1058proc pos_def(matrix A)
1059"USAGE:     pos_def(A); A = constant, symmetric square matrix
1060RETURN:    int:
1061           1  if A is positive definit ,
1062           0  if not,
1063           -1 if unknown
1064EXAMPLE:   example pos_def; shows an example"
1065{
1066  int j;
1067  list Z;
1068  int n = nrows(A);
1069  matrix H[n][n];
1070
1071  if (ncols(A)!=n){
1072    "// input is not a square matrix";
1073    return(0);
1074  }
1075  if(!const_mat(A)){
1076    "// input is not a constant matrix";
1077    return(-1);
1078  }
1079  if(deg(std(A-transpose(A))[1])!=-1){
1080    "// input is not a hermitian (symmetric) matrix";
1081    return(-1);
1082  }
1083
1084  Z=U_D_O(A);
1085
1086  if(Z[1]==-1){
1087    return(0);
1088  }  //A not regular, therefore not pos. definit
1089
1090  H=Z[1];
1091  //es fand Zeilentausch statt: also nicht positiv definit
1092  if(deg(std(H-unitmat(n))[1])!=-1){
1093    return(0);
1094  }
1095
1096  H=Z[3];
1097
1098  for(j=1;j<=n;j=j+1){
1099    if(H[j,j]<=0){
1100      return(0);
1101    } //eigenvalue<=0, not pos.definit
1102  }
1103
1104  return(1); //positiv definit;
1105}
1106example
1107{ "EXAMPLE"; echo=2;
1108  ring r = 0,(x),dp;
1109  matrix A[5][5] = 20,  4,  0, -9,   8,
1110                    4, 12, -6, -4,   9,
1111                    0, -6, -2, -9,  -8,
1112                   -9, -4, -9, -20, 10,
1113                    8,  9, -8,  10, 10;
1114  pos_def(A);
1115  matrix B[3][3] =  3,  2,  0,
1116                    2, 12,  4,
1117                    0,  4,  2;
1118  pos_def(B);
1119}
1120
1121//////////////////////////////////////////////////////////////////////////////
1122proc linsolve(matrix A, matrix b)
1123"USAGE:     linsolve(A,b); A a constant nxm-matrix, b a constant nx1-matrix
1124RETURN:    a 1xm matrix X, solution of inhomogeneous linear system A*X = b
1125           return the 0-matrix if system is not solvable
1126NOTE:      uses gaussred
1127EXAMPLE:   example linsolve; shows an example"
1128{
1129  int i,j,k,rc,r;
1130  poly c;
1131  list Z;
1132  int n  = nrows(A);
1133  int m  = ncols(A);
1134  int n_b= nrows(b);
1135  matrix Ab[n][m+1];
1136  matrix X[m][1];
1137
1138  if(ncols(b)!=1){
1139    "// right hand side b is not a nx1 matrix";
1140    return(X);
1141  }
1142
1143  if(!const_mat(A)){
1144    "// input hand is not a constant matrix";
1145    return(X);
1146  }
1147
1148  if(n_b>n){
1149    for(i=n; i<=n_b; i++){
1150      if(b[i,1]!=0){
1151        "// right hand side b not in Image(A)";
1152        return X;
1153      }
1154    }
1155  }
1156
1157  if(n_b<n){
1158    matrix copy[n_b][1]=b;
1159    matrix b[n][1]=0;
1160    for(i=1;i<=n_b;i=i+1){
1161      b[i,1]=copy[i,1];
1162    }
1163  }
1164
1165  r=mat_rk(A);
1166
1167  //1. b constant vector
1168  if(const_mat(b)){
1169    //extend A with b
1170    for(i=1; i<=n; i++){
1171      for(j=1; j<=m; j++){
1172        Ab[i,j]=A[i,j];
1173      }
1174      Ab[i,m+1]=b[i,1];
1175    }
1176
1177    //Gauss reduction
1178    Z  = gaussred(Ab);
1179    Ab = Z[3];  //normal form
1180    rc = Z[4];  //rank(Ab)
1181    //print(Ab);
1182
1183    if(r<rc){
1184        "// no solution";
1185        return(X);
1186    }
1187    k=m;
1188    for(i=r;i>=1;i=i-1){
1189
1190      j=1;
1191      while(Ab[i,j]==0){j=j+1;}// suche Ecke
1192
1193      for(;k>j;k=k-1){ X[k]=0;}//springe zur Ecke
1194
1195
1196      c=Ab[i,m+1]; //i-te Komponene von b
1197      for(j=m;j>k;j=j-1){
1198        c=c-X[j,1]*Ab[i,j];
1199      }
1200      if(Ab[i,k]==0){
1201        X[k,1]=1; //willkuerlich
1202      }
1203      else{
1204          X[k,1]=c/Ab[i,k];
1205      }
1206      k=k-1;
1207      if(k==0){break;}
1208    }
1209
1210
1211  }//endif (const b)
1212  else{  //b not constant
1213    "// !not implemented!";
1214
1215  }
1216
1217  return(X);
1218}
1219example
1220{ "EXAMPLE";echo=2;
1221  ring r=0,(x),dp;
1222  matrix A[3][2] = -4,-6,
1223                    2, 3,
1224                   -5, 7;
1225  matrix b[3][1] = 10,
1226                   -5,
1227                    2;
1228  matrix X = linsolve(A,b);
1229  print(X);
1230  print(A*X);
1231}
1232//////////////////////////////////////////////////////////////////////////////
1233
1234///////////////////////////////////////////////////////////////////////////////
1235//    PROCEDURES for Jordan normal form
1236//    AUTHOR:  Mathias Schulze, email: mschulze@mathematik.uni-kl.de
1237///////////////////////////////////////////////////////////////////////////////
1238
1239static proc rowcolswap(matrix M,int i,int j)
1240{
1241  if(i==j)
1242  {
1243    return(M);
1244  }
1245  poly p;
1246  for(int k=1;k<=nrows(M);k++)
1247  {
1248    p=M[i,k];
1249    M[i,k]=M[j,k];
1250    M[j,k]=p;
1251  }
1252  for(k=1;k<=ncols(M);k++)
1253  {
1254    p=M[k,i];
1255    M[k,i]=M[k,j];
1256    M[k,j]=p;
1257  }
1258  return(M);
1259}
1260//////////////////////////////////////////////////////////////////////////////
1261
1262static proc rowelim(matrix M,int i,int j,int k)
1263{
1264  if(jet(M[i,k],0)==0||jet(M[j,k],0)==0)
1265  {
1266    return(M);
1267  }
1268  number n=number(jet(M[i,k],0))/number(jet(M[j,k],0));
1269  for(int l=1;l<=ncols(M);l++)
1270  {
1271    M[i,l]=M[i,l]-n*M[j,l];
1272  }
1273  for(l=1;l<=nrows(M);l++)
1274  {
1275    M[l,j]=M[l,j]+n*M[l,i];
1276  }
1277  return(M);
1278}
1279///////////////////////////////////////////////////////////////////////////////
1280
1281static proc colelim(matrix M,int i,int j,int k)
1282{
1283  if(jet(M[k,i],0)==0||jet(M[k,j],0)==0)
1284  {
1285    return(M);
1286  }
1287  number n=number(jet(M[k,i],0))/number(jet(M[k,j],0));
1288  for(int l=1;l<=nrows(M);l++)
1289  {
1290    M[l,i]=M[l,i]-n*M[l,j];
1291  }
1292  for(l=1;l<=ncols(M);l++)
1293  {
1294    M[j,l]=M[j,l]+n*M[i,l];
1295  }
1296  return(M);
1297}
1298///////////////////////////////////////////////////////////////////////////////
1299
1300proc hessenberg(matrix M)
1301"USAGE:   hessenberg(M); matrix M
1302ASSUME:  M constant square matrix
1303RETURN:  matrix H;  Hessenberg form of M
1304EXAMPLE: example hessenberg; shows examples
1305"
1306{
1307  if(system("with","eigenval"))
1308  {
1309    return(system("hessenberg",M));
1310  }
1311
1312  int n=ncols(M);
1313  int i,j;
1314  for(int k=1;k<n-1;k++)
1315  {
1316    j=k+1;
1317    while(j<n&&jet(M[j,k],0)==0)
1318    {
1319      j++;
1320    }
1321    if(jet(M[j,k],0)!=0)
1322    {
1323      M=rowcolswap(M,j,k+1);
1324      for(i=j+1;i<=n;i++)
1325      {
1326        M=rowelim(M,i,k+1,k);
1327      }
1328    }
1329  }
1330  return(M);
1331}
1332example
1333{ "EXAMPLE:"; echo=2;
1334  ring R=0,x,dp;
1335  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1336  print(M);
1337  print(hessenberg(M));
1338}
1339///////////////////////////////////////////////////////////////////////////////
1340
1341proc eigenvals(matrix M)
1342"USAGE:   eigenvals(M); matrix M
1343ASSUME:  eigenvalues of M in basefield
1344RETURN:
1345@format
1346list l;
1347  ideal l[1];
1348    number l[1][i];  i-th eigenvalue of M
1349  intvec l[2];
1350    int l[2][i];  multiplicity of i-th eigenvalue of M
1351@end format
1352EXAMPLE: example eigenvals; shows examples
1353"
1354{
1355  if(system("with","eigenval"))
1356  {
1357    return(system("eigenvals",jet(M,0)));
1358  }
1359
1360  M=jet(hessenberg(M),0);
1361  int n=ncols(M);
1362  int k;
1363  ideal e;
1364  intvec m;
1365  number e0;
1366  intvec v;
1367  list l;
1368  int i,j;
1369  j=1;
1370  while(j<=n)
1371  {
1372    v=j;
1373    j++;
1374    if(j<=n)
1375    {
1376      while(j<n&&M[j,j-1]!=0)
1377      {
1378        v=v,j;
1379        j++;
1380      }
1381      if(M[j,j-1]!=0)
1382      {
1383        v=v,j;
1384        j++;
1385      }
1386    }
1387    if(size(v)==1)
1388    {
1389      k++;
1390      e[k]=M[v,v];
1391      m[k]=1;
1392    }
1393    else
1394    {
1395      l=factorize(det(submat(M,v,v)-var(1)));
1396      for(i=size(l[1]);i>=1;i--)
1397      {
1398        e0=number(jet(l[1][i]/var(1),0));
1399        if(e0!=0)
1400        {
1401          k++;
1402          e[k]=(e0*var(1)-l[1][i])/e0;
1403          m[k]=l[2][i];
1404        }
1405      }
1406    }
1407  }
1408  return(spnf(list(e,m)));
1409}
1410example
1411{ "EXAMPLE:"; echo=2;
1412  ring R=0,x,dp;
1413  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1414  print(M);
1415  eigenvals(M);
1416}
1417///////////////////////////////////////////////////////////////////////////////
1418
1419proc minipoly(matrix M,list #)
1420"USAGE:   minipoly(M); matrix M
1421ASSUME:  eigenvalues of M in basefield
1422RETURN:
1423@format
1424list l;  minimal polynomial of M
1425  ideal l[1];
1426    number l[1][i];  i-th root of minimal polynomial of M
1427  intvec l[2];
1428    int l[2][i];  multiplicity of i-th root of minimal polynomial of M
1429@end format
1430EXAMPLE: example minipoly; shows examples
1431"
1432{
1433  if(nrows(M)==0)
1434  {
1435    ERROR("non empty expected");
1436  }
1437  if(ncols(M)!=nrows(M))
1438  {
1439    ERROR("square matrix expected");
1440  }
1441
1442  M=jet(M,0);
1443
1444  if(size(#)==0)
1445  {
1446    #=eigenvals(M);
1447  }
1448  def e0,m0=#[1..2];
1449
1450  intvec m1;
1451  matrix N0,N1;
1452  for(int i=1;i<=ncols(e0);i++)
1453  {
1454    m1[i]=1;
1455    N0=M-e0[i];
1456    N1=N0;
1457    while(size(syz(N1))<m0[i])
1458    {
1459      m1[i]=m1[i]+1;
1460      N1=N1*N0;
1461    }
1462  }
1463
1464  return(list(e0,m1));
1465}
1466example
1467{ "EXAMPLE:"; echo=2;
1468  ring R=0,x,dp;
1469  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1470  print(M);
1471  minipoly(M);
1472}
1473///////////////////////////////////////////////////////////////////////////////
1474
1475proc spnf(list #)
1476"USAGE:   spnf(list(a[,m])); ideal a, intvec m
1477ASSUME:  ncols(a)==size(m)
1478RETURN:  order a[i] with multiplicity m[i] lexicographically
1479EXAMPLE: example spnf; shows examples
1480"
1481{
1482  list sp=#;
1483  ideal a=sp[1];
1484  int n=ncols(a);
1485  intvec m;
1486  list V;
1487  module v;
1488  int i,j;
1489  for(i=2;i<=size(sp);i++)
1490  {
1491    if(typeof(sp[i])=="intvec")
1492    {
1493      m=sp[i];
1494    }
1495    if(typeof(sp[i])=="module")
1496    {
1497      v=sp[i];
1498      for(j=n;j>=1;j--)
1499      {
1500        V[j]=module(v[j]);
1501      }
1502    }
1503    if(typeof(sp[i])=="list")
1504    {
1505      V=sp[i];
1506    }
1507  }
1508  if(m==0)
1509  {
1510    for(i=n;i>=1;i--)
1511    {
1512      m[i]=1;
1513    }
1514  }
1515
1516  int k;
1517  ideal a0;
1518  intvec m0;
1519  list V0;
1520  number a1;
1521  int m1;
1522  for(i=n;i>=1;i--)
1523  {
1524    if(m[i]!=0)
1525    {
1526      for(j=i-1;j>=1;j--)
1527      {
1528        if(m[j]!=0)
1529        {
1530          if(number(a[i])>number(a[j]))
1531          {
1532            a1=number(a[i]);
1533            a[i]=a[j];
1534            a[j]=a1;
1535            m1=m[i];
1536            m[i]=m[j];
1537            m[j]=m1;
1538            if(size(V)>0)
1539            {
1540              v=V[i];
1541              V[i]=V[j];
1542              V[j]=v;
1543            }
1544          }
1545          if(number(a[i])==number(a[j]))
1546          {
1547            m[i]=m[i]+m[j];
1548            m[j]=0;
1549            if(size(V)>0)
1550            {
1551              V[i]=V[i]+V[j];
1552            }
1553          }
1554        }
1555      }
1556      k++;
1557      a0[k]=a[i];
1558      m0[k]=m[i];
1559      if(size(V)>0)
1560      {
1561        V0[k]=V[i];
1562      }
1563    }
1564  }
1565
1566  if(size(V0)>0)
1567  {
1568    n=size(V0);
1569    module U=std(V0[n]);
1570    for(i=n-1;i>=1;i--)
1571    {
1572      V0[i]=simplify(reduce(V0[i],U),1);
1573      if(i>=2)
1574      {
1575        U=std(U+V0[i]);
1576      }
1577    }
1578  }
1579
1580  if(k>0)
1581  {
1582    sp=a0,m0;
1583    if(size(V0)>0)
1584    {
1585      sp[3]=V0;
1586    }
1587  }
1588  return(sp);
1589}
1590example
1591{ "EXAMPLE:"; echo=2;
1592  ring R=0,(x,y),ds;
1593  list sp=list(ideal(-1/2,-3/10,-3/10,-1/10,-1/10,0,1/10,1/10,3/10,3/10,1/2));
1594  spprint(spnf(sp));
1595}
1596///////////////////////////////////////////////////////////////////////////////
1597
1598proc spprint(list sp)
1599"USAGE:   spprint(sp); list sp (helper routine for spnf, gmssing.lib)
1600RETURN:  string s;  spectrum sp
1601EXAMPLE: example spprint; shows examples
1602SEE ALSO: gmssing_lib, spnf
1603"
1604{
1605  string s;
1606  for(int i=1;i<size(sp[2]);i++)
1607  {
1608    s=s+"("+string(sp[1][i])+","+string(sp[2][i])+"),";
1609  }
1610  s=s+"("+string(sp[1][i])+","+string(sp[2][i])+")";
1611  return(s);
1612}
1613example
1614{ "EXAMPLE:"; echo=2;
1615  ring R=0,(x,y),ds;
1616  list sp=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1));
1617  spprint(sp);
1618}
1619///////////////////////////////////////////////////////////////////////////////
1620
1621proc jordan(matrix M,list #)
1622"USAGE:   jordan(M); matrix M
1623ASSUME:  eigenvalues of M in basefield
1624RETURN:
1625@format
1626list l;  Jordan data of M
1627  ideal l[1];
1628    number l[1][i];  eigenvalue of i-th Jordan block of M
1629  intvec l[2];
1630    int l[2][i];  size of i-th Jordan block of M
1631  intvec l[3];
1632    int l[3][i];  multiplicity of i-th Jordan block of M
1633@end format
1634EXAMPLE: example jordan; shows examples
1635"
1636{
1637  if(nrows(M)==0)
1638  {
1639    ERROR("non empty expected");
1640  }
1641  if(ncols(M)!=nrows(M))
1642  {
1643    ERROR("square matrix expected");
1644  }
1645
1646  M=jet(M,0);
1647
1648  if(size(#)==0)
1649  {
1650    #=eigenvals(M);
1651  }
1652  def e0,m0=#[1..2];
1653
1654  int i;
1655  for(i=1;i<=ncols(e0);i++)
1656  {
1657    if(deg(e0[i])>0)
1658    {
1659
1660      ERROR("eigenvalues in coefficient field expected");
1661      return(list());
1662    }
1663  }
1664
1665  int j,k;
1666  matrix N0,N1;
1667  module K0;
1668  list K;
1669  ideal e;
1670  intvec s,m;
1671
1672  for(i=1;i<=ncols(e0);i++)
1673  {
1674    N0=M-e0[i]*matrix(freemodule(ncols(M)));
1675
1676    N1=N0;
1677    K0=0;
1678    K=module();
1679    while(size(K0)<m0[i])
1680    {
1681      K0=syz(N1);
1682      K=K+list(K0);
1683      N1=N1*N0;
1684    }
1685
1686    for(j=2;j<size(K);j++)
1687    {
1688      if(2*size(K[j])-size(K[j-1])-size(K[j+1])>0)
1689      {
1690        k++;
1691        e[k]=e0[i];
1692        s[k]=j-1;
1693        m[k]=2*size(K[j])-size(K[j-1])-size(K[j+1]);
1694      }
1695    }
1696    if(size(K[j])-size(K[j-1])>0)
1697    {
1698      k++;
1699      e[k]=e0[i];
1700      s[k]=j-1;
1701      m[k]=size(K[j])-size(K[j-1]);
1702    }
1703  }
1704
1705  return(list(e,s,m));
1706}
1707example
1708{ "EXAMPLE:"; echo=2;
1709  ring R=0,x,dp;
1710  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1711  print(M);
1712  jordan(M);
1713}
1714///////////////////////////////////////////////////////////////////////////////
1715
1716proc jordanbasis(matrix M,list #)
1717"USAGE:   jordanbasis(M); matrix M
1718ASSUME:  eigenvalues of M in basefield
1719RETURN:
1720@format
1721list l:
1722  module l[1];  inverse(l[1])*M*l[1] in Jordan normal form
1723  intvec l[2];
1724    int l[2][i];  weight filtration index of l[1][i]
1725@end format
1726EXAMPLE: example jordanbasis; shows examples
1727"
1728{
1729  if(nrows(M)==0)
1730  {
1731    ERROR("non empty matrix expected");
1732  }
1733  if(ncols(M)!=nrows(M))
1734  {
1735    ERROR("square matrix expected");
1736  }
1737
1738  M=jet(M,0);
1739
1740  if(size(#)==0)
1741  {
1742    #=eigenvals(M);
1743  }
1744  def e,m=#[1..2];
1745
1746  for(int i=1;i<=ncols(e);i++)
1747  {
1748    if(deg(e[i])>0)
1749    {
1750      ERROR("eigenvalues in coefficient field expected");
1751      return(freemodule(ncols(M)));
1752    }
1753  }
1754
1755  int j,k,l,n;
1756  matrix N0,N1;
1757  module K0,K1;
1758  list K;
1759  matrix u[ncols(M)][1];
1760  module U;
1761  intvec w;
1762
1763  for(i=1;i<=ncols(e);i++)
1764  {
1765    N0=M-e[i]*matrix(freemodule(ncols(M)));
1766
1767    N1=N0;
1768    K0=0;
1769    K=list();
1770    while(size(K0)<m[i])
1771    {
1772      K0=syz(N1);
1773      K=K+list(K0);
1774      N1=N1*N0;
1775    }
1776
1777    K1=0;
1778    for(j=1;j<size(K);j++)
1779    {
1780      K0=K[j];
1781      K[j]=interred(reduce(K[j],std(K1+module(N0*K[j+1]))));
1782      K1=K0;
1783    }
1784    K[j]=interred(reduce(K[j],std(K1)));
1785
1786    for(l=size(K);l>=1;l--)
1787    {
1788      for(k=size(K[l]);k>0;k--)
1789      {
1790        u=K[l][k];
1791        for(j=l;j>=1;j--)
1792        {
1793          U=U+module(u);
1794          n++;
1795          w[n]=2*j-l-1;
1796          u=N0*u;
1797        }
1798      }
1799    }
1800  }
1801
1802  return(list(U,w));
1803}
1804example
1805{ "EXAMPLE:"; echo=2;
1806  ring R=0,x,dp;
1807  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1808  print(M);
1809  list l=jordanbasis(M);
1810  print(l[1]);
1811  print(l[2]);
1812  print(inverse(l[1])*M*l[1]);
1813}
1814///////////////////////////////////////////////////////////////////////////////
1815
1816proc jordanmatrix(list jd)
1817"USAGE:   jordanmatrix(list(e,s,m)); ideal e, intvec s, intvec m
1818ASSUME:  ncols(e)==size(s)==size(m)
1819RETURN:
1820@format
1821matrix J;  Jordan matrix with list(e,s,m)==jordan(J)
1822@end format
1823EXAMPLE: example jordanmatrix; shows examples
1824"
1825{
1826  ideal e=jd[1];
1827  intvec s=jd[2];
1828  intvec m=jd[3];
1829  if(ncols(e)!=size(s)||ncols(e)!=size(m))
1830  {
1831    ERROR("arguments of equal size expected");
1832  }
1833
1834  int i,j,k,l;
1835  int n=int((transpose(matrix(s))*matrix(m))[1,1]);
1836  matrix J[n][n];
1837  for(k=1;k<=ncols(e);k++)
1838  {
1839    for(l=1;l<=m[k];l++)
1840    {
1841      j++;
1842      J[j,j]=e[k];
1843      for(i=s[k];i>=2;i--)
1844      {
1845        J[j+1,j]=1;
1846        j++;
1847        J[j,j]=e[k];
1848      }
1849    }
1850  }
1851
1852  return(J);
1853}
1854example
1855{ "EXAMPLE:"; echo=2;
1856  ring R=0,x,dp;
1857  ideal e=ideal(2,3);
1858  intvec s=1,2;
1859  intvec m=1,1;
1860  print(jordanmatrix(list(e,s,m)));
1861}
1862///////////////////////////////////////////////////////////////////////////////
1863
1864proc jordannf(matrix M,list #)
1865"USAGE:   jordannf(M); matrix M
1866ASSUME:  eigenvalues of M in basefield
1867RETURN:  matrix J; Jordan normal form of M
1868EXAMPLE: example jordannf; shows examples
1869"
1870{
1871  return(jordanmatrix(jordan(M,#)));
1872}
1873example
1874{ "EXAMPLE:"; echo=2;
1875  ring R=0,x,dp;
1876  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
1877  print(M);
1878  print(jordannf(M));
1879}
1880
1881///////////////////////////////////////////////////////////////////////////////
1882
1883/*
1884///////////////////////////////////////////////////////////////////////////////
1885//          Auskommentierte zusaetzliche Beispiele
1886//
1887///////////////////////////////////////////////////////////////////////////////
1888// Singular for ix86-Linux version 1-3-10  (2000121517)  Dec 15 2000 17:55:12
1889// Rechnungen auf AMD700 mit 632 MB
1890
1891 LIB "linalg.lib";
1892
18931. Sparse integer Matrizen
1894--------------------------
1895ring r1=0,(x),dp;
1896system("--random", 12345678);
1897int n = 70;
1898matrix m = sparsemat(n,n,50,100);
1899option(prot,mem);
1900
1901int t=timer;
1902matrix im = inverse(m,1)[1];
1903timer-t;
1904print(im*m);
1905//list l0 = watchdog(100,"inverse("+"m"+",3)");
1906//bricht bei 100 sec ab und gibt l0[1]: string Killed zurueck
1907
1908//inverse(m,1): std       5sec 5,5 MB
1909//inverse(m,2): interred  12sec
1910//inverse(m,2): lift      nach 180 sec 13MB abgebrochen
1911//n=60: linalgorig: 3  linalg: 5
1912//n=70: linalgorig: 6,7 linalg: 11,12
1913// aber linalgorig rechnet falsch!
1914
19152. Sparse poly Matrizen
1916-----------------------
1917ring r=(0),(a,b,c),dp;
1918system("--random", 12345678);
1919int n=6;
1920matrix m = sparsematrix(n,n,2,0,50,50,9); //matrix of polys of deg <=2
1921option(prot,mem);
1922
1923int t=timer;
1924matrix im = inverse(m);
1925timer-t;
1926print(im*m);
1927//inverse(m,1): std       0sec 1MB
1928//inverse(m,2): interred  0sec 1MB
1929//inverse(m,2): lift      nach 2000 sec 33MB abgebrochen
1930
19313. Sparse Matrizen mit Parametern
1932---------------------------------
1933//liborig rechnet hier falsch!
1934ring r=(0),(a,b),dp;
1935system("--random", 12345678);
1936int n=7;
1937matrix m = sparsematrix(n,n,1,0,40,50,9);
1938ring r1 = (0,a,b),(x),dp;
1939matrix m = imap(r,m);
1940option(prot,mem);
1941
1942int t=timer;
1943matrix im = inverse(m);
1944timer-t;
1945print(im*m);
1946//inverse(m)=inverse(m,3):15 sec inverse(m,1)=1sec inverse(m,2):>120sec
1947//Bei Parametern vergeht die Zeit beim Normieren!
1948
19493. Sparse Matrizen mit Variablen und Parametern
1950-----------------------------------------------
1951ring r=(0),(a,b),dp;
1952system("--random", 12345678);
1953int n=6;
1954matrix m = sparsematrix(n,n,1,0,35,50,9);
1955ring r1 = (0,a),(b),dp;
1956matrix m = imap(r,m);
1957option(prot,mem);
1958
1959int t=timer;
1960matrix im = inverse(m,3);
1961timer-t;
1962print(im*m);
1963//n=7: inverse(m,3):lange sec inverse(m,1)=1sec inverse(m,2):1sec
1964
19654. Ueber Polynomring invertierbare Matrizen
1966-------------------------------------------
1967LIB"random.lib"; LIB"linalg.lib";
1968system("--random", 12345678);
1969int n =3;
1970ring r= 0,(x,y,z),(C,dp);
1971matrix A=triagmatrix(n,n,1,0,0,50,2);
1972intmat B=sparsetriag(n,n,20,1);
1973matrix M = A*transpose(B);
1974M=M*transpose(M);
1975M[1,1..ncols(M)]=M[1,1..n]+xyz*M[n,1..ncols(M)];
1976print(M);
1977//M hat det=1 nach Konstruktion
1978
1979int t=timer;
1980matrix iM=inverse(M);
1981timer-t;
1982print(iM*M);                      //test
1983
1984//ACHTUNG: Interred liefert i.A. keine Inverse, Gegenbeispiel z.B.
1985//mit n=3
1986//eifacheres Gegenbeispiel:
1987matrix M =
19889yz+3y+3z+2,             9y2+6y+1,
19899xyz+3xy+3xz-9z2+2x-6z-1,9xy2+6xy-9yz+x-3y-3z
1990//det M=1, inverse(M,2); ->// ** matrix is not invertible
1991//lead(M); 9xyz*gen(2) 9xy2*gen(2) nicht teilbar!
1992
19935. charpoly:
1994-----------
1995//ring rp=(0,A,B,C),(x),dp;
1996ring r=0,(A,B,C,x),dp;
1997matrix m[12][12]=
1998AC,BC,-3BC,0,-A2+B2,-3AC+1,B2,   B2,  1,   0, -C2+1,0,
19991, 1, 2C,  0,0,     B,     -A,   -4C, 2A+1,0, 0,    0,
20000, 0, 0,   1,0,     2C+1,  -4C+1,-A,  B+1, 0, B+1,  3B,
2001AB,B2,0,   1,0,     1,     0,    1,   A,   0, 1,    B+1,
20021, 0, 1,   0,0,     1,     0,    -C2, 0,   1, 0,    1,
20030, 0, 2,   1,2A,    1,     0,    0,   0,   0, 1,    1,
20040, 1, 0,   1,1,     2,     A,    3B+1,1,   B2,1,    1,
20050, 1, 0,   1,1,     1,     1,    1,   2,   0, 0,    0,
20061, 0, 1,   0,0,     0,     1,    0,   1,   1, 0,    3,
20071, 3B,B2+1,0,0,     1,     0,    1,   0,   0, 1,    0,
20080, 0, 1,   0,0,     0,     0,    1,   0,   0, 0,    0,
20090, 1, 0,   1,1,     3,     3B+1, 0,   1,   1, 1,    0;
2010option(prot,mem);
2011
2012int t=timer;
2013poly q=charpoly(m,"x");         //1sec, charpoly_B 1sec, 16MB
2014timer-t;
2015//1sec, charpoly_B 1sec, 16MB  (gleich in r und rp)
2016
2017*/
Note: See TracBrowser for help on using the repository browser.