Counting the ways to combine long and short syllables and tracking how rabbits breed seem to have nothing to do with each other, yet both lead to recursively defined sequences. The tradition of Indian prosody and Fibonacci’s Liber Abaci of 1202 are different threads in the history of such problems. For the Fibonacci sequence, the ratio of consecutive terms approaches the golden ratio φ=(1+5)/2; Binet’s formula, in turn, writes a sequence of integers as a combination of powers of irrational numbers. What structure is hidden behind all this?
Modern linear algebra lays a remarkably clean card on the table: the golden ratio φ is, in essence, the dominant eigenvalue of a 2×2 state transition matrix. Once you have mastered the geometric viewpoint of diagonalizing a matrix, the square root of five and the irrational powers in Binet’s formula reveal themselves as naturally as a finely made gift being unwrapped—a number-theoretic coincidence spanning two thousand years turns out, in a linear space, to be nothing more than a completely standard eigenvalue computation.
This is precisely the ultimate lens that this chapter sets out to forge for you.
If a nonzero vector v satisfies Av=λv, then the one-dimensional subspace it spans is left invariant by the transformation; v is called an eigenvector and λ an eigenvalue. In the real case this can be pictured as stretching, compressing, reversing, or collapsing to zero along a single line. But a real matrix need not have any real eigendirection—a rotation of the plane by ninety degrees is an example—while the identity matrix has every nonzero vector as an eigenvector. Over the complex numbers every nonempty square matrix has at least one eigenvalue, yet it need not have enough linearly independent eigenvectors to be diagonalized.
The eigen in the German word Eigenwert means “own” or “proper.” Eigenvalues are unchanged by a similarity change of basis, which expresses an intrinsic property of the operator; but a list of eigenvalues alone is usually not enough to reconstruct the whole operator.
This language shows a remarkable universality across modern science and engineering:
The quantum world. The bound-state eigenvalues of the Hamiltonian operator give the discrete energy levels; the frequency of a spectral line is determined by an energy difference hν=Ei−Ej and is not itself an eigenvalue.
Information networks. PageRank models the web with a damped random transition matrix, and the weights of the web pages are given by the nonnegative stationary eigenvector for the eigenvalue 1 whose components sum to 1.
High-dimensional data. Principal component analysis (PCA) in machine learning takes the covariance matrix of high-dimensional data and uses the eigenvector belonging to the largest eigenvalue to lock onto the principal axis of greatest variance (the eigenvalue is a scalar and only gives the amount of variance in that direction); it is a cornerstone of modern dimensionality reduction.
Chapter 9 will reveal why the eigenvalues of symmetric systems must be purely real; Chapter 10 will explain why the observables of quantum mechanics are described by self-adjoint operators, with the measurement rules given jointly by the eigenvalues and the corresponding spectral projections; and the singular value decomposition (SVD) of Chapter 11 will carry this beautiful idea of the eigen-spectrum all the way to matrices of arbitrary shape and to finite-dimensional linear maps.
Different worlds, read through the same eigenspace.
The story of the Fibonacci sequence pays off in full in §8.3: how the recurrence is written in matrix form, how the eigenvalues emerge as the golden ratio, and how diagonalization yields Binet’s formula. But to follow that story, we first need to lay the foundation in the first two sections of this chapter.
§8.1 begins by stating the central problem clearly. How does the geometric intuition of an “unchanged direction” become an algebraic condition that can be computed? The answer lies in the characteristic polynomial, in the equation det(A−λI)=0—finding eigenvalues is equivalent to finding the roots of a polynomial, and the fundamental theorem of algebra guarantees that the roots exist over the complex numbers. Here geometric intuition and algebraic tools shake hands for the first time.
§8.2 goes deeper into the structure of the characteristic polynomial. An eigenvalue can be a repeated root, and the gap between algebraic multiplicity and geometric multiplicity is precisely the watershed that decides whether a matrix can be “fully understood.” This section also introduces the Cayley–Hamilton theorem—every matrix satisfies its own characteristic equation. At first glance it looks like magic; on reflection it is nothing more than an inevitable consequence of linear dependence.
§8.3 reaches the central goal: change the basis so that the matrix becomes as simple as possible. A matrix being diagonalizable means that, in some basis, the linear transformation is nothing but independent scaling along each direction. This section answers “when can this be done” and “what can we do once it is done”—the closed-form formula for the Fibonacci sequence is the most concise demonstration of the power of diagonalization.
§8.4 faces an unavoidable reality: not every matrix can be diagonalized. The Jordan canonical form gives the most general answer—even when a matrix cannot be fully diagonalized, it can be brought to an almost diagonal block structure. This is one of the deepest theorems of finite-dimensional linear algebra, and a stage that cannot be bypassed in understanding the inner structure of matrices.
§8.5 verifies the conclusions of this chapter in Python and implements numerical methods such as power iteration, so that you can feel the distance between “diagonalizing by hand” and “efficient solution by computer”—both near and far.
Once you have read this chapter, you will have a far deeper answer than before to the question “what, really, is a matrix?”; and the sequence that left traces both in the Indian tradition of prosody and in Liber Abaci, and whose structure linear algebra finally brought into view, will become your most concrete memory of the power of eigenvalues.
At its core, the eigenvalue problem is a search for the invariant subspaces and invariant directions of a matrix. When a matrix is viewed as a linear transformation, eigenvalues and eigenvectors give us the simplest way to represent the mapping and reveal the intrinsic structure and properties of the matrix. This section starts from the definition, introduces the basic concepts of eigenvalues and eigenvectors, and explores how to compute them and what they mean geometrically.
8.1.1 The Characteristic Equation and the Characteristic Polynomial¶
The concepts of eigenvalue and eigenvector grew out of a close study of the basic behavior of linear transformations. When a linear transformation acts on certain special vectors, the direction of these vectors is preserved and only their magnitude is scaled.
This definition has three key ingredients:
Square matrices only. The eigenvalue problem applies only to square matrices, that is, matrices whose number of rows equals their number of columns.
Nonzero vectors. An eigenvector must be a nonzero vector; otherwise the equation would hold automatically for every λ.
Invariance of direction. After the transformation, an eigenvector still lies on its original invariant line, and its length is multiplied by ∣λ∣; a negative value reverses it, and the value zero sends it to zero (here we mean real eigenvalues).
To solve for eigenvalues and eigenvectors, we need to turn the defining equation of an eigenvalue into a form that is easier to work with.
The definition of an eigenvalue can be rewritten as:
Av=λv,
Av−λv=0,
(A−λI)v=0
where I is the n×n identity matrix. Since we require the eigenvector v to be nonzero, A−λI must be a singular matrix, that is, its determinant must be zero:
This equation is called the characteristic equation of the matrix A. When the determinant on the left is expanded, it is a polynomial in λ, called the characteristic polynomial of the matrix A.
Historical significance and applications.
This is one of the major achievements of the mathematician Gauss in the early nineteenth century, and a central theorem of algebra. It tells us that the field of complex numbers is algebraically closed: every polynomial equation in one variable with complex coefficients can be solved within the complex numbers.
It is a concise existence theorem; in practice, other constructive methods (such as Newton’s method) are still needed to actually compute the roots, and the relevant Python packages can usually find approximate solutions that meet the required precision.
A direct corollary is that a polynomial of degree n has exactly n roots in the complex numbers (counted with multiplicity), so an n×n matrix has exactly n eigenvalues (possibly repeated). These eigenvalues may be real or complex, even when all the entries of the matrix are real.
Standard procedure for computing eigenvalues and eigenvectors.
Compute the characteristic polynomial pA(λ)=det(A−λI).
Solve the characteristic equation pA(λ)=0 to obtain the eigenvalues.
For each eigenvalue λi, solve the homogeneous linear system (A−λiI)v=0 to obtain the corresponding eigenvectors.
import sympy as sp
# --- Visual hierarchy helpers ---
def print_header(title):
print("=" * 60)
print(f" {title}")
print("=" * 60)
def print_step(step, desc):
print(f"\n▶ Step {step}: {desc}")
print("-" * 40)
# ============================================================
print_header("Example 8.1 | Symbolic Computation of the Characteristic Polynomial")
# ============================================================
# --- Step 1: Define the matrix A ---
print_step("1", "Define the matrix A")
A = sp.Matrix([[3, 1],
[1, 3]])
sp.pprint(A)
# --- Step 2: Compute the characteristic polynomial p_A(λ) = det(A - λI) (consistent with def-characteristic-polynomial) ---
# Note: numerical packages often use the monic convention det(λI - A); the two agree for even n and differ by a sign (-1)^n for odd n,
# while the set of roots (the eigenvalues) stays the same.
print_step("2", "Compute the characteristic polynomial p_A(λ) = det(A - λI)")
lam = sp.Symbol('lambda')
char_poly = (A - lam * sp.eye(2)).det()
print(f" Expanded: p_A(λ) = {sp.expand(char_poly)}")
print(f" Factored: p_A(λ) = {sp.factor(char_poly)}")
# --- Step 3: Find the eigenvalues ---
print_step("3", "Solve p_A(λ) = 0")
eigenvalues = sp.solve(char_poly, lam)
print(f" Eigenvalues: λ₀ = {eigenvalues[0]}, λ₁ = {eigenvalues[1]}")
8.1.2 Geometric Interpretation of Eigenvalues and Eigenvectors¶
Eigenvalues and eigenvectors carry deep geometric meaning: they reveal the essential behavior of a linear transformation. To search for invariant vectors yourself, see Experiment 1.
Basic geometric interpretation.
Eigenvectors represent the invariant directions of a linear transformation.
Eigenvalues represent the stretching or compression ratios along these directions.
When a matrix A acts on a vector space as a linear transformation, most vectors are not only scaled but also change direction. Eigenvectors are the exception—they are only stretched or compressed along their original direction, and the scaling ratio is exactly the corresponding eigenvalue. An interesting and important question: does a rotation matrix still have invariant eigenvectors?
Depending on the eigenvalue, we can observe several typical situations:
When λ>1, the eigenvector is stretched.
When 0<λ<1, the eigenvector is compressed.
When λ<0, the eigenvector’s direction is reversed and it is scaled by ∣λ∣.
When λ=0, the eigenvector is mapped to the zero vector, indicating that these directions “vanish” under the transformation.
When λ=1, the eigenvector is left completely unchanged.
As shown in Chapter 3, several typical transformations have the following eigenvalues and eigenvectors:
The identity matrixI:
Every nonzero vector is an eigenvector, and the corresponding eigenvalue is always 1.
Geometric interpretation: the identity transformation, which leaves every vector unchanged.
A projection matrixP (projecting onto some subspace):
The only eigenvalues are 0 and 1.
The eigenvectors for the eigenvalue 1 lie in the subspace and are left unchanged.
The eigenvectors for the eigenvalue 0 are perpendicular to the subspace and are mapped to zero.
A two-dimensional rotation matrixR:
If the angle of rotation is not an integer multiple of π, there are no real eigenvalues.
The eigenvalues are complex, of the form e±iθ (θ is the angle of rotation).
Geometric interpretation: under this condition on the angle there is no real invariant line.
This also shows that complex matrices arise naturally.
Through geometric intuition we have seen that eigenvalues and eigenvectors reveal the “principal axes” and the “scaling factors” of a linear transformation. But this is only the tip of the iceberg. In Section 8.2 we explore the deeper theoretical properties of eigenvalues, including eigenspaces and the notions of algebraic and geometric multiplicity, which provide the theoretical foundation for understanding the complete structure of a matrix.
import numpy as np
def print_header(title):
print("=" * 60)
print(f" {title}")
print("=" * 60)
def print_step(step, desc):
print(f"\n▶ Step {step}: {desc}")
print("-" * 40)
np.set_printoptions(precision=6, suppress=True, linewidth=100)
# ============================================================
print_header("Verifying the Eigenvalues of Rotation Matrices")
# ============================================================
for theta_label, theta in [("θ = 0", 0.0),
("θ = π", np.pi),
("θ = π/3", np.pi / 3)]:
print(f"\n{'━'*50}")
print(f" {theta_label}")
print(f"{'━'*50}")
# Step 0: Build the rotation matrix
print_step(0, "Build the rotation matrix R_θ")
R = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
print(R)
# Step 1: Compute the eigenvalues and eigenvectors (over the complex numbers)
print_step(1, "NumPy eigendecomposition (over the complex numbers)")
eigvals, eigvecs = np.linalg.eig(R)
for k in range(2):
lam = eigvals[k]
v = eigvecs[:, k]
# Verify R @ v = λ * v
lhs = R @ v
rhs = lam * v
residual = np.max(np.abs(lhs - rhs))
print(f" λ_{k} = {lam:.6f} |λ_{k}| = {abs(lam):.6f}")
print(f" v_{k} = {v}")
print(f" ‖R·v_{k} − λ_{k}·v_{k}‖∞ = {residual:.2e}")
# Step 2: Verify |λ| = 1
print_step(2, "Verify that every eigenvalue has modulus 1 (rotations preserve length)")
print(f" |λ_0| = {abs(eigvals[0]):.8f}")
print(f" |λ_1| = {abs(eigvals[1]):.8f}")
# Step 3: Verify the trace and the determinant
print_step(3, "Verify tr = 2cosθ, det = 1")
print(f" tr(R) = {np.trace(R):.6f}, 2cos(θ) = {2*np.cos(theta):.6f}")
print(f" det(R) = {np.linalg.det(R):.6f}, expected = 1.000000")
This section explores the important theoretical properties of eigenvalues in depth, relates eigenvalues to other properties of a matrix, and introduces the concept of an eigenspace. These theoretical foundations provide a solid framework for understanding matrix structure and for applying eigenvalue analysis.
8.2.1 Relations Between Eigenvalues and Matrix Properties¶
Eigenvalues are closely connected with several basic properties of a matrix, and these connections reveal the essential features of the matrix’s intrinsic structure.
The relation between the trace and the sum of the eigenvalues can be proved from the expansion of the characteristic polynomial. After the characteristic polynomial pA(λ)=det(A−λI) is expanded, the coefficient of λn−1 is exactly (−1)n−1tr(A).
The relation between the determinant and the product of the eigenvalues explains the invertibility condition for a square matrix: a square matrix A is invertible if and only if all of its eigenvalues are nonzero, that is, det(A)=0.
import numpy as np
# --- Visual hierarchy helpers ---
def compare_print(label, actual, expected_desc):
print(f"\n[{label}]")
print(f" Computed value: {actual}")
print(f" Expected value: {expected_desc}")
np.set_printoptions(precision=4, suppress=True, linewidth=100)
# ============================================================
print_header("Example 8.2 | Verifying Basic Properties of Eigenvalues")
# ============================================================
# --- Step 1: Define the matrix A ---
print_step("1", "Define the matrix A")
A = np.array([[4, 2],
[1, 3]])
print(A)
# --- Step 2: Compute the eigenvalues λ₀, λ₁ ---
print_step("2", "Compute the eigenvalues λ₀, λ₁")
eigenvalues = np.linalg.eigvals(A)
print(f" λ₀ = {eigenvalues[0]:.4f}, λ₁ = {eigenvalues[1]:.4f}")
# --- Step 3: Verify the trace and the determinant ---
print_step("3", "Verify tr(A) = Σλᵢ, det(A) = Πλᵢ")
compare_print(
"tr(A) vs λ₀ + λ₁",
f"{np.trace(A):.4f}",
f"λ₀ + λ₁ = {np.sum(eigenvalues):.4f}"
)
compare_print(
"det(A) vs λ₀ × λ₁",
f"{np.linalg.det(A):.4f}",
f"λ₀ × λ₁ = {np.prod(eigenvalues):.4f}"
)
# --- Step 4: Verify the eigenvalues of A² ---
print_step("4", "Verify that the eigenvalues of A² are λᵢ²")
compare_print(
"eig(A²)",
np.linalg.eigvals(A @ A),
f"λᵢ² = {eigenvalues**2}"
)
# --- Step 5: Verify the eigenvalues of A⁻¹ ---
print_step("5", "Verify that the eigenvalues of A⁻¹ are 1/λᵢ")
compare_print(
"eig(A⁻¹)",
np.linalg.eigvals(np.linalg.inv(A)),
f"1/λᵢ = {1/eigenvalues}"
)
# --- Step 6: Verify the eigenvalues of (A + cI) ---
print_step("6", "Verify that the eigenvalues of (A + cI) are λᵢ + c")
c = 3
compare_print(
f"eig(A + {c}I)",
np.linalg.eigvals(A + c * np.eye(2)),
f"λᵢ + {c} = {eigenvalues + c}"
)
8.2.2 Eigenspaces, Algebraic Multiplicity, and Geometric Multiplicity¶
For each eigenvalue, the corresponding eigenvectors (together with the zero vector) form a vector subspace, called the eigenspace.
Eigenspaces have the following important properties:
Subspace property. An eigenspace is a subspace of the vector space: it is closed under addition and under scalar multiplication.
Invariant subspace. If v∈Eλ, then Av∈Eλ. That is, the matrix A maps the eigenspace into itself.
Eigenvectors for distinct eigenvalues are linearly independent. If λ0,λ1,…,λk−1 are pairwise distinct, then the corresponding nonzero eigenvectors v0,…,vk−1 must be linearly independent (see the theorem below).
This theorem is one of the cornerstones of eigenvalue theory: it guarantees that eigenvectors taken from distinct eigenvalues always form a linearly independent set, which lays the theoretical foundation for the diagonalization of matrices that follows.
A short dimension count, together with the finite-dimensional abstract linear algebra of Chapter 4, readily shows that if the eigenvalues of a square matrix A are pairwise distinct, then A can be diagonalized using the corresponding eigenvectors; this means that collecting all the eigenspaces recovers the entire domain. But things do not always go so smoothly—eigenvalues sometimes repeat.
When an eigenvalue λ is a repeated root, “repeated” has two quite different meanings, and the gap between these two meanings decides whether the matrix can be diagonalized.
Algebraic multiplicity answers: how “heavy” is this eigenvalue in the polynomial?
Geometric multiplicity answers: how many independent invariant axes can this eigenvalue hold up?
Side-by-side comparison.
Algebraic multiplicity aλ
Geometric multiplicity gλ
Defined via
the characteristic polynomial (algebra)
the kernel (geometry)
How to compute
the multiplicity of λ as a root
n−rank(A−λI)
Intuitive meaning
how many directions are “expected”
how many independent directions there “actually” are
Over C (or, more generally, when the characteristic polynomial splits completely over F), if gλ=aλ holds for every eigenvalue, the matrix is diagonalizable. If any eigenvalue has gλ<aλ, the Jordan canonical form (§8.4) is needed to handle those “missing directions.”
The next two examples use the same eigenvalue λ=2 to illustrate two extreme situations.
Besides illustrating the situation gλ<aλ, these two examples are highly representative in form—they are exactly the prototypes of the Jordan canonical form, and they preview the conclusions of our study of non-diagonalizable matrices.
The Cayley–Hamilton theorem links a square matrix to its characteristic equation and gives the concise result pA(A)=0. For this expression to make sense, we first need to define polynomial functions of a matrix.
import numpy as np
np.set_printoptions(precision=4, suppress=True, linewidth=100)
# ============================================================
print_header("Example 8.3 | Verifying the Cayley-Hamilton Theorem")
# ============================================================
# --- Step 1: Define the matrix A ---
print_step("1", "Define the matrix A")
A = np.array([[4, 2],
[1, 3]])
print(A)
# --- Step 2: Compute the coefficients of the characteristic polynomial ---
print_step("2", "Compute the coefficients of the characteristic polynomial p(λ)")
coeffs = np.poly(A) # returns [c_n, c_{n-1}, ..., c_0], e.g. [1, -7, 10]
print(f" coefficients of p(λ) (in descending powers): {coeffs}")
print(f" that is, p(λ) = λ² - 7λ + 10")
# --- Step 3: Compute the matrix polynomial p(A) ---
print_step("3", "Compute the matrix polynomial p(A) = A² - 7A + 10I")
n = len(A)
p_A = sum(c * np.linalg.matrix_power(A, n - i) for i, c in enumerate(coeffs))
# --- Step 4: Verify the Cayley-Hamilton theorem ---
print_step("4", "Verify p(A) ≈ O (Cayley-Hamilton theorem)")
print(" p(A) =")
print(np.round(p_A, 10)) # ← split over two lines to avoid a Typst PDF tag error
compare_print(
"Is p(A) the zero matrix?",
np.allclose(p_A, 0),
"the Cayley-Hamilton theorem guarantees p(A) = O"
)
Here F denotes the field containing the entries of the matrix; the Cayley–Hamilton theorem does not require the characteristic polynomial to split over that field.
import numpy as np
from sympy import symbols, Matrix, det, factor, expand, latex, eye, pprint
np.set_printoptions(precision=4, suppress=True, linewidth=100)
def print_header(title):
print("=" * 60)
print(f" {title}")
print("=" * 60)
def print_step(step, desc):
print(f"\n▶ Step {step}: {desc}")
print("-" * 40)
def compare_print(label, actual, expected_desc):
print(f"\n[{label}]")
print(f" Computed value: {actual}")
print(f" Expected value: {expected_desc}")
# ============================================================
print_header("Example: The Proof Strategy of the Cayley-Hamilton Theorem (3×3)")
# ============================================================
lam = symbols('lambda')
# --- Step 1: Define the matrix A and B(λ) ---
print_step("1", "Define the matrix A and B(λ) = A - λI")
A = Matrix([[2, 1, 0],
[0, 2, 1],
[0, 0, 3]])
B = A - lam * eye(3)
print("A ="); pprint(A)
print("\nB(λ) = A - λI ="); pprint(B)
# --- Step 2: Compute the characteristic polynomial p_A(λ) ---
print_step("2", "Compute the characteristic polynomial p_A(λ) = det(B(λ))")
p = expand(det(B))
p_factored = factor(p)
print(f" p_A(λ) = {p}")
compare_print(
"Characteristic polynomial (expanded vs factored)",
p,
f"factored = {p_factored}"
)
# --- Step 3: Compute adj(B(λ)) ---
print_step("3", "Compute adj(B(λ)) and verify adj(B)·B = p_A(λ)·I")
adj_B = B.adjugate()
print("adj(B(λ)) ="); pprint(adj_B)
product = expand(adj_B * B)
expected = expand(p * eye(3))
compare_print(
"adj(B(λ))·B(λ) vs p_A(λ)·I",
"(see the matrices below)",
"the two should be equal"
)
print(" adj(B)·B ="); pprint(product)
print(" p_A(λ)·I ="); pprint(expected)
print(f"\n Equality check: {product == expected}")
# --- Step 4: Expand adj(B(λ)) into the coefficient matrices C2, C1, C0 ---
print_step("4", "Expand adj(B(λ)) = C₂λ² + C₁λ + C₀ and read off the coefficient matrices")
adj_expanded = adj_B.applyfunc(expand)
def coeff_matrix(M, var, deg):
"""Extract the coefficient of var^deg from every entry of the matrix M"""
return M.applyfunc(lambda expr: expr.coeff(var, deg))
C2 = coeff_matrix(adj_expanded, lam, 2)
C1 = coeff_matrix(adj_expanded, lam, 1)
C0 = coeff_matrix(adj_expanded, lam, 0)
print("C₂ ="); pprint(C2)
print("C₁ ="); pprint(C1)
print("C₀ ="); pprint(C0)
# Check the reconstruction: C2*λ² + C1*λ + C0 should equal adj_expanded
reconstructed = expand(C2 * lam**2 + C1 * lam + C0)
compare_print(
"Reconstruction check of C₂λ² + C₁λ + C₀",
reconstructed == adj_expanded.applyfunc(expand),
"True (identical to the original adj(B(λ)))"
)
# --- Step 5: Extract the coefficients c3, c2, c1, c0 and check the four matrix equations ---
print_step("5", "Compare the coefficients of each power of λ and check the system (E0)–(E3)")
from sympy import Poly
coeffs = Poly(p, lam).all_coeffs() # [c3, c2, c1, c0]
c3, c2, c1, c0 = coeffs
print(f" coefficients of the characteristic polynomial: c₃={c3}, c₂={c2}, c₁={c1}, c₀={c0}")
I3 = eye(3)
E0 = C0 * A - c0 * I3
E1 = C1 * A - C0 - c1 * I3
E2 = C2 * A - C1 - c2 * I3
E3 = -C2 - c3 * I3
compare_print("(E0): C₀A = c₀I", E0 == Matrix.zeros(3), "should be the zero matrix")
compare_print("(E1): C₁A - C₀ = c₁I", E1 == Matrix.zeros(3), "should be the zero matrix")
compare_print("(E2): C₂A - C₁ = c₂I", E2 == Matrix.zeros(3), "should be the zero matrix")
compare_print("(E3): -C₂ = c₃I", E3 == Matrix.zeros(3), "should be the zero matrix")
# --- Step 6: Telescoping sum; check p_A(A) = 0 ---
print_step("6", "Telescoping sum: check p_A(A) = c₃A³ + c₂A² + c₁A + c₀I = 0")
A2 = A ** 2
A3 = A ** 3
p_A = c3 * A3 + c2 * A2 + c1 * A + c0 * I3
print("p_A(A) ="); pprint(p_A)
compare_print(
"Cayley-Hamilton theorem: p_A(A) = 0",
p_A == Matrix.zeros(3),
"True (every square matrix satisfies its own characteristic equation)"
)
8.3 Similarity Transformations and Diagonalization¶
In Sections 8.1 and 8.2 we studied eigenvalues and their eigenspaces one at a time. Now we ask a global question: taken together, can these eigenspaces rebuild the entire vector space?
If the answer is yes, we can find a basis made up entirely of eigenvectors, and in that basis the matrix representation of the linear transformation becomes extremely simple—this is diagonalization. To reach this goal we need a tool for “switching viewpoints”: the similarity transformation. It lets us move freely between different bases and thus look for the basis that best reveals the structure of the matrix.
8.3.1 Similarity Transformations: Looking at the Same Thing from Another Angle¶
Geometric meaning.A and B are the matrix representations of the same linear transformationT:V→V in different bases.
Suppose we have two bases:
The standard basisBstd={e0,e1,…,en−1}: the matrix representation of the linear transformation T is A.
A new basisBnew={v0,v1,…,vn−1}: the matrix representation of the same T is B.
Here P=[v0,v1,…,vn−1] is the change-of-basis matrix.
Consider the coordinates [x]Bnew of a vector x in the new basis. To compute the coordinates of T(x) in the new basis, we go through the following steps:
import numpy as np
# --- Visual hierarchy helpers ---
def print_header(title):
print("=" * 60)
print(f" {title}")
print("=" * 60)
def print_step(step, desc):
print(f"\n▶ Step {step}: {desc}")
print("-" * 40)
def compare_print(label, actual, expected_desc):
print(f"\n[{label}]")
print(f" Computed value: {actual}")
print(f" Expected value: {expected_desc}")
np.set_printoptions(precision=4, suppress=True, linewidth=100)
# ============================================================
print_header("Example 8.4 | Diagonalization and Verification of the Invariants")
# ============================================================
# --- Step 1: Define the matrix A ---
print_step("1", "Define the matrix A")
A = np.array([[4, 2],
[1, 3]])
print(A)
# --- Step 2: Compute the eigenvalues λᵢ and the eigenvector matrix P ---
print_step("2", "Compute the eigenvalues λᵢ and the eigenvector matrix P")
eigenvalues, eigenvectors = np.linalg.eig(A)
P = eigenvectors
print(f" Eigenvalues: λ₀ = {eigenvalues[0]:.4f}, λ₁ = {eigenvalues[1]:.4f}")
print("\n Eigenvector matrix P =")
print(P)
# --- Step 3: Construct the diagonal matrix D ---
print_step("3", "Construct the diagonal matrix D = diag(λ₀, λ₁)")
D = np.diag(eigenvalues)
print(D)
# --- Step 4: Verify the diagonalization P⁻¹AP = D ---
print_step("4", "Verify the diagonalization: P⁻¹AP = D")
P_inv_A_P = np.linalg.inv(P) @ A @ P
print(" P⁻¹AP =")
print(P_inv_A_P)
compare_print(
"‖P⁻¹AP − D‖ (Frobenius error)",
f"{np.linalg.norm(P_inv_A_P - D):.2e}",
"a similarity transformation does not change the eigenvalues; the error should be close to 0"
)
# --- Step 5: Verify the similarity invariants ---
print_step("5", "Verify the similarity invariants: tr and det")
compare_print(
"tr(A) vs tr(D)",
f"{np.trace(A):.4f}",
f"tr(D) = {np.trace(D):.4f}"
)
compare_print(
"det(A) vs det(D)",
f"{np.linalg.det(A):.4f}",
f"det(D) = {np.linalg.det(D):.4f}"
)
Intuition. These invariants are all intrinsic properties of the linear transformation itself and do not change with the viewpoint (the choice of basis):
Eigenvalues: the stretching factors along the eigendirections, independent of the coordinate system
Determinant: in real geometry, the signed factor by which volume is scaled (its absolute value is the ordinary volume factor), independent of the coordinate system
Trace: the sum of all the eigenvalues, reflecting the overall “strength” of the transformation
Rank: the dimension of the image, that is, the number of “effective directions” after the transformation
Nullity: the dimension of the kernel, that is, the number of directions “flattened to zero”
8.3.2 Definition of and Conditions for Diagonalization¶
With the concept of a similarity transformation in hand, we can now pose an important question: can we find a special basis in which the matrix takes diagonal form?
Diagonalization is exactly such a special similarity transformation: the new basis is made up of eigenvectors.
Geometric meaning of diagonalization. Diagonalization means that, in the basis formed by the eigenvectors, the linear transformation reduces to simple scaling along each coordinate axis, with no rotation or shear at all.
This corollary follows directly from Theorem Theorem 2: eigenvectors corresponding to pairwise distinct eigenvalues are necessarily linearly independent.
In Section 8.2.2 we saw examples of non-diagonalizable matrices (Examples Example 4 and Example 5). What these matrices have in common is that some eigenvalue has geometric multiplicity smaller than its algebraic multiplicity, that is, gλ<aλ. This means that the eigenvalue does not have enough linearly independent eigenvectors to form a complete diagonalizing basis.
Jordan blocks: intuition and cause
To understand the alternative when diagonalization is impossible, we return to the “pirate ship” analogy of Example Example 5:
Repeated application of the nilpotent matrix A makes vectors “fall level by level”; mathematically, this corresponds to a chain of generalized eigenvectors.
When diagonalization fails, the operator (A−λI) induces this kind of chained filtration structure in the space (because of the minimal polynomial, the chain cannot grow indefinitely):
Merely extending the basis layer by layer along the kernels is not enough; we must choose a chain basis satisfying (A−λI)v0=0 and (A−λI)vj=vj−1. The same eigenvalue may require several chains, and each chain of length k corresponds to a Jordan blockJk(λ):
Superdiagonal: every entry is 1; this is precisely the mathematical trace of vectors being “pushed level by level” along the kernel chain.
Structural essence: a Jordan block captures exactly the property of being “almost diagonalizable”: it differs from the diagonal matrix λIk only by a nilpotent matrix consisting entirely of the 1s on the superdiagonal.
The Jordan canonical form theorem
Since each eigenvalue breaks down into a number of Jordan blocks according to its kernel chains, assembling these blocks along the diagonal like pieces of a jigsaw puzzle produces the ultimate form in the similarity classification of arbitrary matrices.
Theoretical value and numerical limitations
Although the Jordan canonical form is perfect in theory, there is a huge gap between its algebraic structure and numerical computation:
A perfect answer about algebraic structure:
Geometric multiplicity gλ: corresponds to the number of Jordan blocks for the eigenvalue λ (that is, dimker(A−λI)).
Algebraic multiplicity aλ: corresponds to the total size of all the Jordan blocks for the eigenvalue λ.
Exponent of the factor (t−λ) in the minimal polynomial: corresponds to the size of the largest Jordan block for the eigenvalue λ.
A numerical disaster:
Extremely unstable structure: how the Jordan blocks split is extremely sensitive to tiny perturbations of the matrix entries. For example, (0010) has only one block, but adding just an ϵ in the lower right corner immediately makes the matrix diagonalizable.
High computational cost: determining exactly the order at which the generalized eigenspaces stabilize (that is, the end of the kernel chain) involves high powers of matrices, and numerical errors grow rapidly. In practical numerical ODE computations, other, more stable algorithms are used.
Where this topic sits in the course
For these reasons, the numerical procedure of computing generalized eigenvector chains by hand lies outside the practical scope of this course, but the theoretical framework of the existence and uniqueness of the Jordan canonical form is worth understanding. Our main purpose in studying it is to understand how it brings the theory of matrix similarity to a perfect close. In practical numerical applications we turn to more stable tools, such as the singular value decomposition (SVD) of Chapter 11.
The Concavity Theorem for Kernel Dimension Increments¶
Underlying the theory of the Jordan canonical form is a geometrically very elegant property. For a linear map N:V→V, the layer-by-layer dimension increments of its kernel chain
Although computing the Jordan canonical form is beyond the scope of this course, the application formulas for 2×2 Jordan blocks are very important and relatively simple. These formulas are indispensable for solving difference equations and differential equations with non-diagonalizable matrices. For the complete derivations, visual comparisons, and application exercises, see Experiment 7.
Key observation: in the non-diagonalizable case, the general solution admits terms of the “polynomial × exponential” type (for particular initial values the coefficients of the polynomial terms may vanish); this is the essential difference from the diagonalizable case.
This power formula is stated for λ=0. In addition, J0=I; when Jk(0)=N, use Jk(0)n=Nn directly, which is zero for n≥k; this avoids negative powers and the ambiguity of 00.
Comparison with the diagonalizable case.
For the diagonal matrix, (λ00λ)n=(λn00λn); the structure is unchanged by taking powers.
For the Jordan block, the term nλn−1 appears in the upper right corner, that is, a “polynomial × exponential” term.
Where does this extra term in the upper right corner come from? It comes from the fact that the binomial expansion of J2(λ)=λI+N (where the nilpotent matrix satisfies N2=0) terminates after finitely many terms—for the derivation and a numerical check, see Experiment 7, §1.1.
By the power formula of Application 1, when λ=0 the general solution admits terms of the form nλn−1, that is, a polynomial (n) times an exponential (λn); for particular initial values (for example, ones lying in the eigenspace) their coefficients may be zero.
For a complete comparison of the trajectories in the diagonalizable case (gλ=aλ) and the non-diagonalizable case (gλ<aλ), see Part 1 of Experiment 7.
This formula for the matrix exponential holds for all λ (including λ=0) and is not subject to the restriction λ=0 on the discrete powers in Application 1.
Comparison with the diagonalizable case.
For the diagonal matrix, ediag(λ,λ)t=(eλt00eλt); the upper right corner is zero.
For the Jordan block, the term teλt appears in the upper right corner, which is how “polynomial × exponential” shows up in continuous time.
This formula is the core tool for solving systems of differential equations with non-diagonalizable matrices. The t in the upper right corner comes from the fact that the Taylor expansion eNt=I+Nt of the nilpotent part N (N2=0) terminates after finitely many terms—for the derivation, see Part 3 of Experiment 7.
Application 4: Solving systems of differential equations¶
By the matrix exponential formula of Application 3, the general solution admits terms of the form teλt, that is, a polynomial (t) times an exponential (eλt).
For the complete computations in the two cases—decoupling by a similarity transformation (gλ=aλ) and a Jordan block (gλ<aλ)—together with phase-space trajectories and the application to radioactive decay chains, see Part 2 of Experiment 7 and its Exercises 1 and 2.
the general solution admits polynomial factors of degree up to k−1; for particular initial values the coefficients may be zero:
Difference equations: when λ=0, the general solution admits njλn, j=0,1,…,k−1
Differential equations: the general solution admits tjeλt, j=0,1,…,k−1
The 2×2 case (k=2) consists of exactly the two terms j=0,1, that is, a constant term and a linear term. Larger Jordan blocks admit higher-degree polynomials, but the essential “polynomial × exponential” structure is unchanged.
In practice, Jordan blocks of high dimension are computed with a computer algebra system (such as Python’s sympy.jordan_form()) rather than by hand.
The four applications side by side (2×2 Jordan block; the polynomial-times-exponential form for difference equations is restricted to λ=0)
Diagonalizable (gλ=aλ)
Jordan block (gλ<aλ)
An
Pdiag(λn)P−1
nλn−1 appears in the upper right corner (Application 1)
Difference equation xn
superposition of pure exponentials λn
terms of the form nλn appear (Application 2)
eAt
Pdiag(eλt)P−1
teλt appears in the upper right corner (Application 3)
Differential equation x(t)
superposition of pure exponentials eλt
terms of the form teλt appear (Application 4)
The common root: the 2×2 Jordan block here equals λI+N with N2=0, so the binomial expansion or the Taylor expansion terminates after the linear term, which admits a polynomial factor; particular initial values can make its coefficient zero.
The earlier sections of this chapter have already shown NumPy’s basic tools for computing eigenvalues (such as np.linalg.eig()). In this section we explore a few basic iterative numerical methods: the power method and the inverse power method. These methods are especially useful for large matrices or when only particular eigenvalues are needed.
8.5.1 The Power Method: Finding the Largest Eigenvalue Iteratively¶
When we only need the largest eigenvalue of a matrix (the eigenvalue of largest modulus) and its eigenvector, the power method provides a simple and effective iterative algorithm.
First normalize the eigenvectors to unit length. The unimodular coefficient in the equation below is a sign ±1 in the real case and a phase in the complex case; the conclusion is convergence in direction, not necessarily convergence of the vectors themselves. One can show that
that is, the sequence {xk} converges to the direction of the dominant eigenvector v0.
Estimating the eigenvalue with the Rayleigh quotient¶
We estimate the eigenvalue with the Rayleigh quotient; for real symmetric or Hermitian matrices, the error of the eigenvalue estimate can be one order higher than the error of the vector, but this does not change the vector iteration here or its number of iterations:
import numpy as np
# --- Visual hierarchy helpers ---
def print_header(title):
print("=" * 60)
print(f" {title}")
print("=" * 60)
def print_step(step, desc):
print(f"\n▶ Step {step}: {desc}")
print("-" * 40)
def compare_print(label, actual, expected_desc):
print(f"\n[{label}]")
print(f" Computed value: {actual}")
print(f" Expected value: {expected_desc}")
np.set_printoptions(precision=6, suppress=True, linewidth=100)
def power_method(A, tol=1e-10, max_iter=1000):
"""Stop on the scaled eigen-residual; return the estimate, a unit vector, the iteration count, and whether the tolerance was met.
A small residual confirms an approximate eigenpair; singling out the dominant / smallest-modulus one still requires a spectral gap and suitable initial conditions.
"""
A = np.asarray(A)
if A.ndim != 2 or A.shape[0] != A.shape[1] or A.shape[0] == 0:
raise ValueError("A must be a nonempty square matrix")
if tol <= 0 or max_iter < 1:
raise ValueError("tol and max_iter must be positive")
rng = np.random.default_rng(42)
x = rng.random(A.shape[0])
if np.iscomplexobj(A):
x = x + 1j * rng.random(A.shape[0])
x /= np.linalg.norm(x)
scale = np.linalg.norm(A, 2)
for k in range(1, max_iter + 1):
y = A @ x
ynorm = np.linalg.norm(y)
if ynorm == 0:
return np.vdot(x, A @ x) / np.vdot(x, x), x, k, True
x = y / ynorm
value = np.vdot(x, A @ x) / np.vdot(x, x)
residual = np.linalg.norm(A @ x - value * x)
if residual <= tol * (scale + abs(value)):
return value, x, k, True
return value, x, max_iter, False
# ============================================================
print_header("Example 8.5 | Finding the Dominant Eigenvalue by the Power Method")
# ============================================================
# --- Step 1: Define the matrix A ---
print_step("1", "Define the matrix A")
A = np.array([[4, -3, 0],
[-3, 4, 0],
[ 0, 0, 5]])
print(A)
# --- Step 2: Run the power method ---
print_step("2", "Run the power method (tol = 1e-10)")
lambda_max, v_max, iterations, converged = power_method(A)
print(f" Dominant eigenvalue: λ_max = {lambda_max:.10f}")
print(f" Eigenvector: v_max = {v_max}")
print(f" Iterations: {iterations}; tolerance met: {converged}")
# --- Step 3: Verify A v = λ v ---
print_step("3", "Verify the eigenvalue equation Av = λv")
print(" Av =")
print(f" {A @ v_max}")
print(" λv =")
print(f" {lambda_max * v_max}")
compare_print(
"Residual ‖Av − λv‖",
f"{np.linalg.norm(A @ v_max - lambda_max * v_max):.2e}",
"for an exact eigenvector the residual should approach 0"
)
# --- Step 4: Compare with all the eigenvalues from NumPy ---
print_step("4", "Compare with all the eigenvalues from NumPy")
eigs_numpy = sorted(np.linalg.eigvals(A), key=abs, reverse=True)
compare_print(
"Power method λ_max vs NumPy λ₀",
f"{lambda_max:.10f}",
f"NumPy λ₀ = {eigs_numpy[0]:.10f} (sorted by modulus)"
)
print(f"\n All NumPy eigenvalues (in decreasing modulus): {[round(v, 6) for v in eigs_numpy]}")
8.5.2 The Inverse Power Method: Finding the Smallest Eigenvalue¶
The inverse power method is used to compute the smallest eigenvalue of a matrix (smallest in modulus) and its eigenvector. Its core idea is very clever:
The key advantages of the inverse power method are:
No explicit inverse is needed. Each iteration only requires solving the linear system Ay=x.
Numerical stability. For well-conditioned matrices, solving a linear system is more stable than inverting the matrix.
Rate of convergence. It depends on ∣λn−1/λn−2∣ (with the eigenvalues arranged in decreasing order of modulus, the ratio of the eigenvalue of smallest modulus to the one of second-smallest modulus); this conclusion assumes that the matrix is invertible and diagonalizable, that the eigenvalue of smallest modulus is unique, and that the initial vector has a nonzero component along its eigendirection.
import numpy as np
# --- Visual hierarchy helpers ---
def print_header(title):
print("=" * 60)
print(f" {title}")
print("=" * 60)
def print_step(step, desc):
print(f"\n▶ Step {step}: {desc}")
print("-" * 40)
def compare_print(label, actual, expected_desc):
print(f"\n[{label}]")
print(f" Computed value: {actual}")
print(f" Expected value: {expected_desc}")
np.set_printoptions(precision=6, suppress=True, linewidth=100)
# --- Reuse the power method of Example 8.5 ---
def power_method(A, tol=1e-10, max_iter=1000):
"""Stop on the scaled eigen-residual; return the estimate, a unit vector, the iteration count, and whether the tolerance was met.
A small residual confirms an approximate eigenpair; singling out the dominant / smallest-modulus one still requires a spectral gap and suitable initial conditions.
"""
A = np.asarray(A)
if A.ndim != 2 or A.shape[0] != A.shape[1] or A.shape[0] == 0:
raise ValueError("A must be a nonempty square matrix")
if tol <= 0 or max_iter < 1:
raise ValueError("tol and max_iter must be positive")
rng = np.random.default_rng(42)
x = rng.random(A.shape[0])
if np.iscomplexobj(A):
x = x + 1j * rng.random(A.shape[0])
x /= np.linalg.norm(x)
scale = np.linalg.norm(A, 2)
for k in range(1, max_iter + 1):
y = A @ x
ynorm = np.linalg.norm(y)
if ynorm == 0:
return np.vdot(x, A @ x) / np.vdot(x, x), x, k, True
x = y / ynorm
value = np.vdot(x, A @ x) / np.vdot(x, x)
residual = np.linalg.norm(A @ x - value * x)
if residual <= tol * (scale + abs(value)):
return value, x, k, True
return value, x, max_iter, False
def inverse_power_method(A, tol=1e-10, max_iter=1000):
"""Stop on the scaled eigen-residual; return the estimate, a unit vector, the iteration count, and whether the tolerance was met.
A small residual confirms an approximate eigenpair; singling out the dominant / smallest-modulus one still requires a spectral gap and suitable initial conditions.
"""
A = np.asarray(A)
if A.ndim != 2 or A.shape[0] != A.shape[1] or A.shape[0] == 0:
raise ValueError("A must be a nonempty square matrix")
if tol <= 0 or max_iter < 1:
raise ValueError("tol and max_iter must be positive")
rng = np.random.default_rng(42)
x = rng.random(A.shape[0])
if np.iscomplexobj(A):
x = x + 1j * rng.random(A.shape[0])
x /= np.linalg.norm(x)
scale = np.linalg.norm(A, 2)
for k in range(1, max_iter + 1):
y = np.linalg.solve(A, x)
ynorm = np.linalg.norm(y)
if ynorm == 0:
return np.vdot(x, A @ x) / np.vdot(x, x), x, k, True
x = y / ynorm
value = np.vdot(x, A @ x) / np.vdot(x, x)
residual = np.linalg.norm(A @ x - value * x)
if residual <= tol * (scale + abs(value)):
return value, x, k, True
return value, x, max_iter, False
# ============================================================
print_header("Example 8.6 | Finding the Smallest Eigenvalue by the Inverse Power Method")
# ============================================================
# --- Step 1: Define the matrix A ---
print_step("1", "Define the matrix A")
A = np.array([[4, -3, 0],
[-3, 4, 0],
[ 0, 0, 5]], dtype=float)
print(A)
# --- Step 2: Run the inverse power method ---
print_step("2", "Run the inverse power method (tol = 1e-10)")
lambda_min, v_min, iter_min, converged_min = inverse_power_method(A)
print(f" Smallest eigenvalue: λ_min = {lambda_min:.10f}")
print(f" Eigenvector: v_min = {v_min}")
print(f" Iterations: {iter_min}; tolerance met: {converged_min}")
# --- Step 3: Verify A v = λ v ---
print_step("3", "Verify the eigenvalue equation Av = λv")
print(" Av =")
print(f" {A @ v_min}")
print(" λv =")
print(f" {lambda_min * v_min}")
compare_print(
"Residual ‖Av − λv‖",
f"{np.linalg.norm(A @ v_min - lambda_min * v_min):.2e}",
"for an exact eigenvector the residual should approach 0"
)
# --- Step 4: Compare with all the eigenvalues from NumPy ---
print_step("4", "Compare with all the eigenvalues from NumPy")
eigs_numpy = sorted(np.linalg.eigvals(A), key=abs)
compare_print(
"Inverse power method λ_min vs NumPy λ₀ (smallest modulus)",
f"{lambda_min:.10f}",
f"NumPy λ₀ = {eigs_numpy[0]:.10f}"
)
print(f"\n All NumPy eigenvalues (in increasing modulus): {[round(v, 6) for v in eigs_numpy]}")
# --- Step 5: Power method vs inverse power method ---
print_step("5", "Power method vs inverse power method")
lambda_max, _, iter_max, converged_max = power_method(A)
compare_print(
"Dominant eigenvalue λ_max (power method)",
f"{lambda_max:.6f} ({iter_max} iterations, tolerance met: {converged_max})",
"the eigenvalue of largest modulus"
)
compare_print(
"Smallest eigenvalue λ_min (inverse power method)",
f"{lambda_min:.6f} ({iter_min} iterations, tolerance met: {converged_min})",
"the eigenvalue of smallest modulus"
)
print(f"\n Convergence ratio |λ_min / λ_next| = {abs(eigs_numpy[0] / eigs_numpy[1]):.6f}")
print(f" (the smaller this ratio, the faster the inverse power method converges)")
8.6 Summary: From Invariant Directions to a Complete Picture of the Matrix¶
This chapter started from a question that can be stated in almost a single sentence: does a linear transformation have vectors whose “direction stays fixed”? Starting from this question, we followed a tightly linked logical path through five sections and arrived at one of the deepest structure theorems of finite-dimensional linear algebra. Before closing the chapter, it is worth looking back along this path and confirming its place in the book as a whole.
§8.1 set up the language: the characteristic equation det(A−λI)=0 translates the geometric question “which directions are invariant” into the problem of finding the roots of the characteristic polynomial. The fundamental theorem of algebra guarantees that the roots exist over the complex numbers, and geometric intuition tells us how eigenvalues encode stretching, compression, and even reversal along each direction—a two-dimensional rotation through an angle that is not an integer multiple of π has no real eigenvector, which is precisely the algebraic statement that in this case there is no real invariant line.
§8.2 deepened our understanding of eigenvalues: the trace equals the sum of the eigenvalues, and the determinant equals their product; these two equations anchor global properties of the matrix directly to its eigenvalue structure. More important is the inequality 1≤gλ≤aλ between geometric and algebraic multiplicity, which measures precisely how far a matrix is from being diagonalizable. The Cayley–Hamilton theorem builds a bridge between matrices and the algebra of polynomials: every matrix is a solution of its own characteristic equation, and this seemingly magical conclusion is the algebraic foundation of the Jordan theory that follows.
§8.3 answered the global question: if the characteristic polynomial splits completely over the field in use (for example, when working over C) and gλ=aλ for all eigenvalues, then the matrix can be brought to the diagonal form D=P−1AP using eigenvectors as the basis. The similarity invariants (trace, determinant, characteristic polynomial) ensure that a change of basis does not change the essence of the linear transformation. Once diagonalization is achieved, powers of the matrix, functions of the matrix, and even difference equations and systems of differential equations all revolve around scalar operations on the eigenvalues; Binet’s formula for the Fibonacci sequence is the most elegant demonstration of this idea.
§8.4 faced the case of failure honestly: not every matrix is diagonalizable. The Jordan canonical form theorem tells us that even when diagonalization fails, every complex square matrix is similar to a nearly diagonal matrix assembled from Jordan blocks—the sizes of the blocks record the depths of the chains of generalized eigenvectors, and diagonalizability is just the special case in which every Jordan block degenerates to 1×1. This is one of the ultimate classification results of finite-dimensional linear algebra.
§8.5 brought the theory back down to earth: power iteration and the inverse power method use the most basic matrix multiplication (or the solution of linear equations) to approach the dominant eigenvalue and the smallest eigenvalue step by step; the Rayleigh quotient provides an estimate of the eigenvalue; convergence is governed mainly by the spectral ratio and the initial vector; and nontrivial Jordan blocks may also introduce polynomial factors. This path from theory to algorithm embodies the enduring spirit of linear algebra, in which abstraction and computation complement each other.
This chapter does not stand alone. It starts from the determinants of Chapter 7: the characteristic equation det(A−λI)=0 is itself an application of the determinant, and the identity “the determinant equals the product of the eigenvalues” is the most direct bridge between the two chapters. In Chapter 7 the determinant described the factor by which a real linear map scales signed volume, with the ordinary volume factor given by its absolute value; in this chapter that factor is decomposed into the product of the eigenvalues, and its geometric meaning becomes clearer as a result—the matrix scales space separately along each eigendirection, and the determinant is the total product of these scalings.
Chapter 9 introduces inner product structure, and there the theory of eigenvalues takes a qualitative leap. Symmetric (Hermitian) matrices not only have real eigenvalues; their eigenvectors can also be chosen to form a mutually orthogonal basis—diagonalization is then no longer merely an algebraic possibility but the most natural geometric decomposition. Once the spectral decomposition of §9.3 is available, one can see directly that the values of the Rayleigh quotient R(A,x)=x∗Ax/∥x∥2 lie exactly in [λmin,λmax]—the simplest form of the min-max theorem. The similarity invariants discussed in this chapter are refined further, in the context of the symmetric matrices of Chapter 9, into the spectral theorem, which gives a structurally stronger guarantee.
Further on, the singular value decomposition (SVD) of Chapter 11 can be viewed as the natural generalization of eigenvalue theory to non-square matrices: for a general m×n matrix A, the matrices A∗A and AA∗ have the same nonzero eigenvalues, equal to the squares of the nonzero singular values; in their full spectra, the numbers of zero eigenvalues are n−rankA and m−rankA respectively, and the left and right singular vectors are eigenvectors of these two positive semidefinite matrices. The whole language built in this chapter—eigenspaces, algebraic and geometric multiplicity, the minimal polynomial—will be borrowed there, but its object expands from the eigenvalue problem of square matrices to more general matrix factorizations.
If the abstract theory of linear spaces in Chapter 4 laid down the language of the whole book, and the determinants of Chapter 7 supplied the geometric tool of “volume,” then what this chapter does is use eigenvalues and eigenvectors to open up the internal structure of matrices.
Before this, a matrix was still a black box to us: vectors go in, vectors come out, but it is hard to say clearly what the geometric essence of the transformation itself is. Eigenvalue theory gives us a key—find the “principal axis directions” of the matrix and the corresponding scaling ratios, and the geometric behavior of the linear transformation decomposes from a complicated mixture of effects into independent scaling along each eigendirection. From diagonalization to the Jordan canonical form, this decomposition extends from the most ideal case all the way to the most general one, and finally gives a complete picture of the classification in finite-dimensional complex linear algebra.
The influence of this picture reaches far beyond linear algebra itself. The long-term behavior of dynamical systems is determined by the dominant eigenvalue; in quantum mechanics, the eigenvalues of the Hamiltonian operator are the energies of the system; Google’s PageRank algorithm essentially computes the dominant eigenvector of the transition matrix of a Markov chain; and in deep learning, the spectral structure of attention matrices determines a model’s ability to capture long-range dependencies. The eigenvalue problem has flourished for three hundred years precisely because “searching for invariant directions” is itself one of the most pervasive structures in nature and in the world of information.
In this sense, this chapter is not only the end point of one theory but also the starting point of the chapters that follow: with the perspective of eigenvalues, look again at the symmetric matrices of Chapter 9, the quantum operators of Chapter 10, and the singular value decomposition of Chapter 11, and you will find that those more complicated theories are simply different answers, in different settings, to the same core question.