source: git/Singular/LIB/linalg.lib @ 8647dd

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