SOR法

ガウス・ザイデル法の効率を上げたSOR法をやってみた。
http://www.akita-nct.ac.jp/yamamoto/lecture/2004/5E/linear_equations/relaxation/html/node6.html
SOR法 - Wikipedia

import math

def sor(matrix, dim, omega):
	count = 0
	check = 1.0e-10
	oldx = []
	for i in range(dim):
		oldx.append(1.0)   #解の初期値を設定する。今回は1にしてみた。
	newx = oldx[:]

	while True:
		error = []

		if count == 10000:
			print('Error.')
			return -1

		for i in range(dim):
			newx[i] = matrix[i][-1]
			for j in range(dim):
				if j != i:
					if j < i:
						newx[i] -= matrix[i][j] * newx[j]
					else:
						newx[i] -= matrix[i][j] * oldx[j]
			newx[i] /= matrix[i][i]
			newx[i] = (1 - omega) * oldx[i] + omega * newx[i]    #ガウス・ザイデル法と違うところ

		for i in range(dim):
			error.append(math.fabs(oldx[i] - newx[i]))

		count += 1

		if max(error) < check:
			print(newx)
			return count

		oldx = newx[:]

def output(filename, ans):
	f = open(filename, 'w')
	for i in ans:
		f.write('%f %d\n' % (i[0], i[1]))
	f.close()

def main():
	dim = 0
	matrix = []
	num = []
	ans = []
	omega = 0.1
	for line in open('matrix.txt'):
		item = line.split(' ')
		for i in item:
			num.append(float(i))
		matrix.append(num)
		num = []
		dim += 1
	print('Dimensions: %d' % dim)
	while omega <= 3.0:
		count = sor(matrix, dim, omega)
		ans.append([omega, count])
		omega += 0.1
	output('sor.txt', ans)

if __name__ == '__main__':
	main()

matrix.txtの中身。

1 -1 1 5
1 2 0 1
2 0 3 9

実行結果。

Dimensions: 3
[3.0000000009420646, -1.0000000011183832, 0.9999999985088222]
[3.0000000004246195, -1.0000000004868626, 0.9999999993508506]
[3.000000000269135, -1.0000000002967036, 0.9999999996043953]
[3.0000000002026237, -1.0000000002135532, 0.9999999997152625]
[3.0000000001049036, -1.0000000001049036, 0.9999999998601288]
[3.000000000072527, -1.0000000000681017, 0.9999999999091977]
[3.0000000000627702, -1.0000000000545017, 0.9999999999273311]
[3.000000000059581, -1.0000000000466576, 0.9999999999377899]
[3.000000000022313, -1.0000000000150144, 0.9999999999799807]
[3.0000000000042535, -1.0000000000021267, 0.9999999999971644]
[3.000000000002366, -1.0000000000015759, 0.9999999999981658]
[3.000000000015998, -1.0000000000105382, 0.9999999999894444]
[2.999999999989247, -1.0000000000048093, 0.9999999999960981]
[3.000000000000676, -0.9999999999831402, 1.0000000000194054]
[2.999999999990875, -1.000000000021526, 0.9999999999761493]
[3.0000000000242766, -1.0000000000216558, 0.9999999999840582]
[2.9999999999953153, -1.000000000002716, 1.0000000000095044]
[2.9999999999238147, -0.9999999999194701, 1.0000000000700444]
[3.0000000000412554, -1.0000000000403544, 0.9999999999770918]
Error.
Error.
Error.
Error.
Error.
Error.
Error.
Error.
Error.
Error.

sor.txtをgnuplotで棒グラフにして書いたものがこちら。収束しなかったものについては-1とした。

今回の場合、加速パラメータが1.1のとき反復回数が最も少ないことが分かる。
また、加速パラメータが2以上のときは発散していることが分かる。