Dictionary of Applied Machine Learning · eigenvalue

eigenvalue — Python demo

Numerical companion to the entry eigenvalue: it recomputes what the entry states and prints one line per check

One block per paragraph of the entry (marked [P...]): each block verifies numerically what the corresponding statement asserts. Self-contained (numpy/matplotlib only), fixed seed.

Run it with python3 eigenvalue.py, from any directory — it writes its output files into the current directory. Requires NumPy and Matplotlib only, and uses fixed seeds, so the printed numbers reproduce exactly. Download eigenvalue.py

The script, block by block

One cell per block of the script: the code, and what that code printed when it last ran here

setup

"""
eigenvalue.py — numerical companion to the glossary entry 'eigenvalue'.

One block per paragraph of the entry (marked [P...]): each block verifies
numerically what the corresponding statement asserts. Self-contained
(numpy/matplotlib only), fixed seed.

Blocks
------
[P-def] lambda is an eigenvalue of a square matrix A iff A x = lambda x
        for some nonzero vector x: every (lambda, x) pair returned by
        np.linalg.eig satisfies the defining equation, the eigenvectors
        are nonzero, and applying A to an eigenvector only rescales it
        (direction preserved — the content of the entry's figure).

Outputs
-------
eigenvalue.png : preview figure (checking only).

Data generated by pythondemos/eigenvalue.py.
"""

import numpy as np
import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt

rng = np.random.default_rng(42)
report = []


def check(name, ok):
    report.append((name, bool(ok)))
    print(f"  [{'ok' if ok else 'FAIL'}] {name}")

P-def

lambda is an eigenvalue of a square matrix A iff A x = lambda x for some nonzero vector x: every (lambda, x) pair returned by np.linalg.eig satisfies the defining equation, the eigenvectors are nonzero, and applying A to an eigenvector only rescales it (direction preserved — the content of the entry's figure).

print("[P-def] A x = lambda x for every eigenpair")
A = np.array([[2.0, 1.0], [1.0, 3.0]])         # symmetric -> real eigenvalues
lam, V = np.linalg.eig(A)
for i in range(2):
    x = V[:, i]
    check(f"pair {i}: ||A x - lambda x|| < 1e-12 "
          f"(lambda = {lam[i]:.4f})",
          np.linalg.norm(A @ x - lam[i] * x) < 1e-12)
    check(f"pair {i}: eigenvector is nonzero", np.linalg.norm(x) > 0)
    # direction preserved: A x is collinear with x
    cos = abs(x @ (A @ x)) / (np.linalg.norm(x) * np.linalg.norm(A @ x))
    check(f"pair {i}: A x collinear with x (|cos| = 1)",
          abs(cos - 1) < 1e-12)
# a non-eigenvector is NOT mapped to a multiple of itself
u = np.array([1.0, 0.0])
cos_u = abs(u @ (A @ u)) / (np.linalg.norm(u) * np.linalg.norm(A @ u))
check("generic vector changes direction under A (|cos| < 1)",
      cos_u < 1 - 1e-6)

# ------------------------------------------------------------ preview
fig, ax = plt.subplots(figsize=(4.2, 4.0))
for i, c in zip(range(2), ("C0", "C1")):
    x = V[:, i]
    ax.arrow(0, 0, *x, head_width=0.06, color=c, length_includes_head=True)
    ax.arrow(0, 0, *(A @ x), head_width=0.06, color=c, alpha=0.4,
             length_includes_head=True)
    ax.annotate(f"$\\lambda_{i+1}={lam[i]:.2f}$", xy=A @ x)
ax.arrow(0, 0, *u, head_width=0.06, color="k", length_includes_head=True)
ax.arrow(0, 0, *(A @ u), head_width=0.06, color="k", alpha=0.35,
         length_includes_head=True)
ax.set_aspect("equal"); ax.set_title("[P-def] eigenvectors keep direction")
fig.tight_layout()
fig.savefig("eigenvalue.png", dpi=110)
print(f"\n{sum(ok for _, ok in report)}/{len(report)} checks passed")
assert all(ok for _, ok in report)
[P-def] A x = lambda x for every eigenpair
  [ok] pair 0: ||A x - lambda x|| < 1e-12 (lambda = 1.3820)
  [ok] pair 0: eigenvector is nonzero
  [ok] pair 0: A x collinear with x (|cos| = 1)
  [ok] pair 1: ||A x - lambda x|| < 1e-12 (lambda = 3.6180)
  [ok] pair 1: eigenvector is nonzero
  [ok] pair 1: A x collinear with x (|cos| = 1)
  [ok] generic vector changes direction under A (|cos| < 1)

7/7 checks passed
Preview figure produced by eigenvalue.py
The preview figure the block P-def writes when the script runs