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

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