最大固有値と固有ベクトル(べき乗法)

#***************************************/
# 最大固有値と固有ベクトル(べき乗法) */
#      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