From 9665cc4e73007ab2522ae7950dd023eb1a61e956 Mon Sep 17 00:00:00 2001 From: Marco Tezzele Date: Tue, 22 Mar 2016 19:58:45 +0100 Subject: [PATCH 1/2] rref moved outside affine and tests --- pygem/affine_trans.py | 79 ++++++++++++++++++++------------------ tests/test_affine_trans.py | 37 +++++++++++++++++- 2 files changed, 77 insertions(+), 39 deletions(-) diff --git a/pygem/affine_trans.py b/pygem/affine_trans.py index b2afb04..2574a64 100644 --- a/pygem/affine_trans.py +++ b/pygem/affine_trans.py @@ -44,6 +44,45 @@ def angles2matrix(rot_z=0, rot_y=0, rot_x=0): return np.eye(3) +def to_reduced_row_echelon_form(matrix): + """ + This method computes the reduced row echelon form (a.k.a. row canonical form) of a matrix. + The code is taken from https://rosettacode.org/wiki/Reduced_row_echelon_form#Python and + edited with minor changes. + + :param matrix matrix: matrix to be reduced. + + :return matrix: the reduced matrix. + :rtype: matrix + + .. note:: + `matrix` will change after calling this function. + """ + lead = 0 + row_count = len(matrix) + column_count = len(matrix[0]) + for r in range(row_count): + if lead >= column_count: + return matrix + i = r + while matrix[i][lead] == 0: + i += 1 + if i == row_count: + i = r + lead += 1 + if column_count == lead: + return matrix + matrix[i], matrix[r] = matrix[r], matrix[i] + lv = matrix[r][lead] + matrix[r] = [mrx / float(lv) for mrx in matrix[r]] + for i in range(row_count): + if i != r: + lv = matrix[i][lead] + matrix[i] = [iv - lv*rv for rv, iv in zip(matrix[r], matrix[i])] + lead += 1 + return matrix + + def affine_points_fit(points_start, points_end): """ Fit an affine transformation from starting points to ending points through a @@ -60,7 +99,7 @@ def affine_points_fit(points_start, points_end): :Example: >>> import pygem.affine_trans as at - + >>> # Example of a rotation >>> p_start = np.array([[1,0,0], [0,1,0], [0,0,1], [0,0,0]]) >>> p_end = np.array([[0,1,0], [-1,0,0], [0,0,1], [0,0,0]]) @@ -92,43 +131,7 @@ def affine_points_fit(points_start, points_end): Q[i][j] += qt[i] * qt[j] - def to_reduced_row_echelon_form(matrix): - """ - This method computes the reduced row echelon form (a.k.a. row canonical form) of a matrix. - The code is taken from https://rosettacode.org/wiki/Reduced_row_echelon_form#Python and - edited with minor changes. - - :param matrix matrix: matrix to be reduced. - - :return matrix: the reduced matrix. - :rtype: float - """ - lead = 0 - row_count = len(matrix) - column_count = len(matrix[0]) - for r in range(row_count): - if lead >= column_count: - return matrix - i = r - while matrix[i][lead] == 0: - i += 1 - if i == row_count: - i = r - lead += 1 - if column_count == lead: - return matrix - matrix[i], matrix[r] = matrix[r], matrix[i] - lv = matrix[r][lead] - matrix[r] = [mrx / float(lv) for mrx in matrix[r]] - for i in range(row_count): - if i != r: - lv = matrix[i][lead] - matrix[i] = [iv - lv*rv for rv, iv in zip(matrix[r], matrix[i])] - lead += 1 - return matrix - - - # Augement Q with c and solve Q * a' = c by Gauss-Jordan + # Augement Q with c and get the reduced row echelon form of the result M = [Q[i] + c[i] for i in range(dim+1)] if np.linalg.cond(M) < 1/sys.float_info.epsilon: diff --git a/tests/test_affine_trans.py b/tests/test_affine_trans.py index 157e470..bc7ea31 100644 --- a/tests/test_affine_trans.py +++ b/tests/test_affine_trans.py @@ -53,7 +53,42 @@ def test_angles2matrix_rot_xyz(self): mat_test = at.angles2matrix(rotz, roty, rotx) np.testing.assert_array_almost_equal(mat_exact, mat_test) - + + + def test_to_reduced_row_echelon_form_1(self): + matrix = [[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]] + rref_matrix = at.to_reduced_row_echelon_form(matrix) + rref_matrix_exact = [[1.0, 1.0, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] + assert rref_matrix == rref_matrix_exact + + + def test_to_reduced_row_echelon_form_2(self): + matrix = [[1., -1., 1.], [-1., 1., -1.], [3., 4., 5.]] + rref_matrix = at.to_reduced_row_echelon_form(matrix) + rref_matrix_exact = [[1.0, 0.0, 1.2857142857142856], [0.0, 1.0, 0.2857142857142857], [0.0, 0.0, 0.0]] + assert rref_matrix == rref_matrix_exact + + + def test_to_reduced_row_echelon_form_3(self): + matrix = [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]] + rref_matrix = at.to_reduced_row_echelon_form(matrix) + rref_matrix_exact = [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]] + assert rref_matrix == rref_matrix_exact + + + def test_to_reduced_row_echelon_form_4(self): + matrix = [[0., 0., 0.], [-3., 6., -3.], [0., 0., 0.]] + rref_matrix = at.to_reduced_row_echelon_form(matrix) + rref_matrix_exact = [[1.0, -2.0, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] + assert rref_matrix == rref_matrix_exact + + + def test_to_reduced_row_echelon_form_5(self): + matrix = [[0., 0., 0.], [0., 0., 0.], [2., 4., 6.]] + rref_matrix = at.to_reduced_row_echelon_form(matrix) + rref_matrix_exact = [[1.0, 2.0, 3.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] + assert rref_matrix == rref_matrix_exact + def test_affine_points_fit_identity_1(self): p_start = np.array([[1,0,0], [0,1,0], [0,0,1], [0,0,0]]) From 1ba65da972858dd5dd0fc078e93ce7e4eeb6b742 Mon Sep 17 00:00:00 2001 From: Marco Tezzele Date: Tue, 22 Mar 2016 20:17:34 +0100 Subject: [PATCH 2/2] 2 more tests --- tests/test_affine_trans.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_affine_trans.py b/tests/test_affine_trans.py index bc7ea31..d706534 100644 --- a/tests/test_affine_trans.py +++ b/tests/test_affine_trans.py @@ -89,6 +89,20 @@ def test_to_reduced_row_echelon_form_5(self): rref_matrix_exact = [[1.0, 2.0, 3.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] assert rref_matrix == rref_matrix_exact + + def test_to_reduced_row_echelon_form_6(self): + matrix = [[0., 0., 0.], [0., 0., 0.], [2., 4., 6.], [1., 0., 0.]] + rref_matrix = at.to_reduced_row_echelon_form(matrix) + rref_matrix_exact = [[1.0, 0.0, 0.0], [-0.0, 1.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] + assert rref_matrix == rref_matrix_exact + + + def test_to_reduced_row_echelon_form_7(self): + matrix = [[0., 0., 0., 4], [0., 0., -3., 2], [2., 4., 6., 0]] + rref_matrix = at.to_reduced_row_echelon_form(matrix) + rref_matrix_exact = [[1.0, 2.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]] + assert rref_matrix == rref_matrix_exact + def test_affine_points_fit_identity_1(self): p_start = np.array([[1,0,0], [0,1,0], [0,0,1], [0,0,0]])