Skip to content
Numerical Calculus

Linear systems on a computer: LU, pivoting, Cholesky and iterative methods

LU factorisation and its cost, partial pivoting with an example, Cholesky, sparse matrices, Jacobi and Gauss-Seidel methods, spectral radius and the residual.

In Geometry and Algebra linear systems were solved with Gaussian elimination on 3×3 matrices. In real problems matrices have thousands or millions of rows: simulating an integrated circuit, finite element structural analysis, reconstructing an image in a CT scan. What matters here is the cost of the computation, stability with respect to rounding and the structure of the matrix. We look at direct methods (LU and Cholesky factorisations) and iterative ones (Jacobi and Gauss-Seidel).

LU factorisation

Gaussian elimination, recording the multipliers used, splits the matrix into the product

    \[ A = L\,U \]

with L lower triangular (1s on the diagonal and the multipliers below) and U upper triangular (the echelon form). The system A\mathbf x = \mathbf b becomes two triangular systems, solved by substitution:

    \[ L\mathbf y = \mathbf b \;\;(\text{forward}),\qquad U\mathbf x = \mathbf y \;\;(\text{backward}) \]

The advantage. The factorisation costs about \tfrac23 n^3 operations, but the two substitutions only 2n^2. If many systems with the same matrix and different right-hand sides must be solved (as in a simulator where only the sources change at each step), you factorise once. With n = 1000: 6.7\times 10^8 operations for the factorisation, 2\times 10^6 for each new right-hand side.

Example.

    \[ A = \begin{pmatrix} 2 & 1 & 1\\ 4 & 3 & 3\\ 8 & 7 & 9\end{pmatrix} = \begin{pmatrix} 1 & 0 & 0\\ 2 & 1 & 0\\ 4 & 3 & 1\end{pmatrix}\begin{pmatrix} 2 & 1 & 1\\ 0 & 1 & 1\\ 0 & 0 & 2\end{pmatrix} \]

The multipliers 2 and 4 eliminate the first column, the 3 the second.

Pivoting

If a zero appears on the diagonal during elimination the method stops; if a very small number appears, you divide by it and rounding errors blow up.

Example. With A = \begin{pmatrix}10^{-20} & 1\\ 1 & 1\end{pmatrix} and \mathbf b = (1, 2), the true solution is about x_1 = x_2 = 1. Without swaps the multiplier is 10^{20}, and in double precision the second row becomes (0, -10^{20}) because 1 - 10^{20} rounds to -10^{20}: you get x_2 = 1 and then x_1 = 0, completely wrong. Swapping the rows before eliminating gives the correct result.

Partial pivoting chooses at each step, as pivot, the entry of largest magnitude in the column, and swaps rows. The multipliers then have magnitude at most 1 and the method is stable in practice. The factorisation becomes PA = LU, with P a permutation matrix. It is the standard method of every numerical library (LAPACK, NumPy, MATLAB).

Symmetric positive definite matrices: Cholesky

If A is symmetric and positive definite (like structural stiffness matrices, covariance matrices, nodal matrices of resistor-only circuits), then

    \[ A = L\,L^T \]

with L lower triangular. The Cholesky factorisation costs half as much as LU (\tfrac13 n^3), needs no pivoting and is always stable. If the square root of a negative number appears during the calculation, the matrix was not positive definite: it is also the fastest way to check.

Sparse matrices

In applications, large matrices are almost all zeros: in a circuit’s nodal matrix, each row has non-zero entries only for directly connected nodes. A full 10^6\times 10^6 matrix would take 8 terabytes in double precision; sparse, with 10 entries per row, 80 megabytes. Sparse direct methods reorder rows and columns to limit fill-in, the zeros that become non-zero during elimination. This is what SPICE and finite element programs do.

Iterative methods

For huge sparse matrices it is often better to start from an estimate \mathbf x^{(0)} and improve it, without ever factorising.

Jacobi. From equation i solve for x_i using the previous iteration’s values for the other unknowns:

    \[ x_i^{(k+1)} = \frac{1}{a_{ii}}\Big(b_i - \sum_{j \ne i}a_{ij}\,x_j^{(k)}\Big) \]

Gauss-Seidel. Like Jacobi, but it uses the values already updated in the same iteration straight away. It usually converges about twice as fast and uses less memory.

Example. 4x + y = 9, x + 3y = 7 (solution x = 20/11 \approx 1.818, y = 19/11 \approx 1.727). Gauss-Seidel from (0, 0): x = 9/4 = 2.25, y = (7 - 2.25)/3 = 1.583; then x = 1.854, y = 1.715; then x = 1.821, y = 1.726. Three steps, three correct digits.

When they converge

Writing the iteration as \mathbf x^{(k+1)} = B\,\mathbf x^{(k)} + \mathbf c, the error is multiplied by B at each step, so the method converges if and only if the spectral radius of B (the largest magnitude of its eigenvalues, Geometry and Algebra lesson) is less than 1. A sufficient condition that is easy to check: the matrix is diagonally dominant, |a_{ii}| \gt \sum_{j \ne i}|a_{ij}| for every row. The nodal matrices of resistive circuits almost always are.

For the largest problems more sophisticated iterative methods are used, such as the conjugate gradient method for symmetric positive definite matrices, which in exact arithmetic reaches the solution in at most n steps and in practice needs far fewer, especially with a good preconditioner.

The residual is not enough

After computing \hat{\mathbf x}, the residual \mathbf r = \mathbf b - A\hat{\mathbf x} is easy to compute, but a small residual does not guarantee an accurate solution. The relative error is bounded by

    \[ \frac{\|\mathbf x - \hat{\mathbf x}\|}{\|\mathbf x\|} \le K(A)\,\frac{\|\mathbf r\|}{\|\mathbf b\|} \]

with K(A) the condition number of the lesson on errors. If K(A) is large, even a tiny residual can hide a large error.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x