Ticket #57: jacobson.lib.diff.txt

File jacobson.lib.diff.txt, 24.7 KB (added by Oleksandr , 15 years ago)

same, viewable version

Line 
1//////////////////////////////////////////////////////////////////////////////
2version="$Id: jacobson.lib,v 1.9 2009/02/12 20:27:17 levandov Exp $";
3category="System and Control Theory";
4info="
5LIBRARY: jacobson.lib     Algorithms for Smith and Jacobson Normal Form
6AUTHOR: Kristina Schindelar,     Kristina.Schindelar@math.rwth-aachen.de
7
8THEORY: We work over a ring R, that is a principal ideal domain.
9@*   If R is commutative, we suppose R to be a polynomial ring in one variable.
10@* If R is non-commutative, we suppose R to be in two variables, say x and d.
11@* We treat then the basering as principal ideal ring with d a polynomial
12@* variable and x an invertible one. That is, we work in the Ore localization of R
13@* with respect to the mult. closed set S = K[x] without 0.
14@* Note, that in computations no division by x will actually happen.
15@*   Given a rectangular matrix M over R, one can compute unimodular (that is invertible)
16@* square matrices U and V, such that U*M*V=D is a diagonal matrix.
17@*   Depending on the ring, the diagonal entries of D have certain properties.
18
19REFERENCES:
20@* N. Jacobson, 'The theory of rings', AMS, 1943.
21@* Manuel Avelino Insua Hermo, 'Varias perspectives sobre las bases de Groebner: Forma normal de Smith, Algorithme de Berlekamp y algebras de Leibniz'. PhD thesis, Universidad de Santiago de Compostela, 2005.
22
23
24PROCEDURES:
25smith(M[,eng1,eng2]);  compute the Smith Normal Form of M over commutative ring
26jacobson(M[,eng]);       compute a weak Jacobson Normal Form of M over non-commutative ring
27
28SEE ALSO: control_lib
29";
30
31  LIB "poly.lib";
32  LIB "involut.lib";
33
34proc smith(matrix MA, list #)
35"USAGE: smith(M[, eng1, eng2]);  M matrix, eng1 and eng2 are optional integers
36RETURN: matrix or list
37ASSUME: The current ring is assumed to be the commutative polynomial ring in
38        one variable
39PURPOSE: compute the Smith Normal Form of M with transformation matrices (optionally)
40NOTE: If the optional integer eng1 is non-zero, returns the list {U,D,V},
41where U*M*V = D and the diagonal field entries of D are not normalized.
42@*    Otherwise only the matrix D, that is the Smith Normal Form of M, is returned.
43@*    Here, U and V are square unimodular (invertible) matrices. The procedure works for rectangular matrix M.
44@* The optional integer eng2 determines the engine, that computes the Groebner basis:
45@* 0 means 'std' (default), 1 means 'groebner' and 2 means 'slimgb'.
46DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
47@* if @code{printlevel}>=2, all the debug messages will be printed.
48EXAMPLE: example smith; shows examples
49"
50{
51  def R = basering;
52  // check assume: R must be a polynomial ring in 1 variable
53  setring R;
54  if (nvars(R) >1 )
55  {
56    ERROR("Basering must have exactly one variable");
57  }
58
59  int eng = 0;
60  int BASIS = 0;
61
62  if ( size(#)>0 )
63  {
64    if (typeof(#[1])=="int")
65    {
66      eng=#[1]; // zero can also happen
67  }
68
69    if (size(#) > 1)
70    {
71      if (typeof(#[2])=="int")
72  {
73  BASIS=#[2];
74  }
75    }
76  }
77
78
79  int ROW=ncols(MA);
80  int COL=nrows(MA);
81
82  //generate a module consisting of the columns of MA
83  module m = MA;
84  int i;
85
86  //if MA eqauls the zero matrix give back MA
87  if ( (size(m)==0) and (size(transpose(m))==0) )
88  {
89    if( eng > 0 )
90    {
91      return(list( matrix(freemodule(COL)), MA, matrix(freemodule(ROW)) ));
92    }
93   
94    return(MA);
95  }
96
97  if(eng > 0)
98  {
99    list rueckLI=diagonal_with_trafo(R,MA,BASIS);
100    list rueckLII=divisibility(rueckLI[2]);
101    matrix CON=divideByContent(rueckLII[2]);
102    list rueckL=CON*rueckLII[1]*rueckLI[1], CON*rueckLII[2], rueckLI[3]*rueckLII[3];
103    return(rueckL);
104  }
105  else
106  {
107    matrix rueckm=diagonal_without_trafo(R,MA,BASIS);
108    list rueckL=divisibility(rueckm);
109    matrix CON=divideByContent(rueckm);
110    rueckm=CON*rueckL[2];
111    return(rueckm);
112  }
113}
114example
115{ "EXAMPLE:"; echo = 2;
116  ring r = 0,x,Dp;
117  matrix m[3][2]=x, x^4+x^2+21, x^4+x^2+x, x^3+x, 4*x^2+x, x;
118  print(m); // M
119  print(smith(m)); // Smith Normal Form of M
120  list s=smith(m,1);
121  // TODO: BUG THE FOLLOWING GIVES A DIFFERENT RESULT TO ABOVE!
122  print(S[2]); // Smith Normal Form D of M
123  // TODO: ARE U AND V REALLY UNIMODULAR?
124  S[1]; // U
125  det(S[1]);
126  S[3]; // V
127  det(S[3]);
128  print(S[1]*m*S[3] - S[2]); // check that U*M*V = D
129  print(smith(matrix(0))); // Smith Normal Form of 0
130
131}
132
133static proc diagonal_with_trafo( R, matrix MA, int B)
134{
135
136int ppl = printlevel-voice+2;
137
138  int BASIS=B;
139  int ROW=ncols(MA);
140  int COL=nrows(MA);
141  module m=MA[1];
142  int i,j,k;
143  for(i=2;i<=ROW;i++)
144  {
145    m=m,MA[i];
146  }
147
148
149  //add zero rows or columns
150  //add zero rows or columns
151  int adrow=0;
152  for(i=1;i<=COL;i++)
153  {
154  k=0;
155  for(j=1;j<=ROW;j++)
156  {
157  if(MA[i,j]!=0){k=1;}
158  }
159  if(k==0){adrow++;}
160  }
161
162    m=transpose(m);
163    for(i=1;i<=adrow;i++){m=m,0;}
164    m=transpose(m);
165
166  list RINGLIST=ringlist(R);
167  list o="C",0;
168  list oo="lp",1;
169  list ORD=o,oo;
170  RINGLIST[3]=ORD;
171  def r=ring(RINGLIST);
172  setring r;
173  //fix the required ordering
174  map MAP=R,var(1);
175  module m=MAP(m);
176
177  int flag=1;  ///////////////counts if the underlying ring is r (flag mod 2 == 1) or ro (flag mod 2 == 0)
178
179    module TrafoL=freemodule(COL);
180    module TrafoR=freemodule(ROW);
181    module EXL=freemodule(COL); //because we start with transpose(m)
182    module EXR=freemodule(ROW);
183
184    option(redSB);
185    option(redTail);
186    module STD_EX;
187    module Trafo;
188
189    int s,st,p,ff;
190
191    module LT,TSTD;
192    module STD=transpose(m);
193    int finish=0;
194    int fehlpos;
195    list pos;
196    matrix END;
197    matrix ENDSTD;
198    matrix STDFIN;
199    STDFIN=STD;
200    list COMPARE=STDFIN;
201
202    while(finish==0)
203    {
204      dbprint(ppl,"Going into the while cycle");
205
206      if(flag mod 2==1)
207      {
208        STD_EX=EXL,transpose(STD);
209      }
210      else
211      {
212        STD_EX=EXR,transpose(STD);
213      }
214        dbprint(ppl,"Computing Groebner basis: start");
215        dbprint(ppl-1,STD);
216      STD=engine(STD,BASIS);
217        dbprint(ppl,"Computing Groebner basis: finished");
218        dbprint(ppl-1,STD);
219
220      if(flag mod 2==1){s=ROW; st=COL;}else{s=COL; st=ROW;}
221        dbprint(ppl,"Computing Groebner basis for transformation matrix: start");
222        dbprint(ppl-1,STD_EX);
223      STD_EX=transpose(STD_EX);
224      STD_EX=engine(STD_EX,BASIS);
225        dbprint(ppl,"Computing Groebner basis for transformation matrix: finished");
226        dbprint(ppl-1,STD_EX);
227
228      //////// split STD_EX in STD and the transformation matrix
229      STD_EX=transpose(STD_EX);
230      STD=STD_EX[st+1];
231      LT=STD_EX[1];
232
233      ENDSTD=STD_EX;
234      for(i=2; i<=ncols(ENDSTD); i++)
235      {
236        if (i<=st)
237        {
238         LT=LT,STD_EX[i];
239        }
240        if (i>st+1)
241        {
242          STD=STD,STD_EX[i];
243        }
244      }
245
246      STD=transpose(STD);
247      LT=transpose(LT);
248
249      ////////////////////// compute the transformation matrices
250
251      if (flag mod 2 ==1)
252      {
253        TrafoL=transpose(LT)*TrafoL;
254      }
255      else
256      {
257        TrafoR=TrafoR*LT;
258      }
259
260
261      STDFIN=STD;
262      /////////////////////////////////// check if the D-th row is finished ///////////////////////////////////
263      COMPARE=insert(COMPARE,STDFIN);
264             if(size(COMPARE)>=3)
265       {
266        if(STD==COMPARE[3]){finish=1;}
267       }
268////////////////////////////////// change to the opposite module
269       TSTD=transpose(STD);
270       STD=TSTD;
271       flag++;
272      dbprint(ppl,"Finished one while cycle");
273    }
274
275
276   if (flag mod 2!=0) { STD=transpose(STD); }
277
278
279   //zero colums to the end
280    matrix STDMM=STD;
281    pos=list();
282    fehlpos=0;
283    while( size(STD)+fehlpos-ncols(STDMM) < 0)
284    {
285      for(i=1; i<=ncols(STDMM); i++)
286      {
287        ff=0;
288        for(j=1; j<=nrows(STDMM); j++)
289        {
290          if (STD[j,i]==0) { ff++; }
291        }
292        if(ff==nrows(STDMM))
293        {
294          pos=insert(pos,i); fehlpos++;
295        }
296      }
297    }
298    int fehlposc=fehlpos;
299    module SORT;
300    for(i=1; i<=fehlpos; i++)
301    {
302      SORT=gen(2);
303      for (j=3;j<=ROW;j++)
304      {
305        SORT=SORT,gen(j);
306      }
307      SORT=SORT,gen(1);
308      STD=STD*SORT;
309      TrafoR=TrafoR*SORT;
310    }
311
312    //zero rows to the end
313    STDMM=transpose(STD);
314    pos=list();
315    fehlpos=0;
316    while( size(transpose(STD))+fehlpos-ncols(STDMM) < 0)
317    {
318      for(i=1; i<=ncols(STDMM); i++)
319      {
320        ff=0; for(j=1; j<=nrows(STDMM); j++)
321        {
322           if(transpose(STD)[j,i]==0){ ff++;}}
323           if(ff==nrows(STDMM)) { pos=insert(pos,i); fehlpos++; }
324      }
325    }
326    int fehlposr=fehlpos;
327
328    for(i=1; i<=fehlpos; i++)
329    {
330      SORT=gen(2);
331      for(j=3;j<=COL;j++){SORT=SORT,gen(j);}
332      SORT=SORT,gen(1);
333      SORT=transpose(SORT);
334      STD=SORT*STD;
335      TrafoL=SORT*TrafoL;
336    }
337
338    setring R;
339    map MAPinv=r,var(1);
340    module STD=MAPinv(STD);
341    module TrafoL=MAPinv(TrafoL);
342    matrix TrafoLM=TrafoL;
343    module TrafoR=MAPinv(TrafoR);
344    matrix TrafoRM=TrafoR;
345    matrix STDM=STD;
346
347    //Test
348    if(TrafoLM*m*TrafoRM!=STDM){ return(0); }
349
350    list RUECK=TrafoRM;
351    RUECK=insert(RUECK,STDM);
352    RUECK=insert(RUECK,TrafoLM);
353    return(RUECK);
354}
355
356
357static proc divisibility(matrix M)
358   {
359    matrix STDM=M;
360    int i,j;
361    int ROW=nrows(M);
362    int COL=ncols(M);
363    module TrafoR=freemodule(COL);
364    module TrafoL=freemodule(ROW);
365    module SORT;
366    matrix TrafoRM=TrafoR;
367    matrix TrafoLM=TrafoL;
368    list posdeg0;
369    int posdeg=0;
370    int act;
371    int Sort=ROW;
372    if(size(std(STDM))!=0)
373    { while( size(transpose(STDM)[Sort])==0 ){Sort--;}}
374
375    for(i=1;i<=Sort ;i++)
376    {
377      if(leadexp(STDM[i,i])==0){posdeg0=insert(posdeg0,i);posdeg++;}
378    }
379    //entries of degree 0 at the beginning
380    for(i=1; i<=posdeg; i++)
381    {
382      act=posdeg0[i];
383      SORT=gen(act);
384      for(j=1; j<=COL; j++){if(j!=act){SORT=SORT,gen(j);}}
385      STDM=STDM*SORT;
386      TrafoRM=TrafoRM*SORT;
387      SORT=gen(act);
388      for(j=1; j<=ROW; j++){if(j!=act){SORT=SORT,gen(j);}}
389      STDM=transpose(SORT)*STDM;
390      TrafoLM=transpose(SORT)*TrafoLM;
391    }
392
393    poly G;
394    module UNITL=freemodule(ROW);
395    matrix GCDL=UNITL;
396    module UNITR=freemodule(COL);
397    matrix GCDR=UNITR;
398    for(i=posdeg+1; i<=Sort; i++)
399    {
400      for(j=i+1; j<=Sort; j++)
401      {
402        GCDL=UNITL;
403        GCDR=UNITR;
404        G=gcd(STDM[i,i],STDM[j,j]);
405        ideal Z=STDM[i,i],STDM[j,j];
406        matrix T=lift(Z,G);
407        GCDL[i,i]=T[1,1];
408        GCDL[i,j]=T[2,1];
409        GCDL[j,i]=-STDM[j,j]/G;
410        GCDL[j,j]=STDM[i,i]/G;
411        GCDR[i,j]=T[2,1]*STDM[j,j]/G;
412        GCDR[j,j]=T[2,1]*STDM[j,j]/G-1;
413        GCDR[j,i]=1;
414        STDM=GCDL*STDM*GCDR;
415        TrafoLM=GCDL*TrafoLM;
416        TrafoRM=TrafoRM*GCDR;
417      }
418    }
419    list RUECK=TrafoRM;
420    RUECK=insert(RUECK,STDM);
421    RUECK=insert(RUECK,TrafoLM);
422    return(RUECK);
423}
424
425static proc diagonal_without_trafo( R, matrix MA, int B)
426{
427  int ppl = printlevel-voice+2;
428
429  int BASIS=B;
430  int ROW=ncols(MA);
431  int COL=nrows(MA);
432  module m=MA[1];
433  int i;
434  for(i=2;i<=ROW;i++)
435  {m=m,MA[i];}
436
437
438  list RINGLIST=ringlist(R);
439  list o="C",0;
440  list oo="lp",1;
441  list ORD=o,oo;
442  RINGLIST[3]=ORD;
443  def r=ring(RINGLIST);
444  setring r;
445  //RICHTIGE ORDNUNG MACHEN
446  map MAP=R,var(1);
447  module m=MAP(m);
448
449  int flag=1; ///////////////counts if the underlying ring is r (flag mod 2 == 1) or ro (flag mod 2 == 0)
450
451
452    int act, j, ff;
453    option(redSB);
454    option(redTail);
455
456
457    module STD=transpose(m);
458    module TSTD;
459    int finish=0;
460    matrix STDFIN;
461    STDFIN=STD;
462    list COMPARE=STDFIN;
463
464    while(finish==0)
465    {
466      dbprint(ppl,"Going into the while cycle");
467      dbprint(ppl,"Computing Groebner basis: start");
468      dbprint(ppl-1,STD);
469      STD=engine(STD,BASIS);
470      dbprint(ppl,"Computing Groebner basis: finished");
471      dbprint(ppl-1,STD);
472      STDFIN=STD;
473      /////////////////////////////////// check if the D-th row is finished ///////////////////////////////////
474      COMPARE=insert(COMPARE,STDFIN);
475             if(size(COMPARE)>=3)
476       {
477        if(STD==COMPARE[3]){finish=1;}
478       }
479        ////////////////////////////////// change to the opposite module
480
481        TSTD=transpose(STD);
482        STD=TSTD;
483        flag++;
484        dbprint(ppl,"Finished one while cycle");
485    }
486
487    matrix STDMM=STD;
488    list pos=list();
489    int fehlpos=0;
490    while( size(STD)+fehlpos-ncols(STDMM) < 0)
491    {
492      for(i=1; i<=ncols(STDMM); i++)
493      {
494        ff=0;
495        for(j=1; j<=nrows(STDMM); j++)
496        {
497          if (STD[j,i]==0) { ff++; }
498        }
499        if(ff==nrows(STDMM))
500        {
501          pos=insert(pos,i); fehlpos++;
502        }
503      }
504    }
505   int fehlposc=fehlpos;
506    module SORT;
507    for(i=1; i<=fehlpos; i++)
508    {
509      SORT=gen(2);
510      for (j=3;j<=ROW;j++)
511      {
512        SORT=SORT,gen(j);
513      }
514      SORT=SORT,gen(1);
515      STD=STD*SORT;
516    }
517
518    //zero rows to the end
519    STDMM=transpose(STD);
520    pos=list();
521    fehlpos=0;
522    while( size(transpose(STD))+fehlpos-ncols(STDMM) < 0)
523    {
524      for(i=1; i<=ncols(STDMM); i++)
525      {
526        ff=0; for(j=1; j<=nrows(STDMM); j++)
527        {
528           if(transpose(STD)[j,i]==0){ ff++;}}
529           if(ff==nrows(STDMM)) { pos=insert(pos,i); fehlpos++; }
530      }
531    }
532    int fehlposr=fehlpos;
533
534    for(i=1; i<=fehlpos; i++)
535    {
536      SORT=gen(2);
537      for(j=3;j<=COL;j++){SORT=SORT,gen(j);}
538      SORT=SORT,gen(1);
539      SORT=transpose(SORT);
540      STD=SORT*STD;
541    }
542
543   //add zero rows or columns
544
545    int adrow=COL-size(transpose(STD));
546    int adcol=ROW-size(STD);
547
548    for(i=1;i<=adcol;i++){STD=STD,0;}
549    STD=transpose(STD);
550    for(i=1;i<=adrow;i++){STD=STD,0;}
551    STD=transpose(STD);
552
553    setring R;
554    map MAPinv=r,var(1);
555    module STD=MAPinv(STD);
556    matrix STDM=STD;
557    return(STDM);
558}
559
560
561
562static proc engine(module I, int i)
563{
564  module J;
565  if (i==0)
566  {
567    J = std(I);
568  }
569  if (i==1)
570  {
571    J = groebner(I);
572  }
573  if (i==2)
574  {
575    J = slimgb(I);
576  }
577  return(J);
578}
579
580proc jacobson(matrix MA, list #)
581 "USAGE:  jacobson(M[, eng]);  M matrix, eng an optional int
582RETURN: list
583ASSUME: Basering is a noncommutative ring in two variables.
584PURPOSE: compute a weak Jacobson Normal Form of M over a noncommutative ring
585NOTE: A list L of matrices {U,D,V} is returned. That is U*M*V=D, where
586@*      D is a diagonal matrix and U, V square invertible (unimodular) matrices.
587@*      Note, that M can be rectangular.
588@* The optional integer @code{eng} determines the engine, that computes the Groebner basis:
589@* 0 means 'std' (default), 1 means 'groebner' and 2 means 'slimgb'.
590DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
591@* if @code{printlevel}>=2, all the debug messages will be printed.
592EXAMPLE: example jacobson; shows examples
593"
594{
595  def R = basering;
596  // check assume: R must be a polynomial ring in 2 variables
597  setring R;
598  if ( (nvars(R) !=2 ) )
599  {
600    ERROR("Basering must have exactly two variables");
601  }
602
603  // check if MA is zero matrix and return corr. U,V
604  if ( (size(module(MA))==0) and (size(transpose(module(MA)))==0) )
605  {
606    int nr = nrows(MA);
607    int nc = ncols(MA);
608    matrix U = matrix(freemodule(nr));
609    matrix V = matrix(freemodule(nc));
610    list L; L[1]=U; L[2] = MA; L[3] = V;
611    return(L);
612  }
613
614  int B=0;
615  if ( size(#)>0 )
616  {
617    if (typeof(#[1])=="int")
618    {
619      B = #[1]; // zero can also happen
620    }
621  }
622
623  //change ring
624  list RINGLIST=ringlist(R);
625  list o="C",0;
626  intvec v=0,1;
627  list oo="a",v;
628  v=1,1;
629  list ooo="lp",v;
630  list ORD=o,oo,ooo;
631  RINGLIST[3]=ORD;
632  def r=ring(RINGLIST);
633  setring r;
634
635  //fix the required ordering
636  matrix M=imap(R, MA);
637
638  list T = triangle(M,B);
639  module TrafoL = T[1];
640  module m      = T[2];
641  module TrafoR = T[3];
642
643  //back to the ring
644  setring R;
645
646  matrix MAA = imap(r, m);
647  matrix CON=divideByContent(MAA);
648  matrix TL = imap(r, TrafoL);
649  matrix TR = imap(r, TrafoR);
650 
651  // TODO: CHECK WHETHER HERE SHOULD BE CON*TR!?
652  return(list(CON*TL, CON*MAA, TR));
653
654}
655example
656{ "EXAMPLE:"; echo = 2;
657  ring r = 0,(x,d),Dp;
658  def R=nc_algebra(1,1); setring R;
659  R; // the Weyl algebra in x and d
660  jacobson(matrix(0));
661 
662  matrix m[2][2]=d,x,0,d;
663  print(m);
664  list J = jacobson(m); // returns a list with 3 entries
665  print(J[2]); // a Jacobson Form D
666  J[1]; // U
667  J[3]; // V
668
669  print(J[1]*m*J[3] - J[2]); // check that U*M*V = D
670
671  matrix m[3][2]=x, x^4+x^2+21, x^4+x^2+x, x^3+x, 4*x^2+x, x;
672  print(m); // M
673  list JJ = jacobson(m); // returns a list with 3 entries
674
675  // TODO: BUG: WHY THE FOLLOWING JACOBSON FORM IS NOT DIAGONAL???!
676  print(JJ[2]); // a Jacobson Form D
677  print(JJ[1]*m*JJ[3] - JJ[2]); // check that U*M*V = D
678  JJ[1]; // U
679  JJ[3]; // V
680
681  list S=smith(m,1);
682
683  print(S[2]); // Smith Normal Form S of M
684  print(S[1]*m*S[3] - S[2]); // check that U*M*V = S
685
686  S[1]; // U
687  S[3]; // V
688
689  /*   now, let us do the same for the shift algebra  */
690  ring r2 = 0,(x,s),Dp;
691  def R2 = nc_algebra(1,s);   setring R2; // the 1st shift algebra
692  matrix m[2][2] = s,x,0,s; print(m); // matrix of the same for as above
693  list J = jacobson(m);
694  print(J[2]); // a Jacobson Form D, quite different from above
695  print(J[1]*m*J[3] - J[2]); // check that U*M*V = D
696
697}
698
699static proc triangle( matrix MA, int B)
700{
701 int ppl = printlevel-voice+2;
702
703  map inv=ncdetection();
704  int ROW=ncols(MA);
705  int COL=nrows(MA);
706
707  //generate a module consisting of the columns of MA
708  module m=MA[1];
709  int i,j,s,st,p,k,ff,ex, nz, ii,nextp;
710  for(i=2;i<=ROW;i++)
711  {
712    m=m,MA[i];
713  }
714  int BASIS=B;
715
716  //add zero rows or columns
717  int adrow=0;
718  for(i=1;i<=COL;i++)
719  {
720  k=0;
721  for(j=1;j<=ROW;j++)
722  {
723  if(MA[i,j]!=0){k=1;}
724  }
725  if(k==0){adrow++;}
726  }
727
728    m=transpose(m);
729    for(i=1;i<=adrow;i++){m=m,0;}
730    m=transpose(m);
731
732
733    int flag=1;  ///////////////counts if the underlying ring is r (flag mod 2 == 1) or ro (flag mod 2 == 0)
734
735    module TrafoL=freemodule(COL);
736    module TrafoR=freemodule(ROW);
737    module EXL=freemodule(COL); //because we start with transpose(m)
738    module EXR=freemodule(ROW);
739
740    option(redSB);
741    option(redTail);
742    module STD_EX,LT,TSTD, L, Trafo;
743
744
745
746    module STD=transpose(m);
747    int finish=0;
748    list pos, COM, COM_EX;
749    matrix END, ENDSTD, STDFIN;
750    STDFIN=STD;
751    list COMPARE=STDFIN;
752
753
754  while(finish==0)
755    {
756      dbprint(ppl,"Going into the while cycle");
757      if(flag mod 2==1){STD_EX=EXL,transpose(STD); ex=2*COL;} else {STD_EX=EXR,transpose(STD); ex=2*ROW;}
758
759      dbprint(ppl,"Computing Groebner basis: start");
760      dbprint(ppl-1,STD);
761      STD=engine(STD,BASIS);
762      dbprint(ppl,"Computing Groebner basis: finished");
763      dbprint(ppl-1,STD);
764      if(flag mod 2==1){s=ROW; st=COL;}else{s=COL; st=ROW;}
765
766      STD_EX=transpose(STD_EX);
767      dbprint(ppl,"Computing Groebner basis for transformation matrix: start");
768      dbprint(ppl-1,STD_EX);
769      STD_EX=engine(STD_EX,BASIS);
770      dbprint(ppl,"Computing Groebner basis for transformation matrix: finished");
771      dbprint(ppl-1,STD_EX);
772
773      COM=1;
774      COM_EX=1;
775      for(i=2; i<=size(STD); i++)
776         { COM=COM[1..size(COM)],i; COM_EX=COM_EX[1..size(COM_EX)],i; }
777      nz=size(STD_EX)-size(STD);
778
779      //zero rows in the begining
780
781       if(size(STD)!=size(STD_EX) )
782       {
783         for(i=1; i<=size(STD_EX)-size(STD); i++)
784         {
785           COM_EX=0,COM_EX[1..size(COM_EX)];
786         }
787       }
788
789
790
791
792       for(i=nz+1; i<=size(STD_EX); i++ )
793        {if( leadcoef(STD[i-nz])!=leadcoef(STD_EX[i]) )          {STD[i-nz]=leadcoef(STD_EX[i])*STD[i-nz];}
794        }
795
796        //assign the zero rows in STD_EX
797
798       for (j=2; j<=nz; j++)
799       {
800        p=0;
801        i=1;
802        while(STD_EX[j-1][i]==0){i++;};
803        p=i-1;
804        nextp=1;
805        k=0;
806        i=1;
807        while(STD_EX[j][i]==0 and i<=p)
808        { k++; i++;}
809        if (k==p){ COM_EX[j]=-1; }
810       }
811
812      //assign the zero rows in STD
813      for (j=2; j<=size(STD); j++)
814       {
815        i=size(transpose(STD));
816        while(STD[j-1][i]==0){i--;}
817        p=i;
818        i=size(transpose(STD[j]));
819        while(STD[j][i]==0){i--;}
820        if (i==p){ COM[j]=-1; }
821       }
822
823       for(j=1; j<=size(COM); j++)
824        {
825        if(COM[j]<0){COM=delete(COM,j);}
826        }
827
828      for(i=1; i<=size(COM_EX); i++)
829        {ff=0;
830         if(COM_EX[i]==0){ff=1;}
831         else
832          {  for(j=1; j<=size(COM); j++)
833               { if(COM_EX[i]==COM[j]){ff=1;} }
834          }
835         if(ff==0){COM_EX[i]=-1;}
836        }
837
838      L=STD_EX[1];
839      for(i=2; i<=size(COM_EX); i++)
840       {
841        if(COM_EX[i]!=-1){L=L,STD_EX[i];}
842       }
843
844      //////// split STD_EX in STD and the transformation matrix
845
846       L=transpose(L);
847       STD=L[st+1];
848       LT=L[1];
849
850
851       for(i=2; i<=s+st; i++)
852        {
853         if (i<=st)
854          {
855           LT=LT,L[i];
856          }
857         if (i>st+1)
858          {
859          STD=STD,L[i];
860          }
861        }
862
863       STD=transpose(STD);
864       STDFIN=matrix(STD);
865       COMPARE=insert(COMPARE,STDFIN);
866       LT=transpose(LT);
867
868      ////////////////////// compute the transformation matrices
869
870       if (flag mod 2 ==1)
871        {
872         TrafoL=transpose(LT)*TrafoL;
873        }
874       else
875        {
876         TrafoR=TrafoR*involution(LT,inv);
877        }
878
879
880      ///////////////////////// check whether the alg termined /////////////////
881      if(size(COMPARE)>=3)
882       {
883        if(STD==COMPARE[3]){finish=1;}
884       }
885       ////////////////////////////////// change to the opposite module
886       TSTD=transpose(STD);
887       STD=involution(TSTD,inv);
888       flag++;
889       dbprint(ppl,"Finished one while cycle");
890    }
891
892if (flag mod 2 ==0){ STD = involution(STD,inv);} else { STD = transpose(STD);  }
893
894    list REVERSE=TrafoL,STD,TrafoR;
895    return(REVERSE);
896}
897
898static proc divideByContent(matrix M)
899{
900//find first entrie not equal to zero
901int i,k;
902k=1;
903vector CON;
904   for(i=1;i<=ncols(M);i++)
905   {
906    if(leadcoef(M[i])!=0){CON=CON+leadcoef(M[i])*gen(k); k++;}
907   }
908poly con=content(CON);
909matrix TL=1/con*freemodule(nrows(M));
910return(TL);
911}
912
913
914/////interesting examples for smith////////////////
915
916/*
917
918//static proc Ex_One_wheeled_bicycle()
919{
920ring RA=(0,m), D, lp;
921matrix bicycle[2][3]=(1+m)*D^2, D^2, 1, D^2, D^2-1, 0;
922list s=smith(bicycle, 1,0);
923print(s[2]);
924print(s[1]*bicycle*s[3]-s[2]);
925}
926
927
928//static proc Ex_RLC-circuit()
929{
930ring RA=(0,m,R1,R2,L,C), D, lp;
931matrix  circuit[2][3]=D+1/(R1*C), 0, -1/(R1*C), 0, D+R2/L, -1/L;
932list s=smith(circuit, 1,0);
933print(s[2]);
934print(s[1]*circuit*s[3]-s[2]);
935}
936
937
938//static proc Ex_two_pendula()
939{
940ring RA=(0,m,M,L1,L2,m1,m2,g), D, lp;
941matrix pendula[3][4]=m1*L1*D^2,m2*L2*D^2,(M+m1+m2)*D^2,-1,m1*L1^2*D^2-m1*L1*g,0,m1*L1*D^2,0,0,
942m2*L2^2*D^2-m2*L2*g,m2*L2*D^2,0;
943list s=smith(pendula, 1,0);
944print(s[2]);
945print(s[1]*pendula*s[3]-s[2]);
946}
947
948//static proc Ex_linerized_satellite_in_a_circular_equatorial_orbit()
949{
950ring RA=(0,m,omega,r,a,b), D, lp;
951matrix satellite[4][6]=
952D,-1,0,0,0,0,
953-3*omega^2,D,0,-2*omega*r,-a/m,0,
9540,0,D,-1,0,0,
9550,2*omega/r,0,D,0,-b/(m*r);
956list s=smith(satellite, 1,0);
957print(s[2]);
958print(s[1]*satellite*s[3]-s[2]);
959}
960
961//static proc Ex_flexible_one_link_robot()
962{
963ring RA=(0,M11,M12,M13,M21,M22,M31,M33,K1,K2), D, lp;
964matrix robot[3][4]=M11*D^2,M12*D^2,M13*D^2,-1,M21*D^2,M22*D^2+K1,0,0,M31*D^2,0,M33*D^2+K2,0;
965list s=smith(robot, 1,0);
966print(s[2]);
967print(s[1]*robot*s[3]-s[2]);
968}
969
970*/
971
972
973/////interesting examples for jacobson////////////////
974
975/*
976
977//static proc Ex_compare_output_with_maple_package_JanetOre()
978{
979    ring w = 0,(x,d),Dp;
980    def W=nc_algebra(1,1);
981    setring W;
982    matrix m[3][3]=[d2,d+1,0],[d+1,0,d3-x2*d],[2d+1, d3+d2, d2];
983    list J=jacobson(m,0);
984    print(J[1]*m*J[3]);
985    print(J[2]);
986    print(J[1]);
987    print(J[3]);
988    print(J[1]*m*J[3]-J[2]);
989}
990
991// modification for shift algebra
992{
993    ring w = 0,(x,s),Dp;
994    def W=nc_algebra(1,s);
995    setring W;
996    matrix m[3][3]=[s^2,s+1,0],[s+1,0,s^3-x^2*s],[2*s+1, s^3+s^2, s^2];
997    list J=jacobson(m,0);
998    print(J[1]*m*J[3]);
999    print(J[2]);
1000    print(J[1]);
1001    print(J[3]);
1002    print(J[1]*m*J[3]-J[2]);
1003}
1004
1005//static proc Ex_cyclic()
1006{
1007    ring w = 0,(x,d),Dp;
1008    def W=nc_algebra(1,1);
1009    setring W;
1010    matrix m[3][3]=d,0,0,x*d+1,d,0,0,x*d,d;
1011    list J=jacobson(m,0);
1012    print(J[1]*m*J[3]);
1013    print(J[2]);
1014    print(J[1]);
1015    print(J[3]);
1016    print(J[1]*m*J[3]-J[2]);
1017}
1018
1019// modification for shift algebra: gives a module with ann = s^2
1020{
1021    ring w = 0,(x,s),Dp;
1022    def W=nc_algebra(1,s);
1023    setring W;
1024    matrix m[3][3]=s,0,0,x*s+1,s,0,0,x*s,s;
1025    list J=jacobson(m,0);
1026    print(J[1]*m*J[3]);
1027    print(J[2]);
1028    print(J[1]);
1029    print(J[3]);
1030    print(J[1]*m*J[3]-J[2]);
1031}
1032
1033// yet another modification for shift algebra: gives a module with ann = s
1034// xs+1 is replaced by x*s+s
1035{
1036    ring w = 0,(x,s),Dp;
1037    def W=nc_algebra(1,s);
1038    setring W;
1039    matrix m[3][3]=s,0,0,x*s+s,s,0,0,x*s,s;
1040    list J=jacobson(m,0);
1041    print(J[1]*m*J[3]);
1042    print(J[2]);
1043    print(J[1]);
1044    print(J[3]);
1045    print(J[1]*m*J[3]-J[2]);
1046}
1047
1048// variations for above setup with shift algebra:
1049
1050// easy but instructive one: see the difference to Weyl case!
1051matrix m[2][2]=s,x,0,s; print(m);
1052
1053// more interesting:
1054matrix n[3][3]=s,x,0,0,s,x,s,0,x;
1055
1056// things blow up
1057matrix m[3][4] = s,x^2*s,x^3*s,s*x^2,s*x+1,(x+1)^3, (x+s)^2, x*s;
1058
1059// this one is quite nasty and time consuming
1060matrix m[3][4] = s,x^2*s,x^3*s,s*x^2,s*x+1,(x+1)^3, (x+s)^2, x*s,x,x^2,x^3,s;
1061
1062*/
1063