#***********************************************/
# 実対称行列の固有値・固有ベクトル(ヤコビ法) */
# coded by Y.Suganuma */
#***********************************************/
#************************************************************/
# 実対称行列の固有値・固有ベクトル(ヤコビ法) */
# n : 次数 */
# ct : 最大繰り返し回数 */
# eps : 収束判定条件 */
# a : 対象とする行列 */
# a1, a2 : 作業域(nxnの行列),a1の対角要素が固有値 */
# x1, x2 : 作業域(nxnの行列),x1の各列が固有ベクトル */
# return : =0 : 正常 */
# =1 : 収束せず */
# coded by Y.Suganuma */
#************************************************************/
def Jacobi(n, ct, eps, a, a1, a2, x1, x2)
# 初期設定
k = 0
ind = 1
p = 0
q = 0
for i1 in 0 ... n
for i2 in 0 ... n
a1[i1][i2] = a[i1][i2]
x1[i1][i2] = 0.0
end
x1[i1][i1] = 1.0
end
# 計算
while ind > 0 && k < ct
# 最大要素の探索
max = 0.0
for i1 in 0 ... n
for i2 in 0 ... n
if i2 != i1
if a1[i1][i2].abs() > max
max = a1[i1][i2].abs()
p = i1
q = i2
end
end
end
end
# 収束判定
# 収束した
if max < eps
ind = 0
# 収束しない
else
# 準備
s = -a1[p][q]
t = 0.5 * (a1[p][p] - a1[q][q])
v = t.abs() / Math.sqrt(s * s + t * t)
sn = Math.sqrt(0.5 * (1.0 - v))
if s*t < 0.0
sn = -sn
end
cs = Math.sqrt(1.0 - sn * sn)
# akの計算
for i1 in 0 ... n
if i1 == p
for i2 in 0 ... n
if i2 == p
a2[p][p] = a1[p][p] * cs * cs + a1[q][q] * sn * sn -
2.0 * a1[p][q] * sn * cs
elsif i2 == q
a2[p][q] = 0.0
else
a2[p][i2] = a1[p][i2] * cs - a1[q][i2] * sn
end
end
elsif i1 == q
for i2 in 0 ... n
if (i2 == q)
a2[q][q] = a1[p][p] * sn * sn + a1[q][q] * cs * cs +
2.0 * a1[p][q] * sn * cs
elsif i2 == p
a2[q][p] = 0.0
else
a2[q][i2] = a1[q][i2] * cs + a1[p][i2] * sn
end
end
else
for i2 in 0 ... n
if i2 == p
a2[i1][p] = a1[i1][p] * cs - a1[i1][q] * sn
elsif i2 == q
a2[i1][q] = a1[i1][q] * cs + a1[i1][p] * sn
else
a2[i1][i2] = a1[i1][i2]
end
end
end
end
# xkの計算
for i1 in 0 ... n
for i2 in 0 ... n
if i2 == p
x2[i1][p] = x1[i1][p] * cs - x1[i1][q] * sn
elsif i2 == q
x2[i1][q] = x1[i1][q] * cs + x1[i1][p] * sn
else
x2[i1][i2] = x1[i1][i2]
end
end
end
# 次のステップへ
k += 1
for i1 in 0 ... n
for i2 in 0 ... n
a1[i1][i2] = a2[i1][i2]
x1[i1][i2] = x2[i1][i2]
end
end
end
end
return ind
end
# データの設定
ct = 1000
eps = 1.0e-10
n = 3
a = Array.new(n)
a1 = Array.new(n)
a2 = Array.new(n)
x1 = Array.new(n)
x2 = Array.new(n)
for i1 in 0 ... n
a[i1] = Array.new(n)
a1[i1] = Array.new(n)
a2[i1] = Array.new(n)
x1[i1] = Array.new(n)
x2[i1] = Array.new(n)
end
a[0][0] = 1.0
a[0][1] = 0.0
a[0][2] = -1.0
a[1][0] = 0.0
a[1][1] = 1.0
a[1][2] = -1.0
a[2][0] = -1.0
a[2][1] = -1.0
a[2][2] = 2.0
# 計算
ind = Jacobi(n, ct, eps, a, a1, a2, x1, x2)
# 出力
if ind > 0
printf("収束しませんでした!\n")
else
printf("固有値\n")
for i1 in 0 ... n
printf(" %f", a1[i1][i1])
end
printf("\n固有ベクトル(各列が固有ベクトル)\n")
for i1 in 0 ... n
for i2 in 0 ... n
printf(" %f", x1[i1][i2])
end
printf("\n")
end
end