From bcbb359ae0d7370b884936188a95b9cd33b076d9 Mon Sep 17 00:00:00 2001 From: BH4 Date: Fri, 16 Oct 2020 15:16:26 -0700 Subject: [PATCH 1/3] Add Rayleigh quotient iteration algorithm This algorithm is similar to power iteration but is able to find any eigenvalue instead of just the largest eigenvalue. --- .../src/rayleigh_quotient_iteration.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 linear_algebra/src/rayleigh_quotient_iteration.py diff --git a/linear_algebra/src/rayleigh_quotient_iteration.py b/linear_algebra/src/rayleigh_quotient_iteration.py new file mode 100644 index 000000000000..5242f4414b90 --- /dev/null +++ b/linear_algebra/src/rayleigh_quotient_iteration.py @@ -0,0 +1,50 @@ +import numpy as np +from typing import Tuple + + +def rayleigh_quotient_iteration( + input_matrix: np.array, vector: np.array, value: float, + error_tol=1e-12, max_iterations=100) -> Tuple[float, np.array]: + """ + https://en.wikipedia.org/wiki/Rayleigh_quotient_iteration + + Rayleigh quotient iteration + Find an approximate eigenvector and eigenvalue of the input matrix. Which + eigenvalue, eigenvector pair is found depends on the vector and value + input. Has very rapid convergence. + + >>> import numpy as np + >>> input_matrix = np.array([ + ... [41, 4, 20], + ... [ 4, 26, 30], + ... [20, 30, 50] + ... ]) + >>> vector = np.array([1, 1, 1]) + >>> value = 30 + >>> rayleigh_quotient_iteration(input_matrix, vector, value) + (33.60344292195729, array([-0.86306005, 0.45012643, 0.22915836])) + >>> value = 1 + >>> rayleigh_quotient_iteration(input_matrix, vector, value) + (3.735693290153355, array([-0.23946876, -0.7641015 , 0.59900218])) + """ + + N = len(input_matrix) + + error = error_tol + 1 + prev_eigenvalue = value + while error > error_tol: + # Construct the iterating matrix + A = np.linalg.inv(input_matrix - np.eye(N) * value) + # Construct new eigenvector + vector = np.dot(A, vector) + # Normalize new eigenvector + vector = vector / np.linalg.norm(vector) + + # Construct better approximation for eigenvalue + value = np.dot(np.conj(vector).T, + np.dot(input_matrix, vector)) + + error = abs(value - prev_eigenvalue) + prev_eigenvalue = value + + return value, vector From e7832a66b9bedece338858e7b84f05d3f22442ba Mon Sep 17 00:00:00 2001 From: BH4 Date: Fri, 16 Oct 2020 15:46:02 -0700 Subject: [PATCH 2/3] Add iteration limit --- linear_algebra/src/rayleigh_quotient_iteration.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linear_algebra/src/rayleigh_quotient_iteration.py b/linear_algebra/src/rayleigh_quotient_iteration.py index 5242f4414b90..b9920c49c925 100644 --- a/linear_algebra/src/rayleigh_quotient_iteration.py +++ b/linear_algebra/src/rayleigh_quotient_iteration.py @@ -32,7 +32,8 @@ def rayleigh_quotient_iteration( error = error_tol + 1 prev_eigenvalue = value - while error > error_tol: + iterations = 0 + while error > error_tol and iterations < max_iterations: # Construct the iterating matrix A = np.linalg.inv(input_matrix - np.eye(N) * value) # Construct new eigenvector @@ -47,4 +48,6 @@ def rayleigh_quotient_iteration( error = abs(value - prev_eigenvalue) prev_eigenvalue = value + iterations += 1 + return value, vector From 6e59914fa97ee2ccbdff1f4fcfbceadaf22df9d2 Mon Sep 17 00:00:00 2001 From: BH4 Date: Sat, 17 Oct 2020 12:29:11 -0700 Subject: [PATCH 3/3] Ran pre-commit locally --- linear_algebra/src/rayleigh_quotient_iteration.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/linear_algebra/src/rayleigh_quotient_iteration.py b/linear_algebra/src/rayleigh_quotient_iteration.py index b9920c49c925..081535efba01 100644 --- a/linear_algebra/src/rayleigh_quotient_iteration.py +++ b/linear_algebra/src/rayleigh_quotient_iteration.py @@ -1,10 +1,15 @@ -import numpy as np from typing import Tuple +import numpy as np + def rayleigh_quotient_iteration( - input_matrix: np.array, vector: np.array, value: float, - error_tol=1e-12, max_iterations=100) -> Tuple[float, np.array]: + input_matrix: np.array, + vector: np.array, + value: float, + error_tol=1e-12, + max_iterations=100, +) -> Tuple[float, np.array]: """ https://en.wikipedia.org/wiki/Rayleigh_quotient_iteration @@ -42,8 +47,7 @@ def rayleigh_quotient_iteration( vector = vector / np.linalg.norm(vector) # Construct better approximation for eigenvalue - value = np.dot(np.conj(vector).T, - np.dot(input_matrix, vector)) + value = np.dot(np.conj(vector).T, np.dot(input_matrix, vector)) error = abs(value - prev_eigenvalue) prev_eigenvalue = value