【Pythonで学ぶ線形代数学講座(22)】余因子と余因子行列
余因子と余因子行列
すでに $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()を使って計算した逆行列と比較しています。
コメント