/****************************************/
/* 最大固有値と固有ベクトル(べき乗法) */
/* coded by Y.Suganuma */
/****************************************/
#include <stdio.h>
int power(int, int, int, int, double, double **, double **, double **,
double *, double **, double *, double *, double *);
int main()
{
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];
B = new double * [n];
C = new double * [n];
v = new double * [n];
for (i1 = 0; i1 < n; i1++) {
A[i1] = new double [n];
B[i1] = new double [n];
C[i1] = new double [n];
v[i1] = new double [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)
printf("固有値が求まりませんでした!\n");
else {
for (i1 = 0; i1 < ind; i1++) {
printf("固有値 %f", r[i1]);
printf(" 固有ベクトル ");
for (i2 = 0; i2 < n; i2++)
printf(" %f", v[i1][i2]);
printf("\n");
}
}
for (i1 = 0; i1 < n; i1++) {
delete [] A[i1];
delete [] B[i1];
delete [] C[i1];
delete [] v[i1];
}
delete [] A;
delete [] B;
delete [] C;
delete [] v;
delete [] r;
delete [] v0;
delete [] v1;
delete [] v2;
return 0;
}
/****************************************/
/* 最大固有値と固有ベクトル(べき乗法) */
/* i : 何番目の固有値かを示す */
/* n : 次数 */
/* m : 丸め誤差の修正回数 */
/* ct : 最大繰り返し回数 */
/* eps : 収束判定条件 */
/* A : 対象とする行列 */
/* B : nxnの行列,最初は,単位行列 */
/* C : 作業域,nxnの行列 */
/* r : 固有値 */
/* v : 各行が固有ベクトル(nxn) */
/* v0 : 固有ベクトルの初期値 */
/* v1,v2 : 作業域(n次元ベクトル) */
/* return : 求まった固有値の数 */
/* coded by Y.Suganuma */
/****************************************/
#include <math.h>
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 = 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 = 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 = sqrt(l2);
for (i1 = 0; i1 < n; i1++)
v2[i1] /= l2;
// 収束判定
// 収束した場合
if (fabs((l2-l1)/l1) < eps) {
k1 = -1;
for (i1 = 0; i1 < n && k1 < 0; i1++) {
if (fabs(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;
}