fork(1) download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4.  
  5. #define SIZE 4
  6. #define EPSILON_POWER 1e-9
  7. #define EPSILON_NEWTON 1e-7
  8. #define MAX_ITER 1000
  9.  
  10.  
  11. double vector_norm(double *v, int n) {
  12. double sum = 0.0;
  13. for (int i = 0; i < n; i++) {
  14. sum += v[i] * v[i];
  15. }
  16. return sqrt(sum);
  17. }
  18.  
  19. void mat_vec_mul(double A[SIZE][SIZE], double *x, double *y, int n) {
  20. for (int i = 0; i < n; i++) {
  21. y[i] = 0.0;
  22. for (int j = 0; j < n; j++) {
  23. y[i] += A[i][j] * x[j];
  24. }
  25. }
  26. }
  27.  
  28.  
  29. double f(double lambda) {
  30. return pow(lambda, 4) - 2.0 * pow(lambda, 3) - 43.0 * pow(lambda, 2) - 36.0 * lambda + 130.0;
  31. }
  32.  
  33. double df(double lambda) {
  34. return 4.0 * pow(lambda, 3) - 6.0 * pow(lambda, 2) - 86.0 * lambda - 36.0;
  35. }
  36.  
  37. void solve_newton(int attempt, double lambda0) {
  38. double lambda = lambda0;
  39. int iter = 0;
  40.  
  41. while (iter <= MAX_ITER) {
  42. double f_val = f(lambda);
  43. double df_val = df(lambda);
  44.  
  45. if (fabs(df_val) < 1e-12) return;
  46.  
  47. double delta = f_val / df_val;
  48. lambda -= delta;
  49. iter++;
  50.  
  51. if (fabs(delta) < EPSILON_NEWTON) {
  52. printf("試行 #%d (初期値 %5.1f) -> 収束成功 (%2d回) | 固有値解 λ = %.10f\n",
  53. attempt, lambda0, iter, lambda);
  54. return;
  55. }
  56. }
  57. }
  58.  
  59.  
  60. int main() {
  61. double A[SIZE][SIZE] = {
  62. {2.0, 1.0, 2.0, 5.0},
  63. {3.0, -3.0, 1.0, 6.0},
  64. {0.0, 1.0, 2.0, 7.0},
  65. {1.0, 1.0, 3.0, 1.0}
  66. };
  67.  
  68. double x[SIZE], y[SIZE], Ax[SIZE];
  69. double lambda_old = 0.0, lambda_new = 0.0;
  70. printf(" べき乗法 \n");
  71. for (int i = 0; i < SIZE; i++) {
  72. x[i] = 1.0;
  73. }
  74.  
  75. printf("初期ベクトル x(0): [%.1f, %.1f, %.1f, %.1f]\n\n", x[0], x[1], x[2], x[3]);
  76. printf("%-5s | %-12s | %-12s | %-30s\n", "Iter", "固有値(新)", "差分値", "固有ベクトルx(k)");
  77.  
  78. int actual_iters = 0;
  79. for (int iter = 1; iter <= MAX_ITER; iter++) {
  80. actual_iters = iter;
  81. mat_vec_mul(A, x, y, SIZE);
  82.  
  83. double norm_y = vector_norm(y, SIZE);
  84. if (norm_y < 1e-12) break;
  85. for (int i = 0; i < SIZE; i++) {
  86. y[i] /= norm_y;
  87. }
  88.  
  89. mat_vec_mul(A, y, Ax, SIZE);
  90. double num = 0.0, den = 0.0;
  91. for (int i = 0; i < SIZE; i++) {
  92. num += y[i] * Ax[i];
  93. den += y[i] * y[i];
  94. }
  95. lambda_new = num / den;
  96. double diff = fabs(lambda_new - lambda_old);
  97.  
  98. if (iter <= 5 || iter % 5 == 0) {
  99. printf("%-5d | %-12.8f | %-12.4e | [%.5f, %.5f, %.5f, %.5f]\n",
  100. iter, lambda_new, diff, y[0], y[1], y[2], y[3]);
  101. }
  102.  
  103. if (diff < EPSILON_POWER) {
  104. if (iter % 5 != 0 && iter > 5) {
  105. printf("%-5d | %-12.8f | %-12.4e | [%.5f, %.5f, %.5f, %.5f]\n",
  106. iter, lambda_new, diff, y[0], y[1], y[2], y[3]);
  107. }
  108. break;
  109. }
  110.  
  111. for (int i = 0; i < SIZE; i++) {
  112. x[i] = y[i];
  113. }
  114. lambda_old = lambda_new;
  115. }
  116.  
  117. printf("反復回数 %d 回で収束しました。\n", actual_iters);
  118. printf("\n最大固有値 (λ1) : %.10f\n", lambda_new);
  119. printf("対応する固有ベクトル (x1) : [");
  120. for (int i = 0; i < SIZE; i++) {
  121. printf("%.10f%s", y[i], (i == SIZE - 1) ? "]\n" : ", ");
  122. }
  123.  
  124. printf("\n Ax と λx の比較 \n");
  125. mat_vec_mul(A, y, Ax, SIZE);
  126. printf("Ax : [");
  127. for (int i = 0; i < SIZE; i++) {
  128. printf("%.6f%s", Ax[i], (i == SIZE - 1) ? "]\n" : ", ");
  129. }
  130. printf("λ * x : [");
  131. for (int i = 0; i < SIZE; i++) {
  132. printf("%.6f%s", lambda_new * y[i], (i == SIZE - 1) ? "]\n" : ", ");
  133. }
  134.  
  135. printf("\n\n");
  136.  
  137. printf(" 固有値が最大固有値であることの確認:ニュートン・ラフソン法 \n");
  138.  
  139. printf("対象の特性方程式: f(λ) = λ^4 - 2.0λ^3 - 43.0λ^2 - 36.0λ + 130.0 = 0\n\n");
  140.  
  141. double initial_lambda[] = {10.0, 2.0, -2.5, -6.0};
  142. for (int i = 0; i < 4; i++) {
  143. solve_newton(i + 1, initial_lambda[i]);
  144. }
  145. return 0;
  146. }
Success #stdin #stdout 0s 5308KB
stdin
Standard input is empty
stdout
                べき乗法              
初期ベクトル x(0): [1.0, 1.0, 1.0, 1.0]

Iter  | 固有値(新) | 差分値    | 固有ベクトルx(k)        
1     | 7.58947368   | 7.5895e+00   | [0.59235, 0.41464, 0.59235, 0.35541]
2     | 7.97210119   | 3.8263e-01   | [0.59901, 0.42786, 0.53677, 0.41230]
3     | 7.72878414   | 2.4332e-01   | [0.59682, 0.44176, 0.55001, 0.38228]
4     | 7.86852048   | 1.3974e-01   | [0.60110, 0.42802, 0.54559, 0.39724]
5     | 7.78782087   | 8.0700e-02   | [0.59823, 0.43820, 0.54642, 0.38926]
10    | 7.81916110   | 4.7095e-03   | [0.59949, 0.43391, 0.54638, 0.39217]
15    | 7.81737213   | 2.6407e-04   | [0.59941, 0.43420, 0.54635, 0.39202]
20    | 7.81747243   | 1.4759e-05   | [0.59941, 0.43418, 0.54635, 0.39203]
25    | 7.81746682   | 8.2460e-07   | [0.59941, 0.43418, 0.54635, 0.39203]
30    | 7.81746714   | 4.6068e-08   | [0.59941, 0.43418, 0.54635, 0.39203]
35    | 7.81746712   | 2.5737e-09   | [0.59941, 0.43418, 0.54635, 0.39203]
37    | 7.81746712   | 8.1175e-10   | [0.59941, 0.43418, 0.54635, 0.39203]
反復回数 37 回で収束しました。

最大固有値 (λ1)          : 7.8174671191
対応する固有ベクトル (x1) : [0.5994100822, 0.4341839804, 0.5463547658, 0.3920309865]

    Ax と λx の比較   
Ax    : [4.685869, 3.394219, 4.271110, 3.064689]
λ * x : [4.685869, 3.394219, 4.271110, 3.064689]


   固有値が最大固有値であることの確認:ニュートン・ラフソン法     
対象の特性方程式: f(λ) = λ^4 - 2.0λ^3 - 43.0λ^2 - 36.0λ + 130.0 = 0

試行 #1 (初期値  10.0) -> 収束成功 ( 6回) | 固有値解 λ = 7.8174671194
試行 #2 (初期値   2.0) -> 収束成功 ( 5回) | 固有値解 λ = 1.3593330358
試行 #3 (初期値  -2.5) -> 収束成功 ( 4回) | 固有値解 λ = -2.7864676299
試行 #4 (初期値  -6.0) -> 収束成功 ( 7回) | 固有値解 λ = -4.3903325253