余因子#

n次の正方行列A=(aij)から、第i行と第j列を取り除いて得られるn1次の正方行列をAijと書く。

a~ij=(1)i+j|Aij|

を行列Aにおけるaij余因子(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行に関する余因子展開: ai1a~i1+ai2a~i2++aina~in=|A|

  • j列に関する余因子展開: a1ja~1j+a2ja~2j++anja~nj=|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=(aij)の余因子をa~ijとするとき、(i,j)成分に余因子a~ijをもつ行列の転置行列

A~=(a~11a~21a~n1a~12a~22a~n2a~1na~2na~nn)

余因子行列(adjugate matrix)といい、adj(A)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)

余因子行列の性質#

AA~=(|A|OO|A|)=|A|I

行列 AA~ の第 (i,k) 成分は j=1naija~kj である。

  • ai1a~i1+ai2a~i2++aina~in=|A| (第 i 行に関する余因子展開)

  • ai1a~k1+ai2a~k2++aina~kn=0(ki)

を利用すれば, $j=1naija~kj={|A|(i=k)0(ik)$

となる. これより,

AA~=(|A|OO|A|)=|A|I

を得る

(参考:線形代数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次正方行列An次の単位行列Iに対し、

AA1=A1A=I

を満たす行列A1を求める。

AA~=|A|I

より

A1|A|A~A1=I

よって

A1=1|A|A~