Solving Linear Systems (SymPy)
Most linear algebra courses start by considering how to solve a system of linear equations.
In matrix notation, this linear system of
where
We'll look at how to use SymPy to solve linear systems, including those with free variables. We'll also look at how to do row operations (Gaussian elimination).
First we import the necessary libraries.
.solve
and .linsolve
Let's start with a 3x3 linear system:
Verify (by substitution) that
System of Equations
To solve a linear system represented by a system of linear equations we use the sympy.solve
funtion.
may can be a rectangular matrix.
Matrix Form
For a linear system expressed in matrix form linsolve
.
Augmented Matrix Form
For a linear system expressed as an augmented matrix linsolve
.
M = Matrix([[1,1,-2],[0,2,1],[2,1,-5]])
b = Matrix([4,3,7])
M_aug = M.row_join(b)
linsolve(M_aug, (x, y, z))
System with Free Variables
The three methods above can be used to solve a system with free variables.
Consider the system
which has solution space
Example
Consider another example:
We can verify this answer is correct by observing
pprint
is pretty print, which displays matrices in the proper format.
Gaussian Elimination
The general procedure learned to solve a system of linear equations is Gaussian elimination. The goal is to apply row operations to "eliminate" all the variables except for one in each equation (if possible), and this resulting linear system has the same set of solutions as the original, but is easier to solve. We generally do this on the matrix form of the system, and call this the reduced row echelon form (rref) of the matrix. The elementary row operations we use are:
Elementary Row Operations
- Replace row
with times row added to row . - Multiply row
by a scalar . - Swap rows
and .
For example, consider the matrix
Since we are working in python we will index rows starting at
Here are the row operations taking it to rref:
To do row operations in SymPy us the elemetary_row_op
method on a Matrix
object.
elementary_row_op(op='n->kn', row=None, k=None, row1=None, row2=None)
Performs the elementary row operation
"n->kn"
(row n goes to k*n)"n<->m"
(swap row n and row m)"n->n+km
" (row n goes to row n + k*row m)row
is the index of the row to be replaced.row1
is the row that will be added torow
row1
androw2
are the two rows in the swap.
Example
We'll redo the example above, this time using SymPy.
A = Matrix([[2,1,0],[1,1,-1],[0,-1,2]])
pprint(A)
print("Swap rows 0 and 1:")
A1 = A.elementary_row_op("n<->m",0,1)
pprint(A1)
print("Add -2 times row 0 to row 1:")
A2 = A1.elementary_row_op("n->n+km",row=1,k=-2,row1=0)
pprint(A2)
print("Add -1 times row 1 to row 2:")
A3 = A2.elementary_row_op("n->n+km",row=2,k=-1,row1=1)
pprint(A3)
print("Add 1 times row 1 to row 0:")
A4 = A3.elementary_row_op("n->n+km",row=0,k=1,row1=1)
pprint(A4)
print("Multiply row 1 by -1:")
A5 = A4.elementary_row_op("n->kn",row=1,k=-1)
pprint(A5)
[ 2 1 0]
[ 1 1 -1]
[ 0 -1 2]
Swap rows 0 and 1:
[ 1 1 -1 ]
[ 2 1 0 ]
[ 0 -1 2 ]
Add -2 times row 0 to row 1:
[ 1 1 -1 ]
[ 0 -1 2 ]
[ 0 -1 2 ]
Add -1 times row 1 to row 2:
[ 1 1 -1 ]
[ 0 -1 2 ]
[ 0 0 0 ]
Add 1 times row 1 to row 0:
[ 1 0 1 ]
[ 0 -1 2 ]
[ 0 0 0 ]
Multiply row 1 by -1:
[ 1 0 1 ]
[ 0 1 -2 ]
[ 0 0 0 ]
Solving a linear system with Gaussian Elimination
We'll consider the following linear system which has more unknowns than equations. This means the coefficient matrix will not be square.
Write it as an augmented matrix:
Use row operations to take it to rref.
A = Matrix([[2,0,4,4],[-1,0,-1,0],[-3,0,0,6]])
b = Matrix([14,-3,3])
aug_mat = A.row_join(b) # augmented matrix
aug_mat
A2 = A1.elementary_row_op("n->n+km",row=1,k=2,row1=0)
A3 = A2.elementary_row_op("n->n+km",row=2,k=-3,row1=0)
A4 = A3.elementary_row_op("n->kn",row=0,k=-1)
A4
- Use
k=Rational(1,3)
to avoid using floating point numbers.
A6 = A5.elementary_row_op("n->n+km",row=1,k=-2,row1=2)
A7 = A6.elementary_row_op("n->n+km",row=0,k=-1,row1=2)
A7
At this point we have reduced the matrix to rref. We see there are two free variables (
.rref
SymPy has a built-in function to put a matrix in reduced row echelon form (rref). To put a matrix into reduced row echelon form use the method .rref
. .rref
returns a tuple of two elements. The first is the reduced row echelon form, and the second is a tuple of indices of the pivot columns. The length of this tuple is the rank of the matrix.
Example
Compute the rref of the matrix
Example
For the linear system, find the rref of the augmented matrix.
A = Matrix([[2,0,4,4],[-1,0,-1,0],[-3,0,0,6]])
b = Matrix([14,-3,3])
aug_mat = A.row_join(b) # augmented matrix
pprint(aug_mat.rref())
Computing an Inverse with Gaussian Elimination
Recall, if we have an invertible matrix
Matrix
Note
If you are wondering why the inverse matrix can be computed in this way,
it comes back to elementary matrices. Suppose
Therefore, multiplying
This means
Example
Let's find the inverse of
A2 = A1.elementary_row_op("n->n+km",row=0,k=1,row1=1)
A3 = A2.elementary_row_op("n->kn",row=1,k=-1/2)
A3
Therefore, we have
We can verify we found the inverse by checking that
Nullspace
The nullspace of a matrix can be computed with .nullspace
. This returns an orthogonal basis for the nullspace.