In [1]:
from sympy import *
from IPython.display import display
init_printing(use_latex='mathjax')
height = lambda M: len(M[:,0])
width = lambda M: len(M[0,:])

In [2]:
A=Matrix([[1,3,5,0,0,3],[0,0,2,1,2,1],[2,6,12,1,2,7]])
display(A)
Ar,pivots=A.rref()
display(Ar,pivots)

$$\left[\begin{matrix}1 & 3 & 5 & 0 & 0 & 3\\0 & 0 & 2 & 1 & 2 & 1\\2 & 6 & 12 & 1 & 2 & 7\end{matrix}\right]$$
$$\left[\begin{matrix}1 & 3 & 0 & - \frac{5}{2} & -5 & \frac{1}{2}\\0 & 0 & 1 & \frac{1}{2} & 1 & \frac{1}{2}\\0 & 0 & 0 & 0 & 0 & 0\end{matrix}\right]$$
$$\left [ 0, \quad 2\right ]$$
In [14]:
#The echolon rows form a basis of the
#row space of the orginal matrix A.
display(Ar[0:len(pivots),:].transpose())

$$\left[\begin{matrix}1 & 0\\3 & 0\\0 & 1\\- \frac{5}{2} & \frac{1}{2}\\-5 & 1\\\frac{1}{2} & \frac{1}{2}\end{matrix}\right]$$
In [9]:
#The columns of A that become pivots
#form a basis of column space of A.
CB=zeros(len(A[:,0]),len(pivots))
for j in range(len(pivots)):
CB[:,j]=A[:,pivots[j]]
display(CB)

$$\left[\begin{matrix}1 & 5\\0 & 2\\2 & 12\end{matrix}\right]$$
In [12]:
def kernel_basis(A):
'''Returns matrix whose column are a basis for the null space of A.'''
#1. n x n matrix identity matrix B.
#2. m x n matrix R = rref of A.
#3. Subtract each row i of R from row i of B.
#4. For each pivot column j of R, delete column j of B.
m=width(A)
B=eye(m)
tmp=Matrix(A)
R,pivots=tmp.rref()
cols=range(m)
for (p,e) in zip(pivots,range(len(pivots))):
for c in cols:
B[p,c]=B[p,c]-R[e,c]
for p in reversed(pivots):
B.col_del(p)
return(B)

In [13]:
#The free columns of the RREF of A
#encode a basis of the kernel of A.
kernel_basis(A)

Out[13]:
$$\left[\begin{matrix}-3 & \frac{5}{2} & 5 & - \frac{1}{2}\\1 & 0 & 0 & 0\\0 & - \frac{1}{2} & -1 & - \frac{1}{2}\\0 & 1 & 0 & 0\\0 & 0 & 1 & 0\\0 & 0 & 0 & 1\end{matrix}\right]$$
In []: