余因子#
\(n\)次の正方行列\(A=(a_{ij})\)から、第\(i\)行と第\(j\)列を取り除いて得られる\(n-1\)次の正方行列を\(A_{ij}\)と書く。
を行列\(A\)における\(a_{ij}\)の余因子(cofactor)という。
# 例
import numpy as np
A = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 0],
])
# 第1行、第1列を除いたA_11行列
A11 = A[1:, 1:]
# 余因子
(-1)**(1 + 1) * np.linalg.det(A11)
-47.999999999999986
余因子展開(ラプラス展開)#
\(n\)次正方行列\(A\)の行列式\(\det(A)\)は、任意の行や列についての要素と余因子の重み付き和として展開できる。
第\(i\)行に関する余因子展開: \(a_{i 1} \tilde{a}_{i 1}+ a_{i 2} \tilde{a}_{i 2} +\cdots+a_{i n} \tilde{a}_{i n} = |A|\)
第\(j\)列に関する余因子展開: \(a_{1 j} \tilde{a}_{1 j}+ a_{2 j} \tilde{a}_{2 j} +\cdots+a_{n j} \tilde{a}_{n j} = |A|\)
これを余因子展開(cofactor expansion)やラプラス展開(Laplace expansion)という。
# 例
import numpy as np
A = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
])
def cofactor(A, i, j):
"""余因子を計算する関数"""
A_minor = np.delete(A, i, axis=0)
A_minor = np.delete(A_minor, j, axis=1)
return (-1)**(i + j) * np.linalg.det(A_minor)
def cofactor_expansion_along_i(A, i):
"""第i行に関する余因子展開による行列式の計算"""
result = 0
for j in range(A.shape[1]):
result += A[i, j] * cofactor(A, i=i, j=j)
return result
(cofactor_expansion_along_i(A, i=0) - np.linalg.det(A)) < 1e-3
True
余因子行列#
\(n\)次の正方行列\(A=(a_{ij})\)の余因子を\(\tilde{a}_{ij}\)とするとき、\((i, j)\)成分に余因子\(\tilde{a}_{ij}\)をもつ行列の転置行列
を余因子行列(adjugate matrix)といい、\(\text{adj}(A)\)や\(\tilde{A}\)と表す。(※添字が転置したような形になっているのに注意)
def cofactor_matrix(A):
"""余因子行列"""
C = np.zeros_like(A, dtype=np.float32)
for i in range(A.shape[0]):
for j in range(A.shape[1]):
C[i, j] = cofactor(A, i=i, j=j)
return C.T
A_tilde = cofactor_matrix(A)
A_tilde
array([[ -3., 6., -3.],
[ 6., -12., 6.],
[ -3., 6., -3.]], dtype=float32)
余因子行列の性質#
行列 \(A \tilde{A}\) の第 \((i, k)\) 成分は \(\sum_{j=1}^n a_{i j} \tilde{a}_{k j}\) である。
\(a_{i 1} \tilde{a}_{i 1}+a_{i 2} \tilde{a}_{i 2}+\cdots+a_{i n} \tilde{a}_{i n}=|A| \quad\) (第 \(i\) 行に関する余因子展開)
\(a_{i 1} \tilde{a}_{k 1}+a_{i 2} \tilde{a}_{k 2}+\cdots+a_{i n} \tilde{a}_{k n}=0 \quad(k \neq i)\)
を利用すれば, $\( \sum_{j=1}^n a_{i j} \tilde{a}_{k j}=\left\{\begin{array}{lc} |A| & (i=k) \\ 0 & (i \neq k) \end{array}\right. \)$
となる. これより,
を得る
(参考:線形代数1A 第10回 講義資料)
# i != k
def cofactor_expansion_not_along_i(A, i, k):
result = 0
for j in range(A.shape[1]):
print(f"A[{i}, {j}] = {A[i, j]}")
print(f"cofactor(A, i={k}, j={j}) = {cofactor(A, i=k, j=j)}")
result += A[i, j] * cofactor(A, i=k, j=j)
return result
round(cofactor_expansion_not_along_i(A, i=0, k=1), 3)
A[0, 0] = 1
cofactor(A, i=1, j=0) = 6.0
A[0, 1] = 2
cofactor(A, i=1, j=1) = -12.0
A[0, 2] = 3
cofactor(A, i=1, j=2) = 6.0
0.0
print(f"det(A) = {np.linalg.det(A):.0f}")
print(f"A @ A_tilde: \n{A @ A_tilde}")
det(A) = 0
A @ A_tilde:
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
逆行列の導出#
逆行列、すなわち\(n\)次正方行列\(A\)と\(n\)次の単位行列\(I\)に対し、
を満たす行列\(A^{-1}\)を求める。
より
よって