Monocurl Essays
Series Download

Why matrix multiplication is defined the way it is

Multiplying matrices means doing one transformation after another. The rows-times-columns rule, the failure of AB = BA and associativity all follow from that.

20 min·Early college·

AssumesA matrix is a transformation of spaceWhat is a vector? Arrows, lists of numbers, and adding them

The same two moves in the two possible orders. On the left the plane is turned a quarter turn and then sheared; on the right it is sheared and then turned. The grids, the letter F and the two basis arrows end in different places.
Monocurl source
let Both = |s| [Scene(BL, RotShear(s)), Scene(BR, ShearRot(s))]
mesh ground = [Ground(BL, 2), Ground(BR, 2)]
mesh heads = [
    center{[-1.75, 1.82, 0]} Cap("rotate, then shear", 0.78),
    center{[1.95, 1.82, 0]} Cap("shear, then rotate", 0.78)
]
mesh both = Both(s: 0)

slide "orders"
    play Wait(0.8)
    both.s = 1
    play Lerp(2.2, [&both])
    play Wait(0.7)
    both.s = 2
    play Lerp(2.2, [&both])
    play Wait(2.2)

Uses the shared definitions for this lesson's figures.

Matrices are added entry by entry, so you might expect them to be multiplied entry by entry too. The rule that is actually taught looks nothing like that:

$$ \begin{pmatrix} a & b \\ c & d \end{pmatrix}\begin{pmatrix} e & f \\ g & h \end{pmatrix} = \begin{pmatrix} ae + bg & af + bh \\ ce + dg & cf + dh \end{pmatrix}. $$

Each entry of the answer mixes a row of the first matrix with a column of the second. Worse, the result depends on the order: $AB$ and $BA$ are usually different matrices, which never happens with numbers. A rule this strange must have been forced on us by something, and this lesson shows by what. Once you see the source, you will be able to rebuild the rule from nothing, and you will know why order matters before computing anything.

What I rely on from the previous lesson fits in three sentences. A map $T$ of the plane is linear if $T(\mathbf{u} + \mathbf{v}) = T(\mathbf{u}) + T(\mathbf{v})$ and $T(c\,\mathbf{v}) = c\,T(\mathbf{v})$ for all vectors $\mathbf{u}, \mathbf{v}$ and numbers $c$. A linear map is completely determined by where it sends $\mathbf{i} = (1, 0)$ and $\mathbf{j} = (0, 1)$, and writing those two landing spots as columns gives its matrix. Applying the matrix to a vector is

$$ \begin{pmatrix} a & b \\ c & d \end{pmatrix}\begin{pmatrix} x \\ y \end{pmatrix} = x\begin{pmatrix} a \\ c \end{pmatrix} + y\begin{pmatrix} b \\ d \end{pmatrix} = \begin{pmatrix} ax + by \\ cx + dy \end{pmatrix}. $$

One transformation after another

If a matrix is a motion of the plane, the natural thing to do with two matrices is to perform one motion and then the other. Take two that are easy to picture. The quarter turn $R$ rotates the plane $90^\circ$ counterclockwise; it sends $\mathbf{i}$ to $(0, 1)$ and $\mathbf{j}$ to $(-1, 0)$. The shear $S$ slides each point sideways by its height; it leaves $\mathbf{i}$ at $(1, 0)$ and sends $\mathbf{j}$ to $(1, 1)$. As matrices,

$$ R = \begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix}, \qquad S = \begin{pmatrix} 1 & 1 \\ 0 & 1 \end{pmatrix}. $$

Turn the plane with $R$, then shear the result with $S$. The combined motion takes each vector $\mathbf{v}$ to $S(R\mathbf{v})$. The combined motion is again given by a matrix provided it is linear, and that is quick to check for any two linear maps.

So “turn, then shear” has a matrix, and we know how to find the matrix of any linear map: see where $\mathbf{i}$ and $\mathbf{j}$ end up.

Pause and try

Follow $\mathbf{i}$ through the quarter turn and then the shear. Where does it end? Do the same for $\mathbf{j}$, and write the two results as the columns of a matrix. (The shear sends $(x, y)$ to $(x + y, y)$.)

Show answerHide answer

The turn sends $\mathbf{i}$ to $(0, 1)$, and the shear sends $(0, 1)$ to $(0 + 1, 1) = (1, 1)$. The turn sends $\mathbf{j}$ to $(-1, 0)$, and the shear, which does not move points of height 0, leaves it at $(-1, 0)$. The matrix of “turn, then shear” is $\begin{pmatrix} 1 & -1 \\ 1 & 0 \end{pmatrix}$.

  1. Before anything moves, the basis arrows are (1, 0) and (0, 1), and the matrix is the one that does nothing.
  2. First the quarter turn R. The blue arrow goes to (0, 1) and the orange arrow to (-1, 0).
  3. Then the shear S, applied to the arrows where they now are. Blue slides to (1, 1); orange has height 0 and stays.
  4. The final positions, written as columns, are the matrix of the whole motion. We call it the product SR.
Tracking the basis arrows through a quarter turn followed by a shear. The blue arrow goes from $(1, 0)$ to $(0, 1)$ to $(1, 1)$; the orange arrow goes from $(0, 1)$ to $(-1, 0)$ and stays there. The final positions, printed under the matrix after the shear, are its columns.
Monocurl source
let Track = |s| [
    Scene(Bc, RotShear(s)),
    MatBox([2.75, -0.35, 0], RotShear(s), 1)
]
mesh ground = Ground(Bc)
mesh track = Track(s: 0)
mesh head = [center{[2.75, 0.75, 0]} Note("matrix so far", 0.74)]
mesh tips = [
    center{P(Bc, [1.45, -0.32])} Math("(1, 0)", 0.8, AZURE),
    center{P(Bc, [-0.55, 1.2])} Math("(0, 1)", 0.8, EMBER)
]

slide "Before anything moves, the basis arrows are (1, 0) and (0, 1), and the matrix is the one that does nothing."
    play Fade(0.5)

slide "First the quarter turn R. The blue arrow goes to (0, 1) and the orange arrow to (-1, 0)."
    tips = []
    play Fade(0.3, [&tips])
    track.s = 1
    play Lerp(2.2, [&track])
    tips = [
        center{P(Bc, [0.6, 1.2])} Math("(0, 1)", 0.8, AZURE),
        center{P(Bc, [-1.45, -0.32])} Math("(-1, 0)", 0.8, EMBER)
    ]
    play Fade(0.4, [&tips])

slide "Then the shear S, applied to the arrows where they now are. Blue slides to (1, 1); orange has height 0 and stays."
    tips = []
    play Fade(0.3, [&tips])
    track.s = 2
    play Lerp(2.2, [&track])
    tips = [
        center{[2.25, -1.4, 0]} Math("(1, 1)", 0.8, AZURE),
        center{[3.25, -1.4, 0]} Math("(-1, 0)", 0.8, EMBER)
    ]
    play Fade(0.4, [&tips])

slide "The final positions, written as columns, are the matrix of the whole motion. We call it the product SR."
    head = [center{[2.75, 0.75, 0]} Math("SR", 1.0, INK)]
    play Fade(0.5, [&head])

Uses the shared definitions for this lesson's figures.

The rule, derived

Nothing in that computation was special to a turn and a shear. Let $A$ and $B$ be any two matrices,

$$ A = \begin{pmatrix} a & b \\ c & d \end{pmatrix}, \qquad B = \begin{pmatrix} e & f \\ g & h \end{pmatrix}, $$

and apply $B$ first, then $A$. The vector $\mathbf{i}$ goes first to $B\mathbf{i} = (e, g)$, the first column of $B$. Then $A$ acts on that vector. Here is the step that produces the rule: $(e, g)$ is $e$ steps of $\mathbf{i}$ and $g$ steps of $\mathbf{j}$, so $A$ carries it to $e$ steps of $A$’s first column and $g$ steps of $A$’s second,

$$ A\begin{pmatrix} e \\ g \end{pmatrix} = e\begin{pmatrix} a \\ c \end{pmatrix} + g\begin{pmatrix} b \\ d \end{pmatrix} = \begin{pmatrix} ae + bg \\ ce + dg \end{pmatrix}. $$

The figure runs this step on numbers: $A$ is the shear $S$ and $B = \begin{pmatrix} 2 & -1 \\ 1 & 1 \end{pmatrix}$.

  1. B sends i to (2, 1), the first column of B. That is 2 steps of i and 1 step of j.
  2. Now apply the shear A. The grid moves and the path of three steps moves with it.
  3. The path is now 2 steps of A’s first column (1, 0) and 1 step of its second (1, 1). It ends at (3, 1).
  4. The other column: B sends j to (-1, 1), and A carries that to -1(1, 0) + 1(1, 1) = (0, 1).
One column of a product. $B$ sends $\mathbf{i}$ to $(2, 1)$, which is 2 steps of $\mathbf{i}$ and 1 of $\mathbf{j}$. Applying the shear $A$ turns that into 2 steps of $A$’s first column and 1 step of its second: $(3, 1)$, the first column of $AB$. The second column, $(0, 1)$, comes from $B\mathbf{j} = (-1, 1)$ in the same way.
Monocurl source
let Bm = [2, -1, 1, 1]
let Ride = |t, c, col| {
    let m = blend(IDENT, S, t)
    let e1 = [m[0], m[2]]
    let e2 = [m[1], m[3]]
    let sx = sign(c[0])
    var out = []
    for (k in range(0, to_int(abs(c[0])))) {
        out .= Vec(B2, times(sx * k, e1), times(sx * (k + 1), e1), tint(AZURE, 0.7), 4)
    }
    let corner = times(c[0], e1)
    for (k in range(0, to_int(abs(c[1])))) {
        out .= Vec(B2, add(corner, times(k, e2)), add(corner, times(k + 1, e2)), tint(EMBER, 0.75), 4)
    }
    out .= Vec(B2, [0, 0], add(corner, times(c[1], e2)), col, 4.5)
    out .= Pt(P(B2, add(corner, times(c[1], e2))), col, 0.085)
    return out
}
let G = |t| Lines(B2, blend(IDENT, S, t))
mesh ground = Ground(B2)
mesh grid = G(t: 0)
mesh second = []
mesh ride = Ride(t: 0, [2, 1], LEAF)
mesh notes = [
    center{[2.65, 1.3, 0]} Math("B\,\mathbf{i} = (2, 1)", 0.9, LEAF),
    center{[2.65, 0.7, 0]} Math("= 2\,\mathbf{i} + 1\,\mathbf{j}", 0.9, INK)
]

slide "B sends i to (2, 1), the first column of B. That is 2 steps of i and 1 step of j."
    play Fade(0.5)

slide "Now apply the shear A. The grid moves and the path of three steps moves with it."
    notes = []
    play Fade(0.3, [&notes])
    grid.t = 1
    ride.t = 1
    play Lerp(2.4, [&grid, &ride])

slide "The path is now 2 steps of A's first column (1, 0) and 1 step of its second (1, 1). It ends at (3, 1)."
    notes = [
        center{[2.65, 1.3, 0]} Math("A(B\,\mathbf{i})", 0.9, LEAF),
        center{[2.65, 0.7, 0]} Math("= 2\,(1, 0) + 1\,(1, 1)", 0.8, INK),
        center{[2.65, 0.1, 0]} Math("= (3, 1)", 0.9, LEAF)
    ]
    play Fade(0.5, [&notes])

slide "The other column: B sends j to (-1, 1), and A carries that to -1(1, 0) + 1(1, 1) = (0, 1)."
    second = Ride(1, [-1, 1], PLUM)
    notes .= center{[2.65, -0.7, 0]} Math("A(B\,\mathbf{j})", 0.9, PLUM)
    notes .= center{[2.65, -1.3, 0]} Math("= (0, 1)", 0.9, PLUM)
    play Fade(0.6, [&second, &notes])

Uses the shared definitions for this lesson's figures.

The same reasoning applied to $\mathbf{j}$, which $B$ sends to its second column $(f, h)$, gives $A(f, h) = (af + bh,\ cf + dh)$. Those two vectors are where “$B$, then $A$” sends the basis, so they are the columns of its matrix. That matrix is what we define the product to be.

The definition arranges for $AB$ to do the right thing to $\mathbf{i}$ and $\mathbf{j}$. We should confirm that it does the right thing to every vector.

Now look back at the entry in row 1, column 1: $ae + bg$. It pairs the first row of $A$, $(a, b)$, with the first column of $B$, $(e, g)$. The reason is visible in the derivation. A column of $B$ is a vector being fed to $A$, and each row of $A$ produces one component of the output. So the entry in row $r$ and column $s$ of $AB$ is always row $r$ of $A$ paired with column $s$ of $B$. Entry-by-entry multiplication would be simpler to carry out, but it would not describe one motion followed by another, or anything else of geometric interest.

The order of the letters deserves a comment. $AB$ applies $B$ first because the vector stands on the right: in $A(B\mathbf{v})$ the matrix next to $\mathbf{v}$ acts first, as with functions, where $f(g(x))$ applies $g$ first.

Order matters

We found that “turn, then shear” is $SR = \begin{pmatrix} 1 & -1 \\ 1 & 0 \end{pmatrix}$. Now reverse the order.

Pause and try

Compute $RS$, the matrix of “shear, then turn”, by tracking $\mathbf{i}$ and $\mathbf{j}$. Compare it with $SR$. (The turn sends $(x, y)$ to $(-y, x)$.)

Show answerHide answer

The shear leaves $\mathbf{i}$ at $(1, 0)$, and the turn sends that to $(0, 1)$. The shear sends $\mathbf{j}$ to $(1, 1)$, and the turn sends that to $(-1, 1)$. So $RS = \begin{pmatrix} 0 & -1 \\ 1 & 1 \end{pmatrix}$, which is not $SR$. In the animation at the top of the page these are the right and left panels.

This is no accident of the example. Shearing slides points along horizontal lines. If the turn comes first, the lines that were horizontal are vertical by the time the shear arrives, so the shear acts on different material. For motions, order matters far more often than not: putting on socks and then shoes is not the same as shoes and then socks. Numbers commute because stretching a line by 2 and then by 3 is the same as by 3 and then by 2, and that is a special feature of stretches.

Some pairs of matrices do commute, and it is worth knowing which. Two rotations about the origin commute: turning by $30^\circ$ and then by $60^\circ$ gives the same quarter turn as $60^\circ$ and then $30^\circ$.

Two rotations in both orders. On the left the plane turns by $30^\circ$ and then by $60^\circ$; on the right by $60^\circ$ and then by $30^\circ$. Both end at the same quarter turn, so these two matrices commute.
Monocurl source
let Pair = |s| [
    Scene(BL, rotm(30 * clamp(0, s, 1) + 60 * clamp(0, s - 1, 1))),
    Scene(BR, rotm(60 * clamp(0, s, 1) + 30 * clamp(0, s - 1, 1)))
]
mesh ground = [Ground(BL, 2), Ground(BR, 2)]
mesh heads = [
    center{[-1.75, 1.82, 0]} Math("30^\circ \text{, then } 60^\circ", 0.85, INK),
    center{[1.95, 1.82, 0]} Math("60^\circ \text{, then } 30^\circ", 0.85, INK)
]
mesh pair = Pair(s: 0)

slide "turns"
    play Wait(0.8)
    pair.s = 1
    play Lerp(2, [&pair])
    play Wait(0.7)
    pair.s = 2
    play Lerp(2, [&pair])
    play Wait(2)

Uses the shared definitions for this lesson's figures.

Grouping does not matter

With three matrices there is a second worry. The expression $ABC$ could mean $(AB)C$, where we first compute the matrix $AB$ and then multiply by $C$, or $A(BC)$. Checking that these agree by brute force means expanding eight entries, each a sum of four triple products. The transformation view makes the question disappear.

  1. Apply C, then B, then A to the vector v = (2, 0): three hops, ending at (3, 1).
  2. (AB)C: hop by C, then one fused hop AB. By the meaning of AB it lands where the hops B and A would.
  3. A(BC): one fused hop BC, then A. Again the same start and the same end.
Three maps applied to the vector $\mathbf{v} = (2, 0)$: a quarter turn $C$, then a shear $B$, then a stretch $A$. Grouping the hops as $(AB)C$ or as $A(BC)$ changes which two are fused into one, and does not change where $\mathbf{v}$ ends: at $(3, 1)$ in both cases.
Monocurl source
let Ba = Board([-2.3, -0.85, 0], 0.9, -1, 4, -1, 3)
let Am = [1.5, 0, 0, 0.5]
let v0 = [2, 0]
let v1 = apply(R, v0)
let v2 = apply(S, v1)
let v3 = apply(Am, v2)
let coords = |q| str_join(["(", to_string(q[0], 0), ", ", to_string(q[1], 0), ")"])
mesh ground = Ground(Ba)
mesh fused = []
mesh hops = [
    Vec(Ba, v0, v1, SLATE, 3.5),
    Vec(Ba, v1, v2, SLATE, 3.5),
    Vec(Ba, v2, v3, SLATE, 3.5)
]
mesh dots = [
    Pt(P(Ba, v0), INK, 0.09),
    Pt(P(Ba, v1), INK, 0.09),
    Pt(P(Ba, v2), INK, 0.09),
    Pt(P(Ba, v3), LEAF, 0.11)
]
mesh names = [
    center{P(Ba, [2.3, -0.38])} Math("\mathbf{v}", 0.9, INK),
    center{P(Ba, [0.75, 0.8])} Math("C", 0.9, SLATE),
    center{P(Ba, [1, 2.35])} Math("B", 0.9, SLATE),
    center{P(Ba, [2.85, 1.75])} Math("A", 0.9, SLATE),
    center{P(Ba, [3.45, 0.62])} Math(coords(v3), 0.8, LEAF)
]
mesh words = [center{[2.55, 1.2, 0]} Math("A(B(C\mathbf{v}))", 1.0, INK)]

slide "Apply C, then B, then A to the vector v = (2, 0): three hops, ending at (3, 1)."
    play Fade(0.6)

slide "(AB)C: hop by C, then one fused hop AB. By the meaning of AB it lands where the hops B and A would."
    fused = [
        Vec(Ba, v1, v3, LEAF, 4),
        center{P(Ba, [1.3, 1.25])} Math("AB", 0.9, LEAF)
    ]
    words .= center{[2.55, 0.4, 0]} Math("= ((AB)C)\mathbf{v}", 1.0, LEAF)
    play Fade(0.6, [&fused, &words])

slide "A(BC): one fused hop BC, then A. Again the same start and the same end."
    fused .= Vec(Ba, v0, v2, PLUM, 4)
    fused .= center{P(Ba, [2.42, 0.75])} Math("BC", 0.9, PLUM)
    words .= center{[2.55, -0.4, 0]} Math("= (A(BC))\mathbf{v}", 1.0, PLUM)
    play Fade(0.6, [&fused, &words])

Uses the shared definitions for this lesson's figures.

No entry was ever expanded. Both groupings describe “do $C$, then $B$, then $A$”, and the brackets only say where you pause to write down an intermediate matrix. This is the standard example of a fact that is tedious in coordinates and immediate once the objects are understood as functions, because composition of functions is always associative.

Doing nothing, repeating, and losing everything

The identity. The motion that leaves every vector alone sends $\mathbf{i}$ to $\mathbf{i}$ and $\mathbf{j}$ to $\mathbf{j}$, so its matrix is $I = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}$, the identity matrix. Doing nothing before or after $A$ changes nothing: $AI = IA = A$. It plays the part of the number 1.

Powers. $A^2$ means $AA$: perform the motion twice. Two quarter turns make a half turn, which sends every $(x, y)$ to $(-x, -y)$, so $R^2 = \begin{pmatrix} -1 & 0 \\ 0 & -1 \end{pmatrix} = -I$ without any arithmetic. (If you have seen complex numbers, this is $i^2 = -1$ again: multiplying by $i$ is a quarter turn.) For the shear, each application slides a point of height $y$ a further $y$ to the right.

Pause and try

Compute $S^2$ and $S^3$ for $S = \begin{pmatrix} 1 & 1 \\ 0 & 1 \end{pmatrix}$ and guess $S^n$.

Show answerHide answer

$S$ fixes $\mathbf{i}$, so the first column is always $(1, 0)$. For the second column: $S\mathbf{j} = (1, 1)$, then $S(1, 1) = (2, 1)$, then $S(2, 1) = (3, 1)$. So $S^2 = \begin{pmatrix} 1 & 2 \\ 0 & 1 \end{pmatrix}$, $S^3 = \begin{pmatrix} 1 & 3 \\ 0 & 1 \end{pmatrix}$, and the pattern is $S^n = \begin{pmatrix} 1 & n \\ 0 & 1 \end{pmatrix}$ (Problem 5 asks for a proof).

The shear $S$ applied three times in a row. Each application slides the tip of the orange arrow one more unit to the right, and the top-right entry of the matrix counts the applications.
Monocurl source
let Pw = |n| [
    Scene(B2, [1, n, 0, 1]),
    MatBox([2.65, -0.45, 0], [1, n, 0, 1], 1),
    center{[2.65, 0.85, 0]} scale{1.15} color{INK} Number(n, 1)
]
mesh ground = Ground(B2)
mesh pw = Pw(n: 0)
mesh label = [center{[2.65, 1.4, 0]} Note("shears applied", 0.74)]

slide "powers"
    play Wait(0.7)
    pw.n = 1
    play Lerp(1.3, [&pw])
    play Wait(0.6)
    pw.n = 2
    play Lerp(1.3, [&pw])
    play Wait(0.6)
    pw.n = 3
    play Lerp(1.3, [&pw])
    play Wait(1.8)

Uses the shared definitions for this lesson's figures.

Zero without a zero factor. With numbers, $xy = 0$ forces $x = 0$ or $y = 0$. Let $B = \begin{pmatrix} 0 & 0 \\ 0 & 1 \end{pmatrix}$, which flattens the plane onto the vertical axis, and $A = \begin{pmatrix} 1 & 0 \\ 0 & 0 \end{pmatrix}$, which flattens it onto the horizontal axis. Neither is the zero matrix. But $B$ puts everything on the vertical axis, and $A$ sends the whole vertical axis to the origin, so $AB$ sends every vector to $\mathbf{0}$.

A product that is zero although neither factor is. First $B$ flattens the plane onto the vertical axis; then $A$ flattens that axis onto the origin. The matrix of the combined motion has every entry 0. The pale arrows and the grey F stay behind to show where everything started; the red dot is where all of it ends.
Monocurl source
let PY = [0, 0, 0, 1]
let PX = [1, 0, 0, 0]
let Crush = |s| {
    let m = matmul(blend(IDENT, PX, clamp(0, s - 1, 1)), blend(IDENT, PY, clamp(0, s, 1)))
    return [
        Scene(Bc, m),
        MatBox([2.75, -0.35, 0], m, 1)
    ]
}
mesh ground = Ground(Bc)
mesh before = [
    FSmall(Bc, IDENT, SLATE),
    Vec(Bc, [0, 0], [0, 1], tint(EMBER, 0.45), 3.5),
    Vec(Bc, [0, 0], [1, 0], tint(AZURE, 0.45), 3.5)
]
mesh crush = Crush(s: 0)
mesh head = [center{[2.75, 0.75, 0]} Note("matrix so far", 0.74)]
mesh dot = []

slide "crush"
    play Wait(0.8)
    crush.s = 1
    play Lerp(2.2, [&crush])
    play Wait(0.8)
    crush.s = 2
    play Lerp(2.2, [&crush])
    dot = [
        Pt(P(Bc, [0, 0]), ROSE, 0.11),
        center{[2.75, -1.45, 0]} Math("AB = 0", 0.95, ROSE)
    ]
    play Fade(0.5, [&dot])
    play Wait(1.8)

Uses the shared definitions for this lesson's figures.

One consequence is that you cannot cancel freely: from $AB = AC$ it does not follow that $B = C$. (Here $AB = A0$, where $0$ is the zero matrix, and $B \neq 0$.) Which matrices can be cancelled is settled in the next lesson: exactly those with an inverse.

Looking back, the definition of the product is “the matrix of one linear map followed by another”, and the rule at the top of the page is the bookkeeping for it. The harder a fact about the bookkeeping looks (non-commutativity, associativity), the more it helps to restate it about the maps, where it is usually plain. The next lesson asks what a matrix does to areas, and the fact that areas scaled by $B$ and then by $A$ are scaled by $AB$ will do real work there.

Check yourself

$A$ is a reflection and $B$ is a rotation. Which matrix describes “reflect first, then rotate”?

Problems

The first three are computations, the next three ask you to reason with the composition picture, and the last two connect to other topics.

Problem 1

Let $A = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}$ and $B = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}$. Compute $AB$ and $BA$. Describe in words what multiplying by $B$ on the right did to $A$, and what multiplying on the left did.

Show solutionHide solution

The columns of $AB$ are $A$ applied to the columns of $B$: $A(0, 1) = (2, 4)$ and $A(1, 0) = (1, 3)$, so $AB = \begin{pmatrix} 2 & 1 \\ 4 & 3 \end{pmatrix}$. The columns of $BA$ are $B$ applied to the columns of $A$; since $B$ swaps the two coordinates, $B(1, 3) = (3, 1)$ and $B(2, 4) = (4, 2)$, so $BA = \begin{pmatrix} 3 & 4 \\ 1 & 2 \end{pmatrix}$. Multiplying by $B$ on the right swapped the columns of $A$; multiplying on the left swapped its rows.

Problem 2

Let $F = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}$ be the reflection across the horizontal axis and $R = \begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix}$ the quarter turn. Find the matrix of “reflect, then turn” and of “turn, then reflect”, and identify each as a single familiar motion.

Show solutionHide solution

“Reflect, then turn” is $RF$. Track the basis: $F\mathbf{i} = (1, 0)$, and $R(1, 0) = (0, 1)$; $F\mathbf{j} = (0, -1)$, and $R(0, -1) = (1, 0)$. So $RF = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}$, which swaps coordinates: the reflection across the line $y = x$. “Turn, then reflect” is $FR$: $R\mathbf{i} = (0, 1)$ and $F(0, 1) = (0, -1)$; $R\mathbf{j} = (-1, 0)$ and $F(-1, 0) = (-1, 0)$. So $FR = \begin{pmatrix} 0 & -1 \\ -1 & 0 \end{pmatrix}$, which sends $(x, y)$ to $(-y, -x)$: the reflection across the line $y = -x$.

Problem 3

Let $D = \begin{pmatrix} 2 & 0 \\ 0 & 3 \end{pmatrix}$ and $E = \begin{pmatrix} 5 & 0 \\ 0 & -1 \end{pmatrix}$. Compute $DE$ and $ED$, and explain geometrically why they are equal.

Show solutionHide solution

$DE$ has columns $D(5, 0) = (10, 0)$ and $D(0, -1) = (0, -3)$, so $DE = \begin{pmatrix} 10 & 0 \\ 0 & -3 \end{pmatrix}$. $ED$ has columns $E(2, 0) = (10, 0)$ and $E(0, 3) = (0, -3)$: the same matrix. Each of $D$ and $E$ scales the horizontal direction by one number and the vertical direction by another, without mixing the two. Along each axis we are just multiplying numbers, $2 \cdot 5 = 5 \cdot 2$ and $3 \cdot (-1) = (-1) \cdot 3$, and numbers commute.

Problem 4

Find all matrices $B = \begin{pmatrix} e & f \\ g & h \end{pmatrix}$ that commute with the shear $S = \begin{pmatrix} 1 & 1 \\ 0 & 1 \end{pmatrix}$, that is, with $SB = BS$.

Show solutionHide solution

$SB$ has columns $S(e, g) = (e + g, g)$ and $S(f, h) = (f + h, h)$, so $SB = \begin{pmatrix} e + g & f + h \\ g & h \end{pmatrix}$. $BS$ has columns $B(1, 0) = (e, g)$ and $B(1, 1) = (e + f, g + h)$, so $BS = \begin{pmatrix} e & e + f \\ g & g + h \end{pmatrix}$. Comparing entries: $e + g = e$ gives $g = 0$; $f + h = e + f$ gives $h = e$; the bottom-left entries agree; and $h = g + h$ gives $g = 0$ again. So $B$ commutes with $S$ exactly when $B = \begin{pmatrix} e & f \\ 0 & e \end{pmatrix}$ for some numbers $e, f$: a uniform scaling by $e$ combined with a horizontal shear. Check with $e = 2, f = 5$: $SB = \begin{pmatrix} 2 & 7 \\ 0 & 2 \end{pmatrix} = BS$.

Problem 5

Prove that $S^n = \begin{pmatrix} 1 & n \\ 0 & 1 \end{pmatrix}$ for every whole number $n \geq 1$. More generally, show that shears $\begin{pmatrix} 1 & k \\ 0 & 1 \end{pmatrix}$ and $\begin{pmatrix} 1 & m \\ 0 & 1 \end{pmatrix}$ multiply by adding $k$ and $m$.

Show solutionHide solution

Do the general claim first. The product $\begin{pmatrix} 1 & k \\ 0 & 1 \end{pmatrix}\begin{pmatrix} 1 & m \\ 0 & 1 \end{pmatrix}$ has first column $(1, 0)$, since both matrices fix $\mathbf{i}$, and second column $\begin{pmatrix} 1 & k \\ 0 & 1 \end{pmatrix}$ applied to $(m, 1)$, which is $m\,(1, 0) + 1\,(k, 1) = (m + k, 1)$. So the product is $\begin{pmatrix} 1 & k + m \\ 0 & 1 \end{pmatrix}$. For the powers, argue by induction. The claim holds for $n = 1$. If $S^n = \begin{pmatrix} 1 & n \\ 0 & 1 \end{pmatrix}$, then $S^{n+1} = S\,S^n$ is the product of shears with $k = 1$ and $m = n$, which is $\begin{pmatrix} 1 & n + 1 \\ 0 & 1 \end{pmatrix}$. Geometrically: sliding each point by $m$ times its height and then by $k$ times its height slides it by $(k + m)$ times its height.

Problem 6

Let $P = \begin{pmatrix} 1 & 0 \\ 0 & 0 \end{pmatrix}$ and $N = \begin{pmatrix} 0 & 1 \\ 0 & 0 \end{pmatrix}$. Compute $P^2$ and $N^2$, and explain each result by describing what the map does.

Show solutionHide solution

$P$ sends $(x, y)$ to $(x, 0)$: it drops each point straight onto the horizontal axis. A point already on that axis does not move, so doing $P$ twice is the same as doing it once: $P^2 = P$. By columns: $P(1, 0) = (1, 0)$ and $P(0, 0) = (0, 0)$. $N$ sends $(x, y)$ to $(y, 0)$; in particular $N\mathbf{i} = \mathbf{0}$ and $N\mathbf{j} = \mathbf{i}$. Every output of $N$ lies on the horizontal axis, and $N$ sends that whole axis to the origin, so $N^2$ sends everything to $\mathbf{0}$: $N^2 = \begin{pmatrix} 0 & 0 \\ 0 & 0 \end{pmatrix}$. By columns: $N(N\mathbf{i}) = N\mathbf{0} = \mathbf{0}$ and $N(N\mathbf{j}) = N\mathbf{i} = \mathbf{0}$. So a nonzero matrix can have square zero.

Problem 7

Use $R_\theta R_\theta = R_{2\theta}$, where $R_\theta = \begin{pmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{pmatrix}$, to derive formulas for $\cos 2\theta$ and $\sin 2\theta$. Check them at $\theta = 30^\circ$.

Show solutionHide solution

The first column of $R_\theta R_\theta$ is $R_\theta$ applied to $(\cos\theta, \sin\theta)$: $\cos\theta\,(\cos\theta, \sin\theta) + \sin\theta\,(-\sin\theta, \cos\theta) = (\cos^2\theta - \sin^2\theta,\ 2\sin\theta\cos\theta)$. It must equal the first column of $R_{2\theta}$, namely $(\cos 2\theta, \sin 2\theta)$. Hence $\cos 2\theta = \cos^2\theta - \sin^2\theta$ and $\sin 2\theta = 2\sin\theta\cos\theta$. At $\theta = 30^\circ$: $\cos^2 - \sin^2 = \frac34 - \frac14 = \frac12 = \cos 60^\circ$, and $2 \cdot \frac12 \cdot \frac{\sqrt3}{2} = \frac{\sqrt3}{2} = \sin 60^\circ$.

Problem 8

For real numbers $a, b$ let $M(a, b) = \begin{pmatrix} a & -b \\ b & a \end{pmatrix}$. (a) Show that $M(a, b)\,M(c, d) = M(ac - bd,\ ad + bc)$. (b) Deduce that any two matrices of this form commute. (c) Compare with the product of complex numbers $(a + bi)(c + di)$, and say which matrix plays the part of $i$.

Show solutionHide solution

(a) The first column of the product is $M(a, b)$ applied to $(c, d)$: $c\,(a, b) + d\,(-b, a) = (ac - bd,\ bc + ad)$. The second column is $M(a, b)$ applied to $(-d, c)$: $-d\,(a, b) + c\,(-b, a) = (-(ad + bc),\ ac - bd)$. So the product is $\begin{pmatrix} ac - bd & -(ad + bc) \\ ad + bc & ac - bd \end{pmatrix} = M(ac - bd,\ ad + bc)$. (b) Swapping the roles of $(a, b)$ and $(c, d)$ gives $M(c, d)M(a, b) = M(ca - db,\ cb + da)$, which is the same matrix because multiplication of numbers commutes. (c) $(a + bi)(c + di) = (ac - bd) + (ad + bc)i$: the same rule. The matrix $M(a, b)$ acts on the plane the way multiplication by $a + bi$ acts on complex numbers. The part of $i$ is played by $M(0, 1) = \begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix}$, the quarter turn $R$, and $R^2 = M(-1, 0) = -I$ matches $i^2 = -1$.

Shared definitions used by this lesson's figures
# house kit: prepended to every essay figure after the std imports

# palette. AZURE and EMBER are the two actors, LEAF marks an answer, ROSE a problem
let PAPER = [1, 1, 1, 1]
let INK = [0.08, 0.09, 0.11, 1]
let SLATE = [0.40, 0.44, 0.50, 1]
let MIST = [0.85, 0.86, 0.88, 1]
let AZURE = [0.13, 0.42, 0.68, 1]
let EMBER = [0.89, 0.42, 0.12, 1]
let LEAF = [0.13, 0.55, 0.36, 1]
let ROSE = [0.78, 0.22, 0.24, 1]
let PLUM = [0.47, 0.30, 0.66, 1]
let GOLD = [0.85, 0.62, 0.08, 1]

background = PAPER

# an opaque pastel of col; use for fills so overlaps do not darken
let tint = |col, amount = 0.18| [
    1 - (1 - col[0]) * amount,
    1 - (1 - col[1]) * amount,
    1 - (1 - col[2]) * amount,
    1
]

# text: Cap for labels, Note for quiet labels, Math for typeset maths
let Cap = |txt, size = 0.75, col = INK| color{col} Text(txt, size, "Charter")
let Note = |txt, size = 0.65| color{SLATE} Text(txt, size, "Charter")
let Math = |tex, size = 0.9, col = INK| color{col} Tex(tex, size)

# a paper rectangle to sit behind text that crosses lines
let Plate = |pos, size| center{pos} fill{PAPER} stroke{alpha{0} PAPER, 0} Rect(size)

# shapes with fill and stroke both set, so no stray black appears
let Pt = |pos, col = INK, r = 0.075| center{pos} fill{col} stroke{col, 1} Circle(r, 48)
let Ring = |pos, col = INK, r = 0.1, w = 3| center{pos} fill{PAPER} stroke{col, w} Circle(r, 48)
let Seg = |a, b, col = INK, w = 3| stroke{col, w} Line(a, b)
let Path = |pts, col = INK, w = 3| stroke{col, w} Polyline(pts)
let Region = |pts, col| fill{col} stroke{alpha{0} col, 0} Polygon(pts)
let Outline = |pts, col = INK, w = 3| fill{alpha{0} PAPER} stroke{col, w} Polygon(pts)
let Shape = |pts, col, amount = 0.18, w = 3| fill{tint(col, amount)} stroke{col, w} Polygon(pts)
let Disc = |pos, r, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Circle(r, 96)
let Box = |pos, size, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Rect(size)
# a line from a to b ending in a small solid arrowhead
let Tip = |a, b, col = INK, w = 3, head = 0.17| {
    let d = normalize([b[0] - a[0], b[1] - a[1], 0])
    let n = [-d[1], d[0], 0]
    let base = [b[0] - d[0] * head, b[1] - d[1] * head, 0]
    return [
        stroke{col, w} Line(a, base),
        fill{col} stroke{col, 1} Polygon([
            b,
            [base[0] + n[0] * head * 0.42, base[1] + n[1] * head * 0.42, 0],
            [base[0] - n[0] * head * 0.42, base[1] - n[1] * head * 0.42, 0]
        ])
    ]
}

# plots. a frame is [x0, x1, y0, y1, centre, width, height]: a data window and the scene box it fills
let Frame = |x0, x1, y0, y1, c = [0, 0, 0], w = 6.4, h = 3.6| [x0, x1, y0, y1, c, w, h]
let fx = |fr, x| fr[4][0] + (x - (fr[0] + fr[1]) / 2) * fr[5] / (fr[1] - fr[0])
let fy = |fr, y| fr[4][1] + (y - (fr[2] + fr[3]) / 2) * fr[6] / (fr[3] - fr[2])
let at = |fr, x, y| [fx(fr, x), fy(fr, y), 0]

# axes through the data origin (or the nearest edge of the window), with optional names
let Axes = |fr, x_name = "", y_name = "", col = SLATE| {
    let ox = clamp(fr[0], 0, fr[1])
    let oy = clamp(fr[2], 0, fr[3])
    var parts = [
        Tip(at(fr, fr[0], oy), [fx(fr, fr[1]) + 0.25, fy(fr, oy), 0], col, 2.5, 0.15),
        Tip(at(fr, ox, fr[2]), [fx(fr, ox), fy(fr, fr[3]) + 0.25, 0], col, 2.5, 0.15)
    ]
    if (x_name != "") {
        parts .= center{[fx(fr, fr[1]) + 0.5, fy(fr, oy), 0]} Math(x_name, 0.8, col)
    }
    if (y_name != "") {
        parts .= center{[fx(fr, ox), fy(fr, fr[3]) + 0.5, 0]} Math(y_name, 0.8, col)
    }
    return parts
}

# tick marks with numbers at the listed data values
let XTicks = |fr, xs, col = SLATE, places = 0| block {
    let oy = fy(fr, clamp(fr[2], 0, fr[3]))
    for (x in xs) {
        . Seg([fx(fr, x), oy - 0.07, 0], [fx(fr, x), oy + 0.07, 0], col, 2)
        . center{[fx(fr, x), oy - 0.33, 0]} Math(to_string(x, places), 0.72, col)
    }
}
let YTicks = |fr, ys, col = SLATE, places = 0| block {
    let ox = fx(fr, clamp(fr[0], 0, fr[1]))
    for (y in ys) {
        . Seg([ox - 0.07, fy(fr, y), 0], [ox + 0.07, fy(fr, y), 0], col, 2)
        . center{[ox - 0.36, fy(fr, y), 0]} Math(to_string(y, places), 0.72, col)
    }
}

# faint grid lines at the listed data values
let GridLines = |fr, xs, ys, col = MIST| block {
    for (x in xs) {
        . Seg(at(fr, x, fr[2]), at(fr, x, fr[3]), col, 1.5)
    }
    for (y in ys) {
        . Seg(at(fr, fr[0], y), at(fr, fr[1], y), col, 1.5)
    }
}

# the graph of f over [a, b], drawn in the frame. values are clamped to the window
let Graph = |fr, f, a, b, col = AZURE, w = 4, n = 160|
    stroke{col, w} Polyline(map(sample(a, b, n), |x| at(fr, x, clamp(fr[2], f(x), fr[3]))))

# the region between the graph of f and the x axis over [a, b]
let AreaUnder = |fr, f, a, b, col = AZURE, amount = 0.2, n = 80| {
    var pts = [at(fr, a, 0)]
    for (x in sample(a, b, n)) {
        pts .= at(fr, x, clamp(fr[2], f(x), fr[3]))
    }
    pts .= at(fr, b, 0)
    return fill{tint(col, amount)} stroke{alpha{0} col, 0} Polygon(pts)
}

# vectors are pairs [x, y]. a board is [o, u, x0, x1, y0, y1]: the scene point of the origin,
# the unit length, and the window of whole numbers that is drawn
let Board = |o, u, x0, x1, y0, y1| [o, u, x0, x1, y0, y1]
let P = |pl, v| [pl[0][0] + pl[1] * v[0], pl[0][1] + pl[1] * v[1], 0]
let add = |v, w| [v[0] + w[0], v[1] + w[1]]
let times = |c, v| [c * v[0], c * v[1]]
# matrices are [a, b, c, d] with rows (a b) and (c d), so the columns are (a, c) and (b, d)
let IDENT = [1, 0, 0, 1]
let apply = |m, v| [m[0] * v[0] + m[1] * v[1], m[2] * v[0] + m[3] * v[1]]
let blend = |m, n, t| [
    m[0] + (n[0] - m[0]) * t,
    m[1] + (n[1] - m[1]) * t,
    m[2] + (n[2] - m[2]) * t,
    m[3] + (n[3] - m[3]) * t
]
let GRIDC = tint(AZURE, 0.42)
# faint gridlines, both axes, and numbers along the bottom and left edges every `step`
let Ground = |pl, step = 1, mult = 1| {
    var out = []
    let lo = P(pl, [pl[2], pl[4]])
    let hi = P(pl, [pl[3], pl[5]])
    for (x in range(pl[2], pl[3] + 1)) {
        let sx = P(pl, [x, 0])[0]
        out .= Seg([sx, lo[1], 0], [sx, hi[1], 0], MIST, 1.5)
        if (mod(x, step) == 0) {
            out .= center{[sx, lo[1] - 0.27, 0]} Math(to_string(x * mult), 0.72, SLATE)
        }
    }
    for (y in range(pl[4], pl[5] + 1)) {
        let sy = P(pl, [0, y])[1]
        out .= Seg([lo[0], sy, 0], [hi[0], sy, 0], MIST, 1.5)
        if (mod(y, step) == 0) {
            out .= center{[lo[0] - 0.38, sy, 0]} Math(to_string(y * mult), 0.72, SLATE)
        }
    }
    if (pl[4] <= 0 and pl[5] >= 0) {
        out .= Seg(P(pl, [pl[2], 0]), P(pl, [pl[3], 0]), SLATE, 2.5)
    }
    if (pl[2] <= 0 and pl[3] >= 0) {
        out .= Seg(P(pl, [0, pl[4]]), P(pl, [0, pl[5]]), SLATE, 2.5)
    }
    return out
}
# the part of the segment from scene point p to q that lies in the box lo..hi
let ClipSeg = |p, q, lo, hi, col, w| {
    let d = [q[0] - p[0], q[1] - p[1]]
    var t0 = 0
    var t1 = 1
    for (k in [0, 1]) {
        if (abs(d[k]) < 0.00001) {
            if (p[k] < lo[k] - 0.0001 or p[k] > hi[k] + 0.0001) {
                t1 = -1
            }
        }
        if (abs(d[k]) >= 0.00001) {
            let ta = (lo[k] - p[k]) / d[k]
            let tb = (hi[k] - p[k]) / d[k]
            t0 = max(t0, min(ta, tb))
            t1 = min(t1, max(ta, tb))
        }
    }
    if (t1 - t0 < 0.002) {
        return []
    }
    return stroke{col, w} Line(
        [p[0] + t0 * d[0], p[1] + t0 * d[1], 0],
        [p[0] + t1 * d[0], p[1] + t1 * d[1], 0]
    )
}
# a segment between two points of the board, cut off at the window
let Cut = |pl, a, b, col = SLATE, w = 2|
    ClipSeg(P(pl, a), P(pl, b), P(pl, [pl[2], pl[4]]), P(pl, [pl[3], pl[5]]), col, w)
# the whole-number grid after the matrix m: lines along the first column in col_a, along the second in col_b
let Lines = |pl, m, col_a = GRIDC, col_b = GRIDC, n = 8| block {
    for (k in range(-n, n + 1)) {
        var w = 1.8
        if (k == 0) {
            w = 3
        }
        . Cut(pl, apply(m, [-n, k]), apply(m, [n, k]), col_a, w)
        . Cut(pl, apply(m, [k, -n]), apply(m, [k, n]), col_b, w)
    }
}
# an arrow between two points of the board
let Vec = |pl, a, b, col = INK, w = 4.5, head = 0.2| {
    let p = P(pl, a)
    let q = P(pl, b)
    if (sqrt((q[0] - p[0]) ^ 2 + (q[1] - p[1]) ^ 2) < head * 1.3) {
        return Seg(p, q, col, w)
    }
    return Tip(p, q, col, w, head)
}
# transform the grid: the matrix is t of the way from m0 to m1; the first basis arrow is blue, the second orange
let Warp = |pl, m0, m1, t| {
    let m = blend(m0, m1, t)
    return [
        Lines(pl, m),
        Vec(pl, [0, 0], [m[0], m[2]], AZURE),
        Vec(pl, [0, 0], [m[1], m[3]], EMBER)
    ]
}
let Dash = |a, b, col = SLATE, w = 2.5| stroke{col, w} dashed{[0.1, 0.08]} Line(a, b)
let clean = |x| {
    if (abs(x) < 0.005) {
        return 0
    }
    return x
}
# a 2x2 matrix readout with brackets, first column blue and second orange
let MatBox = |c, m, places = 1, s = 0.9| {
    let dx = 0.5
    let dy = 0.3
    let bx = 1.0
    let by = 0.62
    let lip = 0.13
    let q = |x, y| [c[0] + x, c[1] + y, 0]
    return [
        stroke{INK, 2.5} Polyline([q(-bx + lip, by), q(-bx, by), q(-bx, -by), q(-bx + lip, -by)]),
        stroke{INK, 2.5} Polyline([q(bx - lip, by), q(bx, by), q(bx, -by), q(bx - lip, -by)]),
        center{q(-dx, dy)} scale{s} color{AZURE} Number(clean(m[0]), places),
        center{q(dx, dy)} scale{s} color{EMBER} Number(clean(m[1]), places),
        center{q(-dx, -dy)} scale{s} color{AZURE} Number(clean(m[2]), places),
        center{q(dx, -dy)} scale{s} color{EMBER} Number(clean(m[3]), places)
    ]
}
let matmul = |m, n| [
    m[0] * n[0] + m[1] * n[2],
    m[0] * n[1] + m[1] * n[3],
    m[2] * n[0] + m[3] * n[2],
    m[2] * n[1] + m[3] * n[3]
]
# an F, so that turning and mirroring can be told apart
let FPTS = [[0.4, 0.3], [0.8, 0.3], [0.8, 1.1], [1.3, 1.1], [1.3, 1.5], [0.8, 1.5], [0.8, 1.9], [1.6, 1.9], [1.6, 2.3], [0.4, 2.3]]
let FShape = |pl, m, col = LEAF| Shape(map(FPTS, |p| P(pl, apply(m, p))), col, 0.22, 2.5)
let R = [0, -1, 1, 0]
let S = [1, 1, 0, 1]
let rotm = |deg| [cos(deg * PI / 180), -sin(deg * PI / 180), sin(deg * PI / 180), cos(deg * PI / 180)]
let shearm = |k| [1, k, 0, 1]
# two moves in a row as s runs from 0 to 2: the first during 0..1, the second during 1..2
let RotShear = |s| matmul(shearm(clamp(0, s - 1, 1)), rotm(90 * clamp(0, s, 1)))
let ShearRot = |s| matmul(rotm(90 * clamp(0, s - 1, 1)), shearm(clamp(0, s, 1)))
let FSmall = |pl, m, col = LEAF| Shape(map(FPTS, |p| P(pl, apply(m, times(0.45, p)))), col, 0.22, 2.5)
# the grid, a small F and the two basis arrows after the matrix m
let Scene = |pl, m| [
    Lines(pl, m),
    FSmall(pl, m),
    Vec(pl, [0, 0], [m[1], m[3]], EMBER),
    Vec(pl, [0, 0], [m[0], m[2]], AZURE)
]
let BL = Board([-1.75, -0.1, 0], 0.75, -2, 2, -2, 2)
let BR = Board([1.95, -0.1, 0], 0.75, -2, 2, -2, 2)
let Bc = Board([-0.85, 0, 0], 0.8, -3, 3, -2, 2)
let B2 = Board([-1.94, -0.24, 0], 0.68, -2, 5, -2, 3)