Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

 Open In Colab

The Subspace Philosophy

Unlike stationary methods (which continually update a single guess vector), Krylov subspace methods construct a growing set of vector bases (directions) and search within that spanning subspace for the optimal solution.

Because we are building a basis for an nn-dimensional vector space, we would theoretically need at most nn basis vectors. However, the true power of these methods is that they often converge to an acceptable tolerance using significantly fewer than nn vectors!

Conjugate Gradient (CG)

The Conjugate Gradient (CG) method is the gold standard for solving symmetric positive definite (SPD) matrices.

Instead of directly solving Ax=b\mathbf{A}\mathbf{x}=\mathbf{b}, we can reframe the problem as an optimization task. Consider the quadratic surface defined by:

f(x(k))=12x(k)TAx(k)−bTx(k)f(\mathbf{x}^{(k)}) = \frac{1}{2} {\mathbf{x}^{(k)}}^T \mathbf{A} \mathbf{x}^{(k)} - \mathbf{b}^T \mathbf{x}^{(k)}

This surface has an extremum where its gradient is zero:

∇f=dfdx=0⃗=Ax−b0⃗=r\begin{aligned} \nabla f = \frac{d f}{ d \mathbf{x}} = \vec{0} &= \mathbf{A} \mathbf{x} - \mathbf{b} \\ \vec{0} &= \mathbf{r} \end{aligned}

Notice that the gradient is exactly the residual r\mathbf{r}. Therefore, finding the minimum of the surface ff is mathematically identical to solving the linear system!

The surface conception

Why can we now think of a quadratic surface? Why does the matrix A\mathbf{A} need to be symmetric positive definite? This geometric interpretation is only valid if we can think of A\mathbf{A} as the matrix of mixed second derivatives of the surface ff, [∂2f∂x12∂2f∂x1∂x2∂2f∂x2∂x1∂2f∂x22]\begin{bmatrix} \frac{\partial^2 f}{\partial x_1^2} & \frac{\partial^2 f}{\partial x_1 \partial x_2} \\ \frac{\partial^2 f}{\partial x_2 \partial x_1} & \frac{\partial^2 f}{\partial x_2^2} \\ \end{bmatrix} (called the Hessian of ff). This is only possible if A\mathbf{A} is symmetric!

Furthermore, if A\mathbf{A} is positive definite (xTAx>0\mathbf{x}^T \mathbf{A} \mathbf{x} > 0), the quadratic surface is strictly convex (opening upwards like a bowl). This guarantees that the extremum is a global minimum, and that walking “downhill” on the surface will inevitably lead us to the exact solution!

If A\mathbf{A} isn’t positive definite the surface is called a saddle point because if curves upwards in some direction and downwards in others.

Step length

To walk down the bowl towards the minimum, we start at a guess x(k)\mathbf{x}^{(k)}. We must choose a step direction s(k)\mathbf{s}^{(k)} and a step length αk\alpha_k to reach our next, better guess x(k+1)\mathbf{x}^{(k+1)}:

x(k+1)=x(k)+αks(k)\mathbf{x}^{(k+1)} = \mathbf{x}^{(k)} + \alpha_k \mathbf{s}^{(k)}

The magic of these methods lies entirely in how we choose the step direction. To understand this, we will approach this problem backwards:

  1. Find the optimal αk\alpha_k assuming we already have s(k)\mathbf{s}^{(k)}

  2. Find the suitable direction s(k)\mathbf{s}^{(k)}

Given a step direction, an obvious choice for the length αk\alpha_k is whatever minimizes f(x(k+1))f(\mathbf{x}^{(k+1)}) along that specific ray. By setting the derivative with respect to αk\alpha_k to zero, we find the optimal step length:

f(x⃗+αks⃗k)=12[x⃗+αks⃗k]TA[x⃗+αks⃗k]−b⃗T[x⃗+αks⃗k]∂f∂αk=0=s⃗kTA[x⃗+αks⃗k]−b⃗Ts⃗k=s⃗kTAx⃗k+s⃗kTAαks⃗k−s⃗kTb⃗=s⃗kT[Ax⃗k−b⃗]+αks⃗kTAs⃗k\begin{align} f(\vec{x}+\alpha^k \vec{s}^k) &= \frac{1}{2} [\vec{x}+\alpha^k \vec{s}^k]^T A [\vec{x}+\alpha^k \vec{s}^k] -\vec{b}^T [\vec{x}+\alpha^k \vec{s}^k] \\ \frac{\partial f}{\partial \alpha^k} = 0 &= {\vec{s}^k}^T A [\vec{x}+\alpha^k \vec{s}^k] -\vec{b}^T \vec{s}^k\\ &= {\vec{s}^k}^T A \vec{x}^k+ {\vec{s}^k}^T A \alpha^k \vec{s}^k -{\vec{s}^k}^T \vec{b} \\ &= {\vec{s}^k}^T [A \vec{x}^k-\vec{b}] + \alpha^k {\vec{s}^k}^T A \vec{s}^k \end{align}

and therefore the optimal step size is:

αk=s(k)Tr(k)s(k)TAs(k)\begin{aligned} \alpha_k &= \frac{{\mathbf{s}^{(k)}}^T \mathbf{r}^{(k)}}{{\mathbf{s}^{(k)}}^T \mathbf{A} \mathbf{s}^{(k)}} \end{aligned}

So, given any step direction s(k)\mathbf{s}^{(k)}, we can always calculate the mathematically optimal distance to travel.

Step Direction: Steepest Descent

The most intuitive choice is to simply walk straight downhill following the steepest gradient of the surface. We already proved the gradient is the residual, so:

s(k)=−∇f=r(k)\mathbf{s}^{(k)} = -\nabla f = \mathbf{r}^{(k)}

Substituting this into our step length formula yields the classic Steepest Descent algorithm! Let’s code it up and visualize the path it takes down the 2D contour.

Notice the zig-zag path the Steepest Descent algorithm takes. It frantically zig-zags back and forth across the ravine! Why? Because taking the steepest path down often forces the next step to partially undo the progress of the previous step. In an nn-dimensional space, this inefficiency becomes catastrophic.

Step Direction: Conjugate Gradient

To fix the zig-zagging, we must choose step directions that strictly do not undo each other. We enforce this by requiring that every new step direction is conjugate (orthogonal with respect to A\mathbf{A}) to all previous step directions:

s(k+1)TAs(k)=0{\mathbf{s}^{(k+1)}}^T \mathbf{A} \mathbf{s}^{(k)} = 0

This ensures the steps are linearly independent. By building the next direction from a combination of the current residual and the previous direction, we derive the Conjugate Gradient update rule:

s(k+1)=r(k+1)−r(k+1)TAs(k)s(k)TAs(k)s(k)\mathbf{s}^{(k+1)} = \mathbf{r}^{(k+1)} - \frac{{\mathbf{r}^{(k+1)}}^T \mathbf{A} \mathbf{s}^{(k)}}{{\mathbf{s}^{(k)}}^T \mathbf{A} \mathbf{s}^{(k)}} \mathbf{s}^{(k)}

Let’s use scipy.sparse.linalg.cg to see how beautifully this solves the zig-zag problem!

Verifing the properties

As shown in the plot, CG walks directly to the center of the bowl. We can mathematically verify that the steps are indeed conjugate in A\mathbf{A}, (s2TAs1=0{\mathbf{s}^{2}}^T \mathbf{A} \mathbf{s}^{1} =0). It can also be shown that subsequent residuals are also (standard) orthogonal.

Is CG a direct method?

Note the space of the solution vector x\mathbf{x} is just its dimension nn, and if CG determins linearly independent vectors, it can only find, at most nn! Therefore, CG will find the exact solution in nn iterations (baring roundoff error) which some may take to imply it is a direct method. However, the situation is even better, which qualifies it as an iterative technique! Let’s see what happens with a larger system:

Restart and Matrix free methods

Restart: In extreme-scale computations, round-off error can slowly destroy the strict conjugacy of the vectors. Many implementations include a restart parameter that periodically flushes the basis history to keep the algorithm stable.

Matrix-free methods Notice that CG only ever uses A\mathbf{A} to compute matrix-vector products (Ax\mathbf{A} \mathbf{x}). If we can calculate Ax\mathbf{A}\mathbf{x} directly on-the-fly without ever assembling or storing the massive dense matrix A\mathbf{A}, we can save colossal amounts of RAM. This is the foundation of matrix-free HPC solvers!

Generalized Minimal Residual Method (GMRES)

What if A\mathbf{A} is not symmetric?

The GMRES method

f A\mathbf{A} is non-symmetric, it cannot be a Hessian, and the beautiful quadratic bowl surface analogy falls apart. We can no longer enforce A\mathbf{A}-conjugacy.

Instead, we use the Generalized Minimal Residual (GMRES) method. GMRES abandons the bowl analogy and directly minimizes the Euclidean norm of the residual ∣∣Ax−b∣∣||\mathbf{A}\mathbf{x}-\mathbf{b}||. Step directions, sk\mathbf{s}^k are chosen to be orthogonal which is a more general, but less powerful condition. The method will still converge in at most nn iterations (barring roundoff error), but typically converges sooner (not as quickly as CG however).

Because it must enforce standard orthogonality against all previous search directions, its memory footprint grows with every iteration. Therefore, GMRES almost always requires a restart parameter to prevent memory exhaustion on large systems!

CG vs GMRES: Residual Comparison

Now that we understand GMRES, let’s see what happens if we use it to solve a newly generated random 8×88 \times 8 symmetric positive definite matrix and compare it directly to Conjugate Gradient.

Notice something fascinating in the plot below: The Euclidean residual for Conjugate Gradient is not strictly monotonically decreasing. This is a fundamental mathematical property of Conjugate Gradient.

  • Methods like GMRES are designed to strictly minimize the Euclidean norm of the residual at every step.

  • Conjugate Gradient minimizes the energy norm; ΔxTAΔx\sqrt{ \Delta \mathbf{x}^T \mathbf{A} \Delta \mathbf{x} }.

While the energy norm drops monotonically at every single step of CG, the standard Euclidean residual is free to oscillate along the way. This is a brilliant pedagogical reminder of exactly what surface the CG algorithm is navigating!

Notice also how GMRES never exceeds n=8n=8 iterations, but CG often takes 9 or 10? In exact mathematical theory, both algorithms guarantee exact convergence in at most nn steps. However, in finite precision floating-point arithmetic, CG’s reliance on only the previous two vectors (the 3-term recurrence) causes it to slowly lose orthogonality over time, wandering back into previously searched subspaces. GMRES explicitly stores and orthogonalizes against every previous vector, remaining mathematically rigid.

Why use CG if GMRES is smoother?

Looking at the plot above, GMRES seems vastly superior. Its residual drops perfectly smoothly, while CG violently spikes up and down. Since GMRES strictly minimizes the Euclidean residual at every step, why do we use CG for symmetric positive definite matrices?

The answer is Computational Cost and Memory:

  1. GMRES remembers everything: To ensure each new search direction is perfectly orthogonal, GMRES must store every single previous step direction in RAM, and compute dot products against all of them. For a 1-million dimension system taking 10,000 iterations, GMRES would exhaust all available memory, requiring harsh restart parameters that cripple its convergence.

  2. The CG Miracle: Because the matrix is symmetric, the math in Conjugate Gradient collapses beautifully. CG only needs to remember the last two search directions to guarantee conjugacy against all previous steps! It requires constant memory and constant compute per iteration.

So while GMRES takes a more direct path, it does massive amounts of hidden work at each step to achieve it. CG meanders in the Euclidean norm, but it computes incredibly cheaply with a microscopic memory footprint!

Performance Benchmark

To truly appreciate the computational difference between these two algorithms, let’s race them on a much larger system.

We will generate a 2000×20002000 \times 2000 symmetric positive definite matrix and use Jupyter’s %timeit magic command to see how long it takes each solver to converge. Because Conjugate Gradient uses only 2 search directions to compute the next, it should reliably outperform GMRES (which must orthogonalize against a growing history of vectors) on symmetric systems.