行列式の定義と性質を体系的に解説

行列式(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$
  • クラメルの公式 で連立方程式の各成分を行列式の比として求められる

次のステップとして、以下の記事も参考にしてください。