from copy import deepcopy
from positive_definite_system import positive_definite_system
from utilities import mat_mult, mat_minus

def additional_algorithm(verbose, a, rhs, scaling_limit, lam_iters, mat_iters):
	a_copy, rhs_copy = deepcopy(a), deepcopy(rhs)
	sol1 = positive_definite_system(verbose, a, rhs, scaling_limit, lam_iters, mat_iters)
	rhs_arr = [[el] for el in rhs_copy]
	sol1_arr = [[el] for el in sol1]
	res_arr = mat_mult(a_copy, sol1_arr)
	res_arr = mat_minus(rhs_arr, res_arr)
	res = [el[0] for el in res_arr]

	a_copy2, res_copy = deepcopy(a_copy), deepcopy(res)
	sol2 = positive_definite_system(verbose, a_copy, res, scaling_limit, lam_iters, mat_iters)
	rhs_arr = [[el] for el in res_copy]
	sol2_arr = [[el] for el in sol2]
	res_arr = mat_mult(a_copy2, sol2_arr)
	res_arr = mat_minus(rhs_arr, res_arr)
	res = [el[0] for el in res_arr]

	sol3 = positive_definite_system(verbose, a_copy2, res, scaling_limit, lam_iters, mat_iters)

	for i in range(len(a)):
		sol3[i] += sol1[i] + sol2[i]

	return sol3
	
if __name__ == "__main__":
	import sys
	a, rhs = [[3.0, 3.0, 5.0], [3.0, 5.0, 9.0], [5.0, 9.0, 17.0]], [24.0, 40.0, 74.0]
	x = [1.0, 2.0, 3.0]
	lam_iters, mat_iters, scaling_limit = 30, 25, 10
	verbose = False
	sol = additional_algorithm(verbose, a, rhs, scaling_limit, lam_iters, mat_iters)
	print('\n')
	for i in range(len(a)):
		print('x{0:d} = {1:7.4f} (exact {2:7.4f})'.format((i + 1), sol[i], x[i]))

# Typical results:
#
# x1 =  1.0009 (exact  1.0000)
# x2 =  1.9964 (exact  2.0000)
# x3 =  3.0017 (exact  3.0000)