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

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