Skip to content

Instantly share code, notes, and snippets.

@drvinceknight
Created November 22, 2016 19:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drvinceknight/6a7edb4b1d7235a1651fdcff5b59cd25 to your computer and use it in GitHub Desktop.
Save drvinceknight/6a7edb4b1d7235a1651fdcff5b59cd25 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lab sheet 08: Linear Algebra"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q1: Solving linear systems"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np # Import numpy as `np` for short"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 5, 1, -1],\n",
" [-1, 2, 4],\n",
" [ 1, 1, 1]])"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = np.matrix([[5, 1, -1], [-1, 2, 4], [1, 1, 1]]) # Creating a matrix\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 0],\n",
" [-2],\n",
" [ 4]])"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b = np.matrix([[0], [-2], [4]]) # Creating a vector\n",
"b"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[-14.],\n",
" [ 44.],\n",
" [-26.]])"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.linalg.solve(A, b) # We can solve the linear system"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 0.66666667],\n",
" [-0.33333333],\n",
" [ 0.33333333]])"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Creating a different linear system\n",
"A, b = np.matrix([[3, 2, -1], [-4, 2, 4], [1, 0, 1]]), np.matrix([[1], [-2], [1]]) \n",
"np.linalg.solve(A, b) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q2 Manipulating matrices"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"A = np.matrix([[5, 1, -1], [-1, 2, 4], [1, 1, 1]]) # Re creating A, after overwriting it previously\n",
"B = np.matrix([[1, 2, 0], [-4, 2, 2], [1, 3, 1]]) # Creating another matrix"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 6, 3, -1],\n",
" [-5, 4, 6],\n",
" [ 2, 4, 2]])"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A + B"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[25, 5, -5],\n",
" [-5, 10, 20],\n",
" [ 5, 5, 5]])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"5 * A"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 0, 9, 1],\n",
" [-5, 14, 8],\n",
" [-2, 7, 3]])"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A * B"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[107, 33, -1],\n",
" [ -9, 24, 44],\n",
" [ 25, 17, 15]])"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A ** 3"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[-6, 17, -1],\n",
" [-7, 28, 24],\n",
" [-4, 23, 9]])"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Trying different matrices\n",
"A = np.matrix([[1, 2, -1], [-1, 2, 4], [1, 2, 1]]) \n",
"B = np.matrix([[3, 2, 0], [-4, 9, 2], [1, 3, 5]]) \n",
"A * B"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q3 Identity matrix"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Re creating A after overwriting it previously\n",
"A = np.matrix([[5, 1, -1], [-1, 2, 4], [1, 1, 1]]) "
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[1, 0, 0],\n",
" [0, 1, 0],\n",
" [0, 0, 1]])"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"I = np.matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) # Creating an identity matrix\n",
"I"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ True, True, True],\n",
" [ True, True, True],\n",
" [ True, True, True]], dtype=bool)"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"I * A == A # We see that all elements are equal"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.array_equal(I * A, A) # We see that the matrices are equal"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 1., 0., 0.],\n",
" [ 0., 1., 0.],\n",
" [ 0., 0., 1.]])"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"I = np.identity(3) # Shorthand to create an identity 'numpy array'\n",
"I"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 1., 0., 0.],\n",
" [ 0., 1., 0.],\n",
" [ 0., 0., 1.]])"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"I = np.matrix(I) # Turning it in to a matrix\n",
"I"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ True, True, True],\n",
" [ True, True, True],\n",
" [ True, True, True]], dtype=bool)"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"I * B == B"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q4 Matrix inversion"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 1. , 1. , -3. ],\n",
" [-2.5, -3. , 9.5],\n",
" [ 1.5, 2. , -5.5]])"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Ainv = np.linalg.inv(A) # Creating the inverse of a matrix\n",
"Ainv"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 1.00000000e+00, 4.44089210e-16, 0.00000000e+00],\n",
" [ 8.88178420e-16, 1.00000000e+00, -3.55271368e-15],\n",
" [ 2.22044605e-16, 4.44089210e-16, 1.00000000e+00]])"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A * Ainv # This gives the identity matrix"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[-14.],\n",
" [ 44.],\n",
" [-26.]])"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b = np.matrix([[0], [-2], [4]])\n",
"Ainv * b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q5 Determinant of a matrix"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"-2.0"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.linalg.det(A)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q6 Worked example"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 1., 1., 0., 0., 0.],\n",
" [ 0., 1., 1., 0., 0.],\n",
" [ 0., 0., 1., 1., 0.],\n",
" [ 0., 0., 0., 1., 1.],\n",
" [ 1., 0., 0., 0., 1.]])"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"N = 5\n",
"A = np.matrix(np.zeros((N, N))) # An N by N array of zeros\n",
"for deal in range(N): # Putting the 1s in the right position\n",
" A[deal, deal] = 1\n",
" A[deal, (deal + 1) % N] = 1\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[1],\n",
" [2],\n",
" [3],\n",
" [4],\n",
" [5]])"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b = np.matrix([[i + 1] for i in range(N)])\n",
"b"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 1.5],\n",
" [-0.5],\n",
" [ 2.5],\n",
" [ 0.5],\n",
" [ 3.5]])"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"contributions = np.linalg.solve(A, b)\n",
"contributions"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 7.5]])"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sum(contributions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q7"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 1. , 0.5, 0. , 0. , 0. ],\n",
" [ 0. , 1. , 0.5, 0. , 0. ],\n",
" [ 0. , 0. , 1. , 0.5, 0. ],\n",
" [ 0. , 0. , 0. , 1. , 0.5],\n",
" [ 0.5, 0. , 0. , 0. , 1. ]])"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"N = 5\n",
"A = np.matrix(np.zeros((N, N))) # An N by N array of zeros\n",
"for deal in range(N): # Putting the 1s in the right position\n",
" A[deal, deal] = 1\n",
" A[deal, (deal + 1) % N] = 1 / 2\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[5],\n",
" [5],\n",
" [5],\n",
" [5],\n",
" [5]])"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b = np.matrix([[5] for i in range(N)])\n",
"b"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333]])"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"contributions = np.linalg.solve(A, b)\n",
"contributions"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 16.66666667]])"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sum(contributions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the individual contributions are all the same:"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(matrix([[ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333],\n",
" [ 3.33333333]]), matrix([[ 166.66666667]]))"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"N = 50\n",
"A = np.matrix(np.zeros((N, N))) # An N by N array of zeros\n",
"for deal in range(N): # Putting the 1s in the right position\n",
" A[deal, deal] = 1\n",
" A[deal, (deal + 1) % N] = 1 / 2\n",
"b = np.matrix([[5] for i in range(N)])\n",
"contributions = np.linalg.solve(A, b)\n",
"contributions, sum(contributions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q8"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the individual contributions go down as does the total contribution."
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(matrix([[ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273],\n",
" [ 2.72727273]]), matrix([[ 136.36363636]]))"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"N = 50\n",
"A = np.matrix(np.zeros((N, N))) # An N by N array of zeros\n",
"for deal in range(N): # Putting the 1s in the right position\n",
" A[deal, deal] = 1\n",
" A[deal, (deal + 1) % N] = 1 / 2\n",
" A[deal, (deal + 2) % N] = 1 / 3\n",
"b = np.matrix([[5] for i in range(N)])\n",
"contributions = np.linalg.solve(A, b)\n",
"contributions, sum(contributions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q9"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Calculating the eigenvalues and eigenvectors of a matrix is straightforward with numpy:"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"A = np.matrix([[5, 1, -1], [-1, 2, 4], [1, 1, 1]]) # Our original simple matrix"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([-0.12488542, 4.76155718, 3.36332824])"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eigenvalues, eigenvectors = np.linalg.eig(A)\n",
"eigenvalues"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[-0.25902874, 0.96339159, -0.42094483],\n",
" [ 0.82465898, 0.03596159, 0.88552898],\n",
" [-0.50283365, 0.26567539, 0.19658046]])"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eigenvectors"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The columns of the eigenvectors matrix correspond to the eigenmatrix. Let us verify that $Av = \\lambda v$."
]
},
{
"cell_type": "code",
"execution_count": 85,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 0.03234891],\n",
" [-0.10298788],\n",
" [ 0.06279659]])"
]
},
"execution_count": 85,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A * eigenvectors[:,0]"
]
},
{
"cell_type": "code",
"execution_count": 84,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 0.03234891],\n",
" [-0.10298788],\n",
" [ 0.06279659]])"
]
},
"execution_count": 84,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eigenvectors[:,0] * eigenvalues[0]"
]
},
{
"cell_type": "code",
"execution_count": 86,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 4.58724413],\n",
" [ 0.17123314],\n",
" [ 1.26502856]])"
]
},
"execution_count": 86,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A * eigenvectors[:,1]"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 4.58724413],\n",
" [ 0.17123314],\n",
" [ 1.26502856]])"
]
},
"execution_count": 87,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eigenvectors[:,1] * eigenvalues[1]"
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[-1.41577564],\n",
" [ 2.97832462],\n",
" [ 0.6611646 ]])"
]
},
"execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A * eigenvectors[:,2]"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[-1.41577564],\n",
" [ 2.97832462],\n",
" [ 0.6611646 ]])"
]
},
"execution_count": 89,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eigenvectors[:,2] * eigenvalues[2]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is an efficient way of checking this, it makes use of `enumerate` and `numpy.isclose`."
]
},
{
"cell_type": "code",
"execution_count": 90,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n",
"True\n",
"True\n"
]
}
],
"source": [
"# Using the enumerate function to loop and count\n",
"for ind, value in enumerate(eigenvalues): \n",
" print(all(np.isclose(A * eigenvectors[:,ind], eigenvectors[:,ind] * value)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q9 Using scipy and sympy for linalg"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is the documentation on linear algebra in sympy: http://docs.sympy.org/0.7.2/modules/matrices/matrices.html"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import sympy as sym\n",
"sym.init_printing()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAHkAAABLCAMAAABjltjdAAAAPFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo1xBWAAAAE3RSTlMA\nMquZdlQQQOkwRM3viSJmu91sTHWKGgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAmVJREFUaAXtmuty\ngyAQhQmgbcNFLe//rgVskwVW2HQw007gl8Bhv3ggZDGyi4uFs2eVbQcydnFC+jI9C8yWgOMukC9P\ng95BC0pWcmYXca4JOFmHiTD3z3d8Nen5uLPsAXKcrAyXthyXt8xccEcnp3KcTF/m8gGy/+BA/ufI\nyyIFacGDm8jnAqsDOX7Pq588667Y2KwNhMp60CqQ4+Q4at3QwWkjCJV24DUgr5CFIyxvEKpgzWq7\nFbXPHZCjZK5CFEOxG4QqyEgDkKNkHcmC8oUBoRBQ0QTkKFnEEVvkF4PTBhAq7cBrQI6SbUAvmjDN\ncGvAWWlri8ysMFwQtkXBtVN8SaMf1xI5es/HYzv2DHJHM5uhhttNizoKhtsdzWyG+q9uWyHWlZSv\n+YND5kLrnkFqno301Tlkx6QEgrFtzcZXyWlqno30VR5/zrQue4oWqR8i+/HgB7WIxnTMETnhQGgX\n1ZWsYr5EIRvWl7y7sLXztcWeQb62D52zZGeQt/bxL5yH627XU/NyhYUWkX9PS9kUvvEo+e39o5R/\nt1TXttfINniOjwAK8ud7/TlJgzwFsK2nxxMPxWnuZxuU6k7idXXyviVSHi+wvjuJ3YwxglPOnMw9\ntpMkqTlw6vtS7U/UCGSzOpedCFpul7heLYPcy0lKnOE2xaVemuF2LycpcYbbd5eqGf5dxog6RIa6\n3crwf8hEHS5DyT5yPSP4QZN1SLhBfthF6qwMt6O1Y4W98gprZPg3a4g6VHa0wm7BT7sY5NOsRQK/\nrtvxHNx+xoN49qum25ssc3ixRErKH92/AhWD4pssUrIv9NIkPRJqi88AAAAASUVORK5CYII=\n",
"text/latex": [
"$$\\left[\\begin{matrix}5 & 1 & -1\\\\-1 & 2 & 4\\\\1 & 1 & 1\\end{matrix}\\right]$$"
],
"text/plain": [
"⎡5 1 -1⎤\n",
"⎢ ⎥\n",
"⎢-1 2 4 ⎥\n",
"⎢ ⎥\n",
"⎣1 1 1 ⎦"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = sym.Matrix([[5, 1, -1], [-1, 2, 4], [1, 1, 1]])\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAABkAAAAOBAMAAAAoFKpzAAAALVBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMAEM3dMiKZu6uJRO92VKoV\n2MsAAAAJcEhZcwAADsQAAA7EAZUrDhsAAABeSURBVAgdY2CAAta0cgcYm4FBgoHzFYLXyMCwG8Hb\nzMDQh1CqJ4DMA6qyE0AoZeB6icRhYG5gYBAyBgEVoHAashRPAjLvGgNrAJzPksDAg+AFz5zWDJdi\n0Hv37jEDAGBWEJ9xq8kjAAAAAElFTkSuQmCC\n",
"text/latex": [
"$$-2$$"
],
"text/plain": [
"-2"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.det()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAABLCAMAAADnED/zAAAAPFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo1xBWAAAAE3RSTlMA\nMquZdlQQQOkwRM3d72a7Iols+HxWxAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAe5JREFUSA3tl91i\ngyAMhSMg64p/LO//riMgHm0HWC/X5oIe23wCiY2BOo6m6IwNyZmoY22C9WcgmsRVsVDdKQBO0wtU\npzPXovrRZlca5iyrlFVa8UaZ8RwVbm02apncBcrTBWpaLlDW0AXKhz0WVmjdsJlLmV+j0ctVgcrp\n2H0myspUL1O9EuNRhd2JVbMcfke+iK5kmYhPZlmrkZ2a4qr8zLzK5goj8DS09vUExC8+1D4u7xcN\n1EyoHJFyNFAzoZoUaiZUhorPPGom1AYVKdRMqCaFmgkFqDAXaibUDipQqJlQTQo1E2oPxbm+bt+H\n71AzoQ4O9HN7fi+jZkIdqfKzgZoJldkyhZoJ1aJQM6Ey067z8Nyr8gr3Xo/6Q+0j8p7RWLSe57W9\n9d743OlWo2Gl7fZ8D6N1YdRuDWSVUrEPHcfgO0vPO+eGo0qNg9xbhRb8zovIbFXKxfZVqFnmg1Wp\n5DYEll3njZYNRmtTd/Zk2UlbNObjRZsaQiAtx7Xq3NwfqD96UdLxwMAxLlNMQpj0QKVFH0aTThlD\nzNTEqX1rUb1Ay0IqxvDkXOmNbJZwbJKE6xz/6gqXwXuvlexJhZeLPRdDl851MRJea5Uf3ta+DpHB\nRXWFcHtQ/5u6csq2cnA2Zvv3PATseBlP2cbQL/CKIIqPAo/CAAAAAElFTkSuQmCC\n",
"text/latex": [
"$$\\left[\\begin{matrix}-14\\\\44\\\\-26\\end{matrix}\\right]$$"
],
"text/plain": [
"⎡-14⎤\n",
"⎢ ⎥\n",
"⎢44 ⎥\n",
"⎢ ⎥\n",
"⎣-26⎦"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.solve(sym.Matrix([[0], [-2], [4]]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that sympy can be used to carry out symbolic linear algebra:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/latex": [
"$$\\left[\\begin{matrix}- \\frac{1}{\\beta + 1} \\left(- \\frac{4 \\beta}{\\alpha} - \\frac{16 - \\frac{4 \\beta}{\\alpha}}{\\alpha \\left(\\gamma + \\frac{1}{\\alpha}\\right)}\\right) + \\frac{2}{\\alpha \\left(\\gamma + \\frac{1}{\\alpha}\\right)}\\\\- \\frac{16 - \\frac{4 \\beta}{\\alpha}}{\\left(\\beta + 1\\right) \\left(\\gamma + \\frac{1}{\\alpha}\\right)} - \\frac{2}{\\gamma + \\frac{1}{\\alpha}}\\\\\\frac{4}{\\beta + 1}\\end{matrix}\\right]$$"
],
"text/plain": [
"⎡ ⎛ β ⎞ ⎤\n",
"⎢ ⎜ 4 - ─ ⎟ ⎥\n",
"⎢ ⎜ β α ⎟ ⎥\n",
"⎢ 4⋅⎜- ─ - ─────────⎟ ⎥\n",
"⎢ ⎜ α ⎛ 1⎞⎟ ⎥\n",
"⎢ ⎜ α⋅⎜γ + ─⎟⎟ ⎥\n",
"⎢ ⎝ ⎝ α⎠⎠ 2 ⎥\n",
"⎢- ─────────────────── + ─────────⎥\n",
"⎢ β + 1 ⎛ 1⎞⎥\n",
"⎢ α⋅⎜γ + ─⎟⎥\n",
"⎢ ⎝ α⎠⎥\n",
"⎢ ⎥\n",
"⎢ ⎛ β⎞ ⎥\n",
"⎢ 4⋅⎜4 - ─⎟ ⎥\n",
"⎢ ⎝ α⎠ 2 ⎥\n",
"⎢ - ─────────────── - ───── ⎥\n",
"⎢ ⎛ 1⎞ 1 ⎥\n",
"⎢ (β + 1)⋅⎜γ + ─⎟ γ + ─ ⎥\n",
"⎢ ⎝ α⎠ α ⎥\n",
"⎢ ⎥\n",
"⎢ 4 ⎥\n",
"⎢ ───── ⎥\n",
"⎣ β + 1 ⎦"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"alpha, beta, gamma = sym.symbols('alpha, beta, gamma')\n",
"A = sym.Matrix([[alpha, 1, -beta], [-1, gamma, 4], [alpha, 1, 1]])\n",
"A.solve(sym.Matrix([[0], [-2], [4]]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Symbolic computations will often be slower than numeric ones."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is the documentation on linear algebra in scipy: https://docs.scipy.org/doc/scipy-0.18.1/reference/linalg.html"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import scipy as sp\n",
"from scipy import linalg"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 5, 1, -1],\n",
" [-1, 2, 4],\n",
" [ 1, 1, 1]])"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = sp.matrix([[5, 1, -1], [-1, 2, 4], [1, 1, 1]])\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAALgAAAAPBAMAAACl0hg5AAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEM3dMiKZu6uJRO92\nVGZ6zyUAAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABbklEQVQ4EbWUsUrDUBSG/9impaGpQUEqDu3g\nKh3EUcwbtOADNDgU3dzqWNFN0CBWEMRXUNHNpW4ODp1cO0sHiYJYUeo5NHjvPSRjL+RLwvfzJ+Qk\nAeJlt9o+H1o7r74EFq7OoEFkEk1cO9mVUfjmo5m+tSaBFcw3NIhMooF7q/r3gQc+GwKnEqUbFKoK\n6Voz5e1Ild8BJz6d7gEDTyDfgRspyEyiQVErr3mT8i/gui8w24Hzq4BUrRmjnG56w6N5flL5o4le\nJYDzoyAymlamJ8qdEV3AJtS7JsJmiOxIQWQ0rUwoyjMdLqebrndNhM2Ay/8hMppWZlI+t8prmXpb\ntE3rsRQDLueRDHigOmiWLg80hswkGvOxvMBuUHkbePME8rsoRQoyk2iM8myAIpcPgS0J+n5y/BHF\nSNeaMco3L84PUKki07fuJbCOJV+DyCQao7w2Hn+AXhjr8ol+XCaw+HwIDelamdzR+zHPcGrrD61b\nXfn8cUJeAAAAAElFTkSuQmCC\n",
"text/latex": [
"$$-2.000000000000001$$"
],
"text/plain": [
"-2.000000000000001"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"linalg.det(A)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([[-14.],\n",
" [ 44.],\n",
" [-26.]])"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"linalg.solve(A, sp.matrix([[0], [-2], [4]]))"
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python [default]",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment