#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define SIZE 4 // 行列のサイズ
#define MAX_ITER 1000 // 最大反復回数
#define TOL 0.0000001 // 収束判定の許容誤差
// QR分解を行うためのヘルパー関数(グラムシュミット直交化を使用)
void qr_decompose(double A[SIZE][SIZE], double Q[SIZE][SIZE], double R[SIZE][SIZE]) {
int i, j, k;
double norm;
// 初期化
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
Q[i][j] = 0.0;
R[i][j] = 0.0;
}
}
// グラムシュミット直交化
for (k = 0; k < SIZE; k++) {
for (i = 0; i < SIZE; i++) {
Q[i][k] = A[i][k];
}
for (j = 0; j < k; j++) {
R[j][k] = 0.0;
for (i = 0; i < SIZE; i++) {
R[j][k] += Q[i][j] * A[i][k];
}
for (i = 0; i < SIZE; i++) {
Q[i][k] -= R[j][k] * Q[i][j];
}
}
norm = 0.0;
for (i = 0; i < SIZE; i++) {
norm += Q[i][k] * Q[i][k];
}
for (i = 0; i < SIZE; i++) {
Q[i][k] /= R[k][k];
}
}
}
// シフトなしQR法で固有値を計算
void qr_algorithm(double A[SIZE][SIZE], double eigenvalues[SIZE]) {
double Q[SIZE][SIZE], R[SIZE][SIZE], A_next[SIZE][SIZE];
int i, j, k, l;
for (k = 0; k < MAX_ITER; k++) {
qr_decompose(A, Q, R);
// 新しい行列 A = R * Q を計算
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
A_next[i][j] = 0.0;
for (l = 0; l < SIZE; l++) {
A_next[i][j] += R[i][l] * Q[l][j];
}
}
}
// 収束判定(非対角成分が小さいか確認)
double diff_norm = 0.0;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
if (i != j) {
diff_norm += A_next[i][j] * A_next[i][j];
}
}
}
if (sqrt(diff_norm
) < TOL
) break;
// 更新
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
A[i][j] = A_next[i][j];
}
}
}
// 固有値を対角成分として取得
for (i = 0; i < SIZE; i++) {
eigenvalues[i] = A[i][i];
}
}
void solve_linear_system(double A[SIZE][SIZE], double b[SIZE], double x[SIZE]) {
double augmented[SIZE][SIZE + 1];
int i, j, k;
// 拡大係数行列の作成
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
augmented[i][j] = A[i][j];
}
augmented[i][SIZE] = b[i]; // 最右列に b を追加
}
// 前進消去(部分ピボット選択付き)
for (k = 0; k < SIZE; k++) {
// ピボット選択
int max_row = k;
for (i = k + 1; i < SIZE; i++) {
if (fabs(augmented
[i
][k
]) > fabs(augmented
[max_row
][k
])) { max_row = i;
}
}
// 行交換(必要な場合)
if (max_row != k) {
for (j = 0; j <= SIZE; j++) {
double temp = augmented[k][j];
augmented[k][j] = augmented[max_row][j];
augmented[max_row][j] = temp;
}
}
// ピボット列を基準に前進消去
for (i = k + 1; i < SIZE; i++) {
double factor = augmented[i][k] / augmented[k][k];
for (j = k; j <= SIZE; j++) {
augmented[i][j] -= factor * augmented[k][j];
}
}
}
// 後退代入
for (i = SIZE - 1; i >= 0; i--) {
x[i] = augmented[i][SIZE]; // 拡大係数行列の最後の列が定数項
for (j = i + 1; j < SIZE; j++) {
x[i] -= augmented[i][j] * x[j];
}
x[i] /= augmented[i][i];
}
}
void inverse_iteration(double A[SIZE][SIZE], double mu, double eigenvector[SIZE]) {
double I[SIZE][SIZE], shifted_A[SIZE][SIZE], y[SIZE], x[SIZE];
int i, j, k;
// 単位行列 I の作成
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
I[i][j] = (i == j) ? 1.0 : 0.0;
}
}
// 初期ベクトルをランダムに設定
for (i = 0; i < SIZE; i++) {
x
[i
] = (double)rand() / RAND_MAX
; // 0.0~1.0の範囲で初期化 }
// (A - mu * I) の計算
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
shifted_A[i][j] = A[i][j] - mu * I[i][j];
}
}
// 反復計算
for (k = 0; k < MAX_ITER; k++) {
// (A - mu * I)y = x を解く
solve_linear_system(shifted_A, x, y);
// 正規化
double norm = 0.0;
for (i = 0; i < SIZE; i++) {
norm += y[i] * y[i];
}
for (i = 0; i < SIZE; i++) {
y[i] /= norm; // 正規化
}
// 収束判定
double diff = 0.0;
for (i = 0; i < SIZE; i++) {
diff
+= fabs(y
[i
] - x
[i
]); }
if (diff < TOL) {
break;
}
// x を更新
for (i = 0; i < SIZE; i++) {
x[i] = y[i];
}
}
// 固有ベクトルを返す
for (i = 0; i < SIZE; i++) {
eigenvector[i] = y[i];
}
}
// メイン関数
int main() {
double A[SIZE][SIZE] = {
{16, -1, 1, 2},
{2, 12, 1, -1},
{1, 3, 24, 2},
{4, -2, 1, 20}
};
double eigenvalues[SIZE], eigenvector[SIZE];
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
}
}
// シフトなしQR法で固有値を計算
qr_algorithm(A, eigenvalues);
for (int i = 0; i < SIZE; i++) {
printf("lambda[%d] = %8.4f\n", i
, eigenvalues
[i
]); }
return 0;
}