Computing Library › Worked Examples
Worked Examples

Solving a Linear System by Jacobi Iteration

Solve Ax = b without factoring the matrix by repeatedly updating each unknown from the previous sweep's values.

The splitting

Split A = D + R, where D is the diagonal and R the rest. Rearranging Ax = b gives x = D^-1 (b - R x). Jacobi turns this into an iteration: x_new[i] = (b[i] - sum of A[i,j] x_old[j] for j != i) / A[i,i]. Every new component uses only old values.

python
import numpy as np
A=np.array([[4.0,1.0,0.0],[1.0,5.0,1.0],[0.0,1.0,3.0]])
b=np.array([5.0,7.0,4.0])
x=np.zeros(3); D=np.diag(A)
for it in range(100):
    xnew=(b-(A@x-D*x))/D
    if np.max(np.abs(xnew-x))<1e-10: break
    x=xnew
print(np.round(x,5),'in',it,'iters')
Kronos motion — training from sim

Convergence condition

Jacobi converges if A is strictly diagonally dominant - each diagonal entry exceeds the sum of the absolute values of the others in its row. More generally it converges when the spectral radius of the iteration matrix D^-1 R is below 1. The smaller that radius, the faster it converges.

Why iterate instead of factor

Direct methods like LU cost order n^3 and fill in sparse matrices. Jacobi uses only matrix-vector products, preserves sparsity, and parallelizes trivially because every component updates independently from the same old vector. For the huge sparse systems from discretized PDEs, that scalability wins.

Relation to Gauss-Seidel

Using each freshly computed component immediately, rather than waiting for the next sweep, gives Gauss-Seidel, which typically converges about twice as fast but is harder to parallelize. Adding over-relaxation on top yields SOR, faster still when its parameter is tuned.