# Rayleigh quotient iteration

Rayleigh quotient iteration is an eigenvalue algorithm which extends the idea of the inverse iteration by using the Rayleigh quotient to obtain increasingly accurate eigenvalue estimates.

Rayleigh quotient iteration is an iterative method, that is, it must be repeated until it converges to an answer (this is true for all eigenvalue algorithms). Fortunately, very rapid convergence is guaranteed and no more than a few iterations are needed in practice. The Rayleigh quotient iteration algorithm converges cubically for Hermitian or symmetric matrices, given an initial vector that is sufficiently close to an eigenvector of the matrix that is being analyzed.

## Algorithm

The algorithm is very similar to inverse iteration, but replaces the estimated eigenvalue at the end of each iteration with the Rayleigh quotient. Begin by choosing some value ${\displaystyle \mu _{0}}$ as an initial eigenvalue guess for the Hermitian matrix ${\displaystyle A}$. An initial vector ${\displaystyle b_{0}}$ must also be supplied as initial eigenvector guess.

Calculate the next approximation of the eigenvector ${\displaystyle b_{i+1}}$ by

${\displaystyle b_{i+1}={\frac {(A-\mu _{i}I)^{-1}b_{i}}{||(A-\mu _{i}I)^{-1}b_{i}||}},}$
where ${\displaystyle I}$ is the identity matrix, and set the next approximation of the eigenvalue to the Rayleigh quotient of the current iteration equal to
${\displaystyle \mu _{i}={\frac {b_{i}^{*}Ab_{i}}{b_{i}^{*}b_{i}}}.}$

To compute more than one eigenvalue, the algorithm can be combined with a deflation technique.

Note that for very small problems it is beneficial to replace the matrix inverse with the adjugate, which will yield the same iteration because it's equal to the inverse up to an irrelevant scale (the inverse of the determinant, specifically). The adjugate is easier to compute explicitly than the inverse (though the inverse is easier to apply to a vector for problems that aren't small), and is more numerically sound because it remains well defined as the eigenvalue converges.

## Example

Consider the matrix

${\displaystyle A=\left[{\begin{matrix}1&2&3\\1&2&1\\3&2&1\\\end{matrix}}\right]}$

for which the exact eigenvalues are ${\displaystyle \lambda _{1}=3+{\sqrt {5}}}$, ${\displaystyle \lambda _{2}=3-{\sqrt {5}}}$ and ${\displaystyle \lambda _{3}=-2}$, with corresponding eigenvectors

${\displaystyle v_{1}=\left[{\begin{matrix}1\\\varphi -1\\1\\\end{matrix}}\right]}$, ${\displaystyle v_{2}=\left[{\begin{matrix}1\\-\varphi \\1\\\end{matrix}}\right]}$ and ${\displaystyle v_{3}=\left[{\begin{matrix}1\\0\\1\\\end{matrix}}\right]}$.

(where ${\displaystyle \textstyle \varphi ={\frac {1+{\sqrt {5}}}{2}}}$ is the golden ratio).

The largest eigenvalue is ${\displaystyle \lambda _{1}\approx 5.2361}$ and corresponds to any eigenvector proportional to ${\displaystyle v_{1}\approx \left[{\begin{matrix}1\\0.6180\\1\\\end{matrix}}\right].}$

We begin with an initial eigenvalue guess of

${\displaystyle b_{0}=\left[{\begin{matrix}1\\1\\1\\\end{matrix}}\right],~\mu _{0}=200}$.

Then, the first iteration yields

${\displaystyle b_{1}\approx \left[{\begin{matrix}-0.57927\\-0.57348\\-0.57927\\\end{matrix}}\right],~\mu _{1}\approx 5.3355}$

the second iteration,

${\displaystyle b_{2}\approx \left[{\begin{matrix}0.64676\\0.40422\\0.64676\\\end{matrix}}\right],~\mu _{2}\approx 5.2418}$

and the third,

${\displaystyle b_{3}\approx \left[{\begin{matrix}-0.64793\\-0.40045\\-0.64793\\\end{matrix}}\right],~\mu _{3}\approx 5.2361}$

from which the cubic convergence is evident.

## Octave Implementation

The following is a simple implementation of the algorithm in Octave.

function x = rayleigh(A,epsilon,mu,x)
x = x / norm(x);
y = (A-mu*eye(rows(A))) \ x;
lambda = x'*y;
mu = mu + 1 / lambda
err = norm(y-lambda*x) / norm(y)
while err > epsilon
x = y / norm(y);
y = (A-mu*eye(rows(A))) \ x;
lambda = x'*y;
mu = mu + 1 / lambda
err = norm(y-lambda*x) / norm(y)
end
end


## Python Implementation

The following is a simple implementation of the algorithm in Python.

def rayleigh(A,epsilon,mu,x):
x = x / norm(x);
y = solve((A-mu*eye(A.shape[0])),x)
lam = dot(x,y)
mu = mu + 1 / lam
err = norm(y-lam*x) / norm(y)
while err > epsilon:
x = y / norm(y);
y = solve((A-mu*eye(A.shape[0])),x)
lam = dot(x,y)
mu = mu + 1 / lam
err = norm(y-lam*x) / norm(y)
return x