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

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