/****************************************/
/* 最大固有値と固有ベクトル(べき乗法) */
/* coded by Y.Suganuma */
/****************************************/
import java.io.*;
public class Test {
public static void main(String args[]) throws IOException
{
double A[][], B[][], C[][], r[], v[][], v0[], v1[], v2[], eps;
int i1, i2, ind, ct, m, n;
// データの設定
ct = 200;
eps = 1.0e-10;
n = 3;
m = 15;
A = new double [n][n];
B = new double [n][n];
C = new double [n][n];
v = new double [n][n];
r = new double [n];
v0 = new double [n];
v1 = new double [n];
v2 = new double [n];
A[0][0] = 11.0;
A[0][1] = 6.0;
A[0][2] = -2.0;
A[1][0] = -2.0;
A[1][1] = 18.0;
A[1][2] = 1.0;
A[2][0] = -12.0;
A[2][1] = 24.0;
A[2][2] = 13.0;
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++)
B[i1][i2] = 0.0;
B[i1][i1] = 1.0;
v0[i1] = 1.0;
}
// 計算
ind = power(0, n, m, ct, eps, A, B, C, r, v, v0, v1, v2);
// 出力
if (ind == 0)
System.out.println("固有値が求まりませんでした!");
else {
for (i1 = 0; i1 < ind; i1++) {
System.out.print("固有値 " + r[i1]);
System.out.print(" 固有ベクトル ");
for (i2 = 0; i2 < n; i2++)
System.out.print(" " + v[i1][i2]);
System.out.println();
}
}
}
/****************************************/
/* 最大固有値と固有ベクトル(べき乗法) */
/* i : 何番目の固有値かを示す */
/* n : 次数 */
/* m : 丸め誤差の修正回数 */
/* ct : 最大繰り返し回数 */
/* eps : 収束判定条件 */
/* A : 対象とする行列 */
/* B : nxnの行列,最初は,単位行列 */
/* C : 作業域,nxnの行列 */
/* r : 固有値 */
/* v : 各行が固有ベクトル(nxn) */
/* v0 : 固有ベクトルの初期値 */
/* v1,v2 : 作業域(n次元ベクトル) */
/* return : 求まった固有値の数 */
/* coded by Y.Suganuma */
/****************************************/
static int power(int i, int n, int m, int ct, double eps, double A[][], double B[][],
double C[][], double r[], double v[][], double v0[], double v1[], double v2[])
{
double l1, l2, x;
int i1, i2, i3, ind, k, k1;
// 初期設定
ind = i;
k = 0;
l1 = 0.0;
for (i1 = 0; i1 < n; i1++) {
l1 += v0[i1] * v0[i1];
v1[i1] = v0[i1];
}
l1 = Math.sqrt(l1);
// 繰り返し計算
while (k < ct) {
// 丸め誤差の修正
if (k%m == 0) {
l2 = 0.0;
for (i1 = 0; i1 < n; i1++) {
v2[i1] = 0.0;
for (i2 = 0; i2 < n; i2++)
v2[i1] += B[i1][i2] * v1[i2];
l2 += v2[i1] * v2[i1];
}
l2 = Math.sqrt(l2);
for (i1 = 0; i1 < n; i1++)
v1[i1] = v2[i1] / l2;
}
// 次の近似
l2 = 0.0;
for (i1 = 0; i1 < n; i1++) {
v2[i1] = 0.0;
for (i2 = 0; i2 < n; i2++)
v2[i1] += A[i1][i2] * v1[i2];
l2 += v2[i1] * v2[i1];
}
l2 = Math.sqrt(l2);
for (i1 = 0; i1 < n; i1++)
v2[i1] /= l2;
// 収束判定
// 収束した場合
if (Math.abs((l2-l1)/l1) < eps) {
k1 = -1;
for (i1 = 0; i1 < n && k1 < 0; i1++) {
if (Math.abs(v2[i1]) > 0.001) {
k1 = i1;
if (v2[k1]*v1[k1] < 0.0)
l2 = -l2;
}
}
k = ct;
r[i] = l2;
for (i1 = 0; i1 < n; i1++)
v[i][i1] = v2[i1];
if (i == n-1)
ind = i + 1;
else {
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++) {
C[i1][i2] = 0.0;
for (i3 = 0; i3 < n; i3++) {
x = (i1 == i3) ? A[i1][i3] - l2 : A[i1][i3];
C[i1][i2] += x * B[i3][i2];
}
}
}
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++)
B[i1][i2] = C[i1][i2];
}
for (i1 = 0; i1 < n; i1++) {
v1[i1] = 0.0;
for (i2 = 0; i2 < n; i2++)
v1[i1] += B[i1][i2] * v0[i2];
}
for (i1 = 0; i1 < n; i1++)
v0[i1] = v1[i1];
ind = power(i+1, n, m, ct, eps, A, B, C, r, v, v0, v1, v2);
}
}
// 収束しない場合
else {
for (i1 = 0; i1 < n; i1++)
v1[i1] = v2[i1];
l1 = l2;
k++;
}
}
return ind;
}
}