def test_jacobi_method_01(self): b_verbose = 0 if b_verbose: print("test_jacobi_method_01") self.mat_lambda, self.mat_x = evp.jacobi_method(self.mat_h) if b_verbose: print("L =") matrix.show_mat(self.mat_lambda) print("X =") matrix.show_mat(self.mat_x) self.mat_x_transpose = matrix.transpose_mat(self.mat_x) self.mat_xt_h = matrix.mul_mat(self.mat_x_transpose, self.mat_h) self.mat_xt_h_x = matrix.mul_mat(self.mat_xt_h, self.mat_x) if b_verbose: print("XT A X") matrix.show_mat(self.mat_xt_h_x) n = len(self.mat_h) for i in range(n): for j in range(n): st = "XT A X [%d][%d] = %g" % (i, j, self.mat_xt_h_x[i][j], i, j, self.mat_lambda[i][j]) self.assertAlmostEqual(self.mat_xt_h_x[i][j], self.mat_lambda[i][j], msg=st)
def main(): mat_a = [[2.0, 1.0], [1.0, 3.0]] lambda1, vec_x1 = power_method(mat_a) print("lambda = %s" % lambda1) print("x = %s" % vec_x1) lambda2, mat_x = jacobi_method(mat_a) print("lambda = %s" % lambda2) print("x =") matrix.show_mat(mat_x) mat_a3 = [[8.0, 4.0, 2.0], [4.0, 8.0, 4.0], [2.0, 4.0, 8.0]] mat_l, mat_x = jacobi_method(mat_a3, b_verbose=True) print("L =") matrix.show.mat(mat_l) print("X =") matrix.show_mat(mat_x) mat_x_t = matrix.transpose_mat(mat_x) print("XT =") matrix.show_mat(mat_x_t) print("X XT =") matrix.show_mat(matrix.mul_mat(mat_x, mat_x_t)) print("XT A X = L") matrix.show_mat(matrix.mul_mat(matrix.mul_mat(mat_x_t, mat_a3), mat_x)) print("A = X L XT") matrix.show_mat(matrix.mul_mat(matrix.mul_mat(mat_x, mat_l), mat_x_t))
def test_jacobi_method(self): self.mat_a = [[-1.0, -0.5, -0.2], [-0.5, -2.0, -1.0], [-0.2, -1.0, -3.0]] lamda1, x1 = evp.jacobi_method(self.mat_a) self.assertEqual(len(self.mat_a), len(lamda1)) self.assertEqual(len(self.mat_a[0]), len(lamda1[0])) self.assertEqual(len(self.mat_a), len(x1)) self.assertEqual(len(self.mat_a), len(x1[0])) self.mat_a_x1 = matrix.mul_mat(self.mat_a, x1) # check A V = Lambda V for k_pivot in range(len(self.mat_a)): # diagonal term lambda_i = lamda1[k_pivot][k_pivot] # off diagonal for i_row in range(len(self.mat_a)): self.assertAlmostEqual(self.mat_a_x1[i_row][k_pivot], lambda_i * x1[i_row][k_pivot]) # check VT A V = Lambda self.mat_x1_t_a_x1 = matrix.mul_mat(zip(*x1), self.mat_a_x1) for i_row in range(0, len(self.mat_a) -1): # check diagonal self.assertAlmostEqual(self.mat_x1_t_a_x1[i_row][i_row], lamda1[i_row][i_row]) # check off-diagonal for j_column in range(i_row + 1, len(self.mat_a)): self.assertAlmostEqual(self.mat_x1_t_a_x1[i_row][j_column], 0.0)
def test_jacobi_method_03(self): b_verbose = False if b_verbose: print("test_jacobi_method_03") self.mat_lambda, self.mat_x = evp.jacobi_method(self.mat_h) if b_verbose: print("L =") matrix.mat_xt = matrix.transpose_mat(self.mat_x) print("X =") matrix.show_mat(self.mat_x) self.mat_xt = matrix.transpose_mat(self.mat_x) self.mat_x_labda = matrix.mul_mat(self.mat_x, self.mat_labda) self.mat_x_labda_xt = matrix.mul_mat(self.mat_x_labda, self.mat_xt) if b_verbose: print("X L XT") matrix.show_mat(self.mat_x_lambda_xt) n = len(self.mat_h) for i in range(n): for j in range(n): st = "X L XT[%d][%d] = %g vs A[%d][%d] = %g" % ( i, j, self.mat_x_labda_xt[i][j], i, j, self.mat_h[i][j]) self.assertAlmostEqual(self.mat_x_lambda_xt[i][j], self.mat_h[i][j], msg=st)
def test_jacobi_method(self): self.mat_a = [[-1.0, -0.5, -0.2], [-0.5, -2.0, -1.0], [-0.2, -1.0, -3.0]] lamda1, x1 = evp.jacobi_method(self.mat_a) self.assertEqul(len(self.mat_a), len(lamda1)) self.assertEqual(len(self.mat_a[0]), len(lamda1[0])) self.assertEqual(len(self.mat_a), len(x1)) self.mat_a_x1 = matrix.mul_mat(self.mat_a_x1) for k_pivot in range(len(self.mat_a)): lambda_i = lamda1[k_pivot][k_pivot] for i_row in range(len(self.mat_a)): self.assertAlmostEqual(self.mat_a_x[i_row][k_pivot], lambda_i * x1[i_row][k_pivot]) self.mat_x1_t_a_x1 = matrix.mul_mat(zip(*x1), self.mat_a_x1) for i_row in range(0, len(self.mat_a) - 1): self.assertAlmostEqual(self.mat_x1_t_a_x[i_row][i_row], lamda1[i_row][i_row]) for j_column in range(i_row * 1, len(self.mat_a)): self.assertAlmostEqual(self.mat_x1_t_a_x1[i_row][j_column], 0.0)
def general_eigenproblem_symetric(mat_a, mat_b): mat_l = cholesky_decomposition(mat_b) mat_l_t = zip(*mat_l) mat_l_inv = gj.gauss_jordan(mat_l) mat_l_t_inv = gj.gauss_jordan(mat_l_t) del mat_l[:], mat_l_t[:] del mat_l, mat_l_t mat_l_inv_a = matrix.mul_mat(mat_l_inv, mat_a) del mat_l_inv[:] del mat_l_inv mat_c = matrix.mul_mat(mat_l_inv_a, mat_l_t_inv) mat_w, mat_y = jacobi_method(mat_c) del mat_c[:] del mat_c vec_w = [row_vec_w[i] for i, row_vec_w in enumerate(mat_w)] del mat_w[:] del mat_w mat_z = matrix.mul_mat(mat_l_t_inv, mat_y) del mat_y[:] del mat_y return vec_w, mat_z
def general_eigenproblem_symmetric(mat_a, mat_b): """ Solve Az = lambda Bz using Cholesky decomposition Let B = L LT and z = LT**(-1)y then A LT**(-1)y = lambda L LT LT**(-1)y = lambda L y Mutiplying L**(-1) gives L**(-1) A LT**(-1)y = lambda L**(-1) L y = lambda y So let C = L**(-1) A LT**(-1) and find eigenvalues and eigenvectors of C. Later Z = LT**(-1) ref : Susan Blackford, Generalized Symmetric Definite Eigenproblems, 1999 Oct 01 (accessed 2015 Nov 30). :param mat_a: n * n matrix :param mat_b: n * n matrix :return: vec_w : 1 * n eigenvalue vector :return: mat_z : n * n eigenvector matrix """ mat_l = cholesky_decomposition(mat_b) mat_l_t = zip(*mat_l) mat_l_inv = gj.gauss_jordan(mat_l) mat_l_t_inv = gj.gauss_jodan(mat_l_t) del mat_l[:], mat_l_t[:] del mat_l, mat_l_t mat_l_inv_a = matrix.mul_mat(mat_l_inv, mat_a) del mat_l_inv[:] del mat_l_inv mat_c = matrix.mul_mat(mat_l_inv_a, mat_l_t_inv) mat_w, mat_y = jacobi_method(mat_c) del mat_c[:] del mat_c # diagonal elements vec_w = [row_vec_w[i] for i, row_vec_w in enumerate(mat_w)] del mat_w[:] del mat_w mat_z = matrix.mul_mat(mat_l_t_inv, mat_y) del mat_y[:] del mat_y return vec_w, mat_z
def general_eigenproblem_symmetric(mat_a, mat_b): ''' Sove Az = lambda Bz using Cholesky decomposition Let B = L LT and z = Lt**(-1)y than A LT**(-1)y = lambda L LT LT**(-1)y = lambda L y Mutipiying L**(-1) gives L**(-1) A LT**(-1)y = lambda L**(-1) L y = lambda y so let C - L **(-1) A LT**(-1) and find gigenvalues and eigenvectors of C. Later Z = LT**(-1)Y ref : http://www.netlib.org/lapck/lug/node54.html :param mat_a: n x n matrix :param mat_b: n x n matrix :return: vec_w: 1 x n eigenvalue vector :return: mat_z: n x n eigenvector matrix ''' mat_l = cholesky_decomposition(mat_b) mat_l_t = zip(*mat_l) mat_l_inv = gj.gauss_jordan(mat_l) mat_l_t_inv = gj.gauss_jordan(mat_l_t) del mat_l[:], mat_l_t[:] del mat_l, mat_l_t mat_l_inv_a = matrix.mul_mat(mat_l_inv, mat_a) del mat_l_inv[:] del mat_l_inv mat_c = matrix.mul_mat(mat_l_inv_a, mat_l_t_inv) mat_w, mat_y = jacobi_method(mat_c) del mat_c[:] del mat_c vec_w = [row_vec_w[i] for i, row_vec_w in enumerate(mat_w)] del mat_w[:] del mat_w mat_z = matrix.mul_mat(mat_l_t_inv, mat_y) del mat_y[:] del mat_y return vec_w, mat_z
def get_left_inverse(mat_x): ''' :param mat_x: List[List[float]] :return: List[List[float]] ''' # 예를 들어 deta point의 갯수를 n # 매개변수의 갯수를 n이라 할때 mat_x_t = matrix.transpose_mat(mat_x) mat_xt_x = matrix.mul_mat(mat_x_t, mat_x) mat_xt_x_inv = gj.gauss_jordan(mat_xt_x) mat_x_left_inverse = matrix.mul_mat(mat_xt_x_inv, mat_x_t) return mat_x_left_inverse
def get_left_inverse(mat_x): """ :param mat_x: List[List[float]] :return: List[List[float]] """ # 예를 들어 data point 의 갯수를 n, # 매개변수의 갯수를 m 이라 할 때 mat_x_t = matrix.transpose_mat(mat_x) #Q : 이 행렬의 크기는? mat_xt_x = matrix.mul_mat(mat_x_t, mat_x) #Q : 이 행렬의 크기는? mat_xt_x_inv = gj.gauss_jordan(mat_xt_x) #Q : 이 행렬의 크기는? mat_x_left_inverse = matrix.mul_mat(mat_xt_x_inv, mat_x_t) #Q : 이 행렬의 크기는? return mat_x_left_inverse
def mul_left_inverse(mat_x, mat_y): mat_x_left_inverse = get_left_inverse(mat_x) mat_w_estimated = matrix.mul_mat(mat_x_left_inverse, mat_y) del mat_x_left_inverse[:] del mat_x_left_inverse return mat_w_estimated
def test_power_method_01(self): b_verbose = False if b_verbose: print ("Power method 01") for n in range(3, 10): self.mat_a_half = matrix.get_random_mat(n, n) self.mat_a_half_transpose = matrix.transpose_mat(self.mat_a_half) self.mat_a = matrix.mul_mat(self.mat_a_half_transpose, self.mat_a_half) lam, vec_x0 = evp.power_method(self.mat_a, espilon=1e-12) if b_verbose: print ('%s %s' % (lam, vec_x0)) vec_x1 = matrix.mul_mat_vec(self.mat_a, vec_x0) vec_x0l = [lam * x0k for x0k in vec_x0] self.assertEqual(len(vec_x0), n) message = ''' x0 = %s mat_a x0 = %s ''' % (vec_x0, vec_x0l) self.assertSequenceAlmostEqual(vec_x0l, vec_x1, msg=me)
def test_cholesky_decomposition_00(self): self.mat_a = [[ 16.0, 12.0, 4.0, ], [ 12.0, 34.0, 13.0, ][4.0, 13.0, 41.0, ]] self.mat_l_exp = [ [4, 0, 0], [3, 5, 0], [1, 2, 6], ] self.mat_l = evp.cholesky_decomposition(self.mat_a) self.mat_a_exp = matrix.mul_mat(self.mat_l, zip(*self.mat_l)) # sheck size self.asserEqual(len(self.mat_a), len(self.mat_l)) # sheck row for i_row in range(0, len(self.mat_a)): self.assertEqual(len(self.mat_a), len(self.mat_l[i_row])) for j_column in range(0, len(self.mat_a)): self.aseertAlmostEqual(self.mat_a[i_row][j_column], self.mat_a_exp[i_row][j_column]) self.assertAlmostEqual(self.mat_l_exp[i_row][j_column], self.mat_l[i_row][j_column])
def test_gauss_jordan_00(self): for n in range(3, 10): mat_a = m.get_random_mat(n, n) mat_a_inv = gj.gauss_jordan(mat_a) mat_b = m.mul_mat(mat_a, mat_a_inv) for i in range(n): vec_exp = [0.0] * n vec_exp[i] = 1.0 vec_res = mat_b[i] self.assertSequenceAlmostEqual(vec_exp, vec_res) del vec_exp del mat_b[:] del mat_b del mat_a_inv[:] del mat_a_inv del mat_a[:] del mat_a
def test_cholesky_decomposition_01(self): self.mat_l_exp = [[10.0, 0.0, 0.0, 0.0], [4.0, 9.0, 0.0, 0.0], [3.0, 5.0, 8.0, 0.0], [1.0, 2.0, 6.0, 7.0]] self.mat_a = matrix.mul_mat(self.mat_l_exp, zip(*self.mat_l_exp)) self.mat_a_exp = matrix.mul_mat(self.mat_a) self.mat_a_exp = matrix.mul_mat(self.mat_l, zip(*self.mat_l)) # check size self.assertEqual(len(self.mat_a), len(self.mat_l)) # check row for i_row in range(0, len(self.mat_a)): self.assertEqual(len(self.mat_a), len(self.mat_l[i_row])) for j_column in range(0, len(self.mat_a)): self.assertAlmostEqual(self.mat_a[i_row][j_column], self.mat_a_exp[i_row][j_column]) self.assertAlmostEqual(self.mat_l_exp[i_row][j_column], self.mat_l[i_row][j_column])
def mul_left_inverse(mat_x, mat_y): """ 행렬 x의 좌 역행렬 Left inverse Matrix를 찾아서 y행렬과 곱함 예를 들어 X의 행의 갯수는 deta point 갯수와 같고, X의 열의 갯수는 추정하고자 하는 매개변수의 수와 같다. :param mat_x: List[List[float]] :param mat_y: List[List[float]] :return: List[List[float]] """ mat_x_left_inverse = get_left_inverse(mat_x) mat_w_estimated = matrix.mul_mat(mat_x_left_inverse, mat_y) del mat_x_left_inverse[:] del mat_x_left_inverse return mat_w_estimated
matrix.row_mul_add(mat_ai, j_row, i_pivot, -mat_ai[j_row][i_pivot]) inv_mat = matrix.alloc_mat( len(mat_ai), len(mat_ai), ) for i in range(len(mat_ai)): for j in range(len(mat_ai)): inv_mat[i][j] = mat_ai[i][len(mat_ai) + j] del mat_ai[:] del mat_ai return inv_mat # Q : 필요한 memory를 더 절약할 수 잇는 방법이 있을 것인가? if "__main__" == __name__: A = [[3, 2, 1], [2, 3, 2], [1, 2, 3]] A_inverse = gauss_jordan(A) print("A inverse") matrix.show_mat(A_inverse) I_expected = matrix.mul_mat(A, A_inverse) print("I expected") matrix.show_mat(I_expected)
def get_left_inverse(mat_x): mat_x_t = matrix.transpose_mat(mat_x) mat_xt_x = matrix.mul_mat(mat_x_t, mat_x) mat_xt_x_inv = gj.gauss_jordan(mat_xt_x) mat_x_left_inverse = matrix.mul_mat(mat_xt_x_inv, mat_x_t) return mat_x_left_inverse
def test_mul_mat02(self): self.mat_r = m.mul_mat(self.mat_i, self.mat_a) self.assertSequenceEqual(self.mat_r, self.mat_a)
def test_adj01(self): self.mat_r = m.adjugate_matrix(self.mat_d) d = m.det(self.mat_d) self.mat_exp = [[d, 0, 0], [0, d, 0], [0, 0, d]] self.assertEqual(m.mul_mat(self.mat_r, self.mat_d), self.mat_exp) self.assertEqual(m.mul_mat(self.mat_d, self.mat_r), self.mat_exp)