# Chapter 3 - Determinants

Wouldn't it be nice to have a function that told us something about the matrix in one number?

@interact() def _(A=matrix(RDF,[[1,0],[0,1]])): def maketriangle(M): vertex1 = M*vector((0,0)) vertex2 = M*vector((1,3)) vertex3 = M*vector((-1,2)) edges = line([vertex1,vertex2,vertex3,vertex1])+point(vertex1,size=40,color='black')+point(vertex2,size=40,color='red')+point(vertex3,size=40,color='green')+point((0,0),size=0) return edges pretty_print(html('triangle, transformed by $%s$'%latex(A))) G = maketriangle(A) + maketriangle(identity_matrix(2)) G.show(aspect_ratio=1,figsize=[3,3]) pretty_print(html('Notice the new triangle is $%s$ times as big'%latex(det(A))))

## Click to the left again to hide and once more to show the dynamic interactive window

We'll return to this.  The function we need is called the determinant.

How might one calculate the determinant?  With Sage, all you need is one thing.

M = matrix([[1,2],[3,4]])

Just use "det".

det(M)
 -2 -2

(Alternately, you can use the dot notation.)

M.determinant()
 -2 -2

Use square matrices!

det(matrix([[1,2]]))
 Traceback (click to the left of this block for traceback) ... ValueError: self must be a square matrix Traceback (most recent call last): File "", line 1, in File "_sage_input_9.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("ZGV0KG1hdHJpeChbWzEsMl1dKSk="),globals())+"\\n"); execfile(os.path.abspath("___code___.py")) File "", line 1, in File "/tmp/tmp4XvcVm/___code___.py", line 3, in exec compile(u'det(matrix([[_sage_const_1 ,_sage_const_2 ]])) File "", line 1, in File "/usr/local/sage-5.6-linux-64bit-ubuntu_8.04.4_lts-x86_64-Linux/local/lib/python2.7/site-packages/sage/misc/functional.py", line 337, in det return x.det() File "matrix2.pyx", line 1213, in sage.matrix.matrix2.Matrix.det (sage/matrix/matrix2.c:9041) File "matrix_integer_dense.pyx", line 3289, in sage.matrix.matrix_integer_dense.Matrix_integer_dense.determinant (sage/matrix/matrix_integer_dense.c:25942) ValueError: self must be a square matrix
det(matrix([[-1,2,3,0],[3,4,3,0],[5,4,6,6],[4,2,4,3]]))
 114 114

We can visualize that $\det(AB)=\det(A)\det(B)$.

@interact() def _(A=matrix(RDF,[[1,0],[0,1]]),B=matrix(RDF,[[1,0],[0,1]])): def maketriangle(M): vertex1 = M*vector((0,0)) vertex2 = M*vector((1,3)) vertex3 = M*vector((-1,2)) edges = line([vertex1,vertex2,vertex3,vertex1])+point(vertex1,size=40,color='black')+point(vertex2,size=40,color='red')+point(vertex3,size=40,color='green')+point((0,0),size=0) return edges pretty_print(html('triangle, transformed by $%s$'%latex(A))) pretty_print(html('and then transformed further by $%s$'%latex(B))) G = maketriangle(A) H = maketriangle(identity_matrix(2)) I = maketriangle(B*A) show(H+G+I,aspect_ratio=1,figsize=[3,3]) pretty_print(html('Notice the second triangle is $%s$ times as big'%latex(det(A)))) pretty_print(html('And the third triangle is another $%s$ times as big'%latex(det(B)))) pretty_print(html('For a total of $%s\cdot %s=%s$ times as big'%(latex(det(A)),latex(det(B)),latex(det(B*A)))))

## Click to the left again to hide and once more to show the dynamic interactive window

Here is all of this with Smiley Guy.  Notice what happens to his area sometimes; why does it look like he gets smaller when he gets bigger?

t = var('t') @interact(layout=[['A','B'],['auto_update']]) def _(A=matrix(RDF,[[1,0],[0,1]]),B=matrix(RDF,[[1,0],[0,1]]),auto_update=False): ID = matrix(RDF,[[1,0],[0,1]]) def makeface(M): pll=M*vector((-0.5,0.5)) plr=M*vector((-0.3,0.5)) prl=M*vector((0.3,0.5)) prr=M*vector((0.5,0.5)) left_eye=line([pll,plr])+point(pll,size=5)+point(plr,size=5) right_eye=line([prl,prr],color='green')+point(prl,size=5,color='green')+point(prr,size=5,color='green') mouth=parametric_plot(M*vector([t, -0.15*sin(2*pi*t)-0.5]), (t, -0.5, 0),color='red')+parametric_plot(M*vector([t, -0.15*sin(2*pi*t)-0.5]), (t,0,0.5),color='orange') face=parametric_plot(M*vector([cos(t),sin(t)]), (t,0,pi/2),color='black')+parametric_plot(M*vector([cos(t),sin(t)]), (t,pi/2,pi),color='lavender')+parametric_plot(M*vector([cos(t),sin(t)]), (t,pi,3*pi/2),color='cyan')+parametric_plot(M*vector([cos(t),sin(t)]),(t,3*pi/2,2*pi),color='sienna') return right_eye+left_eye+face+mouth pretty_print(html('smiley guy, then transformed by $A$, and next by $B$')) G = graphics_array([[makeface(ID),makeface(A),makeface(B*A)]]) G.show(aspect_ratio=1) pretty_print(html('smiley guy first changes area {} times, then another {} times'.format(det(A),det(B))))

## Click to the left again to hide and once more to show the dynamic interactive window

We can have fun with determinant patterns, too!  This is # 19 from the book's supplementary exercises.

M = matrix(3,[1,1,1,1,2,2,1,2,3]) det(M)
 1 1
M = matrix(4,[1,1,1,1,1,2,2,2,1,2,3,3,1,2,3,4]) det(M)
 1 1
M = matrix(5,[1,1,1,1,1,1,2,2,2,2,1,2,3,3,3,1,2,3,4,4,1,2,3,4,5]) det(M)
 1 1

How long does it take to compute a determinant?

@interact def _(n=5): if n>1000: pretty_print(html("Don't get too big and hog Sage!")) if n>100: M = random_matrix(ZZ, n) time a = det(M) pretty_print(html("determinant is $%s$"%a)) else: M = random_matrix(ZZ, n) show(M) time a = det(M) pretty_print(html("determinant is $%s$"%a))

## Click to the left again to hide and once more to show the dynamic interactive window

@interact def _(n=5): if n>1000: pretty_print(html("Don't get too big and hog Sage!")) else: pretty_print(html("Timing for a random ${}\\times{}$ matrix".format(n,n))) M = random_matrix(ZZ, n) print det(M) # timeit('det(M)')

random_matrix?

# Chapter 4 - Vector Spaces

We didn't use Sage this chapter.  But we could have!

M = matrix([[1,2,3],[1,2,3],[1,2,3]]); show(M)
 \newcommand{\Bold}[1]{\mathbf{#1}}\left(\begin{array}{rrr} 1 & 2 & 3 \\ 1 & 2 & 3 \\ 1 & 2 & 3 \end{array}\right)
M.kernel()
 Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [ 1 0 -1] [ 0 1 -1] Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [ 1 0 -1] [ 0 1 -1]

Oops!  But it's not wrong - Sage just prefers multiplying by matrices on the right instead of on the left like we do in our class usually if I feel like it.

M.right_kernel()
 Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [ 1 1 -1] [ 0 3 -2] Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [ 1 1 -1] [ 0 3 -2]
M.column_space()
 Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [1 1 1] Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [1 1 1]
M.row_space()
 Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [1 2 3] Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: [1 2 3]
M.rank()
 1 1
dimension(M.kernel()) + M.rank()
 3 3