実対称行列の固有値・固有ベクトル(ヤコビ法)

# -*- coding: UTF-8 -*-
from math import *
import numpy as np

############################################
# 実対称行列の固有値・固有ベクトル(ヤコビ法)
#      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 range(0, n) :
		for i2 in range(0, n) :
			A1[i1][i2] = A[i1][i2]
			X1[i1][i2] = 0.0
		X1[i1][i1] = 1.0
			# 計算
	while ind > 0 and k < ct :
				# 最大要素の探索
		max = 0.0
		for i1 in range(0, n) :
			for i2 in range(0, n) :
				if i2 != i1 :
					if abs(A1[i1][i2]) > max :
						max = fabs(A1[i1][i2])
						p   = i1
						q   = i2
				# 収束判定
					# 収束した
		if max < eps :
			ind = 0
					# 収束しない
		else :
						# 準備
			s  = -A1[p][q]
			t  = 0.5 * (A1[p][p] - A1[q][q])
			v  = fabs(t) / sqrt(s * s + t * t)
			sn = sqrt(0.5 * (1.0 - v))
			if s*t < 0.0 :
				sn = -sn
			cs = sqrt(1.0 - sn * sn)
						# Akの計算
			for i1 in range(0, n) :
				if i1 == p :
					for i2 in range(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
						elif i2 == q :
							A2[p][q] = 0.0
						else :
							A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn
				elif i1 == q :
					for i2 in range(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
						elif i2 == p :
							A2[q][p] = 0.0
						else :
							A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn
				else :
					for i2 in range(0, n) :
						if i2 == p :
							A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn
						elif i2 == q :
							A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn
						else :
							A2[i1][i2] = A1[i1][i2]
						# Xkの計算
			for i1 in range(0, n) :
				for i2 in range(0, n) :
					if i2 == p :
						X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn
					elif i2 == q :
						X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn
					else :
						X2[i1][i2] = X1[i1][i2]
						# 次のステップへ
			k += 1
			for i1 in range(0, n) :
				for i2 in range(0, n) :
					A1[i1][i2] = A2[i1][i2]
					X1[i1][i2] = X2[i1][i2]

	return ind

----------------------------------

# -*- coding: UTF-8 -*-
import numpy as np
from math import *
from function import Jacobi

############################################
# 実対称行列の固有値・固有ベクトル(ヤコビ法)
#      coded by Y.Suganuma
############################################
			# データの設定
ct  = 1000
eps = 1.0e-10
n   = 3
A   = np.array([[1, 0, -1],[0, 1, -1],[-1, -1, 2]], np.float)
A1  = np.empty((n, n), np.float)
A2  = np.empty((n, n), np.float)
X1  = np.empty((n, n), np.float)
X2  = np.empty((n, n), np.float)
			# 計算
ind = Jacobi(n, ct, eps, A, A1, A2, X1, X2)
			# 出力
if ind > 0 :
	print("収束しませんでした!")
else :
	print("固有値")
	print(" ", A1[0][0], A1[1][1], A1[2][2])
	print("固有ベクトル(各列が固有ベクトル)")
	for i1 in range(0, n) :
		for i2 in range(0, n) :
			print(" " + str(X1[i1][i2]), end="")
		print()