余因子と余因子行列
すでに $2\times 2$ の逆行列については学んでいますが、サイズの大きな行列の逆行列を求めることは簡単ではありません。一般に逆行列を求める手順として、「掃き出し法」と「余因子行列を用いる方法」があります。この記事では余因子行列について解説します。
小行列式
$n$ 次の正方行列 $A$ について、$i$ 行目と $j$ 列目を取り除いて作った行列の行列式を $A$ の 小行列式 (minor determinant) とよび、$M_{ij}$ のように表します。たとえば、
\[A=\begin{bmatrix}2&7&3\\5&0&9\\3&1&4\end{bmatrix}\tag{1}\]
の小行列式 $M_{12}$ は
\[M_{12}=\begin{vmatrix}5&9\\3&4\end{vmatrix}=-7\tag{2}\]
となります。
余因子
小行列式 $M_{ij}$ に $(-1)^{i+j}$ を掛けた値を $A$ の 余因子 (cofactor) とよび、$A_{ij}$ で表します。
\[A_{ij}=(-1)^{i+j}M_{ij}\tag{3}\]
$i+j$ が偶数のときは $(-1)^{i+j}=1$ なので、余因子は小行列式と同じ値をもちます。
$i+j$ が奇数のときは $(-1)^{i+j}=-1$ なので、余因子は小行列式の符号を反転させた値となります。
cofactor()
NumPy で余因子と小行列式を求める cofactor()関数を定義しておきます。
# Python_Cofactor
# In[1]
import numpy as np
# 余因子または小行列式を求める関数
def cofactor(a, i, j, minor = False):
x = np.delete(a, i, axis = 0)
x = np.delete(x, j, axis = 1)
if minor == False:
a_ij = (-1)**(i + j) * np.linalg.det(x)
else:
a_ij = np.linalg.det(x)
return a_ij
この関数はデフォルトで a の余因子を返すようになっています。
引数 minor に True を指定すると小行列式を返します。
引数 i, j には、それぞれ消去する行と列を渡しますが、NumPy のインデックスの数え方に合わせているので、たとえば 1 行目と 2 列目を消去する場合は、i = 0, j = 1 を渡します。
# In[2]
# 行列aを定義
a = np.array([[2, 7, 3],
[5, 0, 9],
[3, 1, 4]])
# 0行目と1列目を取り除いた小行列式
m_ij = cofactor(a, 0, 1, minor = True)
# 0行目と1列目を取り除いた余因子
a_ij = cofactor(a, 0, 1)
print("m_ij : {:.3f}".format(m_ij))
print("a_ij : {:.3f}".format(a_ij))
# m_ij : -7.000
a_ij : 7.000
余因子行列と逆行列
$A$ の余因子 $A_{ij}$ を $(j,i)$ 成分にもつ行列 $\tilde{A}$ を余因子行列とよびます。
\[\tilde{A}=\begin{bmatrix}A_{11}&A_{21} &\cdots &A_{n1}\\A_{12}&A_{22} &\cdots &A_{n2}\\\vdots & \vdots &\ddots &\vdots\\A_{1n}&A_{2n} &\cdots &A_{nn}\end{bmatrix}\tag{4}\]
証明は省略しますが、$A$ の逆行列 $A^{-1}$ は余因子行列によって、
\[A^{-1}=\frac{1}{\mathrm{det}A}\tilde{A}\tag{5}\]
で与えられます。(1) で定義した行列
\[A=\begin{bmatrix}2&7&3\\5&0&9\\3&1&4\end{bmatrix}\tag{1}\]
の逆行列を求めてみましょう。手計算だとうんざりすると思うので、先ほど定義した cofactor()関数を使いましょう。
# In[3]
# すべての成分が0の3×3行列を生成
a_ij = np.zeros((3, 3))
# 余因子行列を生成
for i in range(3):
for j in range(3):
a_ij[j, i] = cofactor(a, i, j)
# 余因子行列を使って逆行列を計算
a_inv_1 = a_ij / np.linalg.det(a)
# NumPyの関数を使って逆行列を計算
a_inv_2 = np.linalg.inv(a)
print("aの余因子行列\n{}\n".format(a_ij))
print("余因子行列を使って計算した逆行列\n{}\n".format(a_inv_1))
print("numpy.linalg.inv()を使って計算した逆行列\n{}".format(a_inv_2))
'''
aの余因子行列
[[ -9. -25. 63.]
[ 7. -1. -3.]
[ 5. 19. -35.]]
余因子行列を使って計算した逆行列
[[-0.19565217 -0.54347826 1.36956522]
[ 0.15217391 -0.02173913 -0.06521739]
[ 0.10869565 0.41304348 -0.76086957]]
numpy.linalg.inv()を使って計算した逆行列
[[-0.19565217 -0.54347826 1.36956522]
[ 0.15217391 -0.02173913 -0.06521739]
[ 0.10869565 0.41304348 -0.76086957]]
'''
コードの記述ミスがないように、numpy.linalg.inv()を使って計算した逆行列と比較しています。
余因子行列を対話形式で解説します
ChatGPTが余因子行列を対話形式で解説してくれました。
生徒: 先生、余因子行列って何ですか?聞いたことがあるけど、正確には何を指すのかわかりません。
先生: いいですよ、余因子行列について説明しますね。余因子行列は、行列の各要素に対してその余因子を要素とする新しい行列のことです。
生徒: 余因子って何ですか?
先生: 余因子は、行列の各要素に対してその要素を取り除いた残りの行列の行列式です。たとえば、3×3の行列において、ある要素の余因子は、その要素を取り除いた2×2の行列の行列式にマイナス1のべき乗をかけたものになります。
生徒: なるほど、それで余因子行列を作るんですね。でも、具体的な手順はどうなんですか?
先生: いい質問です。余因子行列を作る手順は次のようになります。まず、元の行列の各要素に対して、その要素の余因子を計算します。そのために、各要素を取り除いた残りの行列を作り、それに対して行列式を求めます。そして、それぞれの余因子を要素とする新しい行列を作ります。要素の位置によって正負が変わることに注意してください。
生徒: 分かりました。でも、それを使って何ができるんですか?
先生: 余因子行列は、いくつかの応用があります。たとえば、逆行列を求める際に使うことができます。行列式が非ゼロである場合、元の行列の逆行列は、余因子行列の転置行列を行列式で割ったものになります。また、連立一次方程式の解を求める際にも利用できます。余因子行列を使って連立方程式を解く方法は、クラメルの公式として知られています。
生徒: なるほど、逆行列や連立方程式の解を求めるのに使えるんですね。それは便利そうです。余因子行列についてもっと学びたいです。
先生: 素晴らしいですね。余因子行列は行列の重要な概念の一つですので、さらに学んでいくと数学の理解が深まりますよ。他の行列の性質や計算方法とも関連していますので、ぜひ探求してみてください。