Chapter 3.3 introduced the definition of a linear transformation, T. Here, we will discuss several examples of linear transformations, and learn how to find and use a linear transformation’s associated matrix.
from pathlib import Path
import sys
_notes_root = next(p for p in [Path.cwd(), *Path.cwd().parents] if (p / 'myst.yml').exists())
if str(_notes_root / 'ch03') not in sys.path:
sys.path.insert(0, str(_notes_root / 'ch03'))
from friendly_visuals import mapping, transform, projection_line, projection_plane
from chapter3_visuals import save_figure, widget, show_3d, rotation_slider, show_interactive
from analogy_visuals import lines_stay_lines
It’s not immediately obvious what multiplying by A will do. Let’s try a few inputs:
A[10]=[11],A[01]=[10],A[11]=[21].
The first two outputs are the columns of A. The third is the sum of the two columns of A – this should not be a surprise, since the act of multiplying by A is a linear transformation, and so it must be true that
T(u+v)=T(u)+T(v)
for all possible u and v. (Here, u is the first column of A and v is the second column of A.)
Let e1=[10] and e2=[01] be the standard basis vectors. To see more than individual vectors, let’s draw the square with corners 0, e1, e1+e2, and e2, and apply A to every point in it. This is a visualization strategy we will use repeatedly in this section.
save_figure(transform([[1,1],[1,0]], matrix_name='A'), 'first-transformation', 'The unit square becomes a parallelogram with corners (0,0), (1,1), (2,1), and (1,0). Blue and orange arrows track the two standard basis vectors.')
Loading...
The square becomes a parallelogram! As we will see later in this section, this transformation is an example of a shear. As a function, this is the transformation
T([xy])=[x+yx].
For instance, [2−1] becomes [12].
For the next several examples, we focus on transformations from R2 to R2 – which are defined using a 2×2 matrix – because transformations in which the input and output vectors are both in R2 are easy to visualize. Later, we will consider transformations whose domains and codomains have different shapes.
Suppose we want to stretch everything horizontally by a factor of 2, leaving the vertical coordinates alone. What should happen to [xy]? It should become
T([xy])=[2xy].
Its associated matrix – that is, the matrix H for which T([xy])=H[xy] – is
H=[2001].
We could also find H by following the standard basis vectors. Recall that the standard basis vectors in R2 are
e1=[10],e2=[01].
At the end of Chapter 3.3, we said that if we know the outputs of a linear transformation for e1 and e2 — that is, T(e1) and T(e2) — we know its entire associated matrix:
H=⎣⎡∣T(e1)∣∣T(e2)∣⎦⎤.
Here, the first basis vector doubles in length, while the second stays where it is:
T(e1)=T([10])=[20],T(e2)=T([01])=[01].
Putting these outputs into columns gives H=[2001], as before.
save_figure(transform([[2,0],[0,1]], matrix_name='H'), 'horizontal-stretch', 'The unit square becomes a rectangle twice as wide.')
Loading...
More generally, a diagonal matrix [a00b] multiplies the first coordinate by a and the second by b. When a=b=2, both coordinates double, so the whole square doubles in size. When a scale factor is negative, there is a flip as well, which we can interpret as a reflection across an axis – as we’re about to do.
To reflect across the x-axis, keep the first coordinate and change the sign of the second:
T([xy])=[x−y].
This is slightly counterintuitive, perhaps: reflecting across the x-axis changes the vector’s y component, not its x component.
This transformation has associated matrix
S=[100−1].
For example, [21] becomes [2−1]. A point above the x-axis moves the same distance below it. Points already on the x-axis stay put.
save_figure(transform([[1,0],[0,-1]], matrix_name='S'), 'reflection', 'The unit square is reflected below the x-axis.')
Loading...
What would change if we reflected across the y-axis instead? Now we would change the sign of the first coordinate, giving [−1001].
We’ve shown the two simplest examples of reflections – across the x or y axes. In a homework problem, you’ll explore how to reflect across a line that has some slope, e.g. across the line spanned by [3−5].
What matrix rotates vectors counterclockwise by 90∘ about the origin? Rather than guessing all four entries, let’s follow the standard basis vectors:
e1[10]⟼[01],e2[01]⟼[−10].
These are the columns of the transformation’s associated matrix! Therefore,
R=[01−10],T([xy])=[−yx].
For example, R[21]=[−12].
save_figure(transform([[0,-1],[1,0]], matrix_name='R'), 'quarter-turn', 'The unit square rotates counterclockwise into the second quadrant.')
Loading...
The same idea works for any fixed angle θ. A counterclockwise rotation sends
e1⟼[cosθsinθ],e2⟼[−sinθcosθ].
The first vector, T(e1), comes from the unit circle: trigonometry tells us that the point at distance 1 from (0,0) that makes an angle θ with the x-axis is (cosθ,sinθ). The second vector, T(e2), is a 90∘ counterclockwise rotation from the first. Thus
T([xy])=Rθ[xy],
where the associated matrix is
Rθ=[cosθsinθ−sinθcosθ].
Use the slider below to change θ.
show_interactive(rotation_slider(), 'Rotation by an angle', 'Move the slider to see how the unit square and standard basis vectors rotate.', 620)
Loading...
Rotations preserve lengths and angles between vectors:
Preserving length means that ∥Rθx∥=∥x∥ for all x. This is not true of every linear transformation: a transformation that stretches the x-component by 2 and keeps the y-component fixed doubles the length of e1 but leaves the length of e2 unchanged.
Preserving angles means that the angle between u and v is the same as the angle between Rθu and Rθv. Again, this is also not true in general of all linear transformations.
You might notice that the columns of Rθ form an orthonormal basis for R2. Their dot product is
It turns out that any 2×2 matrix whose columns form an orthonormal basis for R2 represents a rotation, possibly combined with a reflection.
For example, consider
Q=[3/5−4/54/53/5].
Its columns have dot product (53)(54)+(−54)(53)=0, and each has length (3/5)2+(4/5)2=1. This matrix is a rotation with cosθ=3/5 and sinθ=−4/5: it rotates vectors clockwise by approximately 53.1∘. Here is what it does to the unit square and standard basis vectors.
save_figure(transform([[3/5,4/5],[-4/5,3/5]], matrix_name='Q'), 'rational-rotation', 'The unit square rotates clockwise by approximately 53.1 degrees. The first basis vector becomes the column vector with entries 3/5 and minus 4/5, and the second becomes the column vector with entries 4/5 and 3/5.')
In this next transformation, imagine glueing one edge of the unit square to the x-axis, and dragging the top-right corner of it to the right or left. Such a transformation may be of the form:
T([xy])=[x+yy].
Its associated matrix is
K=[1011].
This is called a horizontal shear.
save_figure(transform([[1,1],[0,1]], matrix_name='K'), 'simple-shear', 'The top of the unit square moves right by one unit, while its bottom edge stays fixed.')
Loading...
For example, [21] becomes [31], while [20] stays unchanged. This isn’t moving everything the same distance to the right: how far a point moves depends on its second coordinate.
A stronger horizontal shear is
T([xy])=[x+3yy],
with associated matrix [1031]. More generally, replacing the upper-right entry by k gives the horizontal shear T([xy])=[x+kyy].
save_figure(transform([[1,3],[0,1]], matrix_name='K'), 'strong-horizontal-shear', 'The unit square is transformed by a horizontal shear with factor 3.')
Loading...
A vertical shear instead adds a multiple of the horizontal coordinate to the vertical coordinate. For example,
T([xy])=[x2x+y],
whose associated matrix is [1201].
save_figure(transform([[1,0],[2,1]], matrix_name='K'), 'vertical-shear', 'The unit square is transformed by a vertical shear with factor 2.')
Let’s return to an operation we already know: orthogonal projection. Let’s start with the simplest case, projecting onto the x-axis. We keep the horizontal coordinate and set the vertical coordinate to zero:
T([xy])=[x0].
Its associated matrix is
P=[1000].
What happens to our square this time?
save_figure(transform([[1,0],[0,0]], matrix_name='P'), 'axis-projection', 'The unit square collapses to the segment from (0,0) to (1,0) on the x-axis.')
Loading...
In all previous examples, the unit square on the left got transformed into a parallelogram on the right. Not here: the transformation sent both e1=[10] and e2=[01] to vectors that live on the x-axis ([10] and [00], respectively), so there is no longer a parallelogram — just a line segment.
Different inputs can have the same output: [12] and [15] both become [10].
We defined P:R2→R2, so its codomain is R2. But the outputs it actually produces all lie on the x-axis – that is, its set of actual outputs is different than its set of possible outputs. There is no way for, say, [34] to be the result of Px for any vector x∈R2.
Both output entries are the average of the two input entries, so the associated matrix is
P=[1/21/21/21/2].
For instance, [31] projects to [22].
Here the original vector v and its transformed vector T(v) appear in the same plot, rather than side-by-side in separate plots as in the previous examples.
save_figure(projection_line(), 'diagonal-projection', 'The vector with entries 3 and 1 projects to the vector with entries 2 and 2 on y equals x.')
Loading...
More generally, if L=span(w) and w=[w1w2] is a unit vector, then projection onto L has associated matrix
P=[w12w1w2w1w2w22].
For example, consider projecting onto the line spanned by w=[3−5]. This vector has length 34, so we first normalize it to get the unit direction vector
Here is the unit square before and after this projection. After the transformation, both basis vectors lie on the line spanned by w.
save_figure(transform([[9/34,-15/34],[-15/34,25/34]], matrix_name='P'), 'projection-three-minus-five', 'Before: the unit square and standard basis vectors. After: the square collapses to a line segment on y equals minus five thirds x; the basis vectors become (9/34, -15/34) and (-15/34, 25/34).')
In R3, projection onto the xy-plane is simple: set the third coordinate to zero.
T⎝⎛⎣⎡xyz⎦⎤⎠⎞=⎣⎡xy0⎦⎤.
Its associated matrix is
Q=⎣⎡100010000⎦⎤.
The matrix Q has shape 3×3 because both the input and output vectors are in R3.
For example, ⎣⎡213⎦⎤ becomes ⎣⎡210⎦⎤. You can drag the picture below to see the perpendicular drop to the plane.
show_interactive(projection_plane(), 'Projection onto the xy-plane', 'The first two coordinates stay the same; the third becomes zero. Drag to rotate the picture.')
Loading...
A matrix for projecting onto a plane other than the xy-, xz-, or yz-plane is slightly more complicated. We’ll explore these projections soon.
One thing you should have noticed in all of the transformations we’ve visualized is that the shape formed by transforming the standard basis vectors, e.g. the parallelogram below, always contained straight lines — never any curves.
save_figure(transform([[1,1],[0,1]], matrix_name='K'), 'simple-shear', 'The unit square becomes a parallelogram under a horizontal shear; all edges remain straight.')
Loading...
This is a general property of linear transformations: points that lie along a line in the domain still lie along a line in the output, unless the entire line collapses to a single point.
For example, use the horizontal shear matrix K again:
T(v)=Kv,K=[1011].
Follow three points on a line that does not pass through the origin as we apply K:
[01]⟼[11],[12]⟼[32],[23]⟼[53].
Note that all three points lived on a line before being sent through the transformation, and still live on a line after the transformation. A different line than before, yes, but still a line nonetheless.
save_figure(lines_stay_lines().update_layout(title=dict(text=r'$K=\begin{bmatrix}1&1\\0&1\end{bmatrix}$', x=.5, y=.88, yanchor='middle', font=dict(size=20)), height=470, margin=dict(t=140)), 'lines-stay-lines', 'Points P=(0,1), Q=(1,2), and R=(2,3) lie on a line that does not pass through the origin. Their outputs (1,1), (3,2), and (5,3) lie on another line that does not pass through the origin. Matching colors and marker shapes identify corresponding points.')
Loading...
Why does this happen? Choose a point p on the line and a nonzero direction vector v. Every other point on the line is obtained by adding some multiple of v to p. Because T is a linear transformation, it satisfies both of the following properties:
T(u+v)=T(u)+T(v) for every pair of vectors u,v in its domain.
T(cv)=cT(v) for every vector v in its domain and every scalar c.
Applying these properties gives
T(p+tv)=T(p)+T(tv)=T(p)+tT(v).
So every output is obtained by starting at T(p) and adding a multiple of the same direction vector T(v). The outputs still lie on a line. If T(v)=0, the entire line instead collapses to the single point T(p).
In many applications, keeping straight lines straight is desirable. When drawing a 3D scene on a 2D screen, for example, we want a straight building edge to appear straight in the image. We’ll explore this idea in just a moment.
So far, each transformation has returned the same number of entries it received. We looked at transformations from R2 to R2, described with a 2×2 matrix, and transformations from R3 to R3, described with a 3×3 matrix. But, a transformation can have a different domain (set of possible inputs) and codomain (set of possible outputs).
For example, the function
T:R2→R3,T([xy])=⎣⎡xyx+y⎦⎤
copies the two input entries and adds their sum as a third entry. Its associated matrix is
A=⎣⎡101011⎦⎤.
For example,
A[23]=⎣⎡235⎦⎤.
The domain is R2, the codomain is R3, and the matrix has shape 3×2.
As another example, define
T⎝⎛⎣⎡xyz⎦⎤⎠⎞=[xy].
Its associated matrix is B=[100100].
This has codomain R2. Compare it with projection onto the xy-plane above: [xy] has two entries, while ⎣⎡xy0⎦⎤ has three.
Computer games, and engineering software that visualize physical parts, all involve visualizing a three-dimensional world on your two-dimensional computer screen. To convert a three-dimensional world into a two-dimensional representation, we can use a linear transformation! Explore this below.
Start with the overhead view, then drag View toward Game view. Change Building height, and turn on Show basis arrows to see where the three standard basis vectors go.
widget('projection-widget.html', 'Interactive 3D-to-2D scene projection')
Loading...
In game view, the transformation uses the matrix
A=[40−204020040].
We choose how a one-unit step in each world direction should look on the screen.
One step in the world x-direction should move 40 units right and 20 units down on the screen.
One step in the world y-direction should move 40 units right and 20 units up.
One step upward in the world z-direction should move 40 units up, with no horizontal movement.
These choices tell us where the three standard basis vectors go:
Ae1=[40−20],Ae2=[4020],Ae3=[040].
Put those three outputs into columns, and we get A. The numbers 40 and 20 are drawing choices: their ratio makes the ground directions slope by one screen unit vertically for every two units horizontally: downward for the x-direction and upward for the y-direction. The 40 in the third column sets how tall a one-unit vertical edge appears. Other choices would give a different view or scale; doubling every entry would double the size of the drawing.
For an arbitrary world point, we combine these three screen movements:
For example, the ground corner ⎣⎡110⎦⎤ appears at [800]. The roof corner directly above it has height h, so
A⎣⎡11h⎦⎤=[8040h].
The horizontal coordinate stays at 80, while the vertical coordinate is 40 times the building’s height. At height h=1, the roof corner appears at [8040].
The domain is R3 and the codomain is R2. In the overhead view, we instead use
[40004000].
Now the two ground directions appear horizontal and vertical, and height disappears because the third column is zero. The View slider blends this matrix with the game-view matrix; each setting gives a linear transformation. The current matrix A is shown beneath the transformation in the interactive.
Activity 1
Consider the matrices
A=[1001],B=[1002].
Show that Ae1=Be1. Does this imply that A=B?
Find an input x for which Ax=Bx.
More generally, suppose A and B both have shape n×d and Ax=Bx for every x∈Rd. Explain why A=B by considering the standard basis vectors.
Suppose instead that Ae1=Be1 and A(e1+e2)=B(e1+e2). Must A=B? Use linearity to explain.