#
import numpy as np
import scipy as sp
import pandas as pd
import matplotlib as mp
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn
import laUtilities as ut
import slideUtilities as sl
import demoUtilities as dm
from matplotlib import animation
from importlib import reload
from datetime import datetime
from IPython.display import Image, display_html, display, Math, HTML;
qr_setting = None
mp.rcParams['animation.html'] = 'jshtml';
Homework 4 is out, due 3/3
Upcoming office hours
Aggarwal Section 2.4-2.5
#
display(Image("images/01-modes.jpg", width=600))
[This lecture is based on Prof. Crovella's CS 132 lecture notes.]
So far we've been treating the matrix equation
as simply another way of writing the vector equation
However, we'll now think of the matrix equation in a new way:
We will think of as a function that is "acting on" the vector to create a new vector .
#
display(Image("images/05-2dtransform.jpg", width=1000))
For example, consider Then we find:
In other words, if and , then transforms into .
#
display(Image("images/05-3dtransform.jpg", width=1000))
Notice what has done: it took a vector in and transformed it into a vector in .
Question. How does this fact relate to the shape of ?
is -- that is, .
This gives a new way of thinking about solving .
When we solve , we are finding the vector(s) in that are transformed into in under the "action" of .
For a different , the mapping might be from to :
#
display(Image("images/05-1dtransform.jpg", width=1000))
Question. What would the shape of be in the above case?
Since maps from to , .
That is, has 3 rows and 1 column.
In another case, could be a square matrix.
Then, it would map from to .
#
display(Image("images/05-2dtransform.jpg", width=1000))
We have moved out of the familiar world of functions of one variable: we are now thinking about functions that transform a vector into a vector.
Or, put another way, functions that transform multiple variables into multiple variables.
Some terminology:
A transformation (or function or mapping) from to is a rule that assigns to each vector in a vector in .
The set is called the domain of , and is called the codomain of .
The notation:
indicates that the domain of is and the codomain is .
For in the vector is called the image of (under ). We may sometimes write that maps .
The set of all images is called the range of .
#
display(Image("images/05-image.jpg", width=1000))
Here, the green plane is the set of all points that are possible outputs of for some input .
So in this example:
Let's do an example. Say that I have these points in :
These points form a square in 2-dimensional space, where each side is of length 1.
#
square = np.array([[0, 1, 1, 0],
[1, 1, 0, 0]])
dm.plotSetup()
# print(square)
dm.plotSquare(square)
Now let's transform each of these points according to the following rule. Consider the following matrix, which is called a shear matrix.
We define . Then we have
What is the image of each of these points under ?
#
ax = dm.plotSetup()
# print("square = "); print(square)
dm.plotSquare(square)
#
# create the A matrix
A = np.array([[1.0, 1.5],[0.0,1.0]])
# print("A matrix = "); print(A)
#
# apply the shear matrix to the square
ssquare = np.zeros(np.shape(square))
for i in range(4):
ssquare[:,i] = dm.AxVS(A,square[:,i])
# print("sheared square = "); print(ssquare)
dm.plotSquare(ssquare,'r')
This sort of transformation, where points are successively slid sideways, is called a shear transformation.
By the algebraic properties of matrix-vector multiplication, we know that the transformation has the properties that
for all in and all scalars .
We are now ready to define one of the most fundamental concepts in the course: the concept of a linear transformation. (This is why the subject is called linear algebra!)
Definition. A transformation is linear if:
To fully grasp the significance of what a linear transformation is, don't think of just matrix-vector multiplication. Think of as a function in more general terms.
The definition above captures a lot of transformations that are not matrix-vector multiplication. For example, think of:
is a linear transformation!
A key aspect of a linear transformation is that it preserves the operations of vector addition and scalar multiplication.
For example: for vectors and , one can either:
One gets the same result either way. The transformation and the addition "commute" with each other.
This leads to two important facts.
If is a linear transformation, then
and
In fact, if a transformation satisfies the second equation for all and then it must be a linear transformation.
Both of the rules defining a linear transformation derive from this single equation.
Example.
Given a scalar , define by .
( is called a contraction when and a dilation when .)
Let , and show that is a linear transformation.
Solution.
Let be in and let be scalars. Then
Thus is a linear transformation because it satisfies the rule .
Example.
Let for some .
What sort of operation does implement?
Answer: translation.
Is a linear transformation?
Solution.
We only need to compare
to
So:
and
If , then the above two expressions are not equal.
So is not a linear transformation.
A company manufactures two products, B and C. To do so, it requires materials, labor, and overhead.
For one dollar's worth of product B, it spends 45 cents on materials, 25 cents on labor, and 15 cents on overhead.
For one dollar's worth of product C, it spends 40 cents on materials, 30 cents on labor, and 15 cents on overhead.
Let us construct a "unit cost" matrix:
Let be a production vector, corresponding to dollars of product B and dollars of product C.
Then define by
The mapping transforms a list of production quantities into a list of total costs.
The linearity of this mapping is reflected in two ways:
We have seen that every matrix multiplication is a linear transformation from vectors to vectors.
But, are there any other possible linear transformations from vectors to vectors?
No! In other words, the reverse statement is also true:
Every linear transformation from vectors to vectors is a matrix multiplication.
We'll now prove this fact. We'll do it constructively, meaning we'll actually show how to find the matrix corresponding to any given linear transformation .
Theorem. Let be a linear transformation. Then there is (always) a unique matrix such that:
Let denote the th column of the identity matrix in . These vectors are called the standard basis vectors.
#
ax = dm.plotSetup(-3,3,-3,3,size=(6,6))
ax.plot([0],[1],'ro',markersize=8)
ax.arrow(0, 0, 1, 0, head_width=0.2, head_length=0.2, length_includes_head = True)
ax.arrow(0, 0, 0, 1, head_width=0.2, head_length=0.2, length_includes_head = True)
ax.text(0.25,1,'(0,1)',size=20)
ax.plot([1],[0],'ro',markersize=8)
ax.text(1.25,0.25,'(1,0)',size=20);
Then, is the matrix whose th column is the vector , where
is called the standard matrix of .
Proof. Write
Because is linear, we have:
So ... we see that the ideas of matrix multiplication and linear transformation of vector spaces are essentially equivalent.
In this course, we will use the term linear transformation when we want to focus on a property of the mapping, while the term matrix multiplication focuses on how such a mapping is implemented.
To find the standard matrix of a linear tranformation, ask what the transformation does to the columns of .
Now, in , . So:
To find the matrix of any given linear transformation of vectors in , we only have to know what that transformation does to these two points.
This is a hugely powerful tool. If we start from some given linear transformation, we can use this idea to find the matrix that implements that linear transformation.
For example, let's consider rotation about the origin as a kind of transformation.
#
u = np.array([1.5, 0.75])
v = np.array([0.25, 1])
diamond = np.array([[0,0], u, u+v, v]).T
ax = dm.plotSetup()
plt.plot(u[0], u[1], 'go')
plt.plot(v[0], v[1], 'yo')
ax.text(u[0]+.25,u[1],r'$\bf{u}$',size=20)
ax.text(v[0],v[1]-.35,r'$\bf{v}$',size=20)
rotation = np.array([[0, -1],[1, 0]])
up = rotation @ u
vp = rotation @ v
plt.plot(up[0], up[1], 'go')
plt.plot(vp[0], vp[1], 'yo')
ax.text(up[0]-1,up[1],r'$T(\mathbf{u})$',size=20)
ax.text(vp[0]-.9,vp[1]+.15,r'$T(\mathbf{v})$',size=20)
ax.text(0.75, 1.75, r'$\theta$', size = 20)
ax.text(-.5, 0.25, r'$\theta$', size = 20)
ax.annotate("",
xy=((up)[0]+.1, (up)[1]+.1), xycoords='data',
xytext=((u)[0]-.1, (u)[1]+.1), textcoords='data',
size=20, va="center", ha="center",
arrowprops=dict(arrowstyle="simple",
connectionstyle="arc3,rad=0.3"),
)
ax.annotate("",
xy=((vp)[0]+.1, (vp)[1]+.1), xycoords='data',
xytext=((v)[0]-.1, (v)[1]), textcoords='data',
size=20, va="center", ha="center",
arrowprops=dict(arrowstyle="simple",
connectionstyle="arc3,rad=0.3"),
);
First things first: Is rotation a linear transformation?
Recall that a for a transformation to be linear, it must be true that
I'm going to show you a "geometric proof."
This figure shows that "the rotation of is the sum of the rotation of and the rotation of ".
#
u = np.array([1.5, 0.75])
v = np.array([0.25, 1])
diamond = np.array([[0,0], u, u+v, v]).T
ax = dm.plotSetup()
dm.plotSquare(diamond)
ax.text(u[0]+.25,u[1],r'$\bf{u}$',size=20)
ax.text(v[0],v[1]+.25,r'$\bf{v}$',size=20)
ax.text(u[0]+v[0]+.25,u[1]+v[1],r'$\bf{u + v}$',size=20)
rotation = np.array([[0, -1],[1, 0]])
up = rotation @ u
vp = rotation @ v
diamond = np.array([[0,0], up, up+vp, vp]).T
dm.plotSquare(diamond)
ax.text(0.75, 2.4, r'$\theta$', size = 20)
ax.annotate("",
xy=((up+vp)[0]+.1, (up+vp)[1]+.1), xycoords='data',
xytext=((u+v)[0]-.1, (u+v)[1]+.1), textcoords='data',
size=20, va="center", ha="center",
arrowprops=dict(arrowstyle="simple",
connectionstyle="arc3,rad=0.3"),
);
So the answer is yes, rotation is a linear transformation.
Let's see how to compute the linear transformation that is a rotation.
Specifically: Let be the transformation that rotates each point in about the origin through an angle , with counterclockwise rotation for a positive angle.
Let's find the standard matrix of this transformation.
Question. The columns of are and Where does map the standard basis vectors?
Referring to the diagram below, we can see that rotates into and rotates into
#
import matplotlib.patches as patches
ax = dm.plotSetup(-1.2, 1.2, -0.5, 1.2)
# red circle portion
arc = patches.Arc([0., 0.], 2., 2., 0., 340., 200.,
linewidth = 2, color = 'r',
linestyle = '-.')
ax.add_patch(arc)
#
# labels
ax.text(1.1, 0.1, r'$\mathbf{e}_1 = (1, 0)$', size = 20)
ax.text(0.1, 1.1, r'$\mathbf{e}_2 = (0, 1)$', size = 20)
#
# angle of rotation and rotated points
theta = np.pi / 6
e1t = [np.cos(theta), np.sin(theta)]
e2t = [-np.sin(theta), np.cos(theta)]
#
# theta labels
ax.text(0.5, 0.08, r'$\theta$', size = 20)
ax.text(-0.25, 0.5, r'$\theta$', size = 20)
#
# arrows from origin
ax.arrow(0, 0, e1t[0], e1t[1],
length_includes_head = True,
width = .02)
ax.arrow(0, 0, e2t[0], e2t[1],
length_includes_head = True,
width = .02)
#
# new point labels
ax.text(e1t[0]+.05, e1t[1]+.05, r'$[\cos\; \theta, \sin \;\theta]$', size = 20)
ax.text(e2t[0]-1.1, e2t[1]+.05, r'$[-\sin\; \theta, \cos \;\theta]$', size = 20)
#
# curved arrows showing rotation
ax.annotate("",
xytext=(0.7, 0), xycoords='data',
xy=(0.7*e1t[0], 0.7*e1t[1]), textcoords='data',
size=10, va="center", ha="center",
arrowprops=dict(arrowstyle="simple",
connectionstyle="arc3,rad=0.3"),
)
ax.annotate("",
xytext=(0, 0.7), xycoords='data',
xy=(0.7*e2t[0], 0.7*e2t[1]), textcoords='data',
size=10, va="center", ha="center",
arrowprops=dict(arrowstyle="simple",
connectionstyle="arc3,rad=0.3"),
)
#
# new points
plt.plot([e1t[0], e2t[0]], [e1t[1], e2t[1]], 'bo', markersize = 10)
plt.plot([0, 1], [1, 0], 'go', markersize = 10);
So by the Theorem above,
In particular, a 90 degree counterclockwise rotation corresponds to the matrix
To demonstrate computationally the use of a rotation matrix, let's rotate the following shape note
. It is constructed using an array of 26 vectors in that define its outline. In other words, it is a 2 26 matrix.
note = np.array(
[[193,47],
[140,204],
[123,193],
[99,189],
[74,196],
[58,213],
[49,237],
[52,261],
[65,279],
[86,292],
[113,295],
[135,282],
[152,258],
[201,95],
[212,127],
[218,150],
[213,168],
[201,185],
[192,200],
[203,214],
[219,205],
[233,191],
[242,170],
[244,149],
[242,131],
[233,111]])
note = note.T/150.0
#
dm.plotSetup()
dm.plotShape(note)
To rotate note
we need to multiply each column of note
by the rotation matrix .
Recall that: in Python matrix multiplication is performed using the @
operator. That is, if A
and B
are matrices, then
A @ B
will multiply A
by every column of B
, and the resulting vectors will be formed
into a matrix.
angle = 90
theta = (angle/180) * np.pi
A = np.array(
[[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
rnote = A @ note
#
dm.plotSetup()
dm.plotShape(rnote)