Quant Memo
Core

LU Decomposition

Splitting a matrix into a lower-triangular and upper-triangular piece — turning one hard system of equations into two easy ones, and the standard way computers actually solve Ax=b.

Prerequisites: Matrix Inverses and Linear Systems, Determinants

Solving Ax=bAx=b by literally computing A1A^{-1} is the way to think about it, but real numerical code almost never does that — it's wasteful and less stable. Instead, computers split AA into two simpler triangular pieces and solve two easy triangular systems in sequence. LU decomposition is that split, and it's the standard machinery quietly running behind almost every "solve this linear system" call in scientific computing.

An analogy: undoing a knot by tracking each step

Solving a general system all at once is like untangling a big knot in one motion — hard to see how. LU decomposition is like methodically recording, one crossing at a time, exactly how the knot was tied (that's the "L," lower-triangular, recording each elimination step) and what shape is left after all the tying (that's the "U," upper-triangular, the simplified end result). Once you have both records, undoing the whole knot for a new starting pull is fast: replay the L record forward, then unwind the U record backward — each in one simple pass, no more searching.

The mathematics, one symbol at a time

LU decomposition factors a square matrix AA as

A=LU,A = LU,

where LL is lower-triangular (all entries above the diagonal are zero, with 1s on the diagonal) and UU is upper-triangular (all entries below the diagonal are zero). In words: LL records the row-elimination steps used to reduce AA to the simplified triangular form UU — exactly the steps you'd do by hand doing Gaussian elimination, just kept track of and reusable. To solve Ax=bAx=b, substitute: LUx=bLUx=b. Let y=Uxy=Ux, first solve Ly=bLy=b for yy (easy: triangular systems solve top-to-bottom by simple substitution, no elimination needed), then solve Ux=yUx=y for xx (easy again: triangular, bottom-to-top). Two easy triangular solves replace one hard general solve — and once LL and UU are computed, solving for many different right-hand sides bb is cheap, since the expensive factorization step only needs to be done once.

Worked example 1: factoring a 2×2 matrix by hand

Let A=(4363)A = \begin{pmatrix} 4 & 3 \\ 6 & 3 \end{pmatrix}. Eliminate the first column below the pivot: the multiplier is 6/4=1.56/4=1.5; subtract 1.5 times row 1 from row 2: new row 2 is (61.5(4), 31.5(3))=(0,1.5)(6-1.5(4),\ 3-1.5(3)) = (0, -1.5). So U=(4301.5)U = \begin{pmatrix}4 & 3\\0&-1.5\end{pmatrix} and L=(101.51)L = \begin{pmatrix}1&0\\1.5&1\end{pmatrix} (the multiplier recorded below the diagonal). Check: LU=(101.51)(4301.5)=(4364.51.5)=(4363)LU = \begin{pmatrix}1&0\\1.5&1\end{pmatrix}\begin{pmatrix}4&3\\0&-1.5\end{pmatrix} = \begin{pmatrix}4&3\\6&4.5-1.5\end{pmatrix}=\begin{pmatrix}4&3\\6&3\end{pmatrix} ✓.

Worked example 2: solving with the factorization, two right-hand sides

Solve Ax=b1Ax=b_1 with b1=(10,12)b_1=(10,12). First Ly=b1Ly=b_1: y1=10y_1=10, 1.5y1+y2=12y2=1215=31.5y_1+y_2=12 \Rightarrow y_2=12-15=-3. Then Ux=yUx=y: 1.5x2=3x2=2-1.5x_2=-3 \Rightarrow x_2=2; 4x1+3(2)=10x1=(106)/4=14x_1+3(2)=10 \Rightarrow x_1=(10-6)/4=1. So x=(1,2)x=(1,2). Now a second right-hand side arrives, b2=(7,9)b_2=(7,9) — no need to refactor AA at all: Ly=b2Ly=b_2 gives y1=7y_1=7, y2=91.5(7)=1.5y_2=9-1.5(7)=-1.5; Ux=yUx=y gives x2=1x_2=1, x1=(73)/4=1x_1=(7-3)/4=1. Reusing the same L,UL,U made the second solve nearly free — exactly why LU is the standard choice when the same matrix (say, a fixed hedge structure) is solved against many different target vectors over time.

A (general) L (lower tri.) = U (upper tri.)
A general matrix A splits into a lower-triangular L (elimination steps) and upper-triangular U (simplified end result) — the same L and U are reused for solving against any number of different right-hand sides.
Ly = b forward substitution Ux = y backward substitution
Once A is factored, solving for x is just two cheap triangular substitutions rather than one expensive general solve.

What this means in practice

LU decomposition is what's actually running under the hood of numpy.linalg.solve and virtually every production linear-solve routine, and it's also how determinants are computed efficiently in practice — det(A)=det(L)det(U)\det(A) = \det(L)\det(U), and triangular matrix determinants are just the product of their diagonal entries. Any repeated-solve scenario (recomputing hedge weights against a fixed factor structure but changing target exposures daily) benefits from factoring once and reusing L,UL,U repeatedly.

LU decomposition writes A=LUA=LU as a lower-triangular times an upper-triangular matrix, turning one hard system Ax=bAx=b into two easy triangular solves; the expensive factorization step is done once and reused cheaply for any number of different right-hand sides.

Plain LU decomposition can fail or become numerically unstable if a pivot (a diagonal entry used as a divisor during elimination) is zero or very small, even when AA itself is perfectly well-behaved and invertible — the fix used in practice is "LU with partial pivoting," which reorders rows to always divide by the largest available pivot. Don't assume a library's plain LU call is safe on an arbitrary matrix without pivoting; nearly every real implementation includes it by default, but it's worth knowing it's there and why.

Related concepts

Practice in interviews

Further reading

  • Golub & Van Loan, Matrix Computations, ch. 3
  • Trefethen & Bau, Numerical Linear Algebra, lecture 20
ShareTwitterLinkedIn