『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

行列式の計算手順

【Pythonで学ぶ線形代数学講座(7)】行列式の定義とサラスの方法

行列式の定義

前回記事で扱った $v_1w_2-v_2w_1$ は線形代数において重要な意味をもつ量であり、
 \[\mathrm{det}(\boldsymbol{v},\boldsymbol{w})=\begin{vmatrix}v_1 & w_1\\v_2 & w_2\end{vmatrix}\tag{2}\]
のように書いて行列式(determinant)とよびます。計算するときは対角要素の積をつくってから差をとります。大事なことなので繰り返し述べますが、$\mathrm{det}(\boldsymbol{v},\boldsymbol{w})\neq 0$ のとき、$\boldsymbol{v}$ と $\boldsymbol{w}$ は線形独立であり、この 2 つのベクトルで平面を張ることができます。

線形独立と行列式の関係を幾何学的に考えてみます。
$\mathrm{det}(\boldsymbol{v},\boldsymbol{w})$ は $\boldsymbol{v}$ と $\boldsymbol{w}$ を辺とする平行四辺形の面積を表すことが知られています。
2次元行列式 determinant の幾何学的定義
しかし、$\boldsymbol{v}$ と $\boldsymbol{w}$ が線形従属(平行)であるときは、この平行四辺形は潰れてしまって面積は $0$ になってしまいます。したがって、$\boldsymbol{v}$ と $\boldsymbol{w}$ が線形独立であることは、$\mathrm{det}(\boldsymbol{v},\boldsymbol{w})$ が $0$ 以外の値をもつことに対応します。

scipy.linalg.det()

行列式は scipy.linalg.det() を使って計算できます。

# python_determinant_1

# In[1]

import numpy as np
from scipy.linalg import det

# 配列を定義
x = np.array([[ 5, 2],
              [-3, 4]])

# 行列式を計算
det_x = det(x)

print(det_x)
# 26.0

サラスの方法

線形独立と行列式の関係は 3 次元ベクトルにも拡張できます。
3 次元空間における行列式は以下の式で与えられます。
 \[\begin{align*}\mathrm{det}(\boldsymbol{u},\boldsymbol{v},\boldsymbol{w})&=\begin{vmatrix}u_1 & v_1 & w_1\\u_2 & v_2 & w_2\\u_3 & v_3 & w_3\end{vmatrix}\\[6pt]&=u_1v_2w_3+u_2v_3w_1+u_3v_1w_2-u_1v_3w_2-u_2v_1w_3-u_2v_1w_3\end{align*}\]
こんな式を覚えられるわけないので、以下の図に示すように行列式のを二つ重ねて、対角線上の積をつくって合計します。
Python サラスの方法 (Sarrus' rule)
ただし、左上から右下にとる積はプラス、右上から左下にとる積はマイナスの符号をつけて計算します。この計算法を サラスの方法 (Sarrus’ rule) とよびます。

3次元ベクトルの線形結合

3 次元のベクトルで作られる行列式は、3 つのベクトルが作る立体の体積を表します。
3次元行列式 determinant の幾何学的意味
3 つのベクトルが同じ平面内にあるとき (線形従属の関係にあるとき) には、立体は潰れてしまって体積は $0$ になります。$\boldsymbol{u},\ \boldsymbol{v},\ \boldsymbol{w}$ で空間を張ることができる (線形独立の関係にある) のは、行列式の値が $0$ 以外の値をとるときです。

行列式の計算手順

 実際に行列式を計算するときは、サラスの方法を使う前に、明らかに行列式が $0$ にならないかを確認します。たとえば、
 \[\mathrm{det}A=\begin{vmatrix}2 & 4 & 5\\1 & 2 & 5\\4 & 8 & 3\end{vmatrix}\]
という行列式は、2 列目のベクトルが 1 列目のベクトルの 2 倍になっています。つまり平行なベクトルが含まれているので、この行列式は計算するまでもなく $\mathrm{det}A=0$ だとわかります。
 
あるベクトルの成分に共通の約数があれば行列式の外に出します(詳しくは次回記事 行列式の線形性 で扱います)。すなわち成分の最大公約数を見つけます。たとえば、
 \[\mathrm{det}B=\begin{vmatrix}1 & 5 & 12\\7 & 0 & 16\\9 & 5 & 8\end{vmatrix}\]
の 2 列目の最大公約数は $5$, 3 列目の成分の最大公約数は $4$ なので、この行列式は
 \[\mathrm{det}B=4\cdot 5\begin{vmatrix}1 & 1 & 3\\7 & 0 & 4\\9 & 1 & 2\end{vmatrix}=20\times 39=780\]
のように計算できます。

n次元ベクトルの線形結合

2 次元と 3 次元で展開された議論はそのまま $n$ 次元空間に拡張されます。
$n$ 組の $n$ 次元ベクトルが $n$ 次元空間を張るための条件は、互いに線形独立の関係にあること、すなわち、$n$ 組の $n$ 次元ベクトルから作られた行列式が $0$ 以外の値をとることです。
次元が増えると、もはや紙の上での計算では手に負えなくなるので、コンピュータの力を借りることになります。scipy.linalg.det() を使って、10 次元の行列式の値を計算してみましょう。各成分は np.random.randint() を使って 0 ~ 9 の範囲で無作為に決定します。

# python_determinant_2

# In[1]

import numpy as np
from scipy.linalg import det

# 乱数シードを設定
np.random.seed(10)

# 10次元ベクトルを10個格納した2次元配列
# [[5 0 3 3 7 9 3 5 2 4]
#  [7 6 8 8 1 6 7 7 8 1]
#  [5 9 8 9 4 3 0 3 5 0]
#  [2 3 8 1 3 3 3 7 0 1]
#  [9 9 0 4 7 3 2 7 2 0]
#  [0 4 5 5 6 8 4 1 4 9]
#  [8 1 1 7 9 9 3 6 7 2]
#  [0 3 5 9 4 4 6 4 4 3]
#  [4 4 8 4 3 7 5 5 0 1]
#  [5 9 3 0 5 0 1 2 4 2]]
x = np.random.randint(0, 10, (10, 10))

# 行列式の値を計算
det_x = det(x)

print("{:.3e}".format(det_x))
# 5.825e+07

$5.825\times 10^7$ という大きな桁の数が表示されました。
言うまでもなく、上のコードで設定したベクトルは互いに線形独立です。
次元が大きい場合、ランダムに成分を決めても、線形従属なベクトルの組は滅多に出現しないようです。行列式の値はプラス側にもマイナス側にも大きく振れます。上のコードで seed を 10 に設定すると $-2.982\times 10^8$ となります。
 
同じように、3 次元で 0 ~ 9 の範囲のランダム成分をもつ行列式を 10 万個つくって、そのうち何個が 0 になるか調べてみました。

# In[2]

# 乱数シードを設定
np.random.seed(0)

# カウント数の初期値
ct = 0

# 無作為な3次元行列式を10万個作成して値を計算
for k in range(10**5):
    x = np.random.randint(0, 10, (3, 3))
    if det(x) == 0:
        ct += 1
        
print("行列式が0になった個数:{}".format(ct))
# 行列式が0になった個数:1785

結果は 1785 個です。seed を変えて計算しても、概ね 1700 個前後でした。おおよそ 100 個のうち 2 個程度が線形従属の関係にあるベクトルの組となります。

行列式の展開

行列式を計算する別の手段として、行展開(または列展開)があります。たとえば、3 次元行列式は以下のように展開できることが知られています。
 \[\begin{align*}\begin{vmatrix}u_1 & v_1 & w_1\\u_2 & v_2 & w_2\\u_3 & v_3 & w_3\end{vmatrix}&=u_1\begin{vmatrix}v_2 & w_2 \\ v_3 & w_3\end{vmatrix}-v_1\begin{vmatrix}u_2 & w_2 \\ u_3 & w_3\end{vmatrix}+w_1\begin{vmatrix}u_2 & v_2 \\ u_3 & v_3\end{vmatrix}\end{align*}\]
各項は次のような手順で作られます。
 
Python 行列式の展開 (expand determinant)
符号は +, -, + のように交互に並べます。上の例では 1 行目を使いましたが、係数はどの行または列を選んでも構いません。大きなサイズの行列式についても、同じように次元を 1 つ下げた行列式を使って展開できるので、展開を繰り返すことによって最終的には 2 次元行列式の計算に帰着できます。

コメント