Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

行列式の幾何的な解釈:体積拡大率

2つのベクトルが四角形を表すとみなす。この四角形を変形させる行列AAがあったとき、変換後の四角形の面積はもとの面積のdet(A)\text{det}(A)倍である、と解釈できる

(行列式の値が正の値のとき。負の場合は軸が反転して裏返しになる。det(A)=0\text{det}(A)=0ならぺちゃんこに潰れている状態)

例えばIR2×2I \in \mathbb{R}^{2\times 2}が構成する四角形にAAを乗じてAI=AAI=Aとするときの拡大率ともいえるし、AAの面積とも言える

Source
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import japanize_matplotlib

e0 = [1, 0]
e1 = [0, 1]

I = np.array([e0, e1])
O = np.array([0, 0])

fig, ax = plt.subplots(figsize=[4, 4], dpi=72)
ax.grid(True, alpha=.5)
ax.arrow(*O, *e0, width=0.01, color="black", length_includes_head=True)
ax.arrow(*O, *e1, width=0.01, color="black", length_includes_head=True)
ax.fill_between(x=[0, 1], y1=0, y2=1, alpha=.5)

ax.set(xlim=[-0.5, 1.5], ylim=[-0.5, 1.5], xticks=[0, 1], yticks=[0, 1])
fig.show()
<Figure size 288x288 with 1 Axes>

適当な行列AAで変換するとこうなる

A = np.array([
    [1, 1],
    [0, 1]
])
e0_ = A @ e0
e1_ = A @ e1
y_ = e0_ + e1_
Source
fig, ax = plt.subplots(dpi=72)
ax.grid(True, alpha=.5)
ax.arrow(0, 0, *e0_, width=0.01, color="black", length_includes_head=True)
ax.arrow(0, 0, *e1_, width=0.01, color="black", length_includes_head=True)

d = np.array([e0_, y_])
ax.plot(d[:, 0], d[:, 1], color="black", linestyle="--")
d = np.array([e1_, y_])
ax.plot(d[:, 0], d[:, 1], color="black", linestyle="--")

x = np.linspace(0, y_[0], 11)
ax.fill_between(x=x, y1=[max(e - 1, 0) for e in x], y2=[min(e, 1) for e in x], alpha=.5)
ax.set(xlim=[-0.25, 2.25], ylim=[-0.25, 1.25], xticks=[0, 1, 2], yticks=[0, 1])
fig.show()
<Figure size 460.8x345.6 with 1 Axes>

平行四辺形の面積は底辺×高さ。今回は底辺も高さも1なので、面積は変わっていない。

この行列AAの行列式は1になる

np.linalg.det(A)
1.0

(例)次のような行列の場合は…?

A=(1213),B=(11021103)det(A)=32=1,det(B)=103102=1A = \begin{pmatrix} 1 & 2\\ 1 & 3 \end{pmatrix} , \hspace{2em} B = \begin{pmatrix} 1 & 102\\ 1 & 103 \end{pmatrix} \\ \text{det}(A) = 3 - 2 = 1 , \hspace{2em} \text{det}(B) = 103 - 102 = 1
A = np.array([
    [1, 2],
    [1, 3]
])
B = np.array([
    [1, 102],
    [1, 103]
])
fig, axes = plt.subplots(ncols=2, figsize=[8, 4], dpi=72)

for X, ax in zip([A, B], axes):
    x0_ = X[0]
    x1_ = X[1]
    y_ = x0_ + x1_
    ax.grid(True, alpha=.5)
    ax.arrow(0, 0, *x0_, width=0.01, color="black", length_includes_head=True)
    ax.arrow(0, 0, *x1_, width=0.01, color="black", length_includes_head=True)

    d = np.array([x0_, y_])
    ax.plot(d[:, 0], d[:, 1], color="black", linestyle="--")
    d = np.array([x1_, y_])
    ax.plot(d[:, 0], d[:, 1], color="black", linestyle="--")

    x = np.linspace(0, y_[0], 11)
    ax.set(title=f"det = {np.linalg.det(X)}")
fig.show()
<Figure size 576x288 with 2 Axes>

どうしてそうなるのか

a,b\boldsymbol{a}, \boldsymbol{b} を平面 R2\boldsymbol{R}^2 の 2 つのベクトルとする。 OO を座標の原点とし、 A,BA, BOA\overrightarrow{O A} =a,OB=b=\boldsymbol{a}, \overrightarrow{O B}=\boldsymbol{b} であるような点とする。 OA,OBO A, O B を 2 辺とする平行四辺形 OAPBO A P B を、a,b\boldsymbol{a}, \boldsymbol{b}を2辺とする平行四辺形という。その面積Sを求めたい。

もしa,b\boldsymbol{a}, \boldsymbol{b}が1次従属なら、OAPBは1つの線分になるのでS=0S=0

a,b\boldsymbol{a}, \boldsymbol{b}が1次独立のとき、a,b\boldsymbol{a}, \boldsymbol{b}のなす角をθ\thetaとすれば、 BBから辺OAOAに下した垂線の長さはbsinθ\|\boldsymbol{b}\| \sin \thetaであるから、面積は底辺×高さで

S=absinθS = \|\boldsymbol{a}\| \|\boldsymbol{b}\| \sin \theta

両辺を2乗にする

S2=a2b2sin2θS^2 = \|\boldsymbol{a}\|^2 \|\boldsymbol{b}\|^2 \sin^2 \theta

sin2θ=1cos2θ\sin ^2 \theta=1-\cos ^2 \theta であり cosθ=abab\cos \theta = \frac{ \boldsymbol{a} \cdot \boldsymbol{b} }{ \|\boldsymbol{a}\| \|\boldsymbol{b}\| }なので

S2=a2b2sin2θ=a2b2(1cos2θ)=a2b2(1(ab)2a2b2)=a2b2(ab)2\begin{align} S^2 &= \|\boldsymbol{a}\|^2 \|\boldsymbol{b}\|^2 \sin^2 \theta\\ &= \|\boldsymbol{a}\|^2 \|\boldsymbol{b}\|^2 (1 - \cos ^2 \theta)\\ &= \|\boldsymbol{a}\|^2 \|\boldsymbol{b}\|^2 \left(1 - \frac{ (\boldsymbol{a} \cdot \boldsymbol{b})^2 }{ \|\boldsymbol{a}\|^2 \|\boldsymbol{b}\|^2 }\right)\\ &= \|\boldsymbol{a}\|^2 \|\boldsymbol{b}\|^2 - (\boldsymbol{a} \cdot \boldsymbol{b})^2 \end{align}

a=(a1,a2)T,b=(b1,b2)T\boldsymbol{a} = (a_1, a_2)^T, \boldsymbol{b}=(b_1, b_2)^Tとすれば、

S2=a2b2(ab)2=(a12+a22)(b12+b22)(a1b1+a2b2)2=(a1b2a2b1)2\begin{align} S^2 = \|\boldsymbol{a}\|^2 \|\boldsymbol{b}\|^2 - (\boldsymbol{a} \cdot \boldsymbol{b})^2 &= \left(a_1^2 + a_2^2\right)\left(b_1^2 + b_2^2\right)-\left(a_1 b_1+a_2 b_2\right)^2 \\ &= \left(a_1 b_2-a_2 b_1\right)^2\\ \end{align}

ゆえに

S=a1b2a2b1S = |a_1 b_2-a_2 b_1|
Source
X = np.array([
    [2, 1],
    [0, 1]
])
a = X @ e0
b = X @ e1
P = a + b


fig, ax = plt.subplots(figsize=[4, 4], dpi=100)
ax.grid(True, alpha=.5)

ax.text(0, 0, "O", ha="right", va="top")
ax.text(*a, "A", ha="left", va="top")
ax.text(*b, "B", ha="left", va="bottom")
ax.text(*P, "P", ha="left", va="bottom")

ax.arrow(0, 0, *a, width=0.01, color="black", length_includes_head=True)
ax.arrow(0, 0, *b, width=0.01, color="black", length_includes_head=True)

d = np.array([a, P])
ax.plot(d[:, 0], d[:, 1], color="black", linestyle="--")
d = np.array([b, P])
ax.plot(d[:, 0], d[:, 1], color="black", linestyle="--")

# 垂線 y = |b| sinθ をもとめる
cos_theta = (a @ b) / (np.linalg.norm(a) * np.linalg.norm(b))
theta = np.arccos(cos_theta)
y = np.linalg.norm(b) * np.sin(theta)
ax.vlines(x=b[0], ymin=0, ymax=y, color="black", linestyle="--")
ax.text(b[0], y/2, r"$\|b\| \sin \theta$", ha="left", va="center")

# x = np.linspace(0, y_[0], 11)
# ax.fill_between(x=x, y1=[max(e - 1, 0) for e in x], y2=[min(e, 1) for e in x], alpha=.5)

ax.set(xlim=[-0.25, 3.25], ylim=[-0.25, 1.25],
       xticks=range(4), yticks=range(2))


# Drawing the angle θ near O with an arc
ax.text(0.4, 0.15, "θ", ha="center", va="center")
angle = np.linspace(0, np.arctan2(B[0], B[1]), 100)  # Calculate the angle of OB relative to the x-axis
radius = 0.3  # Radius of the arc for angle representation
x_arc = radius * np.cos(angle)
y_arc = radius * np.sin(angle)
ax.plot(x_arc, y_arc, 'k-')  

fig.show()
<Figure size 400x400 with 1 Axes>
import numpy as np

np.sin(np.pi) - np.cos(np.pi)
1.0000000000000002
- np.cos(np.pi) + np.sin(np.pi) 
1.0000000000000002