行列式(determinant)は、正方行列に対して定まるスカラー値で、行列の「本質的な性質」を一つの数値に凝縮したものです。$2 \times 2$ 行列の行列式は、2本のベクトルが張る 平行四辺形の符号付き面積 に対応し、$3 \times 3$ なら 平行六面体の符号付き体積 を表します。
行列式は、逆行列の存在判定、連立方程式の解(クラメルの公式)、固有値の計算、線形変換による面積・体積の変化率など、線形代数の至るところで登場します。物理学ではヤコビアン(座標変換の体積要素)として、機械学習では共分散行列の性質の把握として活用されます。
本記事の内容
- $2 \times 2$ 行列式の幾何学的意味(面積)
- 一般の $n$ 次行列式の定義(置換を用いた定義)
- 行列式の基本性質
- クラメルの公式
- Pythonでの計算と可視化
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
行列式とは
$2 \times 2$ 行列式の幾何学的意味
$2 \times 2$ 行列 $\bm{A} = \begin{pmatrix} a & b \\ c & d \end{pmatrix}$ の行列式は:
$$ \begin{equation} \det(\bm{A}) = ad – bc \end{equation} $$
この値は、列ベクトル $\bm{v}_1 = (a, c)^T$ と $\bm{v}_2 = (b, d)^T$ が張る 平行四辺形の符号付き面積 に等しいです。
- $\det(\bm{A}) > 0$:$\bm{v}_1$ から $\bm{v}_2$ へ反時計回り
- $\det(\bm{A}) < 0$:$\bm{v}_1$ から $\bm{v}_2$ へ時計回り
- $\det(\bm{A}) = 0$:2本のベクトルが平行(面積が0、線形従属)
$3 \times 3$ 行列式
$3 \times 3$ 行列 $\bm{A} = \begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{pmatrix}$ の行列式は:
$$ \begin{align} \det(\bm{A}) &= a_{11}(a_{22}a_{33} – a_{23}a_{32}) \\ &\quad – a_{12}(a_{21}a_{33} – a_{23}a_{31}) \\ &\quad + a_{13}(a_{21}a_{32} – a_{22}a_{31}) \end{align} $$
この値は、3本の列ベクトルが張る 平行六面体の符号付き体積 に対応します。
一般の $n$ 次行列式の数学的定義
置換
$\{1, 2, \ldots, n\}$ の 置換(permutation)とは、$\{1, 2, \ldots, n\}$ から $\{1, 2, \ldots, n\}$ への全単射 $\sigma$ のことです。$n$ 個の元の置換は全部で $n!$ 個あります。
置換 $\sigma$ の 符号(sign)$\mathrm{sgn}(\sigma)$ は、$\sigma$ が偶数回の互換(2つの元の入れ替え)の合成で表せるとき $+1$、奇数回なら $-1$ です。
行列式の定義
$n \times n$ 行列 $\bm{A} = (a_{ij})$ の 行列式 は:
$$ \begin{equation} \det(\bm{A}) = \sum_{\sigma \in S_n} \mathrm{sgn}(\sigma) \prod_{i=1}^{n} a_{i, \sigma(i)} \end{equation} $$
ここで $S_n$ は $\{1, 2, \ldots, n\}$ の置換全体の集合(対称群)です。
$2 \times 2$ の場合の確認
$S_2 = \{(1,2), (2,1)\}$ で、恒等置換 $\mathrm{id}: 1 \mapsto 1, 2 \mapsto 2$ の符号は $+1$、互換 $\tau: 1 \mapsto 2, 2 \mapsto 1$ の符号は $-1$ です。
$$ \begin{align} \det(\bm{A}) &= (+1) \cdot a_{11} a_{22} + (-1) \cdot a_{12} a_{21} \\ &= a_{11} a_{22} – a_{12} a_{21} \end{align} $$
確かに $ad – bc$ と一致します。
行列式の基本性質
$n \times n$ 行列 $\bm{A}, \bm{B}$ と $c \in \mathbb{R}$ に対して、以下の性質が成り立ちます。
性質1: 転置不変性
$$ \det(\bm{A}^T) = \det(\bm{A}) $$
行の性質と列の性質が対称であることを意味します。
性質2: 多重線形性
行列式は各行(または各列)に対して線形です。第 $i$ 行について:
$$ \det(\ldots, c\bm{r}_i + d\bm{r}_i’, \ldots) = c \det(\ldots, \bm{r}_i, \ldots) + d \det(\ldots, \bm{r}_i’, \ldots) $$
性質3: 交代性
2つの行(または列)を入れ替えると、行列式の符号が反転します。
$$ \det(\ldots, \bm{r}_i, \ldots, \bm{r}_j, \ldots) = -\det(\ldots, \bm{r}_j, \ldots, \bm{r}_i, \ldots) $$
系: 同じ行(または列)が2つあれば $\det(\bm{A}) = 0$ です。
性質4: 積の行列式
$$ \begin{equation} \det(\bm{A}\bm{B}) = \det(\bm{A}) \cdot \det(\bm{B}) \end{equation} $$
性質5: スカラー倍
$$ \det(c\bm{A}) = c^n \det(\bm{A}) $$
性質6: 逆行列の行列式
$$ \det(\bm{A}^{-1}) = \frac{1}{\det(\bm{A})} \quad (\det(\bm{A}) \neq 0) $$
性質7: 三角行列の行列式
上三角行列(または下三角行列)の行列式は、対角成分の積に等しいです。
$$ \det(\bm{A}) = a_{11} a_{22} \cdots a_{nn} $$
性質8: 行基本変形と行列式
| 変形 | 行列式への影響 |
|---|---|
| 行の入れ替え | 符号反転($-1$ 倍) |
| 行のスカラー倍 | $c$ 倍 |
| ある行に別の行のスカラー倍を加える | 変化なし |
行列式と逆行列の関係
$n \times n$ 行列 $\bm{A}$ に対して:
$$ \bm{A} \text{ が正則(逆行列が存在)} \iff \det(\bm{A}) \neq 0 $$
証明の概略:
$\bm{A}$ が正則 $\Rightarrow$ $\bm{A}\bm{A}^{-1} = \bm{I}$ なので $\det(\bm{A})\det(\bm{A}^{-1}) = \det(\bm{I}) = 1$。よって $\det(\bm{A}) \neq 0$。
$\det(\bm{A}) \neq 0$ $\Rightarrow$ $\bm{A}$ の列ベクトルが線形独立 $\Rightarrow$ $\bm{A}$ は正則。
クラメルの公式
連立方程式 $\bm{A}\bm{x} = \bm{b}$ において $\det(\bm{A}) \neq 0$ のとき、解は:
$$ \begin{equation} x_i = \frac{\det(\bm{A}_i)}{\det(\bm{A})}, \quad i = 1, 2, \ldots, n \end{equation} $$
ここで $\bm{A}_i$ は $\bm{A}$ の第 $i$ 列を $\bm{b}$ で置き換えた行列です。
具体例
$$ \begin{cases} 2x + y = 5 \\ x + 3y = 7 \end{cases} $$
$$ \bm{A} = \begin{pmatrix} 2 & 1 \\ 1 & 3 \end{pmatrix}, \quad \bm{b} = \begin{pmatrix} 5 \\ 7 \end{pmatrix} $$
$$ \begin{align} \det(\bm{A}) &= 2 \cdot 3 – 1 \cdot 1 = 5 \\ \det(\bm{A}_1) &= \det \begin{pmatrix} 5 & 1 \\ 7 & 3 \end{pmatrix} = 15 – 7 = 8 \\ \det(\bm{A}_2) &= \det \begin{pmatrix} 2 & 5 \\ 1 & 7 \end{pmatrix} = 14 – 5 = 9 \end{align} $$
$$ x = \frac{8}{5} = 1.6, \quad y = \frac{9}{5} = 1.8 $$
Pythonでの実装
行列式の計算
import numpy as np
# 2x2 行列式
A = np.array([[2, 1],
[1, 3]], dtype=float)
det_A = np.linalg.det(A)
print(f"2x2 行列式: det(A) = {det_A:.4f}")
# 3x3 行列式
B = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 10]], dtype=float)
det_B = np.linalg.det(B)
print(f"3x3 行列式: det(B) = {det_B:.4f}")
# 行列式の性質の確認
C = np.array([[3, 1],
[2, 4]], dtype=float)
print(f"\n=== 行列式の性質 ===")
print(f"det(A) = {np.linalg.det(A):.4f}")
print(f"det(A^T) = {np.linalg.det(A.T):.4f}")
print(f"det(AB) = {np.linalg.det(A @ C):.4f}")
print(f"det(A)*det(C) = {np.linalg.det(A) * np.linalg.det(C):.4f}")
print(f"det(2A) = {np.linalg.det(2*A):.4f}")
print(f"2^n * det(A) = {2**2 * np.linalg.det(A):.4f}")
行列式の幾何学的意味の可視化
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# --- 例1: det > 0 ---
ax = axes[0]
v1 = np.array([2, 1])
v2 = np.array([1, 3])
det_val = v1[0]*v2[1] - v1[1]*v2[0]
# 平行四辺形
parallelogram = np.array([[0, 0], v1, v1 + v2, v2])
poly = Polygon(parallelogram, alpha=0.3, color='blue')
ax.add_patch(poly)
ax.quiver(0, 0, v1[0], v1[1], angles='xy', scale_units='xy', scale=1,
color='blue', linewidth=2, label=f'$\\mathbf{{v}}_1 = ({v1[0]}, {v1[1]})$')
ax.quiver(0, 0, v2[0], v2[1], angles='xy', scale_units='xy', scale=1,
color='red', linewidth=2, label=f'$\\mathbf{{v}}_2 = ({v2[0]}, {v2[1]})$')
ax.set_xlim(-0.5, 5)
ax.set_ylim(-0.5, 5)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
ax.set_title(f'$\\det = {det_val}$ (Area = {abs(det_val)})')
ax.legend(fontsize=8)
# --- 例2: det < 0 ---
ax = axes[1]
v1 = np.array([1, 3])
v2 = np.array([2, 1])
det_val = v1[0]*v2[1] - v1[1]*v2[0]
parallelogram = np.array([[0, 0], v1, v1 + v2, v2])
poly = Polygon(parallelogram, alpha=0.3, color='red')
ax.add_patch(poly)
ax.quiver(0, 0, v1[0], v1[1], angles='xy', scale_units='xy', scale=1,
color='blue', linewidth=2, label=f'$\\mathbf{{v}}_1 = ({v1[0]}, {v1[1]})$')
ax.quiver(0, 0, v2[0], v2[1], angles='xy', scale_units='xy', scale=1,
color='red', linewidth=2, label=f'$\\mathbf{{v}}_2 = ({v2[0]}, {v2[1]})$')
ax.set_xlim(-0.5, 5)
ax.set_ylim(-0.5, 5)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
ax.set_title(f'$\\det = {det_val}$ (Area = {abs(det_val)})')
ax.legend(fontsize=8)
# --- 例3: det = 0 ---
ax = axes[2]
v1 = np.array([1, 2])
v2 = np.array([2, 4]) # v2 = 2*v1
det_val = v1[0]*v2[1] - v1[1]*v2[0]
ax.quiver(0, 0, v1[0], v1[1], angles='xy', scale_units='xy', scale=1,
color='blue', linewidth=2, label=f'$\\mathbf{{v}}_1 = ({v1[0]}, {v1[1]})$')
ax.quiver(0, 0, v2[0], v2[1], angles='xy', scale_units='xy', scale=1,
color='red', linewidth=2, label=f'$\\mathbf{{v}}_2 = ({v2[0]}, {v2[1]})$')
# 直線(平行な2本は同一直線上)
t = np.linspace(-0.5, 3, 100)
ax.plot(t * v1[0] / np.linalg.norm(v1) * np.linalg.norm(v1),
t * v1[1] / np.linalg.norm(v1) * np.linalg.norm(v1),
'g--', alpha=0.5, linewidth=2)
ax.set_xlim(-0.5, 5)
ax.set_ylim(-0.5, 5)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
ax.set_title(f'$\\det = {det_val}$ (Linearly dependent)')
ax.legend(fontsize=8)
plt.tight_layout()
plt.savefig("determinant_geometry.png", dpi=150, bbox_inches='tight')
plt.show()
クラメルの公式の実装
import numpy as np
def cramers_rule(A, b):
"""
クラメルの公式で連立方程式 Ax = b を解く
Parameters
----------
A : ndarray, shape (n, n)
係数行列
b : ndarray, shape (n,)
右辺ベクトル
Returns
-------
ndarray, shape (n,)
解ベクトル
"""
n = len(b)
det_A = np.linalg.det(A)
if abs(det_A) < 1e-12:
raise ValueError("行列式が0です。一意解は存在しません。")
x = np.zeros(n)
for i in range(n):
A_i = A.copy()
A_i[:, i] = b # 第i列をbで置換
x[i] = np.linalg.det(A_i) / det_A
return x
# 例: 2x + y = 5, x + 3y = 7
A = np.array([[2, 1],
[1, 3]], dtype=float)
b = np.array([5, 7], dtype=float)
x_cramer = cramers_rule(A, b)
x_solve = np.linalg.solve(A, b)
print(f"クラメルの公式: x = {x_cramer}")
print(f"np.linalg.solve: x = {x_solve}")
print(f"一致: {np.allclose(x_cramer, x_solve)}")
# 3x3 の例
A3 = np.array([[1, 2, 3],
[2, 5, 3],
[1, 0, 8]], dtype=float)
b3 = np.array([1, 2, 3], dtype=float)
x3_cramer = cramers_rule(A3, b3)
x3_solve = np.linalg.solve(A3, b3)
print(f"\n3x3 クラメルの公式: x = {x3_cramer}")
print(f"3x3 np.linalg.solve: x = {x3_solve}")
print(f"一致: {np.allclose(x3_cramer, x3_solve)}")
行列式と線形変換の面積変化
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 単位正方形の頂点
square = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]).T
# 変換行列
A = np.array([[2, 1],
[0.5, 1.5]])
det_A = np.linalg.det(A)
# 変換後
transformed = A @ square
# 元の正方形
ax = axes[0]
ax.fill(square[0], square[1], alpha=0.3, color='blue', label='Unit square (Area=1)')
ax.plot(square[0], square[1], 'b-', linewidth=2)
ax.set_xlim(-0.5, 4)
ax.set_ylim(-0.5, 4)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
ax.set_title('Before Transformation')
ax.legend()
# 変換後
ax = axes[1]
ax.fill(transformed[0], transformed[1], alpha=0.3, color='red',
label=f'Transformed (Area={abs(det_A):.2f})')
ax.plot(transformed[0], transformed[1], 'r-', linewidth=2)
ax.fill(square[0], square[1], alpha=0.1, color='blue')
ax.plot(square[0], square[1], 'b--', linewidth=1, alpha=0.5)
ax.set_xlim(-0.5, 4)
ax.set_ylim(-0.5, 4)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
ax.set_title(f'After $A$: $\\det(A) = {det_A:.2f}$')
ax.legend()
plt.tight_layout()
plt.savefig("determinant_area_change.png", dpi=150, bbox_inches='tight')
plt.show()
まとめ
本記事では、行列式の定義と性質を体系的に解説しました。
- $2 \times 2$ 行列式は平行四辺形の 符号付き面積、$3 \times 3$ は平行六面体の 符号付き体積 を表す
- 一般の $n$ 次行列式は 置換の符号 を用いて定義される
- 行列式の主要な性質: 転置不変性、多重線形性、交代性、$\det(\bm{A}\bm{B}) = \det(\bm{A})\det(\bm{B})$
- $\bm{A}$ が正則(逆行列が存在) $\Leftrightarrow$ $\det(\bm{A}) \neq 0$
- クラメルの公式 で連立方程式の各成分を行列式の比として求められる
次のステップとして、以下の記事も参考にしてください。