Initial commit
This commit is contained in:
526
skills/sympy/references/matrices-linear-algebra.md
Normal file
526
skills/sympy/references/matrices-linear-algebra.md
Normal file
@@ -0,0 +1,526 @@
|
||||
# SymPy Matrices and Linear Algebra
|
||||
|
||||
This document covers SymPy's matrix operations, linear algebra capabilities, and solving systems of linear equations.
|
||||
|
||||
## Matrix Creation
|
||||
|
||||
### Basic Matrix Construction
|
||||
|
||||
```python
|
||||
from sympy import Matrix, eye, zeros, ones, diag
|
||||
|
||||
# From list of rows
|
||||
M = Matrix([[1, 2], [3, 4]])
|
||||
M = Matrix([
|
||||
[1, 2, 3],
|
||||
[4, 5, 6]
|
||||
])
|
||||
|
||||
# Column vector
|
||||
v = Matrix([1, 2, 3])
|
||||
|
||||
# Row vector
|
||||
v = Matrix([[1, 2, 3]])
|
||||
```
|
||||
|
||||
### Special Matrices
|
||||
|
||||
```python
|
||||
# Identity matrix
|
||||
I = eye(3) # 3x3 identity
|
||||
# [[1, 0, 0],
|
||||
# [0, 1, 0],
|
||||
# [0, 0, 1]]
|
||||
|
||||
# Zero matrix
|
||||
Z = zeros(2, 3) # 2 rows, 3 columns of zeros
|
||||
|
||||
# Ones matrix
|
||||
O = ones(3, 2) # 3 rows, 2 columns of ones
|
||||
|
||||
# Diagonal matrix
|
||||
D = diag(1, 2, 3)
|
||||
# [[1, 0, 0],
|
||||
# [0, 2, 0],
|
||||
# [0, 0, 3]]
|
||||
|
||||
# Block diagonal
|
||||
from sympy import BlockDiagMatrix
|
||||
A = Matrix([[1, 2], [3, 4]])
|
||||
B = Matrix([[5, 6], [7, 8]])
|
||||
BD = BlockDiagMatrix(A, B)
|
||||
```
|
||||
|
||||
## Matrix Properties and Access
|
||||
|
||||
### Shape and Dimensions
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2, 3], [4, 5, 6]])
|
||||
|
||||
M.shape # (2, 3) - returns tuple (rows, cols)
|
||||
M.rows # 2
|
||||
M.cols # 3
|
||||
```
|
||||
|
||||
### Accessing Elements
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2, 3], [4, 5, 6]])
|
||||
|
||||
# Single element
|
||||
M[0, 0] # 1 (zero-indexed)
|
||||
M[1, 2] # 6
|
||||
|
||||
# Row access
|
||||
M[0, :] # Matrix([[1, 2, 3]])
|
||||
M.row(0) # Same as above
|
||||
|
||||
# Column access
|
||||
M[:, 1] # Matrix([[2], [5]])
|
||||
M.col(1) # Same as above
|
||||
|
||||
# Slicing
|
||||
M[0:2, 0:2] # Top-left 2x2 submatrix
|
||||
```
|
||||
|
||||
### Modification
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [3, 4]])
|
||||
|
||||
# Insert row
|
||||
M = M.row_insert(1, Matrix([[5, 6]]))
|
||||
# [[1, 2],
|
||||
# [5, 6],
|
||||
# [3, 4]]
|
||||
|
||||
# Insert column
|
||||
M = M.col_insert(1, Matrix([7, 8]))
|
||||
|
||||
# Delete row
|
||||
M = M.row_del(0)
|
||||
|
||||
# Delete column
|
||||
M = M.col_del(1)
|
||||
```
|
||||
|
||||
## Basic Matrix Operations
|
||||
|
||||
### Arithmetic Operations
|
||||
|
||||
```python
|
||||
from sympy import Matrix
|
||||
|
||||
A = Matrix([[1, 2], [3, 4]])
|
||||
B = Matrix([[5, 6], [7, 8]])
|
||||
|
||||
# Addition
|
||||
C = A + B
|
||||
|
||||
# Subtraction
|
||||
C = A - B
|
||||
|
||||
# Scalar multiplication
|
||||
C = 2 * A
|
||||
|
||||
# Matrix multiplication
|
||||
C = A * B
|
||||
|
||||
# Element-wise multiplication (Hadamard product)
|
||||
C = A.multiply_elementwise(B)
|
||||
|
||||
# Power
|
||||
C = A**2 # Same as A * A
|
||||
C = A**3 # A * A * A
|
||||
```
|
||||
|
||||
### Transpose and Conjugate
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [3, 4]])
|
||||
|
||||
# Transpose
|
||||
M.T
|
||||
# [[1, 3],
|
||||
# [2, 4]]
|
||||
|
||||
# Conjugate (for complex matrices)
|
||||
M.conjugate()
|
||||
|
||||
# Conjugate transpose (Hermitian transpose)
|
||||
M.H # Same as M.conjugate().T
|
||||
```
|
||||
|
||||
### Inverse
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [3, 4]])
|
||||
|
||||
# Inverse
|
||||
M_inv = M**-1
|
||||
M_inv = M.inv()
|
||||
|
||||
# Verify
|
||||
M * M_inv # Returns identity matrix
|
||||
|
||||
# Check if invertible
|
||||
M.is_invertible() # True or False
|
||||
```
|
||||
|
||||
## Advanced Linear Algebra
|
||||
|
||||
### Determinant
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [3, 4]])
|
||||
M.det() # -2
|
||||
|
||||
# For symbolic matrices
|
||||
from sympy import symbols
|
||||
a, b, c, d = symbols('a b c d')
|
||||
M = Matrix([[a, b], [c, d]])
|
||||
M.det() # a*d - b*c
|
||||
```
|
||||
|
||||
### Trace
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
||||
M.trace() # 1 + 5 + 9 = 15
|
||||
```
|
||||
|
||||
### Row Echelon Form
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
||||
|
||||
# Reduced Row Echelon Form
|
||||
rref_M, pivot_cols = M.rref()
|
||||
# rref_M is the RREF matrix
|
||||
# pivot_cols is tuple of pivot column indices
|
||||
```
|
||||
|
||||
### Rank
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
||||
M.rank() # 2 (this matrix is rank-deficient)
|
||||
```
|
||||
|
||||
### Nullspace and Column Space
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
||||
|
||||
# Nullspace (kernel)
|
||||
null = M.nullspace()
|
||||
# Returns list of basis vectors for nullspace
|
||||
|
||||
# Column space
|
||||
col = M.columnspace()
|
||||
# Returns list of basis vectors for column space
|
||||
|
||||
# Row space
|
||||
row = M.rowspace()
|
||||
# Returns list of basis vectors for row space
|
||||
```
|
||||
|
||||
### Orthogonalization
|
||||
|
||||
```python
|
||||
# Gram-Schmidt orthogonalization
|
||||
vectors = [Matrix([1, 2, 3]), Matrix([4, 5, 6])]
|
||||
ortho = Matrix.orthogonalize(*vectors)
|
||||
|
||||
# With normalization
|
||||
ortho_norm = Matrix.orthogonalize(*vectors, normalize=True)
|
||||
```
|
||||
|
||||
## Eigenvalues and Eigenvectors
|
||||
|
||||
### Computing Eigenvalues
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [2, 1]])
|
||||
|
||||
# Eigenvalues with multiplicities
|
||||
eigenvals = M.eigenvals()
|
||||
# Returns dict: {eigenvalue: multiplicity}
|
||||
# Example: {3: 1, -1: 1}
|
||||
|
||||
# Just the eigenvalues as a list
|
||||
eigs = list(M.eigenvals().keys())
|
||||
```
|
||||
|
||||
### Computing Eigenvectors
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [2, 1]])
|
||||
|
||||
# Eigenvectors with eigenvalues
|
||||
eigenvects = M.eigenvects()
|
||||
# Returns list of tuples: (eigenvalue, multiplicity, [eigenvectors])
|
||||
# Example: [(3, 1, [Matrix([1, 1])]), (-1, 1, [Matrix([1, -1])])]
|
||||
|
||||
# Access individual eigenvectors
|
||||
for eigenval, multiplicity, eigenvecs in M.eigenvects():
|
||||
print(f"Eigenvalue: {eigenval}")
|
||||
print(f"Eigenvectors: {eigenvecs}")
|
||||
```
|
||||
|
||||
### Diagonalization
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [2, 1]])
|
||||
|
||||
# Check if diagonalizable
|
||||
M.is_diagonalizable() # True or False
|
||||
|
||||
# Diagonalize (M = P*D*P^-1)
|
||||
P, D = M.diagonalize()
|
||||
# P: matrix of eigenvectors
|
||||
# D: diagonal matrix of eigenvalues
|
||||
|
||||
# Verify
|
||||
P * D * P**-1 == M # True
|
||||
```
|
||||
|
||||
### Characteristic Polynomial
|
||||
|
||||
```python
|
||||
from sympy import symbols
|
||||
lam = symbols('lambda')
|
||||
|
||||
M = Matrix([[1, 2], [2, 1]])
|
||||
charpoly = M.charpoly(lam)
|
||||
# Returns characteristic polynomial
|
||||
```
|
||||
|
||||
### Jordan Normal Form
|
||||
|
||||
```python
|
||||
M = Matrix([[2, 1, 0], [0, 2, 1], [0, 0, 2]])
|
||||
|
||||
# Jordan form (for non-diagonalizable matrices)
|
||||
P, J = M.jordan_form()
|
||||
# J is the Jordan normal form
|
||||
# P is the transformation matrix
|
||||
```
|
||||
|
||||
## Matrix Decompositions
|
||||
|
||||
### LU Decomposition
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]])
|
||||
|
||||
# LU decomposition
|
||||
L, U, perm = M.LUdecomposition()
|
||||
# L: lower triangular
|
||||
# U: upper triangular
|
||||
# perm: permutation indices
|
||||
```
|
||||
|
||||
### QR Decomposition
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [3, 4], [5, 6]])
|
||||
|
||||
# QR decomposition
|
||||
Q, R = M.QRdecomposition()
|
||||
# Q: orthogonal matrix
|
||||
# R: upper triangular matrix
|
||||
```
|
||||
|
||||
### Cholesky Decomposition
|
||||
|
||||
```python
|
||||
# For positive definite symmetric matrices
|
||||
M = Matrix([[4, 2], [2, 3]])
|
||||
|
||||
L = M.cholesky()
|
||||
# L is lower triangular such that M = L*L.T
|
||||
```
|
||||
|
||||
### Singular Value Decomposition (SVD)
|
||||
|
||||
```python
|
||||
M = Matrix([[1, 2], [3, 4], [5, 6]])
|
||||
|
||||
# SVD (note: may require numerical evaluation)
|
||||
U, S, V = M.singular_value_decomposition()
|
||||
# M = U * S * V
|
||||
```
|
||||
|
||||
## Solving Linear Systems
|
||||
|
||||
### Using Matrix Equations
|
||||
|
||||
```python
|
||||
# Solve Ax = b
|
||||
A = Matrix([[1, 2], [3, 4]])
|
||||
b = Matrix([5, 6])
|
||||
|
||||
# Solution
|
||||
x = A.solve(b) # or A**-1 * b
|
||||
|
||||
# Least squares (for overdetermined systems)
|
||||
x = A.solve_least_squares(b)
|
||||
```
|
||||
|
||||
### Using linsolve
|
||||
|
||||
```python
|
||||
from sympy import linsolve, symbols
|
||||
|
||||
x, y = symbols('x y')
|
||||
|
||||
# Method 1: List of equations
|
||||
eqs = [x + y - 5, 2*x - y - 1]
|
||||
sol = linsolve(eqs, [x, y])
|
||||
# {(2, 3)}
|
||||
|
||||
# Method 2: Augmented matrix
|
||||
M = Matrix([[1, 1, 5], [2, -1, 1]])
|
||||
sol = linsolve(M, [x, y])
|
||||
|
||||
# Method 3: A*x = b form
|
||||
A = Matrix([[1, 1], [2, -1]])
|
||||
b = Matrix([5, 1])
|
||||
sol = linsolve((A, b), [x, y])
|
||||
```
|
||||
|
||||
### Underdetermined and Overdetermined Systems
|
||||
|
||||
```python
|
||||
# Underdetermined (infinite solutions)
|
||||
A = Matrix([[1, 2, 3]])
|
||||
b = Matrix([6])
|
||||
sol = A.solve(b) # Returns parametric solution
|
||||
|
||||
# Overdetermined (least squares)
|
||||
A = Matrix([[1, 2], [3, 4], [5, 6]])
|
||||
b = Matrix([1, 2, 3])
|
||||
sol = A.solve_least_squares(b)
|
||||
```
|
||||
|
||||
## Symbolic Matrices
|
||||
|
||||
### Working with Symbolic Entries
|
||||
|
||||
```python
|
||||
from sympy import symbols, Matrix
|
||||
|
||||
a, b, c, d = symbols('a b c d')
|
||||
M = Matrix([[a, b], [c, d]])
|
||||
|
||||
# All operations work symbolically
|
||||
M.det() # a*d - b*c
|
||||
M.inv() # Matrix([[d/(a*d - b*c), -b/(a*d - b*c)], ...])
|
||||
M.eigenvals() # Symbolic eigenvalues
|
||||
```
|
||||
|
||||
### Matrix Functions
|
||||
|
||||
```python
|
||||
from sympy import exp, sin, cos, Matrix
|
||||
|
||||
M = Matrix([[0, 1], [-1, 0]])
|
||||
|
||||
# Matrix exponential
|
||||
exp(M)
|
||||
|
||||
# Trigonometric functions
|
||||
sin(M)
|
||||
cos(M)
|
||||
```
|
||||
|
||||
## Mutable vs Immutable Matrices
|
||||
|
||||
```python
|
||||
from sympy import Matrix, ImmutableMatrix
|
||||
|
||||
# Mutable (default)
|
||||
M = Matrix([[1, 2], [3, 4]])
|
||||
M[0, 0] = 5 # Allowed
|
||||
|
||||
# Immutable (for use as dictionary keys, etc.)
|
||||
I = ImmutableMatrix([[1, 2], [3, 4]])
|
||||
# I[0, 0] = 5 # Error: ImmutableMatrix cannot be modified
|
||||
```
|
||||
|
||||
## Sparse Matrices
|
||||
|
||||
For large matrices with many zero entries:
|
||||
|
||||
```python
|
||||
from sympy import SparseMatrix
|
||||
|
||||
# Create sparse matrix
|
||||
S = SparseMatrix(1000, 1000, {(0, 0): 1, (100, 100): 2})
|
||||
# Only stores non-zero elements
|
||||
|
||||
# Convert dense to sparse
|
||||
M = Matrix([[1, 0, 0], [0, 2, 0]])
|
||||
S = SparseMatrix(M)
|
||||
```
|
||||
|
||||
## Common Linear Algebra Patterns
|
||||
|
||||
### Pattern 1: Solving Ax = b for Multiple b Vectors
|
||||
|
||||
```python
|
||||
A = Matrix([[1, 2], [3, 4]])
|
||||
A_inv = A.inv()
|
||||
|
||||
b1 = Matrix([5, 6])
|
||||
b2 = Matrix([7, 8])
|
||||
|
||||
x1 = A_inv * b1
|
||||
x2 = A_inv * b2
|
||||
```
|
||||
|
||||
### Pattern 2: Change of Basis
|
||||
|
||||
```python
|
||||
# Given vectors in old basis, convert to new basis
|
||||
old_basis = [Matrix([1, 0]), Matrix([0, 1])]
|
||||
new_basis = [Matrix([1, 1]), Matrix([1, -1])]
|
||||
|
||||
# Change of basis matrix
|
||||
P = Matrix.hstack(*new_basis)
|
||||
P_inv = P.inv()
|
||||
|
||||
# Convert vector v from old to new basis
|
||||
v = Matrix([3, 4])
|
||||
v_new = P_inv * v
|
||||
```
|
||||
|
||||
### Pattern 3: Matrix Condition Number
|
||||
|
||||
```python
|
||||
# Estimate condition number (ratio of largest to smallest singular value)
|
||||
M = Matrix([[1, 2], [3, 4]])
|
||||
eigenvals = M.eigenvals()
|
||||
cond = max(eigenvals.keys()) / min(eigenvals.keys())
|
||||
```
|
||||
|
||||
### Pattern 4: Projection Matrices
|
||||
|
||||
```python
|
||||
# Project onto column space of A
|
||||
A = Matrix([[1, 0], [0, 1], [1, 1]])
|
||||
P = A * (A.T * A).inv() * A.T
|
||||
# P is projection matrix onto column space of A
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **Zero-testing:** SymPy's symbolic zero-testing can affect accuracy. For numerical work, consider using `evalf()` or numerical libraries.
|
||||
|
||||
2. **Performance:** For large numerical matrices, consider converting to NumPy using `lambdify` or using numerical linear algebra libraries directly.
|
||||
|
||||
3. **Symbolic computation:** Matrix operations with symbolic entries can be computationally expensive for large matrices.
|
||||
|
||||
4. **Assumptions:** Use symbol assumptions (e.g., `real=True`, `positive=True`) to help SymPy simplify matrix expressions correctly.
|
||||
Reference in New Issue
Block a user