source: git/Singular/LIB/jordan.lib @ 49998f

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