1 package Jama;
2 import Jama.util.*;
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 public class EigenvalueDecomposition implements java.io.Serializable {
22
23
24
25
26
27
28
29
30 private int n;
31
32
33
34
35 private boolean issymmetric;
36
37
38
39
40 private double[] d, e;
41
42
43
44
45 private double[][] V;
46
47
48
49
50 private double[][] H;
51
52
53
54
55 private double[] ort;
56
57
58
59
60
61
62
63 private void tred2 () {
64
65
66
67
68
69
70 for (int j = 0; j < n; j++) {
71 d[j] = V[n-1][j];
72 }
73
74
75
76 for (int i = n-1; i > 0; i--) {
77
78
79
80 double scale = 0.0;
81 double h = 0.0;
82 for (int k = 0; k < i; k++) {
83 scale = scale + Math.abs(d[k]);
84 }
85 if (scale == 0.0) {
86 e[i] = d[i-1];
87 for (int j = 0; j < i; j++) {
88 d[j] = V[i-1][j];
89 V[i][j] = 0.0;
90 V[j][i] = 0.0;
91 }
92 } else {
93
94
95
96 for (int k = 0; k < i; k++) {
97 d[k] /= scale;
98 h += d[k] * d[k];
99 }
100 double f = d[i-1];
101 double g = Math.sqrt(h);
102 if (f > 0) {
103 g = -g;
104 }
105 e[i] = scale * g;
106 h = h - f * g;
107 d[i-1] = f - g;
108 for (int j = 0; j < i; j++) {
109 e[j] = 0.0;
110 }
111
112
113
114 for (int j = 0; j < i; j++) {
115 f = d[j];
116 V[j][i] = f;
117 g = e[j] + V[j][j] * f;
118 for (int k = j+1; k <= i-1; k++) {
119 g += V[k][j] * d[k];
120 e[k] += V[k][j] * f;
121 }
122 e[j] = g;
123 }
124 f = 0.0;
125 for (int j = 0; j < i; j++) {
126 e[j] /= h;
127 f += e[j] * d[j];
128 }
129 double hh = f / (h + h);
130 for (int j = 0; j < i; j++) {
131 e[j] -= hh * d[j];
132 }
133 for (int j = 0; j < i; j++) {
134 f = d[j];
135 g = e[j];
136 for (int k = j; k <= i-1; k++) {
137 V[k][j] -= (f * e[k] + g * d[k]);
138 }
139 d[j] = V[i-1][j];
140 V[i][j] = 0.0;
141 }
142 }
143 d[i] = h;
144 }
145
146
147
148 for (int i = 0; i < n-1; i++) {
149 V[n-1][i] = V[i][i];
150 V[i][i] = 1.0;
151 double h = d[i+1];
152 if (h != 0.0) {
153 for (int k = 0; k <= i; k++) {
154 d[k] = V[k][i+1] / h;
155 }
156 for (int j = 0; j <= i; j++) {
157 double g = 0.0;
158 for (int k = 0; k <= i; k++) {
159 g += V[k][i+1] * V[k][j];
160 }
161 for (int k = 0; k <= i; k++) {
162 V[k][j] -= g * d[k];
163 }
164 }
165 }
166 for (int k = 0; k <= i; k++) {
167 V[k][i+1] = 0.0;
168 }
169 }
170 for (int j = 0; j < n; j++) {
171 d[j] = V[n-1][j];
172 V[n-1][j] = 0.0;
173 }
174 V[n-1][n-1] = 1.0;
175 e[0] = 0.0;
176 }
177
178
179
180 private void tql2 () {
181
182
183
184
185
186
187 for (int i = 1; i < n; i++) {
188 e[i-1] = e[i];
189 }
190 e[n-1] = 0.0;
191
192 double f = 0.0;
193 double tst1 = 0.0;
194 double eps = Math.pow(2.0,-52.0);
195 for (int l = 0; l < n; l++) {
196
197
198
199 tst1 = Math.max(tst1,Math.abs(d[l]) + Math.abs(e[l]));
200 int m = l;
201 while (m < n) {
202 if (Math.abs(e[m]) <= eps*tst1) {
203 break;
204 }
205 m++;
206 }
207
208
209
210
211 if (m > l) {
212 int iter = 0;
213 do {
214 iter = iter + 1;
215
216
217
218 double g = d[l];
219 double p = (d[l+1] - g) / (2.0 * e[l]);
220 double r = Maths.hypot(p,1.0);
221 if (p < 0) {
222 r = -r;
223 }
224 d[l] = e[l] / (p + r);
225 d[l+1] = e[l] * (p + r);
226 double dl1 = d[l+1];
227 double h = g - d[l];
228 for (int i = l+2; i < n; i++) {
229 d[i] -= h;
230 }
231 f = f + h;
232
233
234
235 p = d[m];
236 double c = 1.0;
237 double c2 = c;
238 double c3 = c;
239 double el1 = e[l+1];
240 double s = 0.0;
241 double s2 = 0.0;
242 for (int i = m-1; i >= l; i--) {
243 c3 = c2;
244 c2 = c;
245 s2 = s;
246 g = c * e[i];
247 h = c * p;
248 r = Maths.hypot(p,e[i]);
249 e[i+1] = s * r;
250 s = e[i] / r;
251 c = p / r;
252 p = c * d[i] - s * g;
253 d[i+1] = h + s * (c * g + s * d[i]);
254
255
256
257 for (int k = 0; k < n; k++) {
258 h = V[k][i+1];
259 V[k][i+1] = s * V[k][i] + c * h;
260 V[k][i] = c * V[k][i] - s * h;
261 }
262 }
263 p = -s * s2 * c3 * el1 * e[l] / dl1;
264 e[l] = s * p;
265 d[l] = c * p;
266
267
268
269 } while (Math.abs(e[l]) > eps*tst1);
270 }
271 d[l] = d[l] + f;
272 e[l] = 0.0;
273 }
274
275
276
277 for (int i = 0; i < n-1; i++) {
278 int k = i;
279 double p = d[i];
280 for (int j = i+1; j < n; j++) {
281 if (d[j] < p) {
282 k = j;
283 p = d[j];
284 }
285 }
286 if (k != i) {
287 d[k] = d[i];
288 d[i] = p;
289 for (int j = 0; j < n; j++) {
290 p = V[j][i];
291 V[j][i] = V[j][k];
292 V[j][k] = p;
293 }
294 }
295 }
296 }
297
298
299
300 private void orthes () {
301
302
303
304
305
306
307 int low = 0;
308 int high = n-1;
309
310 for (int m = low+1; m <= high-1; m++) {
311
312
313
314 double scale = 0.0;
315 for (int i = m; i <= high; i++) {
316 scale = scale + Math.abs(H[i][m-1]);
317 }
318 if (scale != 0.0) {
319
320
321
322 double h = 0.0;
323 for (int i = high; i >= m; i--) {
324 ort[i] = H[i][m-1]/scale;
325 h += ort[i] * ort[i];
326 }
327 double g = Math.sqrt(h);
328 if (ort[m] > 0) {
329 g = -g;
330 }
331 h = h - ort[m] * g;
332 ort[m] = ort[m] - g;
333
334
335
336
337 for (int j = m; j < n; j++) {
338 double f = 0.0;
339 for (int i = high; i >= m; i--) {
340 f += ort[i]*H[i][j];
341 }
342 f = f/h;
343 for (int i = m; i <= high; i++) {
344 H[i][j] -= f*ort[i];
345 }
346 }
347
348 for (int i = 0; i <= high; i++) {
349 double f = 0.0;
350 for (int j = high; j >= m; j--) {
351 f += ort[j]*H[i][j];
352 }
353 f = f/h;
354 for (int j = m; j <= high; j++) {
355 H[i][j] -= f*ort[j];
356 }
357 }
358 ort[m] = scale*ort[m];
359 H[m][m-1] = scale*g;
360 }
361 }
362
363
364
365 for (int i = 0; i < n; i++) {
366 for (int j = 0; j < n; j++) {
367 V[i][j] = (i == j ? 1.0 : 0.0);
368 }
369 }
370
371 for (int m = high-1; m >= low+1; m--) {
372 if (H[m][m-1] != 0.0) {
373 for (int i = m+1; i <= high; i++) {
374 ort[i] = H[i][m-1];
375 }
376 for (int j = m; j <= high; j++) {
377 double g = 0.0;
378 for (int i = m; i <= high; i++) {
379 g += ort[i] * V[i][j];
380 }
381
382 g = (g / ort[m]) / H[m][m-1];
383 for (int i = m; i <= high; i++) {
384 V[i][j] += g * ort[i];
385 }
386 }
387 }
388 }
389 }
390
391
392
393
394 private transient double cdivr, cdivi;
395 private void cdiv(double xr, double xi, double yr, double yi) {
396 double r,d;
397 if (Math.abs(yr) > Math.abs(yi)) {
398 r = yi/yr;
399 d = yr + r*yi;
400 cdivr = (xr + r*xi)/d;
401 cdivi = (xi - r*xr)/d;
402 } else {
403 r = yr/yi;
404 d = yi + r*yr;
405 cdivr = (r*xr + xi)/d;
406 cdivi = (r*xi - xr)/d;
407 }
408 }
409
410
411
412
413 private void hqr2 () {
414
415
416
417
418
419
420
421
422 int nn = this.n;
423 int n = nn-1;
424 int low = 0;
425 int high = nn-1;
426 double eps = Math.pow(2.0,-52.0);
427 double exshift = 0.0;
428 double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
429
430
431
432 double norm = 0.0;
433 for (int i = 0; i < nn; i++) {
434 if (i < low | i > high) {
435 d[i] = H[i][i];
436 e[i] = 0.0;
437 }
438 for (int j = Math.max(i-1,0); j < nn; j++) {
439 norm = norm + Math.abs(H[i][j]);
440 }
441 }
442
443
444
445 int iter = 0;
446 while (n >= low) {
447
448
449
450 int l = n;
451 while (l > low) {
452 s = Math.abs(H[l-1][l-1]) + Math.abs(H[l][l]);
453 if (s == 0.0) {
454 s = norm;
455 }
456 if (Math.abs(H[l][l-1]) < eps * s) {
457 break;
458 }
459 l--;
460 }
461
462
463
464
465 if (l == n) {
466 H[n][n] = H[n][n] + exshift;
467 d[n] = H[n][n];
468 e[n] = 0.0;
469 n--;
470 iter = 0;
471
472
473
474 } else if (l == n-1) {
475 w = H[n][n-1] * H[n-1][n];
476 p = (H[n-1][n-1] - H[n][n]) / 2.0;
477 q = p * p + w;
478 z = Math.sqrt(Math.abs(q));
479 H[n][n] = H[n][n] + exshift;
480 H[n-1][n-1] = H[n-1][n-1] + exshift;
481 x = H[n][n];
482
483
484
485 if (q >= 0) {
486 if (p >= 0) {
487 z = p + z;
488 } else {
489 z = p - z;
490 }
491 d[n-1] = x + z;
492 d[n] = d[n-1];
493 if (z != 0.0) {
494 d[n] = x - w / z;
495 }
496 e[n-1] = 0.0;
497 e[n] = 0.0;
498 x = H[n][n-1];
499 s = Math.abs(x) + Math.abs(z);
500 p = x / s;
501 q = z / s;
502 r = Math.sqrt(p * p+q * q);
503 p = p / r;
504 q = q / r;
505
506
507
508 for (int j = n-1; j < nn; j++) {
509 z = H[n-1][j];
510 H[n-1][j] = q * z + p * H[n][j];
511 H[n][j] = q * H[n][j] - p * z;
512 }
513
514
515
516 for (int i = 0; i <= n; i++) {
517 z = H[i][n-1];
518 H[i][n-1] = q * z + p * H[i][n];
519 H[i][n] = q * H[i][n] - p * z;
520 }
521
522
523
524 for (int i = low; i <= high; i++) {
525 z = V[i][n-1];
526 V[i][n-1] = q * z + p * V[i][n];
527 V[i][n] = q * V[i][n] - p * z;
528 }
529
530
531
532 } else {
533 d[n-1] = x + p;
534 d[n] = x + p;
535 e[n-1] = z;
536 e[n] = -z;
537 }
538 n = n - 2;
539 iter = 0;
540
541
542
543 } else {
544
545
546
547 x = H[n][n];
548 y = 0.0;
549 w = 0.0;
550 if (l < n) {
551 y = H[n-1][n-1];
552 w = H[n][n-1] * H[n-1][n];
553 }
554
555
556
557 if (iter == 10) {
558 exshift += x;
559 for (int i = low; i <= n; i++) {
560 H[i][i] -= x;
561 }
562 s = Math.abs(H[n][n-1]) + Math.abs(H[n-1][n-2]);
563 x = y = 0.75 * s;
564 w = -0.4375 * s * s;
565 }
566
567
568
569 if (iter == 30) {
570 s = (y - x) / 2.0;
571 s = s * s + w;
572 if (s > 0) {
573 s = Math.sqrt(s);
574 if (y < x) {
575 s = -s;
576 }
577 s = x - w / ((y - x) / 2.0 + s);
578 for (int i = low; i <= n; i++) {
579 H[i][i] -= s;
580 }
581 exshift += s;
582 x = y = w = 0.964;
583 }
584 }
585
586 iter = iter + 1;
587
588
589
590 int m = n-2;
591 while (m >= l) {
592 z = H[m][m];
593 r = x - z;
594 s = y - z;
595 p = (r * s - w) / H[m+1][m] + H[m][m+1];
596 q = H[m+1][m+1] - z - r - s;
597 r = H[m+2][m+1];
598 s = Math.abs(p) + Math.abs(q) + Math.abs(r);
599 p = p / s;
600 q = q / s;
601 r = r / s;
602 if (m == l) {
603 break;
604 }
605 if (Math.abs(H[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
606 eps * (Math.abs(p) * (Math.abs(H[m-1][m-1]) + Math.abs(z) +
607 Math.abs(H[m+1][m+1])))) {
608 break;
609 }
610 m--;
611 }
612
613 for (int i = m+2; i <= n; i++) {
614 H[i][i-2] = 0.0;
615 if (i > m+2) {
616 H[i][i-3] = 0.0;
617 }
618 }
619
620
621
622 for (int k = m; k <= n-1; k++) {
623 boolean notlast = (k != n-1);
624 if (k != m) {
625 p = H[k][k-1];
626 q = H[k+1][k-1];
627 r = (notlast ? H[k+2][k-1] : 0.0);
628 x = Math.abs(p) + Math.abs(q) + Math.abs(r);
629 if (x != 0.0) {
630 p = p / x;
631 q = q / x;
632 r = r / x;
633 }
634 }
635 if (x == 0.0) {
636 break;
637 }
638 s = Math.sqrt(p * p + q * q + r * r);
639 if (p < 0) {
640 s = -s;
641 }
642 if (s != 0) {
643 if (k != m) {
644 H[k][k-1] = -s * x;
645 } else if (l != m) {
646 H[k][k-1] = -H[k][k-1];
647 }
648 p = p + s;
649 x = p / s;
650 y = q / s;
651 z = r / s;
652 q = q / p;
653 r = r / p;
654
655
656
657 for (int j = k; j < nn; j++) {
658 p = H[k][j] + q * H[k+1][j];
659 if (notlast) {
660 p = p + r * H[k+2][j];
661 H[k+2][j] = H[k+2][j] - p * z;
662 }
663 H[k][j] = H[k][j] - p * x;
664 H[k+1][j] = H[k+1][j] - p * y;
665 }
666
667
668
669 for (int i = 0; i <= Math.min(n,k+3); i++) {
670 p = x * H[i][k] + y * H[i][k+1];
671 if (notlast) {
672 p = p + z * H[i][k+2];
673 H[i][k+2] = H[i][k+2] - p * r;
674 }
675 H[i][k] = H[i][k] - p;
676 H[i][k+1] = H[i][k+1] - p * q;
677 }
678
679
680
681 for (int i = low; i <= high; i++) {
682 p = x * V[i][k] + y * V[i][k+1];
683 if (notlast) {
684 p = p + z * V[i][k+2];
685 V[i][k+2] = V[i][k+2] - p * r;
686 }
687 V[i][k] = V[i][k] - p;
688 V[i][k+1] = V[i][k+1] - p * q;
689 }
690 }
691 }
692 }
693 }
694
695
696
697 if (norm == 0.0) {
698 return;
699 }
700
701 for (n = nn-1; n >= 0; n--) {
702 p = d[n];
703 q = e[n];
704
705
706
707 if (q == 0) {
708 int l = n;
709 H[n][n] = 1.0;
710 for (int i = n-1; i >= 0; i--) {
711 w = H[i][i] - p;
712 r = 0.0;
713 for (int j = l; j <= n; j++) {
714 r = r + H[i][j] * H[j][n];
715 }
716 if (e[i] < 0.0) {
717 z = w;
718 s = r;
719 } else {
720 l = i;
721 if (e[i] == 0.0) {
722 if (w != 0.0) {
723 H[i][n] = -r / w;
724 } else {
725 H[i][n] = -r / (eps * norm);
726 }
727
728
729
730 } else {
731 x = H[i][i+1];
732 y = H[i+1][i];
733 q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
734 t = (x * s - z * r) / q;
735 H[i][n] = t;
736 if (Math.abs(x) > Math.abs(z)) {
737 H[i+1][n] = (-r - w * t) / x;
738 } else {
739 H[i+1][n] = (-s - y * t) / z;
740 }
741 }
742
743
744
745 t = Math.abs(H[i][n]);
746 if ((eps * t) * t > 1) {
747 for (int j = i; j <= n; j++) {
748 H[j][n] = H[j][n] / t;
749 }
750 }
751 }
752 }
753
754
755
756 } else if (q < 0) {
757 int l = n-1;
758
759
760
761 if (Math.abs(H[n][n-1]) > Math.abs(H[n-1][n])) {
762 H[n-1][n-1] = q / H[n][n-1];
763 H[n-1][n] = -(H[n][n] - p) / H[n][n-1];
764 } else {
765 cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);
766 H[n-1][n-1] = cdivr;
767 H[n-1][n] = cdivi;
768 }
769 H[n][n-1] = 0.0;
770 H[n][n] = 1.0;
771 for (int i = n-2; i >= 0; i--) {
772 double ra,sa,vr,vi;
773 ra = 0.0;
774 sa = 0.0;
775 for (int j = l; j <= n; j++) {
776 ra = ra + H[i][j] * H[j][n-1];
777 sa = sa + H[i][j] * H[j][n];
778 }
779 w = H[i][i] - p;
780
781 if (e[i] < 0.0) {
782 z = w;
783 r = ra;
784 s = sa;
785 } else {
786 l = i;
787 if (e[i] == 0) {
788 cdiv(-ra,-sa,w,q);
789 H[i][n-1] = cdivr;
790 H[i][n] = cdivi;
791 } else {
792
793
794
795 x = H[i][i+1];
796 y = H[i+1][i];
797 vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
798 vi = (d[i] - p) * 2.0 * q;
799 if (vr == 0.0 & vi == 0.0) {
800 vr = eps * norm * (Math.abs(w) + Math.abs(q) +
801 Math.abs(x) + Math.abs(y) + Math.abs(z));
802 }
803 cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
804 H[i][n-1] = cdivr;
805 H[i][n] = cdivi;
806 if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
807 H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;
808 H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;
809 } else {
810 cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);
811 H[i+1][n-1] = cdivr;
812 H[i+1][n] = cdivi;
813 }
814 }
815
816
817
818 t = Math.max(Math.abs(H[i][n-1]),Math.abs(H[i][n]));
819 if ((eps * t) * t > 1) {
820 for (int j = i; j <= n; j++) {
821 H[j][n-1] = H[j][n-1] / t;
822 H[j][n] = H[j][n] / t;
823 }
824 }
825 }
826 }
827 }
828 }
829
830
831
832 for (int i = 0; i < nn; i++) {
833 if (i < low | i > high) {
834 for (int j = i; j < nn; j++) {
835 V[i][j] = H[i][j];
836 }
837 }
838 }
839
840
841
842 for (int j = nn-1; j >= low; j--) {
843 for (int i = low; i <= high; i++) {
844 z = 0.0;
845 for (int k = low; k <= Math.min(j,high); k++) {
846 z = z + V[i][k] * H[k][j];
847 }
848 V[i][j] = z;
849 }
850 }
851 }
852
853
854
855
856
857
858
859
860
861
862 public EigenvalueDecomposition (Matrix Arg) {
863 double[][] A = Arg.getArray();
864 n = Arg.getColumnDimension();
865 V = new double[n][n];
866 d = new double[n];
867 e = new double[n];
868
869 issymmetric = true;
870 for (int j = 0; (j < n) & issymmetric; j++) {
871 for (int i = 0; (i < n) & issymmetric; i++) {
872 issymmetric = (A[i][j] == A[j][i]);
873 }
874 }
875
876 if (issymmetric) {
877 for (int i = 0; i < n; i++) {
878 for (int j = 0; j < n; j++) {
879 V[i][j] = A[i][j];
880 }
881 }
882
883
884 tred2();
885
886
887 tql2();
888
889 } else {
890 H = new double[n][n];
891 ort = new double[n];
892
893 for (int j = 0; j < n; j++) {
894 for (int i = 0; i < n; i++) {
895 H[i][j] = A[i][j];
896 }
897 }
898
899
900 orthes();
901
902
903 hqr2();
904 }
905 }
906
907
908
909
910
911
912
913
914
915 public Matrix getV () {
916 return new Matrix(V,n,n);
917 }
918
919
920
921
922
923 public double[] getRealEigenvalues () {
924 return d;
925 }
926
927
928
929
930
931 public double[] getImagEigenvalues () {
932 return e;
933 }
934
935
936
937
938
939 public Matrix getD () {
940 Matrix X = new Matrix(n,n);
941 double[][] D = X.getArray();
942 for (int i = 0; i < n; i++) {
943 for (int j = 0; j < n; j++) {
944 D[i][j] = 0.0;
945 }
946 D[i][i] = d[i];
947 if (e[i] > 0) {
948 D[i][i+1] = e[i];
949 } else if (e[i] < 0) {
950 D[i][i-1] = e[i];
951 }
952 }
953 return X;
954 }
955 }