关键词:线性代数 / 矩阵 / 行列式
矩阵作为绝大多数算法的算子,当矩阵里的数字被赋予了意义,例如每个 row 表示了一个线性方程式,那么如果把这些线性方程用向量的形式在 xyz 空间坐标中表示,从几何角度解释的话,行列式值就可以是这些向量所夹出的一个平行四边形面积,或者平行六面体的体积,甚至是一些更高维度没办法具体表但又类似前两者的一个抽象概念。这回小编要用 Python 的视角重新帮大家复习一下行列式的基本定义,并且用代码来证明行列式计算过程中的重要性质!
import numpy as np
import numpy as np
如果还没安装过numpy
,可以使用下面指令在终端快速安装。
pip install numpy
pip install numpy
行列式 Determinant
若 A 为 n 阶方阵,如下定义:
A 的行列式值则为:
A = np.random.randint(0, 9, 9)
A = A.reshape(3, 3)
print(A)
print(np.linalg.det(A))
A = np.random.randint(0, 9, 9)
A = A.reshape(3, 3)
print(A)
print(np.linalg.det(A))
输出 (1):
[[2, 3, 1],
[0, 5, 6],
[5, 5, 4]]
输出 (1):
[[2, 3, 1],
[0, 5, 6],
[5, 5, 4]]
输出 (2):
44.99999999999999
输出 (2):
44.99999999999999
p.s. 注意只有方阵才能计算行列式值,否则程序报错。
B = np.random.randint(0, 6, 12)
B = B.reshape(4, 3)
print(B)
print(np.linalg.det(B))
B = np.random.randint(0, 6, 12)
B = B.reshape(4, 3)
print(B)
print(np.linalg.det(B))
输出 (1):
[[4, 2, 4],
[3, 0, 0],
[2, 0, 2],
[4, 3, 2]]
输出 (1):
[[4, 2, 4],
[3, 0, 0],
[2, 0, 2],
[4, 3, 2]]
输出 (2):
/Python/Versions/3.6/lib/python3.6/site-packages/numpy/linalg/linalg.py in _assertNdSquareness(*arrays)
211 m, n = a.shape[-2:]
212 if m != n:
--> 213 raise LinAlgError('Last 2 dimensions of the array must be square')
214
215 def _assertFinite(*arrays):
LinAlgError: Last 2 dimensions of the array must be square
输出 (2):
/Python/Versions/3.6/lib/python3.6/site-packages/numpy/linalg/linalg.py in _assertNdSquareness(*arrays)
211 m, n = a.shape[-2:]
212 if m != n:
--> 213 raise LinAlgError('Last 2 dimensions of the array must be square')
214
215 def _assertFinite(*arrays):
LinAlgError: Last 2 dimensions of the array must be square
1. 子行列式 - Minor
若将 A 方阵中的第 i 列与第 j 行删除,所剩下的 n-1 阶方阵的行列式,称为元素 的子行列式,以 表示。
def minor(mat, row=1, col=1):
mat = np.delete(mat, row, axis=0)
mat = np.delete(mat, col, axis=1)
return mat
print(minor(A, 0, 0))
print(minor(A, 1, 0))
print(np.linalg.det(minor(A, 1, 0)))
def minor(mat, row=1, col=1):
mat = np.delete(mat, row, axis=0)
mat = np.delete(mat, col, axis=1)
return mat
print(minor(A, 0, 0))
print(minor(A, 1, 0))
print(np.linalg.det(minor(A, 1, 0)))
输出 (1):
[[5, 6],
[5, 4]]
输出 (1):
[[5, 6],
[5, 4]]
输出 (2):
[[3, 1],
[5, 4]]
输出 (2):
[[3, 1],
[5, 4]]
输出 (3):
7.000000000000001
输出 (3):
7.000000000000001
2. 余因式 - cofactor
在行列式中元素 的余因式定义为:
def cofactor(mat, row, col):
val = np.linalg.det(minor(mat, row, col))
return ((-1) ** (row + col)) * val
print(cofactor(A, 0, 0))
print(cofactor(A, 1, 0))
def cofactor(mat, row, col):
val = np.linalg.det(minor(mat, row, col))
return ((-1) ** (row + col)) * val
print(cofactor(A, 0, 0))
print(cofactor(A, 1, 0))
输出 (1):
-9.999999999999998
输出 (1):
-9.999999999999998
输出 (2):
-7.000000000000001
输出 (2):
-7.000000000000001
3. 行列式展开
- 某元素与该元素余因式 (cofactor) 的乘积和为行列式值
- 行列式值可由任一列 (row) 展开求的
- 行列式值可由任一行 (column) 展开求的
def determinant(mat):
val = 0
for i in range(mat.shape[0]):
val += mat[i, 0] * cofactor(mat, i, 0)
return val
print(determinant(A))
print(np.linalg.det(A))
def determinant(mat):
val = 0
for i in range(mat.shape[0]):
val += mat[i, 0] * cofactor(mat, i, 0)
return val
print(determinant(A))
print(np.linalg.det(A))
输出 (1):
45.0
输出 (1):
45.0
输出 (2):
44.99999999999999
输出 (2):
44.99999999999999
4. 行列式基本性质
4-1
若行列式中有某一列 or 行 的元素全为 0,则行列式值为 0。
print(determinant(
np.array([[0, 0, 0],
[2, 8, 4],
[5, 5, 9]])
)))
print(determinant(
np.array([[0, 0, 0],
[2, 8, 4],
[5, 5, 9]])
)))
输出:
0.0
输出:
0.0
4-2
若行列式中有某一列 or 行 的元素都乘以 k 倍,则行列式值为原行列式的 k 倍。
4-3
若方阵 A 的行列式乘以 k 倍,可把 k 放到任意列 or 行中。
print(A[:, 2] = A[:, 2] * 5)
print(determinant(A))
print(A[:, 2] = A[:, 2] * 5)
print(determinant(A))
输出:
225.0000000000002
输出:
225.0000000000002
4-4
若方阵为上三角 or 下三角矩阵,则该矩阵的行列式值为主对角元素的乘积。
print(determinant(np.triu(A)))
print(determinant(np.tril(A)))
print(determinant(np.triu(A)))
print(determinant(np.tril(A)))
输出 (1):
199.99999999999991
输出 (1):
199.99999999999991
输出 (2):
199.99999999999991
输出 (2):
199.99999999999991
4-5
若方阵中的任意两列 or 行互换位置,则相对应的行列式值为相反数 (差一个负号)。
from copy import copy
c = copy(A[0, :])
A[0, :] = A[1, :]
A[1, :] = c
print(determinant(A))
from copy import copy
c = copy(A[0, :])
A[0, :] = A[1, :]
A[1, :] = c
print(determinant(A))
输出:
-225.0000000000002
输出:
-225.0000000000002
4-6
若方阵中任意两列 or 行的元素皆相同,则行列式值为零
print(determinant(
np.array([[1, 2, 3],
[1, 2, 3],
[7, 8, 5]])
))
print(determinant(
np.array([[1, 2, 3],
[1, 2, 3],
[7, 8, 5]])
))
输出:
0.0
输出:
0.0
4-7
若方阵任意两列 or 行的元素成比例,则行列式值为零
print(determinant(
np.array([[1, 2, 3],
[2, 4, 6],
[7, 10, 9]])
))
print(determinant(
np.array([[1, 2, 3],
[2, 4, 6],
[7, 10, 9]])
))
输出:
-3.552713678800501e-15
输出:
-3.552713678800501e-15
4-8
若 A 与 B 两方阵中除了第 k 列 or 行之外,其他列 or 行的元素皆相同,且 D 方阵中除了第 k 列 or 行为 A 与 B 两方阵第 k 列 or 行的元素和,并且其他元素皆与 A 和 B 相同时,则:
4-9
A 方阵中的第 i 列 or 行乘以 k 倍后,加到第 j 列 or 行中得到的新方阵,行列式值仍然为 |A|。
from copy import copy
c = copy(A[0, :])
# k = 10 in this case.
A[0, :] += A[1, :] * 10
print(determinant(A))
from copy import copy
c = copy(A[0, :])
# k = 10 in this case.
A[0, :] += A[1, :] * 10
print(determinant(A))
输出:
-225.0
输出:
-225.0
4-10
方阵 A 的行列式值与其转置矩阵的行列式值相同。
print((determinant(A),
determinant(A.T)))
print((determinant(A),
determinant(A.T)))
输出:
(-225.0, -224.99999999999994)
输出:
(-225.0, -224.99999999999994)
4-11
若 A 与 B 皆为 n 阶方阵,则
C = np.random.randint(1, 9, 9).reshape(3, 3)
D = np.random.randint(1, 9, 9).reshape(3, 3)
print(determinant(np.dot(C, D)))
print(determinant(C) * determinant(D))
C = np.random.randint(1, 9, 9).reshape(3, 3)
D = np.random.randint(1, 9, 9).reshape(3, 3)
print(determinant(np.dot(C, D)))
print(determinant(C) * determinant(D))
输出 (1):
4050.0000000000146
输出 (1):
4050.0000000000146
输出 (2):
4050.0
输出 (2):
4050.0
4-12
若 A 为 n 阶方阵,k 为常数,则 。
print(determinant(2 * A))
print((2 ** A.shape[0]) *
determinant(A))
print(determinant(2 * A))
print((2 ** A.shape[0]) *
determinant(A))
输出 (1):
-1800.0
输出 (1):
-1800.0
输出 (2):
-1800.0
输出 (2):
-1800.0
4-13
若 A 为 n 阶方阵,则 det(A) 对变数 x 的微分为割裂元素微分的行列式值之和。
4-14
行列式值里面的元素可以另外视为一个矩阵做为行列式值的运算。
G = np.array([[1, 2, 7, 8, 5],
[4, 9, 6, 4, 3],
[0, 0, 1, 2, 3],
[0, 0, 4, 5, 7],
[0, 0, 8, 1, 6]])
print(determinant(G))
print(determinant(G[:2, :2]) *
determinant(G[2:, 2:]))
G = np.array([[1, 2, 7, 8, 5],
[4, 9, 6, 4, 3],
[0, 0, 1, 2, 3],
[0, 0, 4, 5, 7],
[0, 0, 8, 1, 6]])
print(determinant(G))
print(determinant(G[:2, :2]) *
determinant(G[2:, 2:]))
输出 (1):
-21.0
输出 (1):
-21.0
输出 (2):
-21.000000000000032
输出 (2):
-21.000000000000032
4-15
若 A 与 B 为 n 阶方阵,则:
H = np.array([[1, 2, 7, 8],
[4, 9, 6, 4],
[7, 8, 1, 2],
[6, 4, 4, 9]])
print(determinant(H))
print(determinant(H[:2, :2] + H[2:, :2]) *
determinant(H[:2, :2] - H[2:, :2]))
H = np.array([[1, 2, 7, 8],
[4, 9, 6, 4],
[7, 8, 1, 2],
[6, 4, 4, 9]])
print(determinant(H))
print(determinant(H[:2, :2] + H[2:, :2]) *
determinant(H[:2, :2] - H[2:, :2]))
输出 (1):
-168.00000000000023
输出 (1):
-168.00000000000023
输出 (2):
-167.99999999999937
输出 (2):
-167.99999999999937
4-16
计算一个矩阵是由多少个不同的方向向量所组成,该量又称为 秩
(rank).
print(np.linalg.matrix_rank(A))
print(np.linalg.matrix_rank(A))
输出:
3
输出:
3