AlgoVerse

Solving linear systems

Solve A·x = b by LUP decomposition and two substitutions: L·y = P·b forward, then U·x = y backward; in exact fractions.

With the factorization P·A = L·U, the equation A·x = b becomes two triangular ones:

Read the full explanation ↓
Input:
A 3×3 · b 3×1PDF export

A = [[1, 2, 0], [3, 4, 4], [5, 6, 3]] and b = (3, 7, 8); the solution is x = (−7/5, 11/5, 3/5).

  1. from fractions import Fraction
  2. def solve(A, b):
  3. n = len(A)
  4. if len(b) != n:
  5. return None
  6. a = [[Fraction(x) for x in row] for row in A]
  7. pi = list(range(n))
  8. # 1. P·A = L·U (as on the LUP decomposition page).
  9. for k in range(n):
  10. p = max(range(k, n), key=lambda i: abs(a[i][k]))
  11. if a[p][k] == 0:
  12. return None
  13. pi[k], pi[p] = pi[p], pi[k]
  14. a[k], a[p] = a[p], a[k]
  15. for i in range(k + 1, n):
  16. a[i][k] = a[i][k] / a[k][k]
  17. for j in range(k + 1, n):
  18. a[i][j] = a[i][j] - a[i][k] * a[k][j]
  19. lu = a
  20. # 2. Forward substitution: L·y = P·b.
  21. y = [Fraction(0)] * n
  22. for i in range(n):
  23. y[i] = b[pi[i]][0] - sum(lu[i][j] * y[j] for j in range(i))
  24. # 3. Back substitution: U·x = y.
  25. x = [Fraction(0)] * n
  26. for i in range(n - 1, -1, -1):
  27. x[i] = (y[i] - sum(lu[i][j] * x[j] for j in range(i + 1, n))) / lu[i][i]
  28. return [str(v) for v in x]

Invariant: In back substitution, x[i+1] to x[n−1] are already known, so row i's equation has only one unknown.

Start

pi—
y—
x—

The table is still empty.

Local variables

Orange = changed in this step

A list

[1, 2, 0][3, 4, 4][5, 6, 3]

b list

[3][7][8]

Call stack

  1. solve()line 4
Step 1 of 61
Black = backward · Orange = key stepfactored: 0/1 · forward: 0/3 · backward: 0/3
    Explanation

    The idea

    With the factorization P·A = L·U, the equation A·x = b becomes two triangular ones:

    1. L·y = P·b: since L is lower triangular, y[0] is known right away, then y[1], and so on (forward substitution).
    2. U·x = y: since U is upper triangular, start from the last row: x[n−1], then upward (back substitution).

    Cost

    The factorization costs O(n³), but each substitution only O(n²). For several bs with the same A, factor once. (Computing A⁻¹ and multiplying by b is slower and numerically worse.)

    What to watch in the trace

    • The lu table is L and U in one matrix; the y and x cards fill top down and bottom up, respectively.