11. Null space, column space, row space
Every matrix carries three subspaces with it, built from ideas already in hand: §17.0's homogeneous solution sets and §17.1's spans, now applied systematically to a single matrix A. These three — null space, column space, and row space — organize everything Modules 16–17 have done into one picture, and §17.5 uses all three at once.
Null space
The null space of an m\times n matrix A is
\operatorname{Null}(A)=\{\vec x\in\mathbb{R}^n:A\vec x=\vec0\}
— exactly the solution set of the homogeneous system from §17.1's independence test, now named and studied as an object in its own right. It is always a subspace of \mathbb{R}^n (an instance of §17.0's "solution set of a homogeneous linear system," checked there in general): \vec0\in\operatorname{Null}(A) trivially, and if A\vec u=\vec0,A\vec v=\vec0 then A(\vec u+\vec v)=A\vec u+A\vec v=\vec0 and A(c\vec u)=cA\vec u=\vec0, using §16.2's distributive properties of matrix multiplication.
Finding a basis: row-reduce A to RREF; free variables (§16.1) parametrize the solutions, and setting each free variable to 1 in turn (others 0) generates a basis for \operatorname{Null}(A), one vector per free variable.
\operatorname{Null}(A)=\{\vec0\} exactly when A's columns are independent (§17.1's test, restated) — the case with no free variables at all.
Column space
The column space is the span of A's columns:
\operatorname{Col}(A)=\operatorname{span}\{\vec a_1,\dots,\vec a_n\}\subseteq\mathbb{R}^m
By §16.2's column-combination view, \operatorname{Col}(A) is exactly the set of vectors \vec b for which A\vec x=\vec b has a solution — restating §17.1's span question one more time, now as a property of A itself rather than of a hand-picked vector list.
Finding a basis: the pivot columns of A (in the original matrix, not the row-reduced one — row reduction changes column space in general, even though it preserves which columns are pivots) form a basis for \operatorname{Col}(A), by exactly §17.2's "keep the pivot vectors" trimming procedure.
Row space
The row space is the span of A's rows (equivalently, \operatorname{Col}(A^T)):
\operatorname{Row}(A)=\operatorname{span}\{\text{rows of }A\}\subseteq\mathbb{R}^n
Row operations don't change the row space — each elementary row operation (§16.5) replaces some rows with linear combinations of the old ones, and a set's span is unchanged by replacing a vector in it with a combination of the whole set. So A's row space equals its RREF's row space, and since the nonzero rows of an RREF are visibly independent (each has a leading 1 in a column no other row touches), the nonzero rows of RREF form a basis for \operatorname{Row}(A) directly.
How the three relate
\operatorname{Null}(A)\subseteq\mathbb{R}^n and \operatorname{Row}(A)\subseteq\mathbb{R}^n live in the same space as A's inputs; \operatorname{Col}(A)\subseteq\mathbb{R}^m lives in the space of A's outputs. The number of basis vectors for \operatorname{Col}(A) and for \operatorname{Row}(A) are always equal — both equal the number of pivots — a fact worth flagging now and named properly as the rank of A in §17.5, where it's combined with \operatorname{Null}(A)'s dimension into a single equation.
Doing it in Python
import sympy as sp
A = sp.Matrix([
[1, 2, 1, 2],
[2, 4, 0, 0],
[1, 2, 3, 6],
])
rref, pivots = A.rref()
print("RREF:")
for row in rref.tolist():
print(row)
print("pivot columns:", pivots)
col_basis = [A.col(i) for i in pivots]
print("\nColumn space basis (from ORIGINAL A):")
for c in col_basis:
print(list(c))
row_basis = [rref.row(i) for i in range(len(pivots))]
print("\nRow space basis (nonzero RREF rows):")
for r in row_basis:
print(list(r))
RREF:
[1, 2, 0, 0]
[0, 0, 1, 2]
[0, 0, 0, 0]
pivot columns: (0, 2)
Column space basis (from ORIGINAL A):
[1, 2, 1]
[1, 0, 3]
Row space basis (nonzero RREF rows):
[1, 2, 0, 0]
[0, 0, 1, 2]
The null space, via free variables:
import sympy as sp
A = sp.Matrix([
[1, 2, 1, 2],
[2, 4, 0, 0],
[1, 2, 3, 6],
])
ns = A.nullspace()
print(f"nullity = {len(ns)}")
for v in ns:
print(list(v))
for v in ns:
print("A @ v =", list(A * v), " (should be zero)")
nullity = 2
[-2, 1, 0, 0]
[0, 0, -2, 1]
A @ v = [0, 0, 0] (should be zero)
A @ v = [0, 0, 0] (should be zero)
Worked example
Find bases for \operatorname{Null}(A), \operatorname{Col}(A), and \operatorname{Row}(A) for A=\begin{pmatrix}1&2&3\\2&4&7\end{pmatrix}.
Row-reduce: R_2\leftarrow R_2-2R_1 gives \begin{pmatrix}1&2&3\\0&0&1\end{pmatrix}; R_1\leftarrow R_1-3R_2 gives RREF \begin{pmatrix}1&2&0\\0&0&1\end{pmatrix}. Pivots: columns 1,3.
\operatorname{Col}(A): pivot columns of the original A: \boxed{\{(1,2),(3,7)\}}.
\operatorname{Row}(A): nonzero rows of RREF: \boxed{\{(1,2,0),(0,0,1)\}}.
\operatorname{Null}(A): column 2 is free. From RREF, x_1+2x_2=0 and x_3=0, so x_1=-2x_2. Setting x_2=1: \boxed{\operatorname{Null}(A)=\operatorname{span}\{(-2,1,0)\}}.
Sanity check. A(-2,1,0)^T=(1(-2)+2(1)+3(0),\,2(-2)+4(1)+7(0))=(-2+2,\,-4+4)=(0,0) ✓. Also, \dim\operatorname{Col}(A)=\dim\operatorname{Row}(A)=2 (both equal the pivot count) even though they live in different spaces (\mathbb{R}^2 and \mathbb{R}^3 respectively) — exactly the equality flagged above, and the starting point for §17.5.
Your turn
1. For A=\begin{pmatrix}1&0\\0&1\\1&1\end{pmatrix}, is (1,1,3)\in\operatorname{Col}(A)?
2. What is \operatorname{Null}(I_n), the null space of the n\times n identity matrix?
3. True or false: \operatorname{Row}(A) and \operatorname{Col}(A) are always the same subspace.
Solutions
1. No. \operatorname{Col}(A)=\{(x,y,x+y):x,y\in\mathbb{R}\} (every column combination has third coordinate equal to the sum of the first two, since A's third row is (1,1)). For (1,1,3): 1+1=2\neq3, so it's not reachable.
2. \operatorname{Null}(I_n)=\{\vec0\}. I\vec x=\vec x, so I\vec x=\vec0\iff\vec x=\vec0 — no free variables, since I already has a pivot in every column.
3. False, in general. They needn't even live in the same space — \operatorname{Row}(A)\subseteq\mathbb{R}^n while \operatorname{Col}(A)\subseteq\mathbb{R}^m, which are different spaces whenever A is not square. Even for square A, they're generally different subspaces of \mathbb{R}^n (the worked example's A, if made square by dropping a column, would still typically have unequal row and column spaces) — only their dimensions are guaranteed equal, not the subspaces themselves. (One important exception: if A is symmetric, \operatorname{Row}(A)=\operatorname{Col}(A) exactly, since A^T=A means the rows and columns literally coincide.)
Check yourself in code
For A=\begin{pmatrix}1&2&0\\0&1&1\\1&3&1\end{pmatrix}, find the rank (pivot count) and nullity (number of free variables).
Print exactly this:
pivots: (0, 1)
rank = 2
nullity = 1
import sympy as sp
A = sp.Matrix([[1, 2, 0], [0, 1, 1], [1, 3, 1]])
rref, pivots = A.rref()
print("pivots:", pivots)
# print rank (pivot count) and nullity (A.cols - rank)
import sympy as sp
A = sp.Matrix([[1, 2, 0], [0, 1, 1], [1, 3, 1]])
rref, pivots = A.rref()
print("pivots:", pivots)
rank = len(pivots)
print("rank =", rank)
print("nullity =", A.cols - rank)
Every matrix carries a null space (solutions to A\vec x=\vec0, a subspace of the input space), a column space (span of the columns, exactly the reachable outputs), and a row space (span of the rows). RREF reads off bases for all three at once: free variables for the null space, original pivot columns for the column space, nonzero RREF rows for the row space — and the pivot count governs both \dim\operatorname{Col}(A) and \dim\operatorname{Row}(A) identically.
Next: the Rank-Nullity Theorem, which packages the pivot count and free-variable count from this lesson into a single equation that holds for every matrix, no exceptions.