/************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* coded by Y.Suganuma */ /************************************************/ import java.io.*; public class Test { public static void main(String args[]) throws IOException { double A[][], A1[][], A2[][], X1[][], X2[][], eps; int i1, i2, ind, ct, n; // データの設定 ct = 1000; eps = 1.0e-10; n = 3; A = new double [n][n]; A1 = new double [n][n]; A2 = new double [n][n]; X1 = new double [n][n]; X2 = new double [n][n]; A[0][0] = 1.0; A[0][1] = 0.0; A[0][2] = -1.0; A[1][0] = 0.0; A[1][1] = 1.0; A[1][2] = -1.0; A[2][0] = -1.0; A[2][1] = -1.0; A[2][2] = 2.0; // 計算 ind = Jacobi(n, ct, eps, A, A1, A2, X1, X2); // 出力 if (ind > 0) System.out.println("収束しませんでした!"); else { System.out.println("固有値"); for (i1 = 0; i1 < n; i1++) System.out.print(" " + A1[i1][i1]); System.out.println("\n固有ベクトル(各列が固有ベクトル)"); for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) System.out.print(" " + X1[i1][i2]); System.out.println(); } } } /*************************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* n : 次数 */ /* ct : 最大繰り返し回数 */ /* eps : 収束判定条件 */ /* A : 対象とする行列 */ /* A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 */ /* X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */ /* return : =0 : 正常 */ /* =1 : 収束せず */ /* coded by Y.Suganuma */ /*************************************************************/ static int Jacobi(int n, int ct, double eps, double A[][], double A1[][], double A2[][], double X1[][], double X2[][]) { double max, s, t, v, sn, cs; int i1, i2, k = 0, ind = 1, p = 0, q = 0; // 初期設定 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A[i1][i2]; X1[i1][i2] = 0.0; } X1[i1][i1] = 1.0; } // 計算 while (ind > 0 && k < ct) { // 最大要素の探索 max = 0.0; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 != i1) { if (Math.abs(A1[i1][i2]) > max) { max = Math.abs(A1[i1][i2]); p = i1; q = i2; } } } } // 収束判定 // 収束した if (max < eps) ind = 0; // 収束しない else { // 準備 s = -A1[p][q]; t = 0.5 * (A1[p][p] - A1[q][q]); v = Math.abs(t) / Math.sqrt(s * s + t * t); sn = Math.sqrt(0.5 * (1.0 - v)); if (s*t < 0.0) sn = -sn; cs = Math.sqrt(1.0 - sn * sn); // Akの計算 for (i1 = 0; i1 < n; i1++) { if (i1 == p) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn - 2.0 * A1[p][q] * sn * cs; else if (i2 == q) A2[p][q] = 0.0; else A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn; } } else if (i1 == q) { for (i2 = 0; i2 < n; i2++) { if (i2 == q) A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs + 2.0 * A1[p][q] * sn * cs; else if (i2 == p) A2[q][p] = 0.0; else A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn; } } else { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn; else if (i2 == q) A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn; else A2[i1][i2] = A1[i1][i2]; } } } // Xkの計算 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn; else if (i2 == q) X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn; else X2[i1][i2] = X1[i1][i2]; } } // 次のステップへ k++; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A2[i1][i2]; X1[i1][i2] = X2[i1][i2]; } } } } return ind; } }