Skip to content

Systems of Linear Equations

Linear algebra was born from one deceptively simple question: given several linear constraints, what values satisfy all of them at once? That question is a system of linear equations, and it shows up everywhere — from mixing ingredients in a factory to fitting a regression line through data.

The book opens the entire chapter with it, and for a reason worth stating up front: “many problems can be formulated as systems of linear equations, and linear algebra gives us the tools for solving them.”

  • What makes an equation linear, and why that restriction is what makes the subject tractable.
  • The three — and only three — possible solution sets, and how to tell them apart geometrically.
  • The compact forms Ax=b\mathbf{A}\mathbf{x} = \mathbf{b} and jxjaj=b\sum_j x_j \mathbf{a}_j = \mathbf{b}, and why the second is the more revealing one.
  • Why “no exact solution” is the normal case in machine learning, not a failure.
  • What LinAlgError: Singular matrix is actually telling you.

Imagine a small workshop that makes two products, tables and chairs. Each needs wood and labour:

  • A table uses 4 units of wood and 2 hours of labour.
  • A chair uses 1 unit of wood and 2 hours of labour.

This week you have 5 units of wood and 6 hours of labour, and you want to use them up exactly — no waste. How many tables x1x_1 and chairs x2x_2 should you make?

Each resource gives you one equation:

4x1+1x2=5(wood)2x1+2x2=6(labour)\begin{aligned} 4x_1 + 1x_2 &= 5 \quad \text{(wood)}\\ 2x_1 + 2x_2 &= 6 \quad \text{(labour)} \end{aligned}

Two equations, two unknowns. This is a system of linear equations, and it is the book’s own motivating example in miniature: products consuming resources, and an optimal plan being exactly a solution with nothing left over.

diagram Diagram mermaid

With mm equations and nn unknowns x1,,xnx_1, \dots, x_n:

a11x1+a12x2++a1nxn=b1a21x1+a22x2++a2nxn=b2    am1x1+am2x2++amnxn=bm\begin{aligned} a_{11}x_1 + a_{12}x_2 + \cdots + a_{1n}x_n &= b_1\\ a_{21}x_1 + a_{22}x_2 + \cdots + a_{2n}x_n &= b_2\\ &\;\;\vdots\\ a_{m1}x_1 + a_{m2}x_2 + \cdots + a_{mn}x_n &= b_m \end{aligned}

The aija_{ij} are known coefficients, the bib_i known constants, and the xjx_j the unknowns. Any nn-tuple (x1,,xn)(x_1, \dots, x_n) satisfying every equation simultaneously is a solution.

Two compact forms, and why the second one matters more

Section titled “Two compact forms, and why the second one matters more”

Collecting coefficients into a matrix gives the form everyone knows:

[a11a1nam1amn][x1xn]=[b1bm]Ax=b\begin{bmatrix} a_{11} & \cdots & a_{1n}\\ \vdots & & \vdots\\ a_{m1} & \cdots & a_{mn}\end{bmatrix} \begin{bmatrix} x_1 \\ \vdots \\ x_n \end{bmatrix} = \begin{bmatrix} b_1 \\ \vdots \\ b_m \end{bmatrix} \qquad\Longleftrightarrow\qquad \mathbf{A}\mathbf{x} = \mathbf{b}

But the book writes it a second way first, and that ordering is deliberate:

x1[a11am1]+x2[a12am2]++xn[a1namn]=[b1bm]x_1\begin{bmatrix} a_{11}\\ \vdots\\ a_{m1}\end{bmatrix} + x_2\begin{bmatrix} a_{12}\\ \vdots\\ a_{m2}\end{bmatrix} + \cdots + x_n\begin{bmatrix} a_{1n}\\ \vdots\\ a_{mn}\end{bmatrix} = \begin{bmatrix} b_1\\ \vdots\\ b_m\end{bmatrix}

Read that carefully. The unknowns are scaling the columns. So solving Ax=b\mathbf{A}\mathbf{x} = \mathbf{b} is asking: can b\mathbf{b} be built as a weighted combination of the columns of A\mathbf{A}, and if so, with which weights?

That reframing is the single most useful sentence in this chapter, because it converts a question about equations into a question about reach: is b\mathbf{b} inside the set of things the columns can build? §2.5 names that set the span, §2.6 measures it as the rank, and §2.7 calls it the image. Three sections, one question, first asked here.

For a real-valued system there are only three possibilities: no solution, exactly one, or infinitely many. Nothing else can happen — you cannot have exactly two.

With two unknowns, each equation is a line in the x1x2x_1x_2-plane, and a solution must lie on all lines at once, so the solution set is their intersection:

linesintersectionsolutions
cross at a pointa pointexactly one
parallel, distinctemptynone
identicalthe whole lineinfinitely many

With three unknowns each equation is a plane, and intersecting planes gives a plane, a line, a point, or nothing — the same three outcomes, one dimension up. The book states this generalisation explicitly and it keeps holding: in Rn\mathbb{R}^n each equation is a hyperplane, and the solution set is an intersection of hyperplanes.

Why “exactly two” is impossible is worth seeing, because it is the first place the structure shows. Suppose x\mathbf{x} and y\mathbf{y} are both solutions. Then for any λ\lambda,

A(λx+(1λ)y)=λAx+(1λ)Ay=λb+(1λ)b=b,\mathbf{A}\bigl(\lambda\mathbf{x} + (1-\lambda)\mathbf{y}\bigr) = \lambda\mathbf{A}\mathbf{x} + (1-\lambda)\mathbf{A}\mathbf{y} = \lambda\mathbf{b} + (1-\lambda)\mathbf{b} = \mathbf{b},

so the whole line through them is made of solutions. Two solutions therefore force infinitely many. Linearity does not permit a finite crowd.

Back to the tables and chairs:

4x1+x2=52x1+2x2=6\begin{aligned} 4x_1 + x_2 &= 5\\ 2x_1 + 2x_2 &= 6 \end{aligned}

From the second equation, x1+x2=3x_1 + x_2 = 3, so x2=3x1x_2 = 3 - x_1. Substituting into the first:

4x1+(3x1)=5    3x1=2    x1=23,x2=323=73.4x_1 + (3 - x_1) = 5 \;\Longrightarrow\; 3x_1 = 2 \;\Longrightarrow\; x_1 = \tfrac{2}{3}, \qquad x_2 = 3 - \tfrac{2}{3} = \tfrac{7}{3}.

Two-thirds of a table is not a useful production plan, which is a nice reminder that “solvable” and “meaningful” are different questions — but it is the unique solution.

Now the book’s own geometric example, and every step by hand:

4x1+4x2=52x14x2=1\begin{aligned} 4x_1 + 4x_2 &= 5\\ 2x_1 - 4x_2 &= 1 \end{aligned}

Adding the two equations kills x2x_2 outright: 6x1=66x_1 = 6, so x1=1x_1 = 1. Back-substituting into the first, 4+4x2=54 + 4x_2 = 5, so x2=14x_2 = \tfrac14. The solution is (1,14)(1, \tfrac14) — exactly the point the book’s Figure 2.3 marks.

And a system of each of the three kinds, checked in full:

systemmanipulationoutcome
x1+x2=3x_1 + x_2 = 3, x1x2=1x_1 - x_2 = 1add: 2x1=42x_1 = 4one: (2,1)(2, 1)
x1+x2=3x_1 + x_2 = 3, x1+x2=1x_1 + x_2 = 1subtract: 0=20 = 2none — a contradiction
x1+x2=3x_1 + x_2 = 3, 2x1+2x2=62x_1 + 2x_2 = 6halve the second: identicalinfinitely many: (t,3t)(t, 3-t)

The middle row is the one to remember. Elimination did not fail or get stuck; it produced the perfectly well-formed statement 0=20 = 2, which is false. Inconsistency shows up as a false arithmetic claim, and that is precisely what §2.3’s elimination procedure is built to surface.

Two lines. The amber one is fixed; the blue one sweeps through all three regimes. The white dot marks the solution when it exists — watch it fly off to infinity as the lines become parallel, then the lines merge.

sketch The three solution regimes of a 2-variable system p5.js
Two lines on the plane. The amber line is fixed; the blue line sweeps from crossing it (one solution) to parallel (no solution) to coincident (infinitely many). The white dot is the unique solution when it exists.

Watch the det readout in the corner. It slides towards zero as the lines become parallel and hits zero exactly when the regime changes. That number is the determinant (§4.1), and it is the single quantity deciding which of the three cases you are in — the sketch is showing you §4.1’s punchline two chapters early.

Elimination on the workshop system, one row operation per frame. The pivot is ringed; the row being rewritten is amber, and the row doing the rewriting is blue.

matrixThe workshop system, eliminatedreduced row echelon form
415226
pivot columns none yetrank 0
pivots0rank so far0
setupThe augmented matrix. The last column is the right-hand side; every row is one equation.
1/13

Two pivots for two unknowns means exactly one solution, and the reduced form puts it in the right-hand column.

Two pivots for two unknowns — that is what “exactly one solution” looks like mechanically, and §2.3 turns the observation into the general procedure.

solve_system.py
import numpy as np
 
# ---- the workshop system -------------------------------------------------
# 4*x1 + 1*x2 = 5   (wood)
# 2*x1 + 2*x2 = 6   (labour)
A = np.array([[4.0, 1.0],
              [2.0, 2.0]])
b = np.array([5.0, 6.0])
 
x = np.linalg.solve(A, b)
print("tables x1 =", round(x[0], 4), " chairs x2 =", round(x[1], 4))
print("check A @ x =", A @ x)
print("determinant :", np.linalg.det(A))
 
# ---- the columns view: x scales the columns ------------------------------
c1, c2 = A[:, 0], A[:, 1]
print("x1*c1 + x2*c2 =", x[0] * c1 + x[1] * c2, " == b:", np.allclose(x[0] * c1 + x[1] * c2, b))
 
# ---- the book's Figure 2.3 system ---------------------------------------
A2 = np.array([[4.0, 4.0], [2.0, -4.0]])
b2 = np.array([5.0, 1.0])
print("\nFigure 2.3 solution:", np.linalg.solve(A2, b2))
 
# ---- the three regimes, detected rather than guessed --------------------
def classify(A, b):
    """Rank of A versus rank of the augmented matrix decides the regime."""
    rank_A = np.linalg.matrix_rank(A)
    rank_Ab = np.linalg.matrix_rank(np.c_[A, b])
    n = A.shape[1]
    if rank_A < rank_Ab:
        return "no solution"
    return "exactly one" if rank_A == n else f"infinitely many ({n - rank_A} free)"
 
cases = {
    "crossing":  (np.array([[1.0, 1.0], [1.0, -1.0]]), np.array([3.0, 1.0])),
    "parallel":  (np.array([[1.0, 1.0], [1.0,  1.0]]), np.array([3.0, 1.0])),
    "identical": (np.array([[1.0, 1.0], [2.0,  2.0]]), np.array([3.0, 6.0])),
}
print()
for name, (M, v) in cases.items():
    print(f"{name:10s} rk(A)={np.linalg.matrix_rank(M)}  "
          f"rk(A|b)={np.linalg.matrix_rank(np.c_[M, v])}  ->  {classify(M, v)}")
 
# ---- what solve does when there is not exactly one solution -------------
try:
    np.linalg.solve(cases["parallel"][0], cases["parallel"][1])
except np.linalg.LinAlgError as e:
    print("\nsolve on the parallel case:", e)
text
tables x1 = 0.6667  chairs x2 = 2.3333
check A @ x = [5. 6.]
determinant : 6.0
x1*c1 + x2*c2 = [5. 6.]  == b: True
 
Figure 2.3 solution: [1.   0.25]
 
crossing   rk(A)=2  rk(A|b)=2  ->  exactly one
parallel   rk(A)=1  rk(A|b)=2  ->  no solution
identical  rk(A)=1  rk(A|b)=1  ->  infinitely many (1 free)
 
solve on the parallel case: Singular matrix

The classify function is worth more than it looks. Comparing rk(A)\operatorname{rk}(\mathbf{A}) with rk(Ab)\operatorname{rk}(\mathbf{A}\mid\mathbf{b}) decides the regime without trying to solve anything — and that is exactly the criterion §2.6 states as a property of rank. The three-line function is that theorem, executed.

figure The three regimes, with the determinant of each system matplotlib
Three panels showing two lines each. Left: the lines cross at a single marked point. Middle: two parallel lines with no intersection. Right: two identical lines drawn as one, with the whole line marked as the solution set. Three panels showing two lines each. Left: the lines cross at a single marked point. Middle: two parallel lines with no intersection. Right: two identical lines drawn as one, with the whole line marked as the solution set.
The determinant is nonzero only in the left panel. Zero determinant does not distinguish 'none' from 'infinitely many' — that needs the augmented rank.
figure Twelve equations, two unknowns: no exact solution exists matplotlib
Scatter plot of twelve data points with a fitted line. Vertical residual segments connect each point to the line, none of them zero, showing that no line passes through all twelve points. Scatter plot of twelve data points with a fitted line. Vertical residual segments connect each point to the line, none of them zero, showing that no line passes through all twelve points.
Each data point demands the line pass through it — twelve constraints on two parameters. The residuals cannot all be zero, so least squares finds the closest miss instead.

The second figure is the case machine learning actually lives in. Twelve data points give twelve equations in two unknowns (slope and intercept). The system is overdetermined, and unless the points happen to be exactly collinear there is no solution at all — the middle panel of the first figure, in twelve dimensions.

So the correct response is not to hunt for a better solver. It is to change the question: instead of “which line passes through every point”, ask “which line minimises the total squared miss”. That is least squares, it always has an answer, and Chapter 9 derives it. §3.8 then shows the answer is a solution to a related system — the normal equations — so the machinery of this chapter is not abandoned, it is redeployed.

situationshapetypicallywhat to do
m=nm = n, independent rowssquareexactly one solutionnp.linalg.solve
m>nm > n (overdetermined)tallno exact solutionleast squares — lstsq, Chapter 9
m<nm < n (underdetermined)wideinfinitely manyadd constraints, or take the minimum-norm solution via pinv
m=nm = n, dependent rowssquare, singularnone or infinitely manycheck rk(Ab)\operatorname{rk}(\mathbf{A}\mid\mathbf{b})
pch.quizTag Check yourself
  1. A system of linear equations has two distinct solutions. How many does it have in total?

    pch.quizShowAnswer

    B — Infinitely many — Any weighted average of two solutions is also a solution, because the map is linear. So two solutions force the whole line through them to be solutions — a finite crowd larger than one is impossible.

  2. In the columns view, what is the equation Ax = b actually asking?

    pch.quizShowAnswer

    B — Whether b can be built as a weighted combination of the columns of A, and with which weights — The unknowns scale the columns. That turns solvability into a question about reach — is b inside what the columns can build — which sections 2.5, 2.6 and 2.7 name the span, the rank and the image.

  3. You get LinAlgError Singular matrix. What do you know?

    pch.quizShowAnswer

    C — There is not exactly one solution — it could be none or infinitely many — Both the parallel and the identical cases are singular. Distinguishing them needs the rank of A compared against the rank of the augmented matrix.

  4. Twelve data points, a straight-line model with two parameters. What is the situation?

    pch.quizShowAnswer

    A — Twelve equations in two unknowns, almost certainly with no exact solution — Each point demands the line pass through it, so it is overdetermined. Unless the points are exactly collinear no line satisfies all twelve, which is why the answer is least squares rather than a solver.

Exercise 2 – The unknowns scale the columns

Section titled “Exercise 2 – The unknowns scale the columns”

Exercise 3 – Classify a system without solving it

Section titled “Exercise 3 – Classify a system without solving it”

Exercise 4 – Two solutions force infinitely many

Section titled “Exercise 4 – Two solutions force infinitely many”

Exercise 5 – Overdetermined, so least squares

Section titled “Exercise 5 – Overdetermined, so least squares”
  • A system of linear equations asks for values satisfying several linear constraints at once, and every unknown appears to the first power only.
  • Linearity is a condition on the unknowns, not the data — coefficients may be arbitrarily nonlinear functions of the inputs, which is the loophole feature maps exploit.
  • The unknowns scale the columns, so solving asks whether b is reachable as a weighted combination of the columns of A.
  • There are exactly three outcomes — none, one, or infinitely many — because two distinct solutions force the whole line through them to be solutions.
  • Geometrically the solution set is an intersection: of lines in two variables, planes in three, hyperplanes in general.
  • Inconsistency surfaces as a false arithmetic statement like 0=20 = 2, rather than as a stuck computation.
  • Singular matrix means “not exactly one”, not “none” — the parallel and identical cases are both singular.
  • Comparing the rank of A with the rank of the augmented matrix decides the regime without solving anything.
  • Overdetermined systems are the normal case in machine learning, and the response is least squares rather than a better solver.

Next: compress the whole system into one object — the matrix — which both stores data and transforms it.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading