【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}$ を辺とする平行四辺形の面積を表すことが知られています。
しかし、$\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*}\]
こんな式を覚えられるわけないので、以下の図に示すように行列式のを二つ重ねて、対角線上の積をつくって合計します。
ただし、左上から右下にとる積はプラス、右上から左下にとる積はマイナスの符号をつけて計算します。この計算法を サラスの方法 (Sarrus’ rule) とよびます。
3次元ベクトルの線形結合
3 次元のベクトルで作られる行列式は、3 つのベクトルが作る立体の体積を表します。
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*}\]
各項は次のような手順で作られます。
符号は +, -, + のように交互に並べます。上の例では 1 行目を使いましたが、係数はどの行または列を選んでも構いません。大きなサイズの行列式についても、同じように次元を 1 つ下げた行列式を使って展開できるので、展開を繰り返すことによって最終的には 2 次元行列式の計算に帰着できます。
コメント