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

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