跳轉到

6.2 行列式與反矩陣:解開方程組的鑰匙#

本節目標#

  • 理解行列式的幾何意義:面積與體積的縮放倍率
  • 學會用 det() 計算行列式,並掌握「可逆 ⟺ det ≠ 0」
  • 手算 \(2 \times 2\) 反矩陣,與 SymPy 的 inv() 對照
  • 用 Cramer 法則與 solve、linsolve 解聯立方程組
  • 認識矩陣的秩 rank(),並實驗 det = 0 時方程組的解數

行列式:面積的縮放倍率#

對一個 \(2 \times 2\) 矩陣

\[ A = \begin{pmatrix} a & b \\ c & d \end{pmatrix}, \qquad \det(A) = ad - bc \]

行列式不只是一道公式。把 \(A\) 想成一個線性變換:它把平面上以 \((1,0)\) 、 \((0,1)\) 為兩邊的單位正方形,變成以 \((a, c)\) 、 \((b, d)\) 為兩邊的平行四邊形。這個平行四邊形的面積恰好是 \(|ad - bc|\) 。

也就是說:** \(\det(A)\) 是這個變換對面積的縮放倍率**(帶正負號,負號代表翻轉)。三維時, \(\det(A)\) 是體積縮放倍率;更高維就是「超體積」倍率。

一個關鍵推論:如果 \(\det(A) = 0\) ,表示變換把空間「壓扁」了(正方形被壓成一條線或一點),資訊丟失,變換不可逆。

用 det() 計算行列式#

from sympy import Matrix

A = Matrix([[3, 1],
            [2, 4]])
print(A.det())   # 3*4 - 1*2 = 10

行列式有兩個好用的性質(可以寫程式驗證):

  • \(\det(AB) = \det(A)\det(B)\) :先 \(B\) 後 \(A\) 的縮放倍率,等於兩者倍率相乘
  • \(\det(A^T) = \det(A)\)
from sympy import Matrix

A = Matrix([[1, 2], [3, 4]])
B = Matrix([[2, 0], [1, 3]])

print(A.det() * B.det())   # 10
print((A * B).det())       # 10,相等!

可逆條件與 inv()#

\(2 \times 2\) 矩陣的反矩陣有經典公式:

\[ A = \begin{pmatrix} a & b \\ c & d \end{pmatrix} \implies A^{-1} = \frac{1}{ad - bc} \begin{pmatrix} d & -b \\ -c & a \end{pmatrix} = \frac{1}{\det(A)} \begin{pmatrix} d & -b \\ -c & a \end{pmatrix} \]

手算 \(A = \begin{pmatrix} 3 & 1 \\ 2 & 4 \end{pmatrix}\) : \(\det(A) = 10\) ,所以

\[ A^{-1} = \frac{1}{10} \begin{pmatrix} 4 & -1 \\ -2 & 3 \end{pmatrix} = \begin{pmatrix} 2/5 & -1/10 \\ -1/5 & 3/10 \end{pmatrix} \]

用 SymPy 對照:

from sympy import Matrix

A = Matrix([[3, 1],
            [2, 4]])
print(A.inv())
# Matrix([[2/5, -1/10], [-1/5, 3/10]])

驗證反矩陣的定義 \(A A^{-1} = A^{-1} A = I\) :

I2 = A * A.inv()
print(I2)                 # Matrix([[1, 0], [0, 1]])
print(A.inv() * A == I2)  # True(這裡 I2 是單位矩陣)

當 \(\det(A) = 0\) 時,反矩陣不存在,inv() 會直接報錯:

S = Matrix([[1, 2],
            [2, 4]])
print(S.det())  # 0
try:
    S.inv()
except Exception as e:
    print("出錯了:", e)   # Matrix is not invertible (nonzero determinant?)...

用矩陣解聯立方程組#

有了反矩陣,方程組 \(A\mathbf{x} = \mathbf{b}\) 的解就是 \(\mathbf{x} = A^{-1}\mathbf{b}\) (當 \(\det(A) \neq 0\) 時)。

考慮

\[ \begin{cases} 3x + y = 9 \\ 2x + 4y = 16 \end{cases} \]
from sympy import Matrix

A = Matrix([[3, 1],
            [2, 4]])
b = Matrix([9, 16])

print(A.inv() * b)   # Matrix([[2], [3]]),即 x=2, y=3

更推薦的寫法是直接用矩陣的 solve 方法(不需要真的算反矩陣,計算更快也更穩定):

print(A.solve(b))    # Matrix([[2], [3]])

也可以用第 2 章介紹過的 linsolve(線性方程組求解器):

from sympy import linsolve, symbols

x, y = symbols('x y')
sol = linsolve([3*x + y - 9, 2*x + 4*y - 16], (x, y))
print(sol)   # {(2, 3)}

三種方法殊途同歸,但 A.solve(b) 最能凸顯「矩陣方程」的觀點。

Cramer 法則:用行列式解方程組#

Cramer 法則說:當 \(\det(A) \neq 0\) 時,方程組 \(A\mathbf{x} = \mathbf{b}\) 的第 \(i\) 個未知數,是把 \(A\) 的**第 \(i\) 行換成 \(\mathbf{b}\) ** 後的行列式除以 \(\det(A)\) :

\[ x_i = \frac{\det(A_i)}{\det(A)} \]

以 \(\begin{cases} 3x + y = 9 \\ 2x + 4y = 16 \end{cases}\) 為例:

\[ x = \frac{\begin{vmatrix} 9 & 1 \\ 16 & 4 \end{vmatrix}}{\begin{vmatrix} 3 & 1 \\ 2 & 4 \end{vmatrix}} = \frac{36 - 16}{10} = 2, \qquad y = \frac{\begin{vmatrix} 3 & 9 \\ 2 & 16 \end{vmatrix}}{10} = \frac{48 - 18}{10} = 3 \]

用 SymPy 完整實作:

from sympy import Matrix

A = Matrix([[3, 1],
            [2, 4]])
b = Matrix([9, 16])

A1 = A.copy(); A1[:, 0] = b   # 把第 1 行換成 b
A2 = A.copy(); A2[:, 1] = b   # 把第 2 行換成 b

x = A1.det() / A.det()
y = A2.det() / A.det()
print(x, y)   # 2 3

# 與 solve 的結果對照
from sympy import solve, symbols
xs, ys = symbols('x y')
print(solve([3*xs + ys - 9, 2*xs + 4*ys - 16], (xs, ys)))  # {x: 2, y: 3}

Cramer 法則計算量大、實務上不常用,但它把「解」完全用行列式表達出來,理論上非常漂亮。

矩陣的秩:rank()#

秩(rank)是矩陣中「真正獨立的列(或行)」的數量。它告訴我們方程組真正的資訊量:

from sympy import Matrix

A = Matrix([[1, 2],
            [2, 4]])
print(A.rank())   # 1:兩列成比例,只有 1 列是獨立的

B = Matrix([[1, 0, 0],
            [0, 1, 0],
            [0, 0, 1]])
print(B.rank())   # 3:滿秩

對 \(n \times n\) 方陣,有一條美麗的等價關係鏈:

\[ \det(A) \neq 0 \iff A \text{ 可逆} \iff \operatorname{rank}(A) = n \iff A\mathbf{x} = \mathbf{b} \text{ 有唯一解} \]

動手實驗:det = 0 時,方程組何時有無窮多解?#

當 \(\det(A) = 0\) ,方程組要嘛無解、要嘛有無窮多解——但什麼時候是哪一種?讓我們做實驗。

from sympy import Matrix

# 情況一:無窮多解
# x + 2y = 3 和 2x + 4y = 6 是同一條方程(第二條是第一條的兩倍)
A1 = Matrix([[1, 2],
             [2, 4]])
b1 = Matrix([3, 6])
print(A1.det(), A1.rank())          # 0 1
print(A1.rank(), Matrix.hstack(A1, b1).rank())  # 1 1,秩相等 → 有解
print(A1.solve(b1))   # Matrix([[3 - 2*t], [t]]),含自由參數 t 的無窮多解

# 情況二:無解
# x + 2y = 3 和 2x + 4y = 7:兩條「平行」的方程
b2 = Matrix([3, 7])
print(A1.rank(), Matrix.hstack(A1, b2).rank())  # 1 2,增廣矩陣秩更大 → 無解
try:
    A1.solve(b2)
except Exception as e:
    print("無解:", e)

實驗結論可以用秩寫成判別法:

  • \(\operatorname{rank}(A) = \operatorname{rank}([A|\mathbf{b}]) = n\) :唯一解
  • \(\operatorname{rank}(A) = \operatorname{rank}([A|\mathbf{b}]) < n\) :無窮多解
  • \(\operatorname{rank}(A) < \operatorname{rank}([A|\mathbf{b}])\) :無解

再做一個延伸實驗,掃描不同的 \(\mathbf{b}\) ,觀察解數的變化:

from sympy import Matrix

A = Matrix([[1, 2],
            [2, 4]])
for k in range(4, 9):
    b = Matrix([3, k])
    try:
        sol = A.solve(b)
        print(f"b = (3, {k}):有無窮多解,例如 {sol.subs('t', 0).T}")
    except Exception:
        print(f"b = (3, {k}):無解")

你會發現只有 \(k = 6\) (即 \(\mathbf{b}\) 落在被壓扁後那條線上)時才有解——這正是「det = 0 把空間壓扁」的幾何真相:方程組有解 ⟺ \(\mathbf{b}\) 沒被壓扁丟掉。

小結與練習#

本節重點:

  • \(\det(A)\) 是線性變換對(超)體積的縮放倍率; \(\det = 0\) 代表空間被壓扁
  • 可逆 ⟺ \(\det \neq 0\) ⟺ 滿秩 ⟺ 方程組有唯一解
  • \(2 \times 2\) 反矩陣公式 \(A^{-1} = \frac{1}{ad-bc}\begin{pmatrix} d & -b \\ -c & a \end{pmatrix}\) ;SymPy 用 inv()
  • 解方程組:A.solve(b)、linsolve、Cramer 法則三種途徑
  • 秩判別法: \(\operatorname{rank}(A)\) 與 \(\operatorname{rank}([A|\mathbf{b}])\) 的比較決定解數

練習:

  1. 計算 \(A = \begin{pmatrix} 2 & 7 \\ 1 & 4 \end{pmatrix}\) 的行列式與反矩陣,先手算再對照 inv()。
  2. 用三種方法(A.solve(b)、linsolve、Cramer 法則)解 \(\begin{cases} 2x - y = 0 \\ x + 3y = 7 \end{cases}\) ,確認答案一致。
  3. 驗證 \(\det(AB) = \det(A)\det(B)\) :任取兩個 \(3 \times 3\) 矩陣檢查。
  4. 構造一個 \(3 \times 3\) 的矩陣 \(A\) ,使得 \(\det(A) = 0\) 但 \(A\) 不是零矩陣,並求出 \(\operatorname{rank}(A)\) 。
  5. 對 \(A = \begin{pmatrix} 1 & 2 \\ 2 & 4 \end{pmatrix}\) ,找出所有使方程組 \(A\mathbf{x} = \mathbf{b}\) 恰好有無窮多解的 \(\mathbf{b} = (3, k)^T\) 中的 \(k\) ,並用幾何語言(壓扁、直線)解釋原因。