From e57a070beb5df65fd20c6ffa29db16970be58750 Mon Sep 17 00:00:00 2001 From: Zeyad Zaky Date: Mon, 6 Jul 2020 23:28:13 -0700 Subject: [PATCH 1/9] Initial commit of power iteration. --- linear_algebra/src/power_iteration.py | 104 ++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 linear_algebra/src/power_iteration.py diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py new file mode 100644 index 000000000000..86520da4caa4 --- /dev/null +++ b/linear_algebra/src/power_iteration.py @@ -0,0 +1,104 @@ +import numpy as np + +def rayleigh_quotient(input_matrix: np.array, vector: np.array): + + num = np.dot(vector.T, np.dot(input_matrix, vector)) + den = np.dot(vector.T,vector) + + return num/den + +def power_iteration(input_matrix: np.array,vector: np.array, + error_tol = 1e-12, max_iterations=100) -> [float, np.array]: + + """ + Input + input_matrix: input matrix whose largest eigenvalue we will find. + Numpy array. np.shape(matrix) == (N,N). + vector: random initial vector in same space as matrix. + Numpy array. np.shape(init_vector) == (N,) or (N,1) + + Output + largest_eigenvalue: largest eigenvalue of the matrix input_matrix. + Float. Scalar. + largest_eigenvector: eigenvector corresponding to largest_eigenvalue. + Numpy array. np.shape(largest_eigenvector) == (N,) or (N,1). + """ + + #Ensure matrix is square. + assert(np.shape(input_matrix)[0] == np.shape(input_matrix)[1]) + #Ensure proper dimensionality. + assert(np.shape(input_matrix)[0] == np.shape(vector)[0]) + + #Set convergence to False. Will define convergence when we exceed max_iterations + # or when we have small changes from one iteration to next. + + convergence = False + lamda_previous = 0 + iterations = 0 + error = 1e12 + + while (convergence == False): + w = np.dot(input_matrix,vector) + vector = w / np.linalg.norm(w) + lamda = np.dot(vector.T, np.dot(input_matrix, vector)) + + #Check convergence. + error = np.abs(lamda - lamda_previous)/lamda + iterations += 1 + + if (error <= error_tol or iterations >= max_iterations): + convergence = True + + lamda_previous = lamda + + + return lamda, vector + + +if __name__ == "__main__": + # Perform a test of power iteration by comparing to built in numpy.linalg.eigh + + # Example + np.random.seed(100) + #Set dimension of space + n = 10 + + #Create random matrix in space R^{nxn} + A = np.random.rand(n,n) + #Ensure matrix A is Symmetric + A = np.dot(A.T,A) + #Create random vector in space R^n + v = np.random.rand(n) + + # Find eigenvalues using python built in library. + # https://numpy.org/doc/stable/reference/generated/numpy.linalg.eigh.html + # The function will return eignevalues in ascending order and eigenvectors correspondingly. + # The last element is the largest eigenvalue and eigenvector index. + eigenvalues, eigenvectors = np.linalg.eigh(A) + largest_eigenvalue = eigenvalues[-1] + largest_eigenvector = eigenvectors[:,-1] + + print('#########################################################') + print('From Numpy built in library.') + print(f'Largest Eigenvalue: {largest_eigenvalue}') + print(f'Largest Eigenvector: {largest_eigenvector}') + # Now try our own code + largest_eigenvalue_power, largest_eigenvector_power = power_iteration(A,v) + print('#########################################################') + print('From Power Iteration we wrote.') + print(f'Largest Eigenvalue: {largest_eigenvalue_power}') + print(f'Largest Eigenvector: {largest_eigenvector_power}') + + abs_error = np.abs(largest_eigenvalue - largest_eigenvalue_power) + rel_error = abs_error/largest_eigenvalue + print('#########################################################') + print('Eigenvalue Error Between Numpy and our implementation.') + print(f'Absolute Error: {abs_error}') + print(f'Relative Error: {rel_error}') + + abs_error = np.linalg.norm(largest_eigenvector-largest_eigenvector_power) + cos_error = np.arccos(np.dot(largest_eigenvector,largest_eigenvector_power)) + print('#########################################################') + print('Eigenvector Error Between Numpy and our implementation.') + print(f'Absolute norm difference: {abs_error}') + print(f'Cosign error between eigenvectors: {cos_error}') From 2cdf247091378753b2147fdc7d8002933ca12108 Mon Sep 17 00:00:00 2001 From: Zeyad Zaky Date: Wed, 8 Jul 2020 21:36:36 -0700 Subject: [PATCH 2/9] Added more documentation for power iteration and rayleigh quotient --- linear_algebra/src/power_iteration.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 86520da4caa4..ec940ccfa519 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -2,6 +2,18 @@ def rayleigh_quotient(input_matrix: np.array, vector: np.array): + """ + Rayleigh Quotient. + Fine the Rayliegh quotient of matrix and vector. Given an eigenvector, + the Rayleigh quotient is the corresponding eigenvalue. + + Input + input_matrix: input matrix. + Numpy array. np.shape(input_matrix) == (N,N). + vector: input vector. + Numpy array. np.shape(vector) == (N,) or (N,1) + """ + num = np.dot(vector.T, np.dot(input_matrix, vector)) den = np.dot(vector.T,vector) @@ -11,11 +23,17 @@ def power_iteration(input_matrix: np.array,vector: np.array, error_tol = 1e-12, max_iterations=100) -> [float, np.array]: """ + Power Iteration. + Find the largest eignevalue and corresponding eigenvector + of matrix input_matrix given a random vector in the same space. + Will work so long as vector has component of largest eigenvector. + input_matrix must be symmetric. + Input input_matrix: input matrix whose largest eigenvalue we will find. - Numpy array. np.shape(matrix) == (N,N). + Numpy array. np.shape(input_matrix) == (N,N). vector: random initial vector in same space as matrix. - Numpy array. np.shape(init_vector) == (N,) or (N,1) + Numpy array. np.shape(vector) == (N,) or (N,1) Output largest_eigenvalue: largest eigenvalue of the matrix input_matrix. From a639db8467bf0e46909b813712d359fb939364cb Mon Sep 17 00:00:00 2001 From: Zeyad Zaky Date: Wed, 8 Jul 2020 21:38:21 -0700 Subject: [PATCH 3/9] Type hinting for rayleigh quotient --- linear_algebra/src/power_iteration.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index ec940ccfa519..ff2e51df4455 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -1,11 +1,11 @@ import numpy as np -def rayleigh_quotient(input_matrix: np.array, vector: np.array): +def rayleigh_quotient(input_matrix: np.array, vector: np.array) -> float: """ Rayleigh Quotient. Fine the Rayliegh quotient of matrix and vector. Given an eigenvector, - the Rayleigh quotient is the corresponding eigenvalue. + the Rayleigh quotient is the corresponding eigenvalue. Input input_matrix: input matrix. From 3600b3b772ef24627dd1d7cb7f4dac7e5c11794f Mon Sep 17 00:00:00 2001 From: Zeyad Zaky Date: Sun, 12 Jul 2020 10:47:07 -0700 Subject: [PATCH 4/9] Changes after running black and flake8. --- linear_algebra/src/power_iteration.py | 93 ++++++++++++++------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index ff2e51df4455..0852ab118789 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -1,5 +1,6 @@ import numpy as np + def rayleigh_quotient(input_matrix: np.array, vector: np.array) -> float: """ @@ -15,12 +16,14 @@ def rayleigh_quotient(input_matrix: np.array, vector: np.array) -> float: """ num = np.dot(vector.T, np.dot(input_matrix, vector)) - den = np.dot(vector.T,vector) + den = np.dot(vector.T, vector) + + return num / den - return num/den -def power_iteration(input_matrix: np.array,vector: np.array, - error_tol = 1e-12, max_iterations=100) -> [float, np.array]: +def power_iteration( + input_matrix: np.array, vector: np.array, error_tol=1e-12, max_iterations=100 +) -> [float, np.array]: """ Power Iteration. @@ -42,12 +45,12 @@ def power_iteration(input_matrix: np.array,vector: np.array, Numpy array. np.shape(largest_eigenvector) == (N,) or (N,1). """ - #Ensure matrix is square. - assert(np.shape(input_matrix)[0] == np.shape(input_matrix)[1]) - #Ensure proper dimensionality. - assert(np.shape(input_matrix)[0] == np.shape(vector)[0]) + # Ensure matrix is square. + assert np.shape(input_matrix)[0] == np.shape(input_matrix)[1] + # Ensure proper dimensionality. + assert np.shape(input_matrix)[0] == np.shape(vector)[0] - #Set convergence to False. Will define convergence when we exceed max_iterations + # Set convergence to False. Will define convergence when we exceed max_iterations # or when we have small changes from one iteration to next. convergence = False @@ -55,21 +58,20 @@ def power_iteration(input_matrix: np.array,vector: np.array, iterations = 0 error = 1e12 - while (convergence == False): - w = np.dot(input_matrix,vector) + while convergence is False: + w = np.dot(input_matrix, vector) vector = w / np.linalg.norm(w) lamda = np.dot(vector.T, np.dot(input_matrix, vector)) - #Check convergence. - error = np.abs(lamda - lamda_previous)/lamda + # Check convergence. + error = np.abs(lamda - lamda_previous) / lamda iterations += 1 - if (error <= error_tol or iterations >= max_iterations): + if error <= error_tol or iterations >= max_iterations: convergence = True lamda_previous = lamda - return lamda, vector @@ -78,45 +80,46 @@ def power_iteration(input_matrix: np.array,vector: np.array, # Example np.random.seed(100) - #Set dimension of space + # Set dimension of space n = 10 - #Create random matrix in space R^{nxn} - A = np.random.rand(n,n) - #Ensure matrix A is Symmetric - A = np.dot(A.T,A) - #Create random vector in space R^n + # Create random matrix in space R^{nxn} + A = np.random.rand(n, n) + # Ensure matrix A is Symmetric + A = np.dot(A.T, A) + # Create random vector in space R^n v = np.random.rand(n) # Find eigenvalues using python built in library. # https://numpy.org/doc/stable/reference/generated/numpy.linalg.eigh.html - # The function will return eignevalues in ascending order and eigenvectors correspondingly. + # The function will return eignevalues in ascending order and eigenvectors + # correspondingly. # The last element is the largest eigenvalue and eigenvector index. - eigenvalues, eigenvectors = np.linalg.eigh(A) + eigenvalues, eigenvectors = np.linalg.eigh(A) largest_eigenvalue = eigenvalues[-1] - largest_eigenvector = eigenvectors[:,-1] + largest_eigenvector = eigenvectors[:, -1] - print('#########################################################') - print('From Numpy built in library.') - print(f'Largest Eigenvalue: {largest_eigenvalue}') - print(f'Largest Eigenvector: {largest_eigenvector}') + print("#########################################################") + print("From Numpy built in library.") + print(f"Largest Eigenvalue: {largest_eigenvalue}") + print(f"Largest Eigenvector: {largest_eigenvector}") # Now try our own code - largest_eigenvalue_power, largest_eigenvector_power = power_iteration(A,v) - print('#########################################################') - print('From Power Iteration we wrote.') - print(f'Largest Eigenvalue: {largest_eigenvalue_power}') - print(f'Largest Eigenvector: {largest_eigenvector_power}') + largest_eigenvalue_power, largest_eigenvector_power = power_iteration(A, v) + print("#########################################################") + print("From Power Iteration we wrote.") + print(f"Largest Eigenvalue: {largest_eigenvalue_power}") + print(f"Largest Eigenvector: {largest_eigenvector_power}") abs_error = np.abs(largest_eigenvalue - largest_eigenvalue_power) - rel_error = abs_error/largest_eigenvalue - print('#########################################################') - print('Eigenvalue Error Between Numpy and our implementation.') - print(f'Absolute Error: {abs_error}') - print(f'Relative Error: {rel_error}') - - abs_error = np.linalg.norm(largest_eigenvector-largest_eigenvector_power) - cos_error = np.arccos(np.dot(largest_eigenvector,largest_eigenvector_power)) - print('#########################################################') - print('Eigenvector Error Between Numpy and our implementation.') - print(f'Absolute norm difference: {abs_error}') - print(f'Cosign error between eigenvectors: {cos_error}') + rel_error = abs_error / largest_eigenvalue + print("#########################################################") + print("Eigenvalue Error Between Numpy and our implementation.") + print(f"Absolute Error: {abs_error}") + print(f"Relative Error: {rel_error}") + + abs_error = np.linalg.norm(largest_eigenvector - largest_eigenvector_power) + cos_error = np.arccos(np.dot(largest_eigenvector, largest_eigenvector_power)) + print("#########################################################") + print("Eigenvector Error Between Numpy and our implementation.") + print(f"Absolute norm difference: {abs_error}") + print(f"Cosign error between eigenvectors: {cos_error}") From 01dd967bc61b5110b1126083ec95c8ddc2bdb201 Mon Sep 17 00:00:00 2001 From: Zeyad Zaky Date: Fri, 24 Jul 2020 22:19:00 -0700 Subject: [PATCH 5/9] Added doctests, added unit tests. Removed Rayleigh quotient as it is not needed. --- linear_algebra/src/power_iteration.py | 105 ++++++++++---------------- 1 file changed, 38 insertions(+), 67 deletions(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 0852ab118789..2f12caaa1e4c 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -1,26 +1,6 @@ import numpy as np -def rayleigh_quotient(input_matrix: np.array, vector: np.array) -> float: - - """ - Rayleigh Quotient. - Fine the Rayliegh quotient of matrix and vector. Given an eigenvector, - the Rayleigh quotient is the corresponding eigenvalue. - - Input - input_matrix: input matrix. - Numpy array. np.shape(input_matrix) == (N,N). - vector: input vector. - Numpy array. np.shape(vector) == (N,) or (N,1) - """ - - num = np.dot(vector.T, np.dot(input_matrix, vector)) - den = np.dot(vector.T, vector) - - return num / den - - def power_iteration( input_matrix: np.array, vector: np.array, error_tol=1e-12, max_iterations=100 ) -> [float, np.array]: @@ -43,6 +23,16 @@ def power_iteration( Float. Scalar. largest_eigenvector: eigenvector corresponding to largest_eigenvalue. Numpy array. np.shape(largest_eigenvector) == (N,) or (N,1). + + >>> import numpy as np + >>> A = np.array([ + ... [41, 4, 20], + ... [ 4, 26, 30], + ... [20, 30, 50] + ... ]) + >>> v = np.array([41,4,20]) + >>> power_iteration(A,v) + (79.66086378788381, array([0.44472726, 0.46209842, 0.76725662])) """ # Ensure matrix is square. @@ -59,8 +49,13 @@ def power_iteration( error = 1e12 while convergence is False: + + # Multiple matrix by the vector. w = np.dot(input_matrix, vector) + # Normalize the resulting output vector. vector = w / np.linalg.norm(w) + # Find rayleigh quotient + # (faster than usual b/c we know vector is normalized already) lamda = np.dot(vector.T, np.dot(input_matrix, vector)) # Check convergence. @@ -75,51 +70,27 @@ def power_iteration( return lamda, vector +def tests() -> None: + + # Our implementation. + A = np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]) + v = np.array([41, 4, 20]) + eigen_value, eigen_vector = power_iteration(A, v) + + # Numpy implementation. + eigs, eigvs = np.linalg.eigh(A) + eig_max = eigs[-1] + eigv_max = eigvs[:, -1] + + # Check our implementation and numpy gives close answers. + assert np.abs(eigen_value - eig_max) <= 1e-6 + # Take absolute values element wise of each eigenvector + # as they are only unique to a minus sign. + assert np.linalg.norm(np.abs(eigen_vector) - np.abs(eigv_max)) <= 1e-6 + + if __name__ == "__main__": - # Perform a test of power iteration by comparing to built in numpy.linalg.eigh - - # Example - np.random.seed(100) - # Set dimension of space - n = 10 - - # Create random matrix in space R^{nxn} - A = np.random.rand(n, n) - # Ensure matrix A is Symmetric - A = np.dot(A.T, A) - # Create random vector in space R^n - v = np.random.rand(n) - - # Find eigenvalues using python built in library. - # https://numpy.org/doc/stable/reference/generated/numpy.linalg.eigh.html - # The function will return eignevalues in ascending order and eigenvectors - # correspondingly. - # The last element is the largest eigenvalue and eigenvector index. - eigenvalues, eigenvectors = np.linalg.eigh(A) - largest_eigenvalue = eigenvalues[-1] - largest_eigenvector = eigenvectors[:, -1] - - print("#########################################################") - print("From Numpy built in library.") - print(f"Largest Eigenvalue: {largest_eigenvalue}") - print(f"Largest Eigenvector: {largest_eigenvector}") - # Now try our own code - largest_eigenvalue_power, largest_eigenvector_power = power_iteration(A, v) - print("#########################################################") - print("From Power Iteration we wrote.") - print(f"Largest Eigenvalue: {largest_eigenvalue_power}") - print(f"Largest Eigenvector: {largest_eigenvector_power}") - - abs_error = np.abs(largest_eigenvalue - largest_eigenvalue_power) - rel_error = abs_error / largest_eigenvalue - print("#########################################################") - print("Eigenvalue Error Between Numpy and our implementation.") - print(f"Absolute Error: {abs_error}") - print(f"Relative Error: {rel_error}") - - abs_error = np.linalg.norm(largest_eigenvector - largest_eigenvector_power) - cos_error = np.arccos(np.dot(largest_eigenvector, largest_eigenvector_power)) - print("#########################################################") - print("Eigenvector Error Between Numpy and our implementation.") - print(f"Absolute norm difference: {abs_error}") - print(f"Cosign error between eigenvectors: {cos_error}") + import doctest + + doctest.testmod() + tests() From f0e0ac02238fe4d6289b3713dc6a1dac443dfe80 Mon Sep 17 00:00:00 2001 From: zakademic <67771932+zakademic@users.noreply.github.com> Date: Sat, 25 Jul 2020 11:16:48 -0700 Subject: [PATCH 6/9] Update linear_algebra/src/power_iteration.py Changed convergence check line. Co-authored-by: Christian Clauss --- linear_algebra/src/power_iteration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 2f12caaa1e4c..c772a99d6b24 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -48,7 +48,7 @@ def power_iteration( iterations = 0 error = 1e12 - while convergence is False: + while not convergence: # Multiple matrix by the vector. w = np.dot(input_matrix, vector) From 2367a83814ccfebce05355139d9cf1972099da92 Mon Sep 17 00:00:00 2001 From: zakademic <67771932+zakademic@users.noreply.github.com> Date: Sat, 25 Jul 2020 22:34:44 -0700 Subject: [PATCH 7/9] Update linear_algebra/src/power_iteration.py Named tests more clearly. Co-authored-by: Christian Clauss --- linear_algebra/src/power_iteration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index c772a99d6b24..d15e0a75d814 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -70,7 +70,7 @@ def power_iteration( return lamda, vector -def tests() -> None: +def test_power_iteration() -> None: # Our implementation. A = np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]) From cd42d3d92ca7ae674d6fd5d25cbbf31318251097 Mon Sep 17 00:00:00 2001 From: Zeyad Zaky Date: Sat, 25 Jul 2020 22:41:31 -0700 Subject: [PATCH 8/9] Changed naming in test function to be more clear. Changed naming in doctests to match function call. --- linear_algebra/src/power_iteration.py | 35 +++++++++++++++------------ 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 2f12caaa1e4c..5f789b5df238 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -25,13 +25,13 @@ def power_iteration( Numpy array. np.shape(largest_eigenvector) == (N,) or (N,1). >>> import numpy as np - >>> A = np.array([ + >>> input_matrix = np.array([ ... [41, 4, 20], ... [ 4, 26, 30], ... [20, 30, 50] ... ]) - >>> v = np.array([41,4,20]) - >>> power_iteration(A,v) + >>> vector = np.array([41,4,20]) + >>> power_iteration(input_matrix,vector) (79.66086378788381, array([0.44472726, 0.46209842, 0.76725662])) """ @@ -48,7 +48,7 @@ def power_iteration( iterations = 0 error = 1e12 - while convergence is False: + while not convergence: # Multiple matrix by the vector. w = np.dot(input_matrix, vector) @@ -70,27 +70,32 @@ def power_iteration( return lamda, vector -def tests() -> None: +def test_power_iteration() -> None: # Our implementation. - A = np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]) - v = np.array([41, 4, 20]) - eigen_value, eigen_vector = power_iteration(A, v) + input_matrix = np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]) + vector = np.array([41, 4, 20]) + eigen_value, eigen_vector = power_iteration(input_matrix, vector) # Numpy implementation. - eigs, eigvs = np.linalg.eigh(A) - eig_max = eigs[-1] - eigv_max = eigvs[:, -1] + + # Get eigen values and eigen vectors using built in numpy + # eigh (eigh used for symmetric or hermetian matrices). + eigen_values, eigen_vectors = np.linalg.eigh(input_matrix) + # Last eigen value is the maximum one. + eigen_value_max = eigen_values[-1] + # Last column in this matrix is eigen vector corresponding to largest eigen value. + eigen_vector_max = eigen_vectors[:, -1] # Check our implementation and numpy gives close answers. - assert np.abs(eigen_value - eig_max) <= 1e-6 - # Take absolute values element wise of each eigenvector + assert np.abs(eigen_value - eigen_value_max) <= 1e-6 + # Take absolute values element wise of each eigenvector. # as they are only unique to a minus sign. - assert np.linalg.norm(np.abs(eigen_vector) - np.abs(eigv_max)) <= 1e-6 + assert np.linalg.norm(np.abs(eigen_vector) - np.abs(eigen_vector_max)) <= 1e-6 if __name__ == "__main__": import doctest doctest.testmod() - tests() + test_power_iteration() From e2a66919e5a247c0fb1aff0261e91581067927b2 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 26 Jul 2020 10:42:35 +0200 Subject: [PATCH 9/9] Self running tests --- linear_algebra/src/power_iteration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 5f789b5df238..476361e0d433 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -4,7 +4,6 @@ def power_iteration( input_matrix: np.array, vector: np.array, error_tol=1e-12, max_iterations=100 ) -> [float, np.array]: - """ Power Iteration. Find the largest eignevalue and corresponding eigenvector @@ -49,7 +48,6 @@ def power_iteration( error = 1e12 while not convergence: - # Multiple matrix by the vector. w = np.dot(input_matrix, vector) # Normalize the resulting output vector. @@ -71,7 +69,9 @@ def power_iteration( def test_power_iteration() -> None: - + """ + >>> test_power_iteration() # self running tests + """ # Our implementation. input_matrix = np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]) vector = np.array([41, 4, 20])