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 []: