# Initialize Enviroment


```python
from IPython.display import display, Math, Latex 
from sympy import *
init_printing()

from helper import comparator_factory, comparator_eval_factory, comparator_method_factory

x,y,z = symbols('x y z')

func_comparator = comparator_factory('Before applying {}:','After:')
method_comparator = comparator_method_factory('Before calling {}:','After:')
eval_comparator = comparator_eval_factory('Before evaluation:','After evaluation:')
```

# Matrices

## Construct matrix
### Construct matrix from list
To make a matrix in Sympy, initialize a ```Matrix``` class by providing a list of row vectors (nested list).


```python
m = Matrix(
    [
        [1, -1], 
        [3, 4], 
        [0, 2]
    ]
)

m
```




$\displaystyle \left[\begin{matrix}1 & -1\\3 & 4\\0 & 2\end{matrix}\right]$



Pass a single layer list of elements will create a $n \times 1$ matrix.


```python
m = Matrix([1,2,3])

m
```




$\displaystyle \left[\begin{matrix}1\\2\\3\end{matrix}\right]$



## Common Matrix Constructors

Several constructors exist for creating common matrices.

### Identity Matrix
To create identity matrix, use ```eye(n)```


```python
M = eye(3)

M
```




$\displaystyle \left[\begin{matrix}1 & 0 & 0\\0 & 1 & 0\\0 & 0 & 1\end{matrix}\right]$



### Matrix of Zero
To create a zero matrix, use ```zero(n)```


```python
M = zeros(3,4)

display(M)
```


$\displaystyle \left[\begin{matrix}0 & 0 & 0 & 0\\0 & 0 & 0 & 0\\0 & 0 & 0 & 0\end{matrix}\right]$


### Matrix of Ones
To create a zero matrix, use ```one(n)```


```python
M = ones(3,2)

M
```




$\displaystyle \left[\begin{matrix}1 & 1\\1 & 1\\1 & 1\end{matrix}\right]$



### Diagonal
Pass multiple matrix or numbers to construct a diagonal matrix. Numbers will be intepreted as $1 \times 1$ matrix.


```python
M = diag(-1, ones(2, 2), Matrix([5, 7, 5]))

M
```




$\displaystyle \left[\begin{matrix}-1 & 0 & 0 & 0\\0 & 1 & 1 & 0\\0 & 1 & 1 & 0\\0 & 0 & 0 & 5\\0 & 0 & 0 & 7\\0 & 0 & 0 & 5\end{matrix}\right]$



## Basic operations

### Shape

To get the shape of a matrix, use ```shape```


```python
M.shape
```

### Get rows and columns
Use ```row()``` and ```col()``` to get single row and column. 

To get the first row


```python
M.row(0)
```




$\displaystyle \left[\begin{matrix}-1 & 0 & 0 & 0\end{matrix}\right]$



To get the last column


```python
M.col(-1)
```




$\displaystyle \left[\begin{matrix}0\\0\\0\\5\\7\\5\end{matrix}\right]$



### Delete Rows and Columns
To delete a row or column, use ```row_del``` and ```col_del```. These operaitons modify the matrix inplace.

For example, we create a matrix then delete the first row and last column.


```python
M = Matrix([[1, 2, 3], [3, 2, 1]])

display('Before deletion:',M)

M.row_del(0)
M.col_del(-1)

display('After deletion:',M)
```


    'Before deletion:'



$\displaystyle \left[\begin{matrix}1 & 2 & 3\\3 & 2 & 1\end{matrix}\right]$



    'After deletion:'



$\displaystyle \left[\begin{matrix}3 & 2\end{matrix}\right]$


### Transpose of Matrix
Use ```T```


```python
M = Matrix([[1, 2, 3], [4, 5, 6]])

display('Original matrix:',M)
display('Transposed matrix:',M.T)
```


    'Original matrix:'



$\displaystyle \left[\begin{matrix}1 & 2 & 3\\4 & 5 & 6\end{matrix}\right]$



    'Transposed matrix:'



$\displaystyle \left[\begin{matrix}1 & 4\\2 & 5\\3 & 6\end{matrix}\right]$


### Insert Rows and Columns

To insert rows and columns, use ```row_insert``` and ```col_insert```. These operations don't operate inplace and return a new matrix with modified data.

```row_insert()``` accepts a position and a $1 \times n$  matrix.


```python
M = Matrix([[1, 2, 3], [3, 2, 1]])

display('Before insertion:',M)

M = M.row_insert(0, Matrix([[6,6,6]]))

display('After Insertion:',M)
```


    'Before insertion:'



$\displaystyle \left[\begin{matrix}1 & 2 & 3\\3 & 2 & 1\end{matrix}\right]$



    'After Insertion:'



$\displaystyle \left[\begin{matrix}6 & 6 & 6\\1 & 2 & 3\\3 & 2 & 1\end{matrix}\right]$


 ```col_insert()``` accepts position and $n \times 1$  matrix.


```python
M = Matrix([[1, 2, 3], [3, 2, 1]])

display('Before insertion:',M)

M = M.col_insert(-1, Matrix([6,6]))

display('After Insertion:',M)
```


    'Before insertion:'



$\displaystyle \left[\begin{matrix}1 & 2 & 3\\3 & 2 & 1\end{matrix}\right]$



    'After Insertion:'



$\displaystyle \left[\begin{matrix}1 & 2 & 6 & 3\\3 & 2 & 6 & 1\end{matrix}\right]$


## Matrix Computation
Basic matrix computation like addition, substraction, multiplication and inversion can be achived through python operators ```+```,```-```,```*```,```**```


### Addition


```python
M = Matrix([[1, 3], [-2, 3]])
N = Matrix([[0, 3], [0, 7]])

print('M')
display(M)
print('N')
display(N)
print('M+N')
display(M+N)
```

    M



$\displaystyle \left[\begin{matrix}1 & 3\\-2 & 3\end{matrix}\right]$


    N



$\displaystyle \left[\begin{matrix}0 & 3\\0 & 7\end{matrix}\right]$


    M+N



$\displaystyle \left[\begin{matrix}1 & 6\\-2 & 10\end{matrix}\right]$


### Substraction


```python
M = Matrix([[1, 3], [-2, 3]])
N = Matrix([[0, 3], [0, 7]])

print('M')
display(M)
print('N')
display(N)
print('M-N')
display(M-N)
```

    M



$\displaystyle \left[\begin{matrix}1 & 3\\-2 & 3\end{matrix}\right]$


    N



$\displaystyle \left[\begin{matrix}0 & 3\\0 & 7\end{matrix}\right]$


    M-N



$\displaystyle \left[\begin{matrix}1 & 0\\-2 & -4\end{matrix}\right]$


### Multiplication


```python
M = Matrix([[1, 2, 3], [3, 2, 1]])
N = Matrix([0, 1, 1])

print('M')
display(M)
print('N')
display(N)
display('MxN')
display(M*N)
```

    M



$\displaystyle \left[\begin{matrix}1 & 2 & 3\\3 & 2 & 1\end{matrix}\right]$


    N



$\displaystyle \left[\begin{matrix}0\\1\\1\end{matrix}\right]$



    'MxN'



$\displaystyle \left[\begin{matrix}5\\3\end{matrix}\right]$


### Inverse


```python
M = Matrix([[1, 3], [-2, 3]])

print('M')
display(M)
print('inverse of M:')
display(M**(-1))
```

    M



$\displaystyle \left[\begin{matrix}1 & 3\\-2 & 3\end{matrix}\right]$


    inverse of M:



$\displaystyle \left[\begin{matrix}\frac{1}{3} & - \frac{1}{3}\\\frac{2}{9} & \frac{1}{9}\end{matrix}\right]$


## Determinant

To get determinant of matrix, use ```det```


```python
M = Matrix([[1, 0, 1], [2, -1, 3], [4, 3, 2]])

method_comparator(M,'det')
```

### RREF
To put a matrix into reduced echelon form, use ```rref()```. It returns a matrix of two elements, the first is the reduced echelon form and the second is a list of indices of the pivot columns.


```python
M = Matrix([[1, 0, 1, 3], [2, 3, 4, 7], [-1, -3, -3, -4]])

M_rref, pivot_columns = M.rref()

print('Original Matrix:')
display(M)

print('Reduced echelon form:')
display(M_rref)

print('Pivot columns:')
display(pivot_columns)
```

### Nullspace

```nullspace()``` returns a list of column vectors which span the nullspace of a matrix.


```python
M = Matrix([[1, 2, 3, 0, 0], [4, 10, 0, 0, 1]])

print('Matrix M:')
display(M)
print('Spanning vectors for nullspace of M:')
display(M.nullspace())
```

    Matrix M:



$\displaystyle \left[\begin{matrix}1 & 2 & 3 & 0 & 0\\4 & 10 & 0 & 0 & 1\end{matrix}\right]$


    Spanning vectors for nullspace of M:



$\displaystyle \left[ \left[\begin{matrix}-15\\6\\1\\0\\0\end{matrix}\right], \  \left[\begin{matrix}0\\0\\0\\1\\0\end{matrix}\right], \  \left[\begin{matrix}1\\- \frac{1}{2}\\0\\0\\1\end{matrix}\right]\right]$


### Column space

```columnspace()``` returns a list of column vectors which span the columnspace of a matrix.


```python
M = Matrix([[1, 1, 2], [2 ,1 , 3], [3 , 1, 4]])

print('Matrix M:')
display(M)
print('Spanning vectors for columnspace of M:')
display(M.columnspace())
```

    Matrix M:



$\displaystyle \left[\begin{matrix}1 & 1 & 2\\2 & 1 & 3\\3 & 1 & 4\end{matrix}\right]$


    Spanning vectors for columnspace of M:



$\displaystyle \left[ \left[\begin{matrix}1\\2\\3\end{matrix}\right], \  \left[\begin{matrix}1\\1\\1\end{matrix}\right]\right]$


### Eigenvalues and Eigenvectors
To find the eigenvalues of a matrix, use ```eigenvals```. It returns a dictionary of eigenvalue:algebraic multiplicity pairs.


```python
M = Matrix([[3, -2,  4, -2], [5,  3, -3, -2], [5, -2,  2, -2], [5, -2, -3,  3]])

print('Matrix M')
display(M)

print('Eigenvalues and their algebraic multiplicity:')
display(M.eigenvals())
```

```eigenvectors``` return a list of tuples of the form ```(eigenvalue, algebraic multiplicity, [eigenvectors])```


```python
M = Matrix(
    [
        [3, -2,  4, -2], 
        [5,  3, -3, -2], 
        [5, -2,  2, -2], 
        [5, -2, -3,  3]
    ]
)

print('Matrix M')
display(M)

print('Eigenvalues, their algebraic multiplicity and eigenvectors:')
display(M.eigenvects())
```

    Matrix M



$\displaystyle \left[\begin{matrix}3 & -2 & 4 & -2\\5 & 3 & -3 & -2\\5 & -2 & 2 & -2\\5 & -2 & -3 & 3\end{matrix}\right]$


    Eigenvalues, their algebraic multiplicity and eigenvectors:



$\displaystyle \left[ \left( -2, \  1, \  \left[ \left[\begin{matrix}0\\1\\1\\1\end{matrix}\right]\right]\right), \  \left( 3, \  1, \  \left[ \left[\begin{matrix}1\\1\\1\\1\end{matrix}\right]\right]\right), \  \left( 5, \  2, \  \left[ \left[\begin{matrix}1\\1\\1\\0\end{matrix}\right], \  \left[\begin{matrix}0\\-1\\0\\1\end{matrix}\right]\right]\right)\right]$


If all you want is the characteristic polymonial, use ```charpoly()``` and ```factor()```


```python
print('Matrix M')
display(M)

lamda = symbols('lamda')
p = M.charpoly(lamda).factor()

print('characteristic polymonial of M')
display(p)
```

## Diagonalization

To diagonalize a matrix , use ```diagonalize()```. diagonalize returns a tuple ($P$,$D$), where D is diagonal and $M = PDP^{-1}$.


```python
M = Matrix(
    [
        [3, -2,  4, -2], 
        [5,  3, -3, -2], 
        [5, -2,  2, -2], 
        [5, -2, -3,  3]
    ]
)

P, D = M.diagonalize()

print('Matrix M')
display(M)

print('Matrix P')
display(P)

print('Matrix D')
display(D)

display(Latex('$PDP^{-1}$'))
display(P*D*P**-1)
```

    Matrix M



$\displaystyle \left[\begin{matrix}3 & -2 & 4 & -2\\5 & 3 & -3 & -2\\5 & -2 & 2 & -2\\5 & -2 & -3 & 3\end{matrix}\right]$


    Matrix P



$\displaystyle \left[\begin{matrix}0 & 1 & 1 & 0\\1 & 1 & 1 & -1\\1 & 1 & 1 & 0\\1 & 1 & 0 & 1\end{matrix}\right]$


    Matrix D



$\displaystyle \left[\begin{matrix}-2 & 0 & 0 & 0\\0 & 3 & 0 & 0\\0 & 0 & 5 & 0\\0 & 0 & 0 & 5\end{matrix}\right]$



$PDP^{-1}$



$\displaystyle \left[\begin{matrix}3 & -2 & 4 & -2\\5 & 3 & -3 & -2\\5 & -2 & 2 & -2\\5 & -2 & -3 & 3\end{matrix}\right]$


# Solvers

## Basic equations
The main function for solving algebraic equations is ```solveset()```. The syntax for ```solveset()``` is ```solveset(equation, variable=None, domain=S.Complexes)```.


```python
eq = Eq(x**2-1, 0)

func_comparator(eq, solveset, x)
```

If an expresison instead of a Eq instance is passed in ```solveset()```, it is automatically assumed to be zero. 


```python
expr = x**2-1

func_comparator(eq, solveset, x)
```

Result of the solver can be a infinite set.


```python
eq = Eq(sin(x) - 1)

func_comparator(eq, solveset, x)
```

Result of the solver can be an empty set.


```python
eq = Eq(exp(x))

func_comparator(eq, solveset, x)
```

When solver fails to find solutions, it returns an conditional set.


```python
eq = Eq(cos(x) - x)

func_comparator(eq, solveset, x)
```

```solveset()``` reports each solution only once. 


```python
eq = Eq(x**3 - 6*x**2 + 9*x,0)

func_comparator(eq, solveset, x)
```

To get the solutions with polymonial equation with multiplicity, use ```roots()```


```python
eq = Eq(x**3 - 6*x**2 + 9*x,0)

func_comparator(eq, roots, x)
```

## Linear System

```linsolve()``` is the solver to solve a linear system. A linear system can be defined using differet method.

### list of equations


```python
ls = [
    Eq(x + y + z - 1), 
    Eq(x + y + 2*z - 3)
]

func_comparator(ls,linsolve, x, z)
```

List of equatons can be simplified into list of expressions if all of them are equal to zero。


```python
ls = [
    x + y + z - 1, 
    x + y + 2*z - 3
]
```

### Augmeted matrix form


```python
M = Matrix(
    [
        [1, 1, 1, 1], 
        [1, 1, 2, 3]
    ]
)
    
func_comparator(M,linsolve, x, y, z)
```

### $Ax = b$ form


```python
M = Matrix(
    [
        [1, 1, 1, 1], 
        [1, 1, 2, 3]
    ]
)
ls = A, b = M[:, :-1], M[:, -1]

func_comparator(M,linsolve, x, y, z)
```

## Non-linear Systems

```solvset()``` is not capable of solving mutiple variable non-linear system. In this situation, use ```solve()``` instead.


```python
eq_list = [
    Eq(x*y - 1, 0),
    Eq(x-2, 0)
]

func_comparator(eq_list, solve, x, y)
```

## Differential equition

First define needed function symbol variables.


```python
f = symbols('f', cls = Function)
```

Then define the differential equation. For example, $f''(x) - 2f'(x) + f(x) = \sin(x)$


```python
diffeq = Eq(f(x).diff(x, 2) - 2*f(x).diff(x) + f(x), sin(x))
```

Then use ```dsolve()``` to solve the equation.


```python
func_comparator(diffeq, dsolve, f(x))
```

If the equation cannot be solved explicitly, ```dsolve()``` returns an implicit equation.


```python
diffeq = Eq(f(x).diff(x)*(1 - sin(f(x))), 0)

func_comparator(diffeq, dsolve, f(x))
```

# Reference
[Sympy Documentation](http://docs.sympy.org/latest/index.html)

# Related Articles
* [Sympy Notes I]({filename}0026_sympy_intro_1_en.ipynb)
* [Sympy Notes II]({filename}0027_sympy_intro_2_en.ipynb)
* [Sympy Notes III]({filename}0028_sympy_intro_3_en.ipynb)
* [Sympy Notes IV]({filename}0029_sympy_intro_4_en.ipynb)

ed59bcea22625d8d97c9090eed32bf768a26727e
ipynb
Jupyter Notebook
0011_sympy/0028_sympy_intro_3_en.ipynb
junjiecai/jupyter_demos
8aa8a0320545c0ea09e05e94aea82bc8aa537750
MIT
2019-09-16T10:44:39.000Z
2021-09-04T18:55:52.000Z
0011_sympy/0028_sympy_intro_3_en.ipynb
junjiecai/jupyter_demos
8aa8a0320545c0ea09e05e94aea82bc8aa537750
MIT
0011_sympy/0028_sympy_intro_3_en.ipynb
junjiecai/jupyter_demos
8aa8a0320545c0ea09e05e94aea82bc8aa537750
MIT
2020-10-24T16:19:29.000Z
2021-09-04T18:55:57.000Z
Qwen/Qwen-72B
1. YES
2. YES