#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SIZE 4
#define EPSILON 1e-9 // 収束判定条件
#define MAX_ITER 1000 // 最大反復回数
// ベクトルのノルム(ユークリッド長)を計算
double vector_norm(double *v, int n) {
double sum = 0.0;
for (int i = 0; i < n; i++) {
sum += v[i] * v[i];
}
}
// 行列とベクトルの積 y = A * x
void mat_vec_mul(double A[SIZE][SIZE], double *x, double *y, int n) {
for (int i = 0; i < n; i++) {
y[i] = 0.0;
for (int j = 0; j < n; j++) {
y[i] += A[i][j] * x[j];
}
}
}
int main() {
// 自身で設定した行列A
double A[SIZE][SIZE] = {
{1.0, 2.0, 3.0, 5.0},
{3.0, -5.0, 1.0, 4.0},
{5.0, 9.0, 2.0, -6.0},
{1.0, 7.0, 4.0, 1.0}
};
double x[SIZE], y[SIZE], Ax[SIZE];
double lambda_old = 0.0, lambda_new = 0.0;
// 1. 初期値の設定 [1, 1, 1, 1]^T
for (int i = 0; i < SIZE; i++) {
x[i] = 1.0;
}
printf("=== べき乗法による収束状況の確認 ===\n"); printf("初期ベクトル x(0): [%.1f, %.1f, %.1f, %.1f]\n\n", x
[0], x
[1], x
[2], x
[3]); printf("%-5s | %-12s | %-12s | %-30s\n", "Iter", "固有値(新)", "差分値", "固有ベクトルx(k)"); printf("----------------------------------------------------------------------------\n");
// べき乗法の反復ループ
int actual_iters = 0;
for (int iter = 1; iter <= MAX_ITER; iter++) {
actual_iters = iter;
// y = A * x
mat_vec_mul(A, x, y, SIZE);
// ノルムで正規化
double norm_y = vector_norm(y, SIZE);
if (norm_y < 1e-12) break;
for (int i = 0; i < SIZE; i++) {
y[i] /= norm_y;
}
// レイリー商を用いて固有値を高精度に推定
mat_vec_mul(A, y, Ax, SIZE);
double num = 0.0, den = 0.0;
for (int i = 0; i < SIZE; i++) {
num += y[i] * Ax[i];
den += y[i] * y[i];
}
lambda_new = num / den;
// 前のステップとの変化量を追跡
double diff
= fabs(lambda_new
- lambda_old
);
// 収束状況の出力表示 (10回ごと、および最終ステップ)
if (iter <= 5 || iter % 5 == 0) {
printf("%-5d | %-12.8f | %-12.4e | [%.5f, %.5f, %.5f, %.5f]\n", iter, lambda_new, diff, y[0], y[1], y[2], y[3]);
}
// 収束判定条件のチェック
if (diff < EPSILON) {
if (iter % 5 != 0 && iter > 5) { // 最終ステップを確実に表示させる
printf("%-5d | %-12.8f | %-12.4e | [%.5f, %.5f, %.5f, %.5f]\n", iter, lambda_new, diff, y[0], y[1], y[2], y[3]);
}
break;
}
// 次のステップに向けて x を更新
for (int i = 0; i < SIZE; i++) {
x[i] = y[i];
}
lambda_old = lambda_new;
}
printf("----------------------------------------------------------------------------\n"); printf("反復回数 %d 回で収束しました。\n", actual_iters
);
// === 計算結果の表示 ===
printf("最大固有値 (λ1) : %.10f\n", lambda_new
); printf("対応する固有ベクトル (x1) : ["); for (int i = 0; i < SIZE; i++) {
printf("%.10f%s", y
[i
], (i
== SIZE
- 1) ? "]\n" : ", "); }
// === 確かに固有値・固有ベクトルであることの検証 (Ax = λx) ===
printf("\n=== 検証: Ax と λx の比較 ===\n"); mat_vec_mul(A, y, Ax, SIZE); // Axを再計算
for (int i = 0; i < SIZE; i++) {
printf("%.6f%s", Ax
[i
], (i
== SIZE
- 1) ? "]\n" : ", "); }
for (int i = 0; i < SIZE; i++) {
printf("%.6f%s", lambda_new
* y
[i
], (i
== SIZE
- 1) ? "]\n" : ", "); }
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KCiNkZWZpbmUgU0laRSA0CiNkZWZpbmUgRVBTSUxPTiAxZS05ICAgLy8g5Y+O5p2f5Yik5a6a5p2h5Lu2CiNkZWZpbmUgTUFYX0lURVIgMTAwMCAgLy8g5pyA5aSn5Y+N5b6p5Zue5pWwCgovLyDjg5njgq/jg4jjg6vjga7jg47jg6vjg6DvvIjjg6bjg7zjgq/jg6rjg4Pjg4nplbfvvInjgpLoqIjnrpcKZG91YmxlIHZlY3Rvcl9ub3JtKGRvdWJsZSAqdiwgaW50IG4pIHsKICAgIGRvdWJsZSBzdW0gPSAwLjA7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIHN1bSArPSB2W2ldICogdltpXTsKICAgIH0KICAgIHJldHVybiBzcXJ0KHN1bSk7Cn0KCi8vIOihjOWIl+OBqOODmeOCr+ODiOODq+OBruepjSB5ID0gQSAqIHgKdm9pZCBtYXRfdmVjX211bChkb3VibGUgQVtTSVpFXVtTSVpFXSwgZG91YmxlICp4LCBkb3VibGUgKnksIGludCBuKSB7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIHlbaV0gPSAwLjA7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgeVtpXSArPSBBW2ldW2pdICogeFtqXTsKICAgICAgICB9CiAgICB9Cn0KCmludCBtYWluKCkgewogICAgLy8g6Ieq6Lqr44Gn6Kit5a6a44GX44Gf6KGM5YiXQQogICAgZG91YmxlIEFbU0laRV1bU0laRV0gPSB7CiAgICAgICAgezEuMCwgIDIuMCwgMy4wLCAgNS4wfSwKICAgICAgICB7My4wLCAtNS4wLCAxLjAsICA0LjB9LAogICAgICAgIHs1LjAsICA5LjAsIDIuMCwgLTYuMH0sCiAgICAgICAgezEuMCwgIDcuMCwgNC4wLCAgMS4wfQogICAgfTsKCiAgICBkb3VibGUgeFtTSVpFXSwgeVtTSVpFXSwgQXhbU0laRV07CiAgICBkb3VibGUgbGFtYmRhX29sZCA9IDAuMCwgbGFtYmRhX25ldyA9IDAuMDsKCiAgICAvLyAxLiDliJ3mnJ/lgKTjga7oqK3lrpogWzEsIDEsIDEsIDFdXlQKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgU0laRTsgaSsrKSB7CiAgICAgICAgeFtpXSA9IDEuMDsKICAgIH0KCiAgICBwcmludGYoIj09PSDjgbnjgY3kuZfms5Xjgavjgojjgovlj47mnZ/nirbms4Hjga7norroqo0gPT09XG4iKTsKICAgIHByaW50Zigi5Yid5pyf44OZ44Kv44OI44OrIHgoMCk6IFslLjFmLCAlLjFmLCAlLjFmLCAlLjFmXVxuXG4iLCB4WzBdLCB4WzFdLCB4WzJdLCB4WzNdKTsKICAgIHByaW50ZigiJS01cyB8ICUtMTJzIHwgJS0xMnMgfCAlLTMwc1xuIiwgIkl0ZXIiLCAi5Zu65pyJ5YCkKOaWsCkiLCAi5beu5YiG5YCkIiwgIuWbuuacieODmeOCr+ODiOODq3goaykiKTsKICAgIHByaW50ZigiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIik7CgogICAgLy8g44G544GN5LmX5rOV44Gu5Y+N5b6p44Or44O844OXCiAgICBpbnQgYWN0dWFsX2l0ZXJzID0gMDsKICAgIGZvciAoaW50IGl0ZXIgPSAxOyBpdGVyIDw9IE1BWF9JVEVSOyBpdGVyKyspIHsKICAgICAgICBhY3R1YWxfaXRlcnMgPSBpdGVyOwogICAgICAgIAogICAgICAgIC8vIHkgPSBBICogeAogICAgICAgIG1hdF92ZWNfbXVsKEEsIHgsIHksIFNJWkUpOwoKICAgICAgICAvLyDjg47jg6vjg6DjgafmraPopo/ljJYKICAgICAgICBkb3VibGUgbm9ybV95ID0gdmVjdG9yX25vcm0oeSwgU0laRSk7CiAgICAgICAgaWYgKG5vcm1feSA8IDFlLTEyKSBicmVhazsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IFNJWkU7IGkrKykgewogICAgICAgICAgICB5W2ldIC89IG5vcm1feTsKICAgICAgICB9CgogICAgICAgIC8vIOODrOOCpOODquODvOWVhuOCkueUqOOBhOOBpuWbuuacieWApOOCkumrmOeyvuW6puOBq+aOqOWumgogICAgICAgIG1hdF92ZWNfbXVsKEEsIHksIEF4LCBTSVpFKTsKICAgICAgICBkb3VibGUgbnVtID0gMC4wLCBkZW4gPSAwLjA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBTSVpFOyBpKyspIHsKICAgICAgICAgICAgbnVtICs9IHlbaV0gKiBBeFtpXTsKICAgICAgICAgICAgZGVuICs9IHlbaV0gKiB5W2ldOwogICAgICAgIH0KICAgICAgICBsYW1iZGFfbmV3ID0gbnVtIC8gZGVuOwoKICAgICAgICAvLyDliY3jga7jgrnjg4bjg4Pjg5fjgajjga7lpInljJbph4/jgpLov73ot6EKICAgICAgICBkb3VibGUgZGlmZiA9IGZhYnMobGFtYmRhX25ldyAtIGxhbWJkYV9vbGQpOwoKICAgICAgICAvLyDlj47mnZ/nirbms4Hjga7lh7rlipvooajnpLogKDEw5Zue44GU44Go44CB44GK44KI44Gz5pyA57WC44K544OG44OD44OXKQogICAgICAgIGlmIChpdGVyIDw9IDUgfHwgaXRlciAlIDUgPT0gMCkgewogICAgICAgICAgICBwcmludGYoIiUtNWQgfCAlLTEyLjhmIHwgJS0xMi40ZSB8IFslLjVmLCAlLjVmLCAlLjVmLCAlLjVmXVxuIiwgCiAgICAgICAgICAgICAgICAgICBpdGVyLCBsYW1iZGFfbmV3LCBkaWZmLCB5WzBdLCB5WzFdLCB5WzJdLCB5WzNdKTsKICAgICAgICB9CgogICAgICAgIC8vIOWPjuadn+WIpOWumuadoeS7tuOBruODgeOCp+ODg+OCrwogICAgICAgIGlmIChkaWZmIDwgRVBTSUxPTikgewogICAgICAgICAgICBpZiAoaXRlciAlIDUgIT0gMCAmJiBpdGVyID4gNSkgeyAvLyDmnIDntYLjgrnjg4bjg4Pjg5fjgpLnorrlrp/jgavooajnpLrjgZXjgZvjgosKICAgICAgICAgICAgICAgIHByaW50ZigiJS01ZCB8ICUtMTIuOGYgfCAlLTEyLjRlIHwgWyUuNWYsICUuNWYsICUuNWYsICUuNWZdXG4iLCAKICAgICAgICAgICAgICAgICAgICAgICBpdGVyLCBsYW1iZGFfbmV3LCBkaWZmLCB5WzBdLCB5WzFdLCB5WzJdLCB5WzNdKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIC8vIOasoeOBruOCueODhuODg+ODl+OBq+WQkeOBkeOBpiB4IOOCkuabtOaWsAogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgU0laRTsgaSsrKSB7CiAgICAgICAgICAgIHhbaV0gPSB5W2ldOwogICAgICAgIH0KICAgICAgICBsYW1iZGFfb2xkID0gbGFtYmRhX25ldzsKICAgIH0KCiAgICBwcmludGYoIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiIpOwogICAgcHJpbnRmKCLlj43lvqnlm57mlbAgJWQg5Zue44Gn5Y+O5p2f44GX44G+44GX44Gf44CCXG4iLCBhY3R1YWxfaXRlcnMpOwoKICAgIC8vID09PSDoqIjnrpfntZDmnpzjga7ooajnpLogPT09CiAgICBwcmludGYoIlxuPT09IOioiOeul+e1kOaenCA9PT1cbiIpOwogICAgcHJpbnRmKCLmnIDlpKflm7rmnInlgKQgKM67MSkgICAgICAgICAgOiAlLjEwZlxuIiwgbGFtYmRhX25ldyk7CiAgICBwcmludGYoIuWvvuW/nOOBmeOCi+WbuuacieODmeOCr+ODiOODqyAoeDEpIDogWyIpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBTSVpFOyBpKyspIHsKICAgICAgICBwcmludGYoIiUuMTBmJXMiLCB5W2ldLCAoaSA9PSBTSVpFIC0gMSkgPyAiXVxuIiA6ICIsICIpOwogICAgfQoKICAgIC8vID09PSDnorrjgYvjgavlm7rmnInlgKTjg7vlm7rmnInjg5njgq/jg4jjg6vjgafjgYLjgovjgZPjgajjga7mpJzoqLwgKEF4ID0gzrt4KSA9PT0KICAgIHByaW50ZigiXG49PT0g5qSc6Ki8OiBBeCDjgaggzrt4IOOBruavlOi8gyA9PT1cbiIpOwogICAgbWF0X3ZlY19tdWwoQSwgeSwgQXgsIFNJWkUpOyAvLyBBeOOCkuWGjeioiOeulwogICAgcHJpbnRmKCJBeCAgICA6IFsiKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgU0laRTsgaSsrKSB7CiAgICAgICAgcHJpbnRmKCIlLjZmJXMiLCBBeFtpXSwgKGkgPT0gU0laRSAtIDEpID8gIl1cbiIgOiAiLCAiKTsKICAgIH0KICAgIHByaW50ZigizrsgKiB4IDogWyIpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBTSVpFOyBpKyspIHsKICAgICAgICBwcmludGYoIiUuNmYlcyIsIGxhbWJkYV9uZXcgKiB5W2ldLCAoaSA9PSBTSVpFIC0gMSkgPyAiXVxuIiA6ICIsICIpOwogICAgfQoKICAgIHJldHVybiAwOwp9Cg==
=== べき乗法による収束状況の確認 ===
初期ベクトル x(0): [1.0, 1.0, 1.0, 1.0]
Iter | 固有値(新) | 差分値 | 固有ベクトルx(k)
----------------------------------------------------------------------------
1 | 7.06015038 | 7.0602e+00 | [0.55069, 0.15019, 0.50063, 0.65081]
2 | 7.56272200 | 5.0257e-01 | [0.68485, 0.48918, 0.14675, 0.51975]
3 | 7.79665790 | 2.3394e-01 | [0.53345, 0.20811, 0.56744, 0.59172]
4 | 8.36088120 | 5.6422e-01 | [0.66241, 0.41253, 0.25086, 0.57281]
5 | 8.52180634 | 1.6093e-01 | [0.58882, 0.28456, 0.47179, 0.59139]
10 | 8.69758623 | 9.4221e-03 | [0.62524, 0.34192, 0.38099, 0.58908]
15 | 8.69591999 | 7.0277e-04 | [0.62205, 0.33644, 0.39006, 0.58967]
20 | 8.69624282 | 7.2845e-05 | [0.62237, 0.33699, 0.38916, 0.58962]
25 | 8.69621204 | 7.2757e-06 | [0.62234, 0.33693, 0.38925, 0.58962]
30 | 8.69621514 | 7.2934e-07 | [0.62235, 0.33694, 0.38924, 0.58962]
35 | 8.69621483 | 7.3086e-08 | [0.62234, 0.33694, 0.38924, 0.58962]
40 | 8.69621486 | 7.3240e-09 | [0.62234, 0.33694, 0.38924, 0.58962]
45 | 8.69621486 | 7.3395e-10 | [0.62234, 0.33694, 0.38924, 0.58962]
----------------------------------------------------------------------------
反復回数 45 回で収束しました。
=== 計算結果 ===
最大固有値 (λ1) : 8.6962148610
対応する固有ベクトル (x1) : [0.6223447229, 0.3369369049, 0.3892384556, 0.5896219066]
=== 検証: Ax と λx の比較 ===
Ax : [5.412043, 2.930076, 3.384901, 5.127479]
λ * x : [5.412043, 2.930076, 3.384901, 5.127479]