source: git/Singular/LIB/jordan.lib @ 371848

fieker-DuValspielwiese
Last change on this file since 371848 was 64e332, checked in by Gert-Martin Greuel <greuel@…>, 23 years ago
*GMG: Kosmetik, ERROR in invmat eingefuegt git-svn-id: file:///usr/local/Singular/svn/trunk@5009 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 11.5 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="$Id: jordan.lib,v 1.20 2001-01-02 14:33:25 greuel Exp $";
3category="Linear Algebra";
4info="
5LIBRARY: jordan.lib  Jordan Normal Form of a Matrix with rational Eigenvalues
6AUTHOR:  Mathias Schulze, email: mschulze@mathematik.uni-kl.de
7
8PROCEDURES:
9 jordan(M[,opt]);  eigenvalues, Jordan block sizes, Jordan transformation of M
10 jordanmatrix(l);  Jordan matrix with eigenvalues l[1], Jordan block sizes l[2]
11 jordanform(M);    Jordan normal form of constant square matrix M
12 invmat(M);        inverse matrix of invertible constant matrix M
13";
14
15LIB "ring.lib";
16///////////////////////////////////////////////////////////////////////////////
17
18static proc countblocks(matrix M)
19{
20  int b,r,r0;
21
22  int i=1;
23  while(i<=nrows(M))
24  {
25    b++;
26    r=nrows(M[i]);
27    r0=r;
28
29    dbprint(printlevel-voice+2,"//searching for block "+string(b)+"...");
30    while(i<r0&&i<nrows(M))
31    {
32      i++;
33      if(i<=nrows(M))
34      {
35        r=nrows(M[i]);
36        if(r>r0)
37        {
38          r0=r;
39        }
40      }
41    }
42    dbprint(printlevel-voice+2,"//...block "+string(b)+" found");
43
44    i++;
45  }
46
47  return(b);
48}
49///////////////////////////////////////////////////////////////////////////////
50
51static proc getblock(matrix M,intvec v)
52{
53  matrix M0[size(v)][size(v)]=M[v,v];
54  return(M0);
55}
56///////////////////////////////////////////////////////////////////////////////
57
58proc jordan(matrix M,list #)
59"USAGE:   jordan(M[,opt]); M constant square matrix, opt integer
60ASSUME:  The eigenvalues of M are in the coefficient field.
61RETURN:  The procedure returns a list jd with 3 entries:
62@format       
63         - jd[1] ideal, eigenvalues of M,
64         - jd[2] list of intvecs, jd[2][i][j] size of j-th Jordan block with
65           eigenvalue jd[1][i], and
66         - jd[3] a matrix, jd[3]^(-1)*M*jd[3] in Jordan normal form.
67         Depending on opt, only certain entries of jd are computed.
68           If opt=-1, jd[1] is computed,
69           if opt= 0, jd[1] and jd[2] are computed,
70           if opt= 1, jd[1], jd[2], and jd[3] are computed, and,
71           if opt= 2, jd[1] and jd[3] are computed.
72         By default, opt=0.
73@end format
74NOTE:    A non constant polynomial matrix M is replaced by its constant part.
75DISPLAY: The procedure displays comments if printlevel>=1.
76EXAMPLE: example jordan; shows an example.
77"
78{
79  int n=nrows(M);
80  if(n==0)
81  {
82    print("//empty matrix");
83    return(list());
84  }
85  if(n!=ncols(M))
86  {
87    print("//no square matrix");
88    return(list());
89  }
90
91  M=jet(M,0);
92
93  dbprint(printlevel-voice+2,"//counting blocks of matrix...");
94  int i=countblocks(M);
95  dbprint(printlevel-voice+2,"//...blocks of matrix counted");
96  if(i==1)
97  {
98    dbprint(printlevel-voice+2,"//matrix has 1 block");
99  }
100  else
101  {
102    dbprint(printlevel-voice+2,"//matrix has "+string(i)+" blocks");
103  }
104
105  dbprint(printlevel-voice+2,"//counting blocks of transposed matrix...");
106  int j=countblocks(transpose(M));
107  dbprint(printlevel-voice+2,"//...blocks of transposed matrix counted");
108  if(j==1)
109  {
110    dbprint(printlevel-voice+2,"//transposed matrix has 1 block");
111  }
112  else
113  {
114    dbprint(printlevel-voice+2,"//transposed matrix has "+string(j)+" blocks");
115  }
116
117  if(i<j)
118  {
119    dbprint(printlevel-voice+2,"//transposing matrix...");
120    M=transpose(M);
121    dbprint(printlevel-voice+2,"//...matrix transposed");
122  }
123
124  list fd;
125  matrix M0;
126  poly cp;
127  ideal eM,eM0;
128  intvec mM,mM0;
129  intvec u;
130  int b,r,r0;
131
132  i=1;
133  while(i<=nrows(M))
134  {
135    b++;
136    u=i;
137    r=nrows(M[i]);
138    r0=r;
139
140    dbprint(printlevel-voice+2,"//searching for block "+string(b)+"...");
141    while(i<r0&&i<nrows(M))
142    {
143      i++;
144      if(i<=nrows(M))
145      {
146        u=u,i;
147        r=nrows(M[i]);
148        if(r>r0)
149        {
150          r0=r;
151        }
152      }
153    }
154    dbprint(printlevel-voice+2,"//...block "+string(b)+" found");
155
156    if(size(u)==1)
157    {
158      dbprint(printlevel-voice+2,"//1x1-block:");
159      dbprint(printlevel-voice+2,M[u[1]][u[1]]);
160
161      if(mM[1]==0)
162      {
163        eM=M[u[1]][u[1]];
164        mM=1;
165      }
166      else
167      {
168        eM=eM,ideal(M[u[1]][u[1]]);
169        mM=mM,1;
170      }
171    }
172    else
173    {
174      dbprint(printlevel-voice+2,
175        "//"+string(size(u))+"x"+string(size(u))+"-block:");
176      M0=getblock(M,u);
177      dbprint(printlevel-voice+2,M0);
178
179      dbprint(printlevel-voice+2,"//characteristic polynomial:");
180      cp=det(module(M0-var(1)*freemodule(size(u))));
181      dbprint(printlevel-voice+2,cp);
182
183      dbprint(printlevel-voice+2,"//factorizing characteristic polynomial...");
184      fd=factorize(cp,2);
185      dbprint(printlevel-voice+2,"//...characteristic polynomial factorized");
186
187      dbprint(printlevel-voice+2,"//computing eigenvalues...");
188      eM0,mM0=fd[1..2];
189      if(1<var(1))
190      {
191        for(j=ncols(eM0);j>=1;j--)
192        {
193          if(deg(eM0[j])>1)
194          {
195            print("//eigenvalues not in the coefficient field");
196            return(list());
197          }
198          if(eM0[j][1]==0)
199          {
200            eM0[j]=0;
201          }
202          else
203          {
204            eM0[j]=-eM0[j][2]/(eM0[j][1]/var(1));
205          }
206        }
207      }
208      else
209      {
210        for(j=ncols(eM0);j>=1;j--)
211        {
212          if(deg(eM0[j])>1)
213          {
214            print("//eigenvalues not in the coefficient field");
215            return(list());
216          }
217          if(eM0[j][2]==0)
218          {
219            eM0[j]=0;
220          }
221          else
222          {
223            eM0[j]=-eM0[j][1]/(eM0[j][2]/var(1));
224          }
225        }
226      }
227      dbprint(printlevel-voice+2,"//...eigenvalues computed");
228
229      if(mM[1]==0)
230      {
231        eM=eM0;
232        mM=mM0;
233      }
234      else
235      {
236        eM=eM,eM0;
237        mM=mM,mM0;
238      }
239    }
240
241    i++;
242  }
243
244  dbprint(printlevel-voice+2,"//sorting eigenvalues...");
245  poly e;
246  int m;
247  for(i=ncols(eM);i>=2;i--)
248  {
249    for(j=i-1;j>=1;j--)
250    {
251     if(eM[i]<eM[j])
252      {
253        e=eM[i];
254        eM[i]=eM[j];
255        eM[j]=e;
256        m=mM[i];
257        mM[i]=mM[j];
258        mM[j]=m;
259      }
260    }
261  }
262  dbprint(printlevel-voice+2,"//...eigenvalues sorted");
263
264  dbprint(printlevel-voice+2,"//removing multiple eigenvalues...");
265  i=1;
266  j=2;
267  while(j<=ncols(eM))
268  {
269    if(eM[i]==eM[j])
270    {
271      mM[i]=mM[i]+mM[j];
272    }
273    else
274    {
275      i++;
276      eM[i]=eM[j];
277      mM[i]=mM[j];
278    }
279    j++;
280  }
281  eM=eM[1..i];
282  mM=mM[1..i];
283  dbprint(printlevel-voice+2,"//...multiple eigenvalues removed");
284
285  dbprint(printlevel-voice+2,"//eigenvalues:");
286  dbprint(printlevel-voice+2,eM);
287  dbprint(printlevel-voice+2,"//multiplicities:");
288  dbprint(printlevel-voice+2,mM);
289
290  int opt=0;
291  if(size(#)>0)
292  {
293    if(typeof(#[1])=="int")
294    {
295      opt=#[1];
296    }
297  }
298  if(opt<0)
299  {
300    return(list(eM));
301  }
302  int k,l;
303  matrix I=freemodule(n);
304  matrix Mi,Ni;
305  module sNi;
306  list K;
307  if(opt>=1)
308  {
309    module V,K1,K2;
310    matrix v[n][1];
311  }
312  if(opt<=1)
313  {
314    list bM;
315    intvec bMi;
316  }
317
318  for(i=ncols(eM);i>=1;i--)
319  {
320    Mi=M-eM[i]*I;
321
322    dbprint(printlevel-voice+2,
323      "//computing kernels of powers of matrix minus eigenvalue "
324      +string(eM[i]));
325    K=list(module());
326    for(Ni,sNi=Mi,0;size(sNi)<mM[i];Ni=Ni*Mi)
327    {
328      sNi=syz(Ni);
329      K=K+list(sNi);
330    }
331    dbprint(printlevel-voice+2,"//...kernels computed");
332
333    if(opt<=1)
334    {
335      dbprint(printlevel-voice+2,
336        "//computing Jordan block sizes for eigenvalue "
337        +string(eM[i])+"...");
338      bMi=0;
339      bMi[size(K[2])]=0;
340      for(j=size(K);j>=2;j--)
341      {
342        for(k=size(bMi);k>size(bMi)+size(K[j-1])-size(K[j]);k--)
343        {
344          bMi[k]=bMi[k]+1;
345        }
346      }
347      bM=list(bMi)+bM;
348      dbprint(printlevel-voice+2,"//...Jordan block sizes computed");
349    }
350
351    if(opt>=1)
352    {
353      dbprint(printlevel-voice+2,
354        "//computing Jordan basis vectors for eigenvalue "
355        +string(eM[i])+"...");
356      if(size(K)>1)
357      {
358        for(j,K1=2,0;j<=size(K)-1;j++)
359        {
360          K2=K[j];
361          K[j]=interred(reduce(K[j],std(K1+module(Mi*K[j+1]))));
362          K1=K2;
363        }
364        K[j]=interred(reduce(K[j],std(K1)));
365      }
366      for(j=size(K);j>=2;j--)
367      {
368        for(k=size(K[j]);k>=1;k--)
369        {
370          v=K[j][k];
371          for(l=j;l>=1;l--)
372          {
373            V=module(v)+V;
374            v=Mi*v;
375          }
376        }
377      }
378      dbprint(printlevel-voice+2,"//...Jordan basis vectors computed");
379    }
380  }
381
382  list jd=eM;
383  if(opt<=1)
384  {
385    jd[2]=bM;
386  }
387  if(opt>=1)
388  {
389    jd[3]=V;
390  }
391  return(jd);
392}
393example
394{ "EXAMPLE:"; echo=2;
395  ring R=0,x,dp;
396  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
397  print(M);
398  jordan(M);
399}
400///////////////////////////////////////////////////////////////////////////////
401
402proc jordanmatrix(list jd)
403"USAGE:   jordanmatrix(jd); jd list of ideal and list of intvecs
404RETURN:  The procedure returns the Jordan matrix J, satisfying:
405@*       - eigenvalues of J are given by jd[1]
406@*       - j-th Jordan block of J with eigenvalue jd[1][i] has size jd[2][i][j]
407DISPLAY: The procedure displays comments if printlevel>=1.
408EXAMPLE: example jordanmatrix; shows an example.
409"
410{
411  if(size(jd)<2)
412  {
413    print("//not enough entries in argument list");
414    matrix J[1][0];
415    return(J);
416  }
417  def eJ,bJ=jd[1..2];
418  if(typeof(eJ)!="ideal")
419  {
420    print("//first entry in argument list not an ideal");
421    matrix J[1][0];
422    return(J);
423  }
424  if(typeof(bJ)!="list")
425  {
426    print("//second entry in argument list not a list");
427    matrix J[1][0];
428    return(J);
429  }
430  if(size(eJ)<size(bJ))
431  {
432    int s=size(eJ);
433  }
434  else
435  {
436    int s=size(bJ);
437  }
438
439  int i,j,k,n;
440  for(i=s;i>=1;i--)
441  {
442    if(typeof(bJ[i])!="intvec")
443    {
444      print("//second entry in argument list not a list of intvecs");
445      matrix J[1][0];
446      return(J);
447    }
448    else
449    {
450      for(j=size(bJ[i]);j>=1;j--)
451      {
452        k=bJ[i][j];
453        if(k>0)
454        {
455          n=n+k;
456        }
457      }
458    }
459  }
460
461  int l;
462  matrix J[n][n];
463  for(i,l=1,1;i<=s;i++)
464  {
465    for(j=1;j<=size(bJ[i]);j++)
466    {
467      k=bJ[i][j];
468      if(k>0)
469      {
470        while(k>=2)
471        {
472          J[l,l]=eJ[i];
473          J[l,l+1]=1;
474          k,l=k-1,l+1;
475        }
476        J[l,l]=eJ[i];
477        l++;
478      }
479    }
480  }
481
482  return(J);
483}
484example
485{ "EXAMPLE:"; echo=2;
486  ring R=0,x,dp;
487  list l;
488  l[1]=ideal(2,3);
489  l[2]=list(intvec(1),intvec(2));
490  print(jordanmatrix(l));
491}
492///////////////////////////////////////////////////////////////////////////////
493
494proc jordanform(matrix M)
495"USAGE:   jordanform(M); M constant square matrix
496ASSUME:  The eigenvalues of M are in the coefficient field.
497RETURN:  matrix, the Jordan normal form of M.
498NOTE:    A non constant polynomial matrix M is replaced by its constant part.
499DISPLAY: The procedure displays more comments for higher printlevel.
500EXAMPLE: example jordanform; shows an example.
501"
502{
503  return(jordanmatrix(jordan(M)));
504}
505example
506{ "EXAMPLE:"; echo=2;
507  ring R=0,x,dp;
508  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
509  print(M);
510  print(jordanform(M));
511}
512///////////////////////////////////////////////////////////////////////////////
513
514proc invmat(matrix M)
515"USAGE:   invmat(M); M constant square matrix
516ASSUME:  M is invertible.
517RETURN:  The procedure returns the inverse matrix of M.
518NOTE:    A non constant polynomial matrix M is replaced by its constant part.
519EXAMPLE: example invmat; shows an example.
520"
521{
522  if(nrows(M)==ncols(M))
523  {
524    matrix invM=lift(jet(M,0),freemodule(nrows(M)));
525  }
526  else
527  {
528    ERROR("// ** no square matrix");
529    //matrix invM[1][0];
530  }
531  return(invM);
532}
533example
534{ "EXAMPLE:"; echo=2;
535  ring R=0,x,dp;
536  matrix M[3][3]=3,2,1,0,2,1,0,0,3;
537  print(M);
538  print(invmat(M));
539}
540///////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.