#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 4 // Matrix dimension
#define MAX_ITER 100 // Maximum number of sweeps
#define EPSILON 1e-6 // 収束判定条件 (Convergence threshold)
// Function prototypes
void jacobi_method(double A[N][N], double eigenvalues[N], double eigenvectors[N][N]);
void verify_results(double orig_A[N][N], double eigenvalues[N], double eigenvectors[N][N]);
int main() {
// 1. Define the matrix from image_4.png
double A[N][N] = {
{5.0, 4.0, 1.0, 1.0},
{4.0, 5.0, 1.0, 1.0},
{1.0, 1.0, 4.0, 2.0},
{1.0, 1.0, 2.0, 4.0}
};
// Keep a copy of the original matrix for validation later
double orig_A[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
orig_A[i][j] = A[i][j];
}
}
double eigenvalues[N];
double eigenvectors[N][N];
// 2. Run Jacobi Method (Prints iteration history)
jacobi_method(A, eigenvalues, eigenvectors);
// 3. Print Final Results
printf("\n--- Final Results ---\n"); for (int i = 0; i < N; i++) {
printf("Eigenvalue %d (固有値): %9.6f\n", i
+ 1, eigenvalues
[i
]); printf("Eigenvector %d (固有ベクトル): [ ", i
+ 1); for (int j = 0; j < N; j++) {
printf("%9.6f ", eigenvectors
[j
][i
]); // Columns are eigenvectors }
}
// 4. Verification Check (固有値・固有ベクトルの確認)
verify_results(orig_A, eigenvalues, eigenvectors);
return 0;
}
void jacobi_method(double A[N][N], double eigenvalues[N], double eigenvectors[N][N]) {
// Initialize eigenvector matrix as identity matrix
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
eigenvectors[i][j] = (i == j) ? 1.0 : 0.0;
}
}
printf("--- Iteration Process (収束状況) ---\n");
int iter_count = 0;
for (int iter = 1; iter <= MAX_ITER; iter++) {
double max_off_diag = 0.0;
int p = 0, q = 0;
// Find the largest off-diagonal element |A[p][q]|
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (fabs(A
[i
][j
]) > max_off_diag
) { max_off_diag
= fabs(A
[i
][j
]); p = i;
q = j;
}
}
}
iter_count++;
// Print the iteration count and the maximum off-diagonal value remaining
printf("%d: Max off-diagonal element = %e\n", iter_count
, max_off_diag
);
// Check for convergence
if (max_off_diag < EPSILON) {
printf("\n[Convergence Achieved]\n"); break;
}
// --- Pure Algebraic Calculation of cos(theta) and sin(theta) ---
double app = A[p][p];
double aqq = A[q][q];
double apq = A[p][q];
double c, s;
c = 1.0;
s = 0.0;
} else {
double phi = 0.5 * (app - aqq) / apq;
double t;
if (phi >= 0.0) {
t
= 1.0 / (phi
+ sqrt(phi
* phi
+ 1.0)); } else {
t
= -1.0 / (-phi
+ sqrt(phi
* phi
+ 1.0)); }
c
= 1.0 / sqrt(1.0 + t
* t
); s = t * c;
}
// Update elements of matrix A
for (int i = 0; i < N; i++) {
if (i != p && i != q) {
double a_ip = A[i][p];
double a_iq = A[i][q];
A[i][p] = A[p][i] = c * a_ip + s * a_iq;
A[i][q] = A[q][i] = -s * a_ip + c * a_iq;
}
}
A[p][p] = c * c * app + 2.0 * s * c * apq + s * s * aqq;
A[q][q] = s * s * app - 2.0 * s * c * apq + c * c * aqq;
A[p][q] = A[q][p] = 0.0;
// Update accumulated eigenvector matrix P
for (int i = 0; i < N; i++) {
double v_ip = eigenvectors[i][p];
double v_iq = eigenvectors[i][q];
eigenvectors[i][p] = c * v_ip + s * v_iq;
eigenvectors[i][q] = -s * v_ip + c * v_iq;
}
}
// Extract eigenvalues from the diagonal elements
for (int i = 0; i < N; i++) {
eigenvalues[i] = A[i][i];
}
}
// Verification function: Explicitly checks the defining equation: Ax - lambda * x = 0
void verify_results(double orig_A[N][N], double eigenvalues[N], double eigenvectors[N][N]) {
printf("--- Verification Check (コード内での固有値・固有ベクトル関係性の確認) ---\n"); printf("Equation verified: Ax - lambda * x = 0\n\n");
for (int k = 0; k < N; k++) {
double x[N];
double Ax[N];
double lambda_x[N];
double error_vector[N];
// Extract the k-th eigenvector from the matrix columns
for (int i = 0; i < N; i++) {
x[i] = eigenvectors[i][k];
}
// Calculate elements of vector Ax, vector lambda*x, and the resulting error vector
for (int i = 0; i < N; i++) {
Ax[i] = 0.0;
for (int j = 0; j < N; j++) {
Ax[i] += orig_A[i][j] * x[j];
}
lambda_x[i] = eigenvalues[k] * x[i];
error_vector[i] = Ax[i] - lambda_x[i];
}
// Print the element breakdown showing the equation results
printf("Pair %d Verification:\n", k
+ 1); printf(" Ax vector = [ %9.6f %9.6f %9.6f %9.6f ]\n", Ax
[0], Ax
[1], Ax
[2], Ax
[3]); printf(" lambda * x vector = [ %9.6f %9.6f %9.6f %9.6f ]\n", lambda_x
[0], lambda_x
[1], lambda_x
[2], lambda_x
[3]); printf(" Ax - lambda * x = [ %9.6f %9.6f %9.6f %9.6f ]\n\n", error_vector
[0], error_vector
[1], error_vector
[2], error_vector
[3]); }
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KCiNkZWZpbmUgTiA0ICAgICAgICAgICAgIC8vIE1hdHJpeCBkaW1lbnNpb24KI2RlZmluZSBNQVhfSVRFUiAxMDAgICAgLy8gTWF4aW11bSBudW1iZXIgb2Ygc3dlZXBzCiNkZWZpbmUgRVBTSUxPTiAxZS02ICAgIC8vIOWPjuadn+WIpOWumuadoeS7tiAoQ29udmVyZ2VuY2UgdGhyZXNob2xkKQoKLy8gRnVuY3Rpb24gcHJvdG90eXBlcwp2b2lkIGphY29iaV9tZXRob2QoZG91YmxlIEFbTl1bTl0sIGRvdWJsZSBlaWdlbnZhbHVlc1tOXSwgZG91YmxlIGVpZ2VudmVjdG9yc1tOXVtOXSk7CnZvaWQgdmVyaWZ5X3Jlc3VsdHMoZG91YmxlIG9yaWdfQVtOXVtOXSwgZG91YmxlIGVpZ2VudmFsdWVzW05dLCBkb3VibGUgZWlnZW52ZWN0b3JzW05dW05dKTsKCmludCBtYWluKCkgewogICAgLy8gMS4gRGVmaW5lIHRoZSBtYXRyaXggZnJvbSBpbWFnZV80LnBuZwogICAgZG91YmxlIEFbTl1bTl0gPSB7CiAgICAgICAgezUuMCwgNC4wLCAxLjAsIDEuMH0sCiAgICAgICAgezQuMCwgNS4wLCAxLjAsIDEuMH0sCiAgICAgICAgezEuMCwgMS4wLCA0LjAsIDIuMH0sCiAgICAgICAgezEuMCwgMS4wLCAyLjAsIDQuMH0KICAgIH07CgogICAgLy8gS2VlcCBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIG1hdHJpeCBmb3IgdmFsaWRhdGlvbiBsYXRlcgogICAgZG91YmxlIG9yaWdfQVtOXVtOXTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBOOyBqKyspIHsKICAgICAgICAgICAgb3JpZ19BW2ldW2pdID0gQVtpXVtqXTsKICAgICAgICB9CiAgICB9CgogICAgZG91YmxlIGVpZ2VudmFsdWVzW05dOwogICAgZG91YmxlIGVpZ2VudmVjdG9yc1tOXVtOXTsKCiAgICAvLyAyLiBSdW4gSmFjb2JpIE1ldGhvZCAoUHJpbnRzIGl0ZXJhdGlvbiBoaXN0b3J5KQogICAgamFjb2JpX21ldGhvZChBLCBlaWdlbnZhbHVlcywgZWlnZW52ZWN0b3JzKTsKCiAgICAvLyAzLiBQcmludCBGaW5hbCBSZXN1bHRzCiAgICBwcmludGYoIlxuLS0tIEZpbmFsIFJlc3VsdHMgLS0tXG4iKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgcHJpbnRmKCJFaWdlbnZhbHVlICVkICjlm7rmnInlgKQpOiAlOS42ZlxuIiwgaSArIDEsIGVpZ2VudmFsdWVzW2ldKTsKICAgICAgICBwcmludGYoIkVpZ2VudmVjdG9yICVkICjlm7rmnInjg5njgq/jg4jjg6spOiBbICIsIGkgKyAxKTsKICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IE47IGorKykgewogICAgICAgICAgICBwcmludGYoIiU5LjZmICIsIGVpZ2VudmVjdG9yc1tqXVtpXSk7IC8vIENvbHVtbnMgYXJlIGVpZ2VudmVjdG9ycwogICAgICAgIH0KICAgICAgICBwcmludGYoIl1cblxuIik7CiAgICB9CgogICAgLy8gNC4gVmVyaWZpY2F0aW9uIENoZWNrICjlm7rmnInlgKTjg7vlm7rmnInjg5njgq/jg4jjg6vjga7norroqo0pCiAgICB2ZXJpZnlfcmVzdWx0cyhvcmlnX0EsIGVpZ2VudmFsdWVzLCBlaWdlbnZlY3RvcnMpOwoKICAgIHJldHVybiAwOwp9Cgp2b2lkIGphY29iaV9tZXRob2QoZG91YmxlIEFbTl1bTl0sIGRvdWJsZSBlaWdlbnZhbHVlc1tOXSwgZG91YmxlIGVpZ2VudmVjdG9yc1tOXVtOXSkgewogICAgLy8gSW5pdGlhbGl6ZSBlaWdlbnZlY3RvciBtYXRyaXggYXMgaWRlbnRpdHkgbWF0cml4CiAgICBmb3IgKGludCBpID0gMDsgaSA8IE47IGkrKykgewogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgTjsgaisrKSB7CiAgICAgICAgICAgIGVpZ2VudmVjdG9yc1tpXVtqXSA9IChpID09IGopID8gMS4wIDogMC4wOwogICAgICAgIH0KICAgIH0KCiAgICBwcmludGYoIi0tLSBJdGVyYXRpb24gUHJvY2VzcyAo5Y+O5p2f54q25rOBKSAtLS1cbiIpOwoKICAgIGludCBpdGVyX2NvdW50ID0gMDsKICAgIGZvciAoaW50IGl0ZXIgPSAxOyBpdGVyIDw9IE1BWF9JVEVSOyBpdGVyKyspIHsKICAgICAgICBkb3VibGUgbWF4X29mZl9kaWFnID0gMC4wOwogICAgICAgIGludCBwID0gMCwgcSA9IDA7CgogICAgICAgIC8vIEZpbmQgdGhlIGxhcmdlc3Qgb2ZmLWRpYWdvbmFsIGVsZW1lbnQgfEFbcF1bcV18CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IGkgKyAxOyBqIDwgTjsgaisrKSB7CiAgICAgICAgICAgICAgICBpZiAoZmFicyhBW2ldW2pdKSA+IG1heF9vZmZfZGlhZykgewogICAgICAgICAgICAgICAgICAgIG1heF9vZmZfZGlhZyA9IGZhYnMoQVtpXVtqXSk7CiAgICAgICAgICAgICAgICAgICAgcCA9IGk7CiAgICAgICAgICAgICAgICAgICAgcSA9IGo7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGl0ZXJfY291bnQrKzsKICAgICAgICAKICAgICAgICAvLyBQcmludCB0aGUgaXRlcmF0aW9uIGNvdW50IGFuZCB0aGUgbWF4aW11bSBvZmYtZGlhZ29uYWwgdmFsdWUgcmVtYWluaW5nCiAgICAgICAgcHJpbnRmKCIlZDogTWF4IG9mZi1kaWFnb25hbCBlbGVtZW50ID0gJWVcbiIsIGl0ZXJfY291bnQsIG1heF9vZmZfZGlhZyk7CgogICAgICAgIC8vIENoZWNrIGZvciBjb252ZXJnZW5jZQogICAgICAgIGlmIChtYXhfb2ZmX2RpYWcgPCBFUFNJTE9OKSB7CiAgICAgICAgICAgIHByaW50ZigiXG5bQ29udmVyZ2VuY2UgQWNoaWV2ZWRdXG4iKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICAvLyAtLS0gUHVyZSBBbGdlYnJhaWMgQ2FsY3VsYXRpb24gb2YgY29zKHRoZXRhKSBhbmQgc2luKHRoZXRhKSAtLS0KICAgICAgICBkb3VibGUgYXBwID0gQVtwXVtwXTsKICAgICAgICBkb3VibGUgYXFxID0gQVtxXVtxXTsKICAgICAgICBkb3VibGUgYXBxID0gQVtwXVtxXTsKICAgICAgICAKICAgICAgICBkb3VibGUgYywgczsgCgogICAgICAgIGlmIChmYWJzKGFwcSkgPCAxZS0xMikgewogICAgICAgICAgICBjID0gMS4wOwogICAgICAgICAgICBzID0gMC4wOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGRvdWJsZSBwaGkgPSAwLjUgKiAoYXBwIC0gYXFxKSAvIGFwcTsKICAgICAgICAgICAgZG91YmxlIHQ7CiAgICAgICAgICAgIGlmIChwaGkgPj0gMC4wKSB7CiAgICAgICAgICAgICAgICB0ID0gMS4wIC8gKHBoaSArIHNxcnQocGhpICogcGhpICsgMS4wKSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0ID0gLTEuMCAvICgtcGhpICsgc3FydChwaGkgKiBwaGkgKyAxLjApKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjID0gMS4wIC8gc3FydCgxLjAgKyB0ICogdCk7CiAgICAgICAgICAgIHMgPSB0ICogYzsKICAgICAgICB9CgogICAgICAgIC8vIFVwZGF0ZSBlbGVtZW50cyBvZiBtYXRyaXggQQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgICAgIGlmIChpICE9IHAgJiYgaSAhPSBxKSB7CiAgICAgICAgICAgICAgICBkb3VibGUgYV9pcCA9IEFbaV1bcF07CiAgICAgICAgICAgICAgICBkb3VibGUgYV9pcSA9IEFbaV1bcV07CiAgICAgICAgICAgICAgICBBW2ldW3BdID0gQVtwXVtpXSA9IGMgKiBhX2lwICsgcyAqIGFfaXE7CiAgICAgICAgICAgICAgICBBW2ldW3FdID0gQVtxXVtpXSA9IC1zICogYV9pcCArIGMgKiBhX2lxOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIEFbcF1bcF0gPSBjICogYyAqIGFwcCArIDIuMCAqIHMgKiBjICogYXBxICsgcyAqIHMgKiBhcXE7CiAgICAgICAgQVtxXVtxXSA9IHMgKiBzICogYXBwIC0gMi4wICogcyAqIGMgKiBhcHEgKyBjICogYyAqIGFxcTsKICAgICAgICBBW3BdW3FdID0gQVtxXVtwXSA9IDAuMDsgCgogICAgICAgIC8vIFVwZGF0ZSBhY2N1bXVsYXRlZCBlaWdlbnZlY3RvciBtYXRyaXggUAogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgICAgIGRvdWJsZSB2X2lwID0gZWlnZW52ZWN0b3JzW2ldW3BdOwogICAgICAgICAgICBkb3VibGUgdl9pcSA9IGVpZ2VudmVjdG9yc1tpXVtxXTsKICAgICAgICAgICAgZWlnZW52ZWN0b3JzW2ldW3BdID0gYyAqIHZfaXAgKyBzICogdl9pcTsKICAgICAgICAgICAgZWlnZW52ZWN0b3JzW2ldW3FdID0gLXMgKiB2X2lwICsgYyAqIHZfaXE7CiAgICAgICAgfQogICAgfQoKICAgIC8vIEV4dHJhY3QgZWlnZW52YWx1ZXMgZnJvbSB0aGUgZGlhZ29uYWwgZWxlbWVudHMKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgZWlnZW52YWx1ZXNbaV0gPSBBW2ldW2ldOwogICAgfQp9CgovLyBWZXJpZmljYXRpb24gZnVuY3Rpb246IEV4cGxpY2l0bHkgY2hlY2tzIHRoZSBkZWZpbmluZyBlcXVhdGlvbjogQXggLSBsYW1iZGEgKiB4ID0gMAp2b2lkIHZlcmlmeV9yZXN1bHRzKGRvdWJsZSBvcmlnX0FbTl1bTl0sIGRvdWJsZSBlaWdlbnZhbHVlc1tOXSwgZG91YmxlIGVpZ2VudmVjdG9yc1tOXVtOXSkgewogICAgcHJpbnRmKCItLS0gVmVyaWZpY2F0aW9uIENoZWNrICjjgrPjg7zjg4nlhoXjgafjga7lm7rmnInlgKTjg7vlm7rmnInjg5njgq/jg4jjg6vplqLkv4LmgKfjga7norroqo0pIC0tLVxuIik7CiAgICBwcmludGYoIkVxdWF0aW9uIHZlcmlmaWVkOiBBeCAtIGxhbWJkYSAqIHggPSAwXG5cbiIpOwogICAgCiAgICBmb3IgKGludCBrID0gMDsgayA8IE47IGsrKykgewogICAgICAgIGRvdWJsZSB4W05dOwogICAgICAgIGRvdWJsZSBBeFtOXTsKICAgICAgICBkb3VibGUgbGFtYmRhX3hbTl07CiAgICAgICAgZG91YmxlIGVycm9yX3ZlY3RvcltOXTsKCiAgICAgICAgLy8gRXh0cmFjdCB0aGUgay10aCBlaWdlbnZlY3RvciBmcm9tIHRoZSBtYXRyaXggY29sdW1ucwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgICAgIHhbaV0gPSBlaWdlbnZlY3RvcnNbaV1ba107CiAgICAgICAgfQoKICAgICAgICAvLyBDYWxjdWxhdGUgZWxlbWVudHMgb2YgdmVjdG9yIEF4LCB2ZWN0b3IgbGFtYmRhKngsIGFuZCB0aGUgcmVzdWx0aW5nIGVycm9yIHZlY3RvcgogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgICAgIEF4W2ldID0gMC4wOwogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IE47IGorKykgewogICAgICAgICAgICAgICAgQXhbaV0gKz0gb3JpZ19BW2ldW2pdICogeFtqXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsYW1iZGFfeFtpXSA9IGVpZ2VudmFsdWVzW2tdICogeFtpXTsKICAgICAgICAgICAgZXJyb3JfdmVjdG9yW2ldID0gQXhbaV0gLSBsYW1iZGFfeFtpXTsKICAgICAgICB9CgogICAgICAgIC8vIFByaW50IHRoZSBlbGVtZW50IGJyZWFrZG93biBzaG93aW5nIHRoZSBlcXVhdGlvbiByZXN1bHRzCiAgICAgICAgcHJpbnRmKCJQYWlyICVkIFZlcmlmaWNhdGlvbjpcbiIsIGsgKyAxKTsKICAgICAgICBwcmludGYoIiAgQXggdmVjdG9yICAgICAgICAgPSBbICU5LjZmICAlOS42ZiAgJTkuNmYgICU5LjZmIF1cbiIsIEF4WzBdLCBBeFsxXSwgQXhbMl0sIEF4WzNdKTsKICAgICAgICBwcmludGYoIiAgbGFtYmRhICogeCB2ZWN0b3IgPSBbICU5LjZmICAlOS42ZiAgJTkuNmYgICU5LjZmIF1cbiIsIGxhbWJkYV94WzBdLCBsYW1iZGFfeFsxXSwgbGFtYmRhX3hbMl0sIGxhbWJkYV94WzNdKTsKICAgICAgICBwcmludGYoIiAgQXggLSBsYW1iZGEgKiB4ICAgPSBbICU5LjZmICAlOS42ZiAgJTkuNmYgICU5LjZmIF1cblxuIiwgZXJyb3JfdmVjdG9yWzBdLCBlcnJvcl92ZWN0b3JbMV0sIGVycm9yX3ZlY3RvclsyXSwgZXJyb3JfdmVjdG9yWzNdKTsKICAgIH0KfQoK