{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# css styling of the notebook - execute and then ignore\n", "import requests, IPython.core.display\n", "IPython.core.display.HTML(requests.get(\"https://git.io/fj7u5\").text)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Linear algebra with Python and SymPy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy is a Python module for performing symbolic computations. This notebook explain how use it to perform linear algebra computations." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Execute this cell to load SymPy: " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "#load SymPy module content\n", "from sympy import *\n", "\n", "#this makes printouts of matrices and vectors more readeable:\n", "init_printing(use_latex='mathjax')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Constructions of matrices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The simplest way to create a matrix is to lists its elements. Matrices are entered row by row. Each row must be enclosed in square brackets, and then the whole collection of rows is again enclosed in square brackets: " ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 5 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3⎤\n", "⎢ ⎥\n", "⎢4 5 6⎥\n", "⎢ ⎥\n", "⎣7 8 9⎦" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 2, 3], [4, 5, 6], [7,8,9]])\n", "A #this displays the matrix" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note.** In order to create a matrix with one row we need to enclose it entries in double square brackets (one set indicating the beginning and the end of the row, and another enclosing the whole matrix:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}12 & 13 & 14\\end{matrix}\\right]$$" ], "text/plain": [ "[12 13 14]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[12, 13, 14]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using only one set of square brackets creates a column vector, i.e. a matrix with one column:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}12\\\\13\\\\14\\end{matrix}\\right]$$" ], "text/plain": [ "⎡12⎤\n", "⎢ ⎥\n", "⎢13⎥\n", "⎢ ⎥\n", "⎣14⎦" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = Matrix([12, 13, 14])\n", "v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Entering fractions\n", "\n", "Say that we want to enter the matrix\n", "\n", "\\begin{equation*}\n", "\\begin{bmatrix}\n", "\\frac{1}{7} & -1 \\\\\n", "0 & -\\frac{1}{3} \\\\\n", "\\end{bmatrix}\n", "\\end{equation*}\n", "\n", "We can try to do it as follows:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0.142857142857143 & -1\\\\0 & -0.333333333333333\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0.142857142857143 -1 ⎤\n", "⎢ ⎥\n", "⎣ 0 -0.333333333333333⎦" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = Matrix([[1/7 , -1],[0, -1/3]])\n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you see fractions got converted to decimals, and rounded to some number of decimal places. For some applications in this course this would be inconvenient, since we will want to work with fractions and keep their exact values. We can deal with this issue as follows:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}\\frac{1}{7} & -1\\\\0 & - \\frac{1}{3}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1/7 -1 ⎤\n", "⎢ ⎥\n", "⎣ 0 -1/3⎦" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = Matrix([[Rational(1,7) , -1],[0, Rational(-1,3)]])\n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Matrices of zeros and ones\n", "\n", "For larger matrices it is tedious to enter all their entries manually. It is often faster to create first a base matrix whose entries are e.g. all zeros or all ones, and then modify entries of this matrix as needed. It is easy to create such base matrices of any size:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- a zero matrix:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 0 0 0⎤\n", "⎢ ⎥\n", "⎢0 0 0 0⎥\n", "⎢ ⎥\n", "⎣0 0 0 0⎦" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C = zeros(3, 4) # 3 rows, 4 columns\n", "C" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- a matrix of ones:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 1 & 1 & 1 & 1 & 1 & 1\\\\1 & 1 & 1 & 1 & 1 & 1 & 1\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 1 1 1 1 1 1⎤\n", "⎢ ⎥\n", "⎣1 1 1 1 1 1 1⎦" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D = ones(2, 7) # 2 rows, 7 columns\n", "D" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Diagonal matrices\n", "\n", "A diagonal matrix is a square matrix whose all entries outside its main diagonal are zeros. Such matrix can be created as follows: " ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 0 & 0 & 0\\\\0 & 2 & 0 & 0\\\\0 & 0 & 3 & 0\\\\0 & 0 & 0 & -3\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 0 0 0 ⎤\n", "⎢ ⎥\n", "⎢0 2 0 0 ⎥\n", "⎢ ⎥\n", "⎢0 0 3 0 ⎥\n", "⎢ ⎥\n", "⎣0 0 0 -3⎦" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D = diag(1, 2, 3, -3)\n", "D" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The identity matrix is a diagonal matrix whose all entries on the main diagonal are ones. Since this matrix is used very often, there is a special way to create it:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 0 & 0 & 0\\\\0 & 1 & 0 & 0\\\\0 & 0 & 1 & 0\\\\0 & 0 & 0 & 1\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 0 0 0⎤\n", "⎢ ⎥\n", "⎢0 1 0 0⎥\n", "⎢ ⎥\n", "⎢0 0 1 0⎥\n", "⎢ ⎥\n", "⎣0 0 0 1⎦" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "I = eye(4) # 4x4 identity matrix\n", "I" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Matrices from lists\n", "\n", "In some cases it may be convenient to enter all entries of a matrix as a list, and then to reshape this list into a matrix:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left [ 1, \\quad 2, \\quad 3, \\quad 4, \\quad 5, \\quad 6, \\quad 7, \\quad 8, \\quad 9, \\quad 10, \\quad 11, \\quad 12\\right ]$$" ], "text/plain": [ "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#create a list of elements\n", "a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n", "a" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3 & 4\\\\5 & 6 & 7 & 8\\\\9 & 10 & 11 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3 4 ⎤\n", "⎢ ⎥\n", "⎢5 6 7 8 ⎥\n", "⎢ ⎥\n", "⎣9 10 11 12⎦" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#reshape the list into a 3x4 matrix\n", "A = Matrix(a).reshape(3, 4)\n", "A" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3 & 4 & 5 & 6\\\\7 & 8 & 9 & 10 & 11 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3 4 5 6 ⎤\n", "⎢ ⎥\n", "⎣7 8 9 10 11 12⎦" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#reshape the list into a 2x6 matrix\n", "B = Matrix(a).reshape(2, 6)\n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note 1.** Reshaping works only if the number of elements of the list is exactly equal to the number of entries of a matrix of specified dimensions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note 2.** Reshaping makes consecutive chunks of a list into rows of a matrix. In order for such chunks to become columns of a matrix, we can apply transpose of a matrix, which makes rows into columns: " ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3 & 4\\\\5 & 6 & 7 & 8\\\\9 & 10 & 11 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3 4 ⎤\n", "⎢ ⎥\n", "⎢5 6 7 8 ⎥\n", "⎢ ⎥\n", "⎣9 10 11 12⎦" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 5 & 9\\\\2 & 6 & 10\\\\3 & 7 & 11\\\\4 & 8 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 5 9 ⎤\n", "⎢ ⎥\n", "⎢2 6 10⎥\n", "⎢ ⎥\n", "⎢3 7 11⎥\n", "⎢ ⎥\n", "⎣4 8 12⎦" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# B is the transpose of A, rows of A are columns of B\n", "B = A.T \n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Matrix elements, rows, and columns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is a sample matrix we will be working with:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 5 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3⎤\n", "⎢ ⎥\n", "⎢4 5 6⎥\n", "⎢ ⎥\n", "⎣7 8 9⎦" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 2, 3], [4, 5, 6], [7,8,9]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access elements of a matrix by specifying the row and column of the element. \n", "\n", "**Note.** In Python indexing starts with 0. Thus, the first row of a matrix has index 0, the second row has index 1 and so on. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$4$$" ], "text/plain": [ "4" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1,0] #the element in row 1, column 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use this to modify elements of a matrix " ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 100 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3⎤\n", "⎢ ⎥\n", "⎢4 100 6⎥\n", "⎢ ⎥\n", "⎣7 8 9⎦" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1,1] = 100\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Accessing matrix rows:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\end{matrix}\\right]$$" ], "text/plain": [ "[1 2 3]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[0, :] # get row 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Accessing columns:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}3\\\\6\\\\9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡3⎤\n", "⎢ ⎥\n", "⎢6⎥\n", "⎢ ⎥\n", "⎣9⎦" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[:, 2] # get column 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can modify the whole row (or column) of a matrix at once:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 100 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3⎤\n", "⎢ ⎥\n", "⎢4 100 6⎥\n", "⎢ ⎥\n", "⎣7 8 9⎦" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}-10 & -20 & -30\\end{matrix}\\right]$$" ], "text/plain": [ "[-10 -20 -30]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w = Matrix([[-10, -20, -30]])\n", "w" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 100 & 6\\\\-10 & -20 & -30\\end{matrix}\\right]$$" ], "text/plain": [ "⎡ 1 2 3 ⎤\n", "⎢ ⎥\n", "⎢ 4 100 6 ⎥\n", "⎢ ⎥\n", "⎣-10 -20 -30⎦" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[2, :] = w # make row 2 of A equal to w\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Inserting and rows and columns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrices can be modified by inserting into them additional rows and columns. For example, we start with the following matrix:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 5 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3⎤\n", "⎢ ⎥\n", "⎢4 5 6⎥\n", "⎢ ⎥\n", "⎣7 8 9⎦" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 2, 3], [4, 5, 6], [7,8,9]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Assume the we want to insert the following column into this matrix:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}-1\\\\-2\\\\-3\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-1⎤\n", "⎢ ⎥\n", "⎢-2⎥\n", "⎢ ⎥\n", "⎣-3⎦" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = Matrix([-1, -2, -3]) # matrix with one column\n", "v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This can be done as follows:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & -1 & 3\\\\4 & 5 & -2 & 6\\\\7 & 8 & -3 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 -1 3⎤\n", "⎢ ⎥\n", "⎢4 5 -2 6⎥\n", "⎢ ⎥\n", "⎣7 8 -3 9⎦" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = A.col_insert(2, v) # insert v as the column number 2\n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note.** Column insertion creates a new matrix, the matrix `A` remains unchanged:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 5 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3⎤\n", "⎢ ⎥\n", "⎢4 5 6⎥\n", "⎢ ⎥\n", "⎣7 8 9⎦" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Row insertion works the same way:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}100 & 200 & 300\\end{matrix}\\right]$$" ], "text/plain": [ "[100 200 300]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C = Matrix([[100, 200, 300]]) # matrix with one row\n", "C" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\100 & 200 & 300\\\\4 & 5 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡ 1 2 3 ⎤\n", "⎢ ⎥\n", "⎢100 200 300⎥\n", "⎢ ⎥\n", "⎢ 4 5 6 ⎥\n", "⎢ ⎥\n", "⎣ 7 8 9 ⎦" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.row_insert(1, C) #insert C as the row number 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Row/column insertion works also with matrices consisting of more then one row or column:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 5 & 6\\\\7 & 8 & 9\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3⎤\n", "⎢ ⎥\n", "⎢4 5 6⎥\n", "⎢ ⎥\n", "⎣7 8 9⎦" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 0 & 0\\\\0 & 1 & 0\\\\0 & 0 & 1\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 0 0⎤\n", "⎢ ⎥\n", "⎢0 1 0⎥\n", "⎢ ⎥\n", "⎣0 0 1⎦" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "I = eye(3)\n", "I" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Insert the matrix `I` into `A`, so that the first column of `I` becomes column number 3 of the new matrix:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3 & 1 & 0 & 0\\\\4 & 5 & 6 & 0 & 1 & 0\\\\7 & 8 & 9 & 0 & 0 & 1\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3 1 0 0⎤\n", "⎢ ⎥\n", "⎢4 5 6 0 1 0⎥\n", "⎢ ⎥\n", "⎣7 8 9 0 0 1⎦" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = A.col_insert(3, eye(3))\n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Deleting rows and columns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrices can be also modified by deleting their rows and columns. Unlike row/column insertions, deletion modifies the original matrix: " ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3\\\\4 & 5 & 6\\\\7 & 8 & 9\\\\10 & 11 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3 ⎤\n", "⎢ ⎥\n", "⎢4 5 6 ⎥\n", "⎢ ⎥\n", "⎢7 8 9 ⎥\n", "⎢ ⎥\n", "⎣10 11 12⎦" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 2, 3], [4, 5, 6], [7,8,9], [10, 11, 12]])\n", "A" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}4 & 5 & 6\\\\7 & 8 & 9\\\\10 & 11 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡4 5 6 ⎤\n", "⎢ ⎥\n", "⎢7 8 9 ⎥\n", "⎢ ⎥\n", "⎣10 11 12⎦" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.row_del(0) #delete row 0\n", "A" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}4 & 6\\\\7 & 9\\\\10 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡4 6 ⎤\n", "⎢ ⎥\n", "⎢7 9 ⎥\n", "⎢ ⎥\n", "⎣10 12⎦" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.col_del(1) #delete column 1\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Elementary row and column operations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will work with the following matrix:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 1 & 2 & 3 & 4\\\\5 & 6 & 7 & 8 & 9\\\\9 & 10 & 11 & 12 & 13\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1 2 3 4 ⎤\n", "⎢ ⎥\n", "⎢5 6 7 8 9 ⎥\n", "⎢ ⎥\n", "⎣9 10 11 12 13⎦" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[0 , 1, 2, 3, 4], [5, 6, 7, 8, 9], [9, 10, 11, 12, 13]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will denote by R$_i$ the row number $i$ of the matrix (remember that in Python indexing starts with 0)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiply R$_1$ by $\\frac{1}{5}$:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 1 & 2 & 3 & 4\\\\1 & \\frac{6}{5} & \\frac{7}{5} & \\frac{8}{5} & \\frac{9}{5}\\\\9 & 10 & 11 & 12 & 13\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1 2 3 4 ⎤\n", "⎢ ⎥\n", "⎢1 6/5 7/5 8/5 9/5⎥\n", "⎢ ⎥\n", "⎣9 10 11 12 13 ⎦" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1, :] = A[1, :]*Rational(1, 5)\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Subtract 9R$_1$ from R$_2$:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 1 & 2 & 3 & 4\\\\1 & \\frac{6}{5} & \\frac{7}{5} & \\frac{8}{5} & \\frac{9}{5}\\\\0 & - \\frac{4}{5} & - \\frac{8}{5} & - \\frac{12}{5} & - \\frac{16}{5}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1 2 3 4 ⎤\n", "⎢ ⎥\n", "⎢1 6/5 7/5 8/5 9/5 ⎥\n", "⎢ ⎥\n", "⎣0 -4/5 -8/5 -12/5 -16/5⎦" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[2, :] = A[2, :] - 9*A[1, :]\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Interchange R$_0$ and R$_1$:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & \\frac{6}{5} & \\frac{7}{5} & \\frac{8}{5} & \\frac{9}{5}\\\\0 & 1 & 2 & 3 & 4\\\\0 & - \\frac{4}{5} & - \\frac{8}{5} & - \\frac{12}{5} & - \\frac{16}{5}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 6/5 7/5 8/5 9/5 ⎤\n", "⎢ ⎥\n", "⎢0 1 2 3 4 ⎥\n", "⎢ ⎥\n", "⎣0 -4/5 -8/5 -12/5 -16/5⎦" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.row_swap(0,1)\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Elementary operations on columns can be done in the same way. For example, here we interchange column 0 and column 1:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}\\frac{6}{5} & 1 & \\frac{7}{5} & \\frac{8}{5} & \\frac{9}{5}\\\\1 & 0 & 2 & 3 & 4\\\\- \\frac{4}{5} & 0 & - \\frac{8}{5} & - \\frac{12}{5} & - \\frac{16}{5}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡6/5 1 7/5 8/5 9/5 ⎤\n", "⎢ ⎥\n", "⎢ 1 0 2 3 4 ⎥\n", "⎢ ⎥\n", "⎣-4/5 0 -8/5 -12/5 -16/5⎦" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.col_swap(0,1)\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Row reduction" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3 & 12\\\\4 & 5 & 6 & 13\\\\7 & 8 & 9 & 14\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3 12⎤\n", "⎢ ⎥\n", "⎢4 5 6 13⎥\n", "⎢ ⎥\n", "⎣7 8 9 14⎦" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 2, 3, 12], [4, 5, 6, 13], [7,8,9, 14]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The function `rref()` computes the row reduced echelon form of a matrix:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left ( \\left[\\begin{matrix}1 & 0 & -1 & - \\frac{34}{3}\\\\0 & 1 & 2 & \\frac{35}{3}\\\\0 & 0 & 0 & 0\\end{matrix}\\right], \\quad \\left ( 0, \\quad 1\\right )\\right )$$" ], "text/plain": [ "⎛⎡1 0 -1 -34/3⎤ ⎞\n", "⎜⎢ ⎥ ⎟\n", "⎜⎢0 1 2 35/3 ⎥, (0, 1)⎟\n", "⎜⎢ ⎥ ⎟\n", "⎝⎣0 0 0 0 ⎦ ⎠" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R = A.rref()\n", "R" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note.** `A.rref()` returns a tuple consisting of a reduced matrix and a list of indices of pivot columns. To get the reduced matrix only we need to select the first entry of this tuple:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 0 & -1 & - \\frac{34}{3}\\\\0 & 1 & 2 & \\frac{35}{3}\\\\0 & 0 & 0 & 0\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 0 -1 -34/3⎤\n", "⎢ ⎥\n", "⎢0 1 2 35/3 ⎥\n", "⎢ ⎥\n", "⎣0 0 0 0 ⎦" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = A.rref()[0]\n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Errors in row reduction with decimals\n", "\n", "Here is an example showing that row reduction of matrices with decimal entries can give wrong results:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 3\\\\0.1 & 0.3\\end{matrix}\\right]$$" ], "text/plain": [ "⎡ 1 3 ⎤\n", "⎢ ⎥\n", "⎣0.1 0.3⎦" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 3],[0.1, 0.3]])\n", "A" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left ( \\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right], \\quad \\left ( 0, \\quad 1\\right )\\right )$$" ], "text/plain": [ "⎛⎡1 0⎤ ⎞\n", "⎜⎢ ⎥, (0, 1)⎟\n", "⎝⎣0 1⎦ ⎠" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.rref() # the result is wrong!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Such issues occur because computer operations on numbers in the decimal form involve rounding errors, and this distorts the end result. \n", "\n", "We can avoid such problems by entering all entries of a matrix as rational numbers:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 3\\\\\\frac{1}{10} & \\frac{3}{10}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡ 1 3 ⎤\n", "⎢ ⎥\n", "⎣1/10 3/10⎦" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 3],[Rational(1,10), Rational(3,10)]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now the reduced echelon form is computed correctly:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left ( \\left[\\begin{matrix}1 & 3\\\\0 & 0\\end{matrix}\\right], \\quad \\left ( 0\\right )\\right )$$" ], "text/plain": [ "⎛⎡1 3⎤ ⎞\n", "⎜⎢ ⎥, (0,)⎟\n", "⎝⎣0 0⎦ ⎠" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.rref()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Matrix algebra" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will be working with the following matrices `A` and `B`:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 1\\\\2 & 3\\\\4 & 5\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1⎤\n", "⎢ ⎥\n", "⎢2 3⎥\n", "⎢ ⎥\n", "⎣4 5⎦" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[0, 1], [2, 3], [4,5]])\n", "A" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}3 & 2\\\\1 & 0\\\\-1 & 2\\end{matrix}\\right]$$" ], "text/plain": [ "⎡3 2⎤\n", "⎢ ⎥\n", "⎢1 0⎥\n", "⎢ ⎥\n", "⎣-1 2⎦" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = Matrix([[3, 2], [1, 0], [-1,2]])\n", "B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Addition of matrices:**" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}3 & 3\\\\3 & 3\\\\3 & 7\\end{matrix}\\right]$$" ], "text/plain": [ "⎡3 3⎤\n", "⎢ ⎥\n", "⎢3 3⎥\n", "⎢ ⎥\n", "⎣3 7⎦" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A+B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Multiplication of a matrix by a scalar:**" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & \\frac{1}{2}\\\\1 & \\frac{3}{2}\\\\2 & \\frac{5}{2}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1/2⎤\n", "⎢ ⎥\n", "⎢1 3/2⎥\n", "⎢ ⎥\n", "⎣2 5/2⎦" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Rational(1, 2)*A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Transpose of a matrix:**" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 2 & 4\\\\1 & 3 & 5\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 2 4⎤\n", "⎢ ⎥\n", "⎣1 3 5⎦" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Matrix multiplication:**" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}-2 & 8\\\\1 & 12\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-2 8 ⎤\n", "⎢ ⎥\n", "⎣1 12⎦" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C = (A.T)*B\n", "C" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can multiply a matrix by a column vector in the same way:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 1\\\\2 & 3\\\\4 & 5\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1⎤\n", "⎢ ⎥\n", "⎢2 3⎥\n", "⎢ ⎥\n", "⎣4 5⎦" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}-1\\\\2\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-1⎤\n", "⎢ ⎥\n", "⎣2 ⎦" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = Matrix([-1, 2])\n", "v" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}2\\\\4\\\\6\\end{matrix}\\right]$$" ], "text/plain": [ "⎡2⎤\n", "⎢ ⎥\n", "⎢4⎥\n", "⎢ ⎥\n", "⎣6⎦" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A*v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Matrix inverse:**" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}- \\frac{3}{8} & \\frac{1}{4}\\\\\\frac{1}{32} & \\frac{1}{16}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-3/8 1/4 ⎤\n", "⎢ ⎥\n", "⎣1/32 1/16⎦" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C.inv()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Not every matrix is invertible. An attempt to compute an inverse of a non-invertible matrix will give an error:" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 0\\\\1 & 0\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 0⎤\n", "⎢ ⎥\n", "⎣1 0⎦" ] }, "execution_count": 93, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# this matrix is non-invertible\n", "A = Matrix([[1, 0], [1, 0]])\n", "A" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "Matrix det == 0; not invertible.", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/anaconda3/lib/python3.7/site-packages/sympy/matrices/matrices.py\u001b[0m in \u001b[0;36minv\u001b[0;34m(self, method, **kwargs)\u001b[0m\n\u001b[1;32m 2916\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2917\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'method'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmethod\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2918\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_eval_inverse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2919\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2920\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mis_nilpotent\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/anaconda3/lib/python3.7/site-packages/sympy/matrices/dense.py\u001b[0m in \u001b[0;36m_eval_inverse\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 264\u001b[0m \u001b[0mM\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_mutable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 265\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"GE\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 266\u001b[0;31m \u001b[0mrv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minverse_GE\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miszerofunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0miszerofunc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 267\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"LU\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 268\u001b[0m \u001b[0mrv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minverse_LU\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miszerofunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0miszerofunc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/anaconda3/lib/python3.7/site-packages/sympy/matrices/matrices.py\u001b[0m in \u001b[0;36minverse_GE\u001b[0;34m(self, iszerofunc)\u001b[0m\n\u001b[1;32m 2831\u001b[0m \u001b[0mred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrref\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miszerofunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0miszerofunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msimplify\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2832\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miszerofunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mred\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mred\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrows\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2833\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Matrix det == 0; not invertible.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2834\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2835\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_new\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mred\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrows\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: Matrix det == 0; not invertible." ] } ], "source": [ "A.inv()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Matrix powers:**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Taking the $n$-th power of a matrix has the same effect as multiplying the matrix by itself $n$ times." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "A = Matrix([[1, 2], [3, 4]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiplying the matrix by itself 4 times:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}199 & 290\\\\435 & 634\\end{matrix}\\right]$" ], "text/plain": [ "⎡199 290⎤\n", "⎢ ⎥\n", "⎣435 634⎦" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A*A*A*A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Taking the 4-th power of $A$:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}199 & 290\\\\435 & 634\\end{matrix}\\right]$" ], "text/plain": [ "⎡199 290⎤\n", "⎢ ⎥\n", "⎣435 634⎦" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A**4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Determinant" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 1 & 2\\\\3 & 4 & 5\\\\6 & 7 & 8\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 1 2⎤\n", "⎢ ⎥\n", "⎢3 4 5⎥\n", "⎢ ⎥\n", "⎣6 7 8⎦" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 1, 2], [3, 4, 5], [6,7,8]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compute the determinant of the matrix `A`:" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$-3$$" ], "text/plain": [ "-3" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.det()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Row space, column space, and null space" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}1 & 2 & 3 & 4\\\\5 & 6 & 7 & 8\\\\4 & 4 & 4 & 4\\end{matrix}\\right]$$" ], "text/plain": [ "⎡1 2 3 4⎤\n", "⎢ ⎥\n", "⎢5 6 7 8⎥\n", "⎢ ⎥\n", "⎣4 4 4 4⎦" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[1, 2, 3, 4],[5, 6, 7, 8], [4, 4, 4, 4]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A basis of the row space:" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left [ \\left[\\begin{matrix}1 & 2 & 3 & 4\\end{matrix}\\right], \\quad \\left[\\begin{matrix}0 & -4 & -8 & -12\\end{matrix}\\right]\\right ]$$" ], "text/plain": [ "[[1 2 3 4], [0 -4 -8 -12]]" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.rowspace()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A basis of the column space:" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left [ \\left[\\begin{matrix}1\\\\5\\\\4\\end{matrix}\\right], \\quad \\left[\\begin{matrix}2\\\\6\\\\4\\end{matrix}\\right]\\right ]$$" ], "text/plain": [ "⎡⎡1⎤ ⎡2⎤⎤\n", "⎢⎢ ⎥ ⎢ ⎥⎥\n", "⎢⎢5⎥, ⎢6⎥⎥\n", "⎢⎢ ⎥ ⎢ ⎥⎥\n", "⎣⎣4⎦ ⎣4⎦⎦" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.columnspace()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A basis of the null space:" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left [ \\left[\\begin{matrix}1\\\\-2\\\\1\\\\0\\end{matrix}\\right], \\quad \\left[\\begin{matrix}2\\\\-3\\\\0\\\\1\\end{matrix}\\right]\\right ]$$" ], "text/plain": [ "⎡⎡1 ⎤ ⎡2 ⎤⎤\n", "⎢⎢ ⎥ ⎢ ⎥⎥\n", "⎢⎢-2⎥ ⎢-3⎥⎥\n", "⎢⎢ ⎥, ⎢ ⎥⎥\n", "⎢⎢1 ⎥ ⎢0 ⎥⎥\n", "⎢⎢ ⎥ ⎢ ⎥⎥\n", "⎣⎣0 ⎦ ⎣1 ⎦⎦" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.nullspace()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dot product and Gram-Schmidt process" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define a few column vectors:" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left ( \\left[\\begin{matrix}1\\\\1\\\\1\\end{matrix}\\right], \\quad \\left[\\begin{matrix}1\\\\2\\\\3\\end{matrix}\\right], \\quad \\left[\\begin{matrix}1\\\\-1\\\\0\\end{matrix}\\right]\\right )$$" ], "text/plain": [ "⎛⎡1⎤ ⎡1⎤ ⎡1 ⎤⎞\n", "⎜⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎟\n", "⎜⎢1⎥, ⎢2⎥, ⎢-1⎥⎟\n", "⎜⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎟\n", "⎝⎣1⎦ ⎣3⎦ ⎣0 ⎦⎠" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u = Matrix([1, 1, 1])\n", "v = Matrix([1, 2, 3])\n", "w = Matrix([1, -1, 0])\n", "u, v, w" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dot product of vectors `v` and `w`:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$-1$$" ], "text/plain": [ "-1" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.dot(w)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gram-Schmidt orthogonalization of the set of vectors $[$ `u`, `v`, `w` $]$:" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left [ \\left[\\begin{matrix}1\\\\1\\\\1\\end{matrix}\\right], \\quad \\left[\\begin{matrix}-1\\\\0\\\\1\\end{matrix}\\right], \\quad \\left[\\begin{matrix}\\frac{1}{2}\\\\-1\\\\\\frac{1}{2}\\end{matrix}\\right]\\right ]$$" ], "text/plain": [ "⎡⎡1⎤ ⎡-1⎤ ⎡1/2⎤⎤\n", "⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥\n", "⎢⎢1⎥, ⎢0 ⎥, ⎢-1 ⎥⎥\n", "⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥\n", "⎣⎣1⎦ ⎣1 ⎦ ⎣1/2⎦⎦" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "GramSchmidt([u, v, w])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Adding the option `orthonormal=True` we obtain a set of orthonormal vectors:" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left [ \\left[\\begin{matrix}\\frac{\\sqrt{3}}{3}\\\\\\frac{\\sqrt{3}}{3}\\\\\\frac{\\sqrt{3}}{3}\\end{matrix}\\right], \\quad \\left[\\begin{matrix}- \\frac{\\sqrt{2}}{2}\\\\0\\\\\\frac{\\sqrt{2}}{2}\\end{matrix}\\right], \\quad \\left[\\begin{matrix}\\frac{\\sqrt{6}}{6}\\\\- \\frac{\\sqrt{6}}{3}\\\\\\frac{\\sqrt{6}}{6}\\end{matrix}\\right]\\right ]$$" ], "text/plain": [ "⎡⎡√3⎤ ⎡ √6 ⎤⎤\n", "⎢⎢──⎥ ⎡-√2 ⎤ ⎢ ── ⎥⎥\n", "⎢⎢3 ⎥ ⎢────⎥ ⎢ 6 ⎥⎥\n", "⎢⎢ ⎥ ⎢ 2 ⎥ ⎢ ⎥⎥\n", "⎢⎢√3⎥ ⎢ ⎥ ⎢-√6 ⎥⎥\n", "⎢⎢──⎥, ⎢ 0 ⎥, ⎢────⎥⎥\n", "⎢⎢3 ⎥ ⎢ ⎥ ⎢ 3 ⎥⎥\n", "⎢⎢ ⎥ ⎢ √2 ⎥ ⎢ ⎥⎥\n", "⎢⎢√3⎥ ⎢ ── ⎥ ⎢ √6 ⎥⎥\n", "⎢⎢──⎥ ⎣ 2 ⎦ ⎢ ── ⎥⎥\n", "⎣⎣3 ⎦ ⎣ 6 ⎦⎦" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "GramSchmidt([u, v, w], orthonormal=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Eigenvalues, eigenvectors, diagonalization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Characteristic polynomial" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}3 & -2 & 4 & -2\\\\5 & 3 & -3 & -2\\\\5 & -2 & 2 & -2\\\\5 & -2 & -3 & 3\\end{matrix}\\right]$$" ], "text/plain": [ "⎡3 -2 4 -2⎤\n", "⎢ ⎥\n", "⎢5 3 -3 -2⎥\n", "⎢ ⎥\n", "⎢5 -2 2 -2⎥\n", "⎢ ⎥\n", "⎣5 -2 -3 3 ⎦" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[3, -2, 4, -2], [5, 3, -3, -2], [5, -2, 2, -2], [5, -2, -3, 3]])\n", "A" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\operatorname{PurePoly}{\\left( \\lambda^{4} - 11 \\lambda^{3} + 29 \\lambda^{2} + 35 \\lambda - 150, \\lambda, domain=\\mathbb{Z} \\right)}$$" ], "text/plain": [ "PurePoly(lamda**4 - 11*lamda**3 + 29*lamda**2 + 35*lamda - 150, lamda, domain=\n", "'ZZ')" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# declare a variable lamda (this is not a misspeling, \n", "#\"lambda\" already has a different meaning in Python)\n", "lamda = symbols('lamda') \n", "\n", "# compute the characteristic polynomial of matrix A with lamda as the variable\n", "p = A.charpoly(lamda)\n", "p" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Factorization of the polynomial:" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left(\\lambda - 5\\right)^{2} \\left(\\lambda - 3\\right) \\left(\\lambda + 2\\right)$$" ], "text/plain": [ " 2 \n", "(λ - 5) ⋅(λ - 3)⋅(λ + 2)" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "factor(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Eigenvalues and eigenvectors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eigenvalues of the matrix `A` with their algebraic multiplicities:" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left \\{ -2 : 1, \\quad 3 : 1, \\quad 5 : 2\\right \\}$$" ], "text/plain": [ "{-2: 1, 3: 1, 5: 2}" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.eigenvals()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eigenvalues with their algebraic multiplicities and bases of eigenspaces:" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left [ \\left ( -2, \\quad 1, \\quad \\left [ \\left[\\begin{matrix}0\\\\1\\\\1\\\\1\\end{matrix}\\right]\\right ]\\right ), \\quad \\left ( 3, \\quad 1, \\quad \\left [ \\left[\\begin{matrix}1\\\\1\\\\1\\\\1\\end{matrix}\\right]\\right ]\\right ), \\quad \\left ( 5, \\quad 2, \\quad \\left [ \\left[\\begin{matrix}1\\\\1\\\\1\\\\0\\end{matrix}\\right], \\quad \\left[\\begin{matrix}0\\\\-1\\\\0\\\\1\\end{matrix}\\right]\\right ]\\right )\\right ]$$" ], "text/plain": [ "⎡⎛ ⎡⎡0⎤⎤⎞ ⎛ ⎡⎡1⎤⎤⎞ ⎛ ⎡⎡1⎤ ⎡0 ⎤⎤⎞⎤\n", "⎢⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥ ⎢ ⎥⎥⎟⎥\n", "⎢⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥ ⎢-1⎥⎥⎟⎥\n", "⎢⎜-2, 1, ⎢⎢ ⎥⎥⎟, ⎜3, 1, ⎢⎢ ⎥⎥⎟, ⎜5, 2, ⎢⎢ ⎥, ⎢ ⎥⎥⎟⎥\n", "⎢⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥ ⎢0 ⎥⎥⎟⎥\n", "⎢⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥ ⎢ ⎥⎥⎟⎥\n", "⎣⎝ ⎣⎣1⎦⎦⎠ ⎝ ⎣⎣1⎦⎦⎠ ⎝ ⎣⎣0⎦ ⎣1 ⎦⎦⎠⎦" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.eigenvects()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Diagonalization of matrices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Diagonalization of a matrix (returns a tuple consistsing of matrices $P$ and $D$ such that $A = PDP^{-1}$):" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left ( \\left[\\begin{matrix}0 & 1 & 1 & 0\\\\1 & 1 & 1 & -1\\\\1 & 1 & 1 & 0\\\\1 & 1 & 0 & 1\\end{matrix}\\right], \\quad \\left[\\begin{matrix}-2 & 0 & 0 & 0\\\\0 & 3 & 0 & 0\\\\0 & 0 & 5 & 0\\\\0 & 0 & 0 & 5\\end{matrix}\\right]\\right )$$" ], "text/plain": [ "⎛⎡0 1 1 0 ⎤ ⎡-2 0 0 0⎤⎞\n", "⎜⎢ ⎥ ⎢ ⎥⎟\n", "⎜⎢1 1 1 -1⎥ ⎢0 3 0 0⎥⎟\n", "⎜⎢ ⎥, ⎢ ⎥⎟\n", "⎜⎢1 1 1 0 ⎥ ⎢0 0 5 0⎥⎟\n", "⎜⎢ ⎥ ⎢ ⎥⎟\n", "⎝⎣1 1 0 1 ⎦ ⎣0 0 0 5⎦⎠" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.diagonalize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complex diagonalization:" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 1\\\\-1 & 0\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1⎤\n", "⎢ ⎥\n", "⎣-1 0⎦" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = Matrix([[0, 1],[-1, 0]])\n", "B" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left ( \\left[\\begin{matrix}i & - i\\\\1 & 1\\end{matrix}\\right], \\quad \\left[\\begin{matrix}- i & 0\\\\0 & i\\end{matrix}\\right]\\right )$$" ], "text/plain": [ "⎛⎡ⅈ -ⅈ⎤ ⎡-ⅈ 0⎤⎞\n", "⎜⎢ ⎥, ⎢ ⎥⎟\n", "⎝⎣1 1 ⎦ ⎣0 ⅈ⎦⎠" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B.diagonalize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Not every matrix is diagonalizable. For such matrices we will get an error:" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}2 & 1\\\\0 & 2\\end{matrix}\\right]$$" ], "text/plain": [ "⎡2 1⎤\n", "⎢ ⎥\n", "⎣0 2⎦" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# this matrix is not diagonalizable\n", "C = Matrix([[2, 1], [0, 2]])\n", "C" ] }, { "cell_type": "code", "execution_count": 97, "metadata": { "scrolled": true }, "outputs": [ { "ename": "MatrixError", "evalue": "Matrix is not diagonalizable", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mMatrixError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mC\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdiagonalize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/anaconda3/lib/python3.7/site-packages/sympy/matrices/matrices.py\u001b[0m in \u001b[0;36mdiagonalize\u001b[0;34m(self, reals_only, sort, normalize)\u001b[0m\n\u001b[1;32m 1085\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1086\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_diagonalizable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreals_only\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mreals_only\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mclear_cache\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1087\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mMatrixError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Matrix is not diagonalizable\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1088\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1089\u001b[0m \u001b[0meigenvecs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_cache_eigenvects\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mMatrixError\u001b[0m: Matrix is not diagonalizable" ] } ], "source": [ "C.diagonalize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Singular Value Decomposition" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}0 & 1 & 2 & 3\\\\4 & 6 & 7 & 0\\\\1 & 1 & 0 & 0\\end{matrix}\\right]$$" ], "text/plain": [ "⎡0 1 2 3⎤\n", "⎢ ⎥\n", "⎢4 6 7 0⎥\n", "⎢ ⎥\n", "⎣1 1 0 0⎦" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = Matrix([[0, 1, 2, 3], [4, 6, 7, 0], [1, 1, 0, 0]])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sympy` does not include a function for computing singular value decomposition, but such function can be imported from from `mpmath`:" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [], "source": [ "from mpmath import svd" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [], "source": [ "U, S, V = svd(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`U` and `V` are orthogonal matrices, `S` is the vector of singular values:" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}-0.211721215903945 & -0.971337526391343 & 0.108062651087702\\\\-0.972676773708509 & 0.198644273600799 & -0.120167992633721\\\\-0.0952576538875581 & 0.130552144331522 & 0.986854658491451\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-0.211721215903945 -0.971337526391343 0.108062651087702 ⎤\n", "⎢ ⎥\n", "⎢-0.972676773708509 0.198644273600799 -0.120167992633721⎥\n", "⎢ ⎥\n", "⎣-0.0952576538875581 0.130552144331522 0.986854658491451 ⎦" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix(\n", "[['10.3117751931661'],\n", " ['3.12657593986521'],\n", " ['0.944359707876459']])" ] }, "execution_count": 89, "metadata": {}, "output_type": "execute_result" } ], "source": [ "S" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix(\n", "[['-0.386544961857121', '-0.595730550459802', '-0.701351582272704', '-0.0615959556733527'],\n", " ['0.295892137766083', '0.112289055598665', '-0.176603782603437', '-0.932014009965052'],\n", " ['0.536006231242966', '0.395939545766543', '-0.661877715712972', '0.34328863309098']])" ] }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "V" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`S` and `V` are not displayed nicely since they are `mpmath` matrices, and not `sympy` matrices. This can be fixed as follows:" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}-0.386544961857121 & -0.595730550459802 & -0.701351582272704 & -0.0615959556733527\\\\0.295892137766083 & 0.112289055598665 & -0.176603782603437 & -0.932014009965052\\\\0.536006231242966 & 0.395939545766543 & -0.661877715712972 & 0.34328863309098\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-0.386544961857121 -0.595730550459802 -0.701351582272704 -0.06159595567335\n", "⎢ \n", "⎢0.295892137766083 0.112289055598665 -0.176603782603437 -0.93201400996505\n", "⎢ \n", "⎣0.536006231242966 0.395939545766543 -0.661877715712972 0.34328863309098\n", "\n", "27⎤\n", " ⎥\n", "2 ⎥\n", " ⎥\n", " ⎦" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "V = Matrix(np.array(V.tolist(),dtype=np.float64))\n", "V" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}10.3117751931661 & 0 & 0\\\\0 & 3.12657593986521 & 0\\\\0 & 0 & 0.944359707876459\\end{matrix}\\right]$$" ], "text/plain": [ "⎡10.3117751931661 0 0 ⎤\n", "⎢ ⎥\n", "⎢ 0 3.12657593986521 0 ⎥\n", "⎢ ⎥\n", "⎣ 0 0 0.944359707876459⎦" ] }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "S = diag(*[Float(x) for x in S])\n", "S" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.7.6" } }, "nbformat": 4, "nbformat_minor": 4 }