Note
Go to the end to download the full example code or to run this example in your browser via JupyterLite.
Animated: power iteration turning a vector towards the dominant eigenvector#
Each step of power iteration, \(v_{k+1} = A v_k / \|A v_k\|\), stretches the component of \(v_k\) along each eigenvector by its eigenvalue. The component along the eigenvector of largest \(|\lambda|\) grows fastest, so \(v_k\) swings round onto that direction, the angle shrinking by the factor \(|\lambda_2 / \lambda_1|\) per step.
import matplotlib.pyplot as plt
import numpy as np
from mathematicskit.linalg import power_iteration
from mathematicskit.linalg.visualizers import animate_power_iteration
# In Jupyter or JupyterLite, show animations as an HTML/JavaScript player
# (no ffmpeg needed).
plt.rcParams["animation.html"] = "jshtml"
A 2x2 matrix in the plane#
Eigenvalues 3 and 1.8, so the angle to the dominant eigenvector shrinks by \(1.8/3 = 0.6\) per step. The start vector lies close to the other eigenvector, to give the iterate a long way to turn.
theta = np.deg2rad(30.0)
Q = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
A = Q @ np.diag([3.0, 1.8]) @ Q.T
result = power_iteration(A, tol=1e-12, max_iter=40, v0=Q[:, 1] + 0.02 * Q[:, 0])
print(f"lambda ~ {result.eigenvalues[0]:.10f} after {result.iterations} iterations")
anim = animate_power_iteration(A, result)
anim
lambda ~ 3.0000000000 after 35 iterations
plt.show()
Total running time of the script: (0 minutes 6.385 seconds)