Vectors & Matrices (SymPy)
Let's begin by importing the SymPy package.
The *
means the namespace for all functions in SymPy are loaded, so we can call them directly without having to preface them with the package name.
SymPy Matrices
Vectors and Matrices are created as instances of a SymPy Matrix
object. It is constructed by providing a list of row vectors that make up the matrix. Providing just a single list of entries creates a column vector. We'll get up and running with a number of examples below. So learn more check out the full SymPy Matrix documentation.
Vectors
Let's create a vector of integers.
\(\left[ \begin{matrix} 1 \\ 2 \\ 3 \\ 4 \\ \end{matrix} \right]\)
We can verify the shape.
shape
returns a pair of numbers (rows, columns).
Matrices
Let's create a matrix.
\(\left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ \end{matrix} \right]\)
The matrix was entered as a list of rows.
Alternatively, we can construct a matrix by first stating its size, then the list of entries.
\(\left[ \begin{matrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \\ \end{matrix} \right]\)
.reshape
Another way to create a matrix is to first create column vector and then use the .reshape
method to change its shape as desired.
\(\left[ \begin{matrix} 1 & 2 & 3 & 4 & 5 & 6 \\ 7 & 8 & 9 & 10 & 11 & 12\\ \end{matrix} \right]\)
- This does not change the matrix stored in the variable A, it creates a new instance that has been reshaped.
\(\left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ 10 & 11 & 12\\ \end{matrix} \right]\)
Variable entries
Variables can be used in SymPy. First we need to declare them.
\(\left[ \begin{matrix} a & 2 & 3 \\ 2a & b+1 & bc+a \\ \end{matrix} \right]\)
Indexing
In Python indices begin at 0. Therefore, to select the first entry of vector a
we use a[0]
.
We can also use index slicing to select multiple entries in a matrix.
- select entries from index 1 (inclusive) to 3 (non-inclusive). That is, select entries with index from 1 to 2.
This can be done for matrices by specifying both indices.
\(\left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ 10 & 11 & 12 \\ \end{matrix} \right]\)
- This selects the entry in row indexed by 3, and column indexed by 2. Remember indexing starts at 0.
We can use slicing to select submatricies.
- This selects all entries from row 0 (inclusive) up to row 2 (not inclusive), and column 0 (inclusive) up to column 3 (not inclusive). This will be a 2x3 submatrix.
\(\left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ \end{matrix} \right]\)
An entire column can be selected using slicing.
:
means run over all values of the index. Therefore, this selects the first column.
\(\left[ \begin{matrix} 1 \\ 4 \\ 7 \\ 10 \\ \end{matrix} \right]\)
Notice that b
is a column vector.
Accessing Rows and Columns
Columns and rows can also be extracted using .col
and .row
.
\(\left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ 10 & 11 & 12 \\ \end{matrix} \right]\)
\(\left[ \begin{matrix} 1 \\ 4 \\ 7 \\ 10 \\ \end{matrix} \right]\)
\(\left[ \begin{matrix} 7 & 8 & 9 \\ \end{matrix} \right]\)
Inserting and Deleting Rows and Columns
Columns and rows can be inserted using .col_insert
and .row_insert
.
This does not change the original matrix.
Here we add a column of \(1\)'s to the end of matrix \(A\).
\(\left[ \begin{matrix} 1 & 2 & 3 & 1\\ 4 & 5 & 6 & 1\\ 7 & 8 & 9 & 1\\ 10 & 11 & 12 & 1\\ \end{matrix} \right]\)
Two matrices can be joined together using row_join
or col_join
. These names may be at first counterintuitive. The row_join
command concatenates rows, therefore making more columns. Similar, col_join
concatenates columns.
A = Matrix([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
B = Matrix([[1,2],[1,2],[1,2],[1,2]])
A.row_join(B)
\(\left[ \begin{matrix} 1 & 2 & 3 & 1 & 2\\ 4 & 5 & 6 & 1 & 2\\ 7 & 8 & 9 & 1 & 2\\ 10 & 11 & 12 & 1 & 2\\ \end{matrix} \right]\)
Columns and rows can be deleted using .col_del
and .row_del
.
This changes the original matrix.
\(\left[ \begin{matrix} 1 & 2 1\\ 4 & 5 \\ 7 & 8 \\ 10 & 11\\ \end{matrix} \right]\)
Special Matrices
SymPy has some predefined special matrices which can be useful for quickly constructing matrices.
Identity
An \(n \times n\) identity matrix is constructed with eye(n)
. Can also use eye(m,n)
for rectangular matrices.
\(\left[ \begin{matrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{matrix} \right]\)
Zeros
An \(n \times m\) zero matrix is constructed with zeros(n,m)
. Can also use zeros(n)
for square matrices.
\(\left[ \begin{matrix} 0 & 0 \\ 0 & 0 \\ 0 & 0 \\ \end{matrix} \right]\)
Ones
An nxm matrix of all 1's is constructed with ones(n,m)
. Can also use ones(n)
for square matrices.
\(\left[ \begin{matrix} 1 & 1 \\ 1 & 1 \\ 1 & 1 \\ \end{matrix} \right]\)
Example
Construct the \(5 \times 5\) lower diagonal matrix.
\(\left[ \begin{matrix} 0 & 0 & 0 & 0 & 0\\ 1 & 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1 & 0 \end{matrix} \right]\)
Example
Construct the \(5 \times 5\) matrix with lower and upper diagonals of \(1\)'s.
AL = zeros(5)
AL[1:,:-1] = eye(4) # lower diagonal
AU = zeros(5)
AU[:-1,1:] = eye(4) # upper diagonal
A = AL + AU
A
\(\left[ \begin{matrix} 0 & 1 & 0 & 0 & 0 \\ 1 & 0 & 1 & 0 & 0 \\ 0 & 1 & 0 & 1 & 0 \\ 0 & 0 & 1 & 0 & 1 \\ 0 & 0 & 0 & 1 & 0 \\ \end{matrix} \right]\)
diagonal and block
To create a diagonal matrix use the SymPy diag
function.
\(\left[\begin{matrix} 1 & 0 & 0 \\ 0 & 2 & 0 \\ 0 & 0 & 3 \end{matrix}\right]\)
We can also use diag
to create a block matrix.
\(\left[\begin{matrix} 1 & 0 & 0 & 0 & 0 & 0\\ 0 & 2 & 2 & 0 & 0 & 0\\ 0 & 2 & 2 & 0 & 0 & 0\\ 0 & 0 & 0 & 3 & 3 & 3\\ 0 & 0 & 0 & 3 & 3 & 3\\ 0 & 0 & 0 & 3 & 3 & 3 \end{matrix}\right]\)
For further creation of block matrices lookup the BlockMatrix
command in SymPy.
random
To generate a random matrix in SymPy we use the random
package to first generate a list of random integers in some range. Then we reshape the list into a matrix.
import random
#Generate 8 random numbers between -10 and 10
randomlist = random.sample(range(-10, 10), 8)
A = Matrix(randomlist).reshape(2,4)
A
\(\left[ \begin{matrix} -2 & 0 & -9 & 4 \\ 8 & -5 & 7 & 3 \\ \end{matrix} \right]\)
Vector Operations
Dot Product
The dot product of two vectors can be done with the .dot
function.
Length (Norm)
The length (also called the norm) of an \(n\)-dimensional vector \(\vec{v} = [v_1, v_2, \ldots , v_n]\) is defined by
The norm of a vector can be done with the .norm
function.
SymPy returns the exact value of the norm.
\(\sqrt{14}\)
If we want a decimal approximation we can use .evalf()
or .n()
or N()
to covert to floating point (whichever you prefer). By default numerical evaluation is performed to an accuracy of 15 decimal digits. You can optionally pass a desired accuracy (a positive integer) as an argument to .evalf()
or .n()
or N()
. Below we show all three functions, with both the default number of places, and with \(25\) decimal places.
Angle between two vectors
The angle \(\theta\) between two vectors satisfies
\(\frac{\pi}{4}\)
We can build this into a function to make it easier to call.
\(\frac{3\pi}{4}\)
Let's do an example where the angle isn't so nice.
Matrix Operations
Matrix Scalar Multiplication
\(\left[ \begin{matrix} 3 & 6 \\ 9 & 12 \\ \end{matrix} \right]\)
Matrix Addition
\(\left[ \begin{matrix} -1 & 7 \\ 10 & 5 \\ \end{matrix} \right]\)
Matrix Multiplication
Let's start with the two matrices.
\(A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}\) and \(B = \begin{bmatrix} -2 & 5 \\ 7 & 1 \end{bmatrix}\)
The matix multiplication operator in SymPy is *
.
\(\left[ \begin{matrix} 12 & 7 \\ 22 & 19 \\ \end{matrix} \right]\)
Here is another example,
\(C = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix}\) and \(D = \begin{bmatrix} 1 & 2 & 1 & 2 \\ 1 & 2 & 1 & 2 \\ 1 & 2 & 1 & 2 \end{bmatrix}\)
The matrix product is a 2x4 matrix.
\(\left[ \begin{matrix} 6 & 12 & 6 & 12 \\ 15 & 30 & 15 & 30 \\ \end{matrix} \right]\)
Example
Putting this all together, let's compute \(3I + 2A -AB\) for
\(A = \begin{bmatrix} 1 & 2 \\ 2 & 1 \end{bmatrix}\) and \(B = \begin{bmatrix} 1 & 1 \\ 1 & 1 \end{bmatrix}\)
\(\left[ \begin{matrix} 2 & 1 \\ 1 & 2 \\ \end{matrix} \right]\)
Matrix Powers
To compute a matrix power we use the **
operator.
\(\left[ \begin{matrix} -1 & 4 \\ -2 & -1 \\ \end{matrix} \right]\)
Transpose
The transpose of a matrix can be taken by using either of these methods on an array
: .T
or .transpose
.
\(\left[ \begin{matrix} 1 & 2 \\ 3 & 4 \\ \end{matrix} \right]\)
\(\left[ \begin{matrix} 1 & 3 \\ 2 & 4 \\ \end{matrix} \right]\)
Inverse
To find the inverse of a matrix raise it to the power of -1
.
\(\left[ \begin{matrix} 1 & 2 \\ 3 & 4 \\ \end{matrix} \right]\)
\(\left[ \begin{matrix} -2 & 1 \\ 3/2 & -1/2 \\ \end{matrix} \right]\)
Trace
We can find the trace of a matrix by using .trace
, either called as a method A.trace()
or a function trace(A)
.
Determinant
We can find the determinant of a matrix by using .det
, either called as a method A.det()
or a function det(A)
.
Rank
We can find the rank using the .rank
function.
Examples
Characteristic Polynomial and the Cayley-Hamilton Theorem
The characteristic polynomial of a 2x2 matrix \(A\) is
The Cayley-Hamilton Theorem states that any square matrix satisfies its characteristic polynomial. This means
Let's check that this is the case for some matrices.
def check_cayley_hamilton(A):
# input: a 2x2 matrix A
trace_A = A.trace()
det_A = A.det()
I = eye(2)
return A*A - trace_A*A + det_A*I
Example
\(\left[ \begin{matrix} 0 & 1 \\ 7 & 5 \\ \end{matrix} \right]\)\(\left[ \begin{matrix} 0 & 0 \\ 0 & 0 \\ \end{matrix} \right]\)
Projections
The projection of a vector \(\vec{v}\) onto a vector \(\vec{w}\) is
The perpendicular of the projection of \(\vec{v}\) onto \(\vec{w}\) is
This decomposes the vector \(\vec{w}\) into two parts:
where \(\operatorname{proj}_{\vec{w}}(\vec{v})\) is parallel to \(\vec{w}\) and \(\operatorname{perp}_{\vec{w}}(\vec{v})\) is perpenicular to \(\vec{w}\).
Let's define a function called proj
which returns the projection of \(\vec{v}\) onto \(\vec{w}\), and a function called perp
.
def proj(v,w):
# input: v, w are vectors represented as 1D arrays
# output: projection of v onto w
return (v.dot(w)/w.dot(w))*w
def perp(v,w):
# input: v, w are vectors represented as lists
# output: perpendicular of the projection of v onto w
return v-proj(v,w)
Example
Consider the vectors \(\vec{v} = [4,2]\) and \(\vec{w} = [1,1]\). The projection of \(\vec{v}\) onto \(\vec{w}\) is \(3\vec{w} = [3,3]\).
\(\left[ \begin{matrix} 3 \\ 3 \\ \end{matrix} \right]\)
The perpendicular is \([1,-1]\):
\(\left[ \begin{matrix} 1 \\ -1 \\ \end{matrix} \right]\)
We can verify the sum is the vector \(\vec{v}\).
\(\left[ \begin{matrix} 4 \\ 2 \\ \end{matrix} \right]\)
Example
Consider the vectors \(\vec{v} = [1,3,-1]\) and \(\vec{w} = [1,1,2]\). The projection of \(\vec{v}\) onto \(\vec{w}\) is \(3\vec{w} = [1/3,1/3,2/3]\).
\(\left[ \begin{matrix} 1/3 \\ 1/3 \\ 2/3 \\ \end{matrix} \right]\)
The perpendicular is \([2/3, 8/3, -5/3]\):
\(\left[ \begin{matrix} 2/3 \\ 8/3 \\ -5/3 \\ \end{matrix} \right]\)
We can check these sum to \(\vec{v}\):
\(\left[ \begin{matrix} 1 \\ 3 \\ -1 \\ \end{matrix} \right]\)