#***************************************/ # 最大固有値と固有ベクトル(べき乗法) */ # coded by Y.Suganuma */ #***************************************/ #***************************************/ # 最大固有値と固有ベクトル(べき乗法) */ # i : 何番目の固有値かを示す */ # n : 次数 */ # m : 丸め誤差の修正回数 */ # ct : 最大繰り返し回数 */ # eps : 収束判定条件 */ # a : 対象とする行列 */ # b : nxnの行列,最初は,単位行列 */ # c : 作業域,nxnの行列 */ # r : 固有値 */ # v : 各行が固有ベクトル(nxn) */ # v0 : 固有ベクトルの初期値 */ # v1,v2 : 作業域(n次元ベクトル) */ # return : 求まった固有値の数 */ # coded by Y.Suganuma */ #***************************************/ def power(i, n, m, ct, eps, a, b, c, r, v, v0, v1, v2) # 初期設定 ind = i k = 0 l1 = 0.0 for i1 in 0 ... n l1 += v0[i1] * v0[i1] v1[i1] = v0[i1] end l1 = Math.sqrt(l1) # 繰り返し計算 while k < ct # 丸め誤差の修正 if k%m == 0 l2 = 0.0 for i1 in 0 ... n v2[i1] = 0.0 for i2 in 0 ... n v2[i1] += b[i1][i2] * v1[i2] end l2 += v2[i1] * v2[i1] end l2 = Math.sqrt(l2) for i1 in 0 ... n v1[i1] = v2[i1] / l2 end end # 次の近似 l2 = 0.0 for i1 in 0 ... n v2[i1] = 0.0 for i2 in 0 ... n v2[i1] += a[i1][i2] * v1[i2] end l2 += v2[i1] * v2[i1] end l2 = Math.sqrt(l2) for i1 in 0 ... n v2[i1] /= l2 end # 収束判定 # 収束した場合 if ((l2-l1)/l1).abs() < eps k1 = -1 for i1 in 0 ... n if v2[i1].abs() > 0.001 k1 = i1 if v2[k1]*v1[k1] < 0.0 l2 = -l2 end end if k1 >= 0 break end end k = ct r[i] = l2 for i1 in 0 ... n v[i][i1] = v2[i1] end if i == n-1 ind = i + 1 else for i1 in 0 ... n for i2 in 0 ... n c[i1][i2] = 0.0 for i3 in 0 ... n x = (i1 == i3) ? a[i1][i3] - l2 : a[i1][i3] c[i1][i2] += x * b[i3][i2] end end end for i1 in 0 ... n for i2 in 0 ... n b[i1][i2] = c[i1][i2] end end for i1 in 0 ... n v1[i1] = 0.0 for i2 in 0 ... n v1[i1] += b[i1][i2] * v0[i2] end end for i1 in 0 ... n v0[i1] = v1[i1] end ind = power(i+1, n, m, ct, eps, a, b, c, r, v, v0, v1, v2) end # 収束しない場合 else for i1 in 0 ... n v1[i1] = v2[i1] end l1 = l2 k += 1 end end return ind end # データの設定 ct = 200 eps = 1.0e-10 n = 3 m = 15 a = Array.new(n) b = Array.new(n) c = Array.new(n) v = Array.new(n) for i1 in 0 ... n a[i1] = Array.new(n) b[i1] = Array.new(n) c[i1] = Array.new(n) v[i1] = Array.new(n) end r = Array.new(n) v0 = Array.new(n) v1 = Array.new(n) v2 = Array.new(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 in 0 ... n for i2 in 0 ... n b[i1][i2] = 0.0 end b[i1][i1] = 1.0 v0[i1] = 1.0 end # 計算 ind = power(0, n, m, ct, eps, a, b, c, r, v, v0, v1, v2) # 出力 if ind == 0 printf("固有値が求まりませんでした!\n") else for i1 in 0 ... ind printf("固有値 %f", r[i1]) printf(" 固有ベクトル ") for i2 in 0 ... n printf(" %f", v[i1][i2]) end printf("\n") end end