Mathematics · 2023

Exponentiation
by Matrices

How eigendecomposition turns a matrix differential equation into a closed-form solution, and what phase portraits reveal about long-run behavior. Advanced Topics Math, 2023.

Given a matrix and an initial state , the differential equation has the exact solution . The catch: computing the matrix exponential directly is expensive. Eigendecomposition provides a shortcut that reduces the problem to scalar exponentials, one per eigenvalue of .

This project builds the intuition from first principles, implements interactive phase-plane visualizations in Python, and explores how the sign and magnitude of eigenvalues dictate qualitatively different long-run behaviors.

Context
Advanced Topics Mathematics, senior year
Tools
PythonNumPyMatplotlibipywidgets
Topics
Eigendecomposition · matrix exponential · phase planes · linear ODEs · Euler's method
The Problem

A linear autonomous system is a differential equation of the form:

System of ODEs

where is a constant matrix and is the state we want to find. In 2D this describes trajectories in the plane. Each point has a velocity attached to it, forming a vector field.

The exact solution is the matrix exponential:

Exact solution

This generalizes the scalar case: when , the solution to is .

The matrix exponential is defined by a power series:

Definition

This converges for any square matrix , but computing many matrix powers is per term — expensive. Eigendecomposition replaces those matrix multiplications with cheap scalar ones.

Key property

If , then . The matrix exponential inherits the eigenstructure of .

Eigendecomposition

A nonzero vector is an eigenvector of if applying only scales it, never rotates it:

Eigenvalue equation

Collecting eigenvectors as columns of and eigenvalues on the diagonal of :

Matrix form

This holds whenever has linearly independent eigenvectors (the diagonalizable case, which covers most matrices in practice).

Substituting into the power series, every , so:

Key simplification

Because is diagonal, its exponential is just:

Diagonal matrix exponential

The full closed-form solution is:

Closed-form solution
Three-Step Computation
Solution steps
Solution steps
Computing in three steps: (1) project into the eigenvector basis with ; (2) apply scalar growth/decay along each eigendirection; (3) project back with .
Scalar exponentials
Scalar exponentials
The diagonal entries of . Negative eigenvalues produce exponential decay (stable modes); positive ones grow without bound (unstable modes). The rate is , the time constant .

In the eigenvector basis , the system decouples completely:

Decoupled in eigenbasis

Each coordinate evolves independently as a scalar exponential. Coupling only reappears when projecting back into the original basis with .

Equivalently, the solution is a superposition of modes:

Modal decomposition

Each mode decays or grows along its eigenvector direction. Long-run behavior is dominated by the mode with the largest real part of .

Phase Portraits

A phase portrait overlays the vector field with solution curves for many initial conditions simultaneously. The qualitative shape — whether trajectories converge, diverge, spiral, or oscillate — is entirely determined by the eigenvalues of . Dashed lines mark eigenvector directions.

Stable node
Stable node
Stable node: both eigenvalues real and negative, . All trajectories converge to the origin. Near the origin, curves align with the slower eigenvector (smaller ).
Unstable node
Unstable node
Unstable node: both eigenvalues real and positive, . Trajectories diverge from the origin. Equivalent to replacing with in the stable case.
Saddle point
Saddle point
Saddle point: eigenvalues of opposite sign, . Trajectories are attracted along the stable manifold (gold dashes) and repelled along the unstable manifold (red dashes). Almost all initial conditions eventually escape to infinity.
Stable spiral
Stable spiral
Stable spiral: complex eigenvalues with . Trajectories rotate with angular frequency while decaying at rate . Pure imaginary () gives closed orbits — a center.
Project: convergent field
Project: convergent field
Phase portrait from the project. The matrix was constructed interactively by entering two eigenvectors and eigenvalues; the code reconstructed and plotted the resulting vector field and integral curves in real time.
Project: Euler's method path
Project: Euler's method path
The orange path traces a single solution using Euler's method with step size . Each step computes , following the vector field numerically. At small this closely matches the analytic solution .
Euler's Method

Euler's method approximates the solution by taking small linear steps along the vector field:

Euler update rule

After steps of size :

N steps

This limit is exactly the compound-interest definition of the exponential, now applied to matrices. It connects numerical integration directly to the analytic formula.

Euler integration (forward + backward)
def generate_path(x0, A, steps=1000):
    fwd = [x0]
    for _ in range(steps):           # forward in time
        fwd.append(fwd[-1] + A @ fwd[-1] / steps)

    bwd = [x0]
    for _ in range(steps):           # backward in time
        bwd.append(bwd[-1] - A @ bwd[-1] / steps)

    return np.concatenate([bwd[::-1], fwd[1:]])
Build the vector field
X, Y = np.meshgrid(np.arange(-15, 16), np.arange(-15, 16))
U = A[0,0]*X + A[0,1]*Y   # ẋ₁ = a₁₁x₁ + a₁₂x₂
V = A[1,0]*X + A[1,1]*Y   # ẋ₂ = a₂₁x₁ + a₂₂x₂
mag = np.hypot(U, V)
ax.quiver(X, Y, U/mag, V/mag, pivot='mid')
Reconstructing A from Eigenpairs

The interactive part of the project lets a user specify eigenvectors and eigenvalues directly. Given and :

Reconstruction

The resulting is guaranteed to have exactly those eigenpairs. Flipping eigenvalue signs immediately transforms a stable phase portrait into an unstable one — making the connection between eigenvalues and long-run behavior viscerally clear.

Reconstruct A from eigenpairs
def make_A(eigenvectors, eigenvalues):
    V      = np.column_stack(eigenvectors)
    Lambda = np.diag(eigenvalues)
    return V @ Lambda @ np.linalg.inv(V)   # A = V Λ V⁻¹

# Stable node: both eigenvalues negative
A = make_A([[1, 0], [0, 1]], [-1, -3])
# → [[-1,  0],
#    [ 0, -3]]

# Saddle: mixed signs
A = make_A([[1, 0], [0, 1]], [-1, 2])
# → [[-1,  0],
#    [ 0,  2]]
Key Takeaway

The solution to is entirely determined by the eigenstructure of . Each eigenvalue contributes a mode to the solution. Negative real parts produce decay; positive real parts produce growth; imaginary parts produce oscillation. The phase portrait makes all three readable at a glance.