6.1 群:axioms 即 typeclass#
本節目標#
- 理解群的定義:結合律、單位元素、反元素三條公理(四公理的常見寫法)
- 認識 Mathlib 中
class Group (G : Type*)的實際定義 - 建立 typeclass 與 instance 的直覺:「這個型別配上了這套代數結構」
- 看懂
Semigroup → Monoid → Group的繼承層級 - 使用
abel、ring、field_simp處理代數等式 - 親手宣告一個具體群的 instance:整數模 \(n\) 群 \(\mathbb{Z}/n\)
6.1.1 群的數學定義#
一個 群(group) 是一個集合 \(G\) 配上一個二元運算 \(\cdot : G \times G \to G\) ,滿足:
- 結合律: \((a \cdot b) \cdot c = a \cdot (b \cdot c)\) ,對所有 \(a, b, c \in G\) 。
- 單位元素:存在 \(e \in G\) 使得 \(e \cdot a = a \cdot e = a\) 。
- 反元素:對每個 \(a \in G\) ,存在 \(a^{-1} \in G\) 使得 \(a \cdot a^{-1} = a^{-1} \cdot a = e\) 。
教科書常把 1 拆成「封閉性」與「結合律」兩條,合稱四公理。但在 Lean 裡,二元運算的型別 \(G \to G \to G\) 天生就封閉——你根本寫不出一個「運算結果落在集合外」的項。這是型別論的第一個紅利:公理變少,因為型別系統幫你免費檢查了一條。
例子: \((\mathbb{Z}, +)\) 是群而 \((\mathbb{N}, +)\) 不是(沒有反元素);非零有理數 \((\mathbb{Q}^\times, \times)\) 是群而 \((\mathbb{Q}, \times)\) 不是( \(0\) 沒有反元素); \(n\) 階對稱群 \(S_n\) :所有 \(\{1, \dots, n\}\) 的排列在合成運算下成群。
6.1.2 Mathlib 的 Group class#
打開 Mathlib,你會看到(簡化後):
class Group (G : Type*) extends DivInvMonoid G where
div_eq_mul_inv : ∀ a b : G, a / b = a * b⁻¹
-- 以及由 DivInvMonoid 繼承而來的:
mul_assoc : ∀ a b c : G, a * b * c = a * (b * c)
one_mul : ∀ a : G, 1 * a = a
mul_one : ∀ a : G, a * 1 = a
inv_mul_cancel_left : ∀ a : G, a⁻¹ * a = 1
看起來比教科書定義囉嗦,那是因為 Mathlib 為了 API 完整性多列了幾條 可推導的性質(它們能由另外幾條證出,但聲明出來方便取用)。核心只有一件事:
Group G是一個「證明攜帶的包裹」:型別 \(G\) 、一個乘法Mul G、一個單位元One G、一個反元素Inv G,以及它們滿足公理的證明。
在 Lean 裡,Group 是 class,所以這個包裹可以靠 typeclass inference 自動被找到——這就是下一節的主題。
6.1.3 typeclass 的直覺:instance 是「結構的註冊」#
初學者最常卡住的地方:a * b⁻¹ 這種寫法裡,* 和 ⁻¹ 到底是什麼?
答案是:* 是 HMul 型別類的投影函數,⁻¹ 是 Inv 型別類的投影函數。當你寫 a * b 且 a b : G 時,Lean 會搜尋 instance : Mul G,找到就展開,找不到就報錯 failed to synthesize Mul G。所以:
| 數學語言 | Lean 語言 |
|---|---|
| 「 \(G\) 是一個群」 | Group G 的 instance 存在 |
| 「設 \(a \in G\) 」 | variable {G : Type*} [Group G] (a : G) |
| 「因為 \(G\) 是群,故結合律成立」 | mul_assoc(Lean 自動從 instance 取出證明) |
關鍵心智模型:[Group G] 這個方括號參數,就是「假設 G 是群」的形式化。你的定理不再需要寫「設 \((G, \cdot)\) 為一群」——型別簽名本身就說完了。
6.1.4 代數結構層級#
Mathlib 把代數結構排成一座塔,每往上一層多一條公理:
graph TD
Mul["Mul G<br/>只指定一個二元運算"] --> SG["Semigroup<br/>+ 結合律"]
SG --> MO["Monoid<br/>+ 單位元素"]
MO --> GP["Group<br/>+ 反元素"]
Mul --> CS["CommSemigroup<br/>+ 交換律"]
CS --> CMO["CommMonoid"]
CMO --> CG["CommGroup<br/>= 交換群 (abelian group)"]教科書的「阿貝爾群」在 Mathlib 叫 CommGroup。塔的設計有一個實際好處:一個關於 Monoid 的定理,自動對群、對交換群、對 \(\mathbb{N}\) 都適用,不用重寫三次。
6.1.5 常用 API:inv_mul_cancel_left 與朋友們#
群論第一章的等式證明,在 Lean 裡幾乎都是重寫 (rewriting):
example {G : Type*} [Group G] (a b : G) : a⁻¹ * (a * b) = b := by
rw [← mul_assoc, inv_mul_cancel_left]
常用引理(值得背下來):mul_assoc、one_mul、mul_one、inv_mul_cancel_left : a⁻¹ * (a * b) = b、mul_inv_cancel_left : a * (a⁻¹ * b) = b、inv_inv : a⁻¹⁻¹ = a、mul_left_inv : a⁻¹ * a = 1(即公理本身)。
而當運算是交換的(CommGroup 或之後的 Field),直接交給 abel tactic(如 abel 一行證 a * b⁻¹ * c = c * b⁻¹ * a);環上的多項式恆等式交給 ring;分式等式交給 field_simp(6.3 節實戰)。
6.1.6 實例一:整數模 \(n\) 的加法群#
現在親手註冊一個群。取 \(G = \mathbb{Z}/n\) ,即「餘數的世界」,運算是加法後取餘數。Mathlib 已經提供 ZMod n,並且它就是群——但我們把 instance 驗證的過程攤開來看:
import Mathlib.Tactic
-- ZMod n 上的加法已是交換群,Mathlib 內建 instance。驗證公理可用:
example (n : ℕ) (a : ZMod n) : a + 0 = a := by simp
-- 反元素就是「負的」:在 ZMod 5 中 2 的反元素是 3
example : (2 : ZMod 5) + 3 = 0 := by decide
注意最後一個例子:decide 對有限型別直接暴力檢查——這是 Lean 獨有的玩法:有限群可以窮舉證明。
6.1.7 實例二:自訂對稱群 \(S_3\) 的一小塊#
我們自訂一個 3 元素的型別,讓它攜帶一個自己寫的群結構(用乘法表定義的循環群 \(\mathbb{Z}/3\) ,它正是 \(S_3\) 的子群):
import Mathlib.Tactic
inductive T3 | z | o | t -- 三元素型別
open T3
def mul3 : T3 → T3 → T3 -- 循環群 Z/3 的乘法表
| z, x => x | x, z => x
| o, o => t | o, t => z | t, o => z | t, t => o
instance : One T3 := ⟨z⟩
instance : Mul T3 := ⟨mul3⟩
@[simp] lemma mul3_z_left (x : T3) : mul3 z x = x := by cases x <;> rfl
@[simp] lemma mul3_z_right (x : T3) : mul3 x z = x := by cases x <;> rfl
@[simp] lemma o_mul_t : mul3 o t = z := rfl
@[simp] lemma t_mul_o : mul3 t o = z := rfl
@[simp] lemma o_mul_o : mul3 o o = t := rfl
@[simp] lemma t_mul_t : mul3 t t = o := rfl
-- 結合律與反元素公理:對三元素型別窮舉即可
instance : Group T3 := by
constructor
case mul_assoc =>
intro a b c
cases a <;> cases b <;> cases c <;> simp [mul3] <;> rfl
case inv_mul_cancel_left =>
intro a
cases a <;> simp [mul3] <;> rfl
all_goals exact inferInstance
cases a <;> cases b <;> cases c 一口氣展開 \(3^3 = 27\) 個子目標,每個都是 rfl 級別的計算。有限結構的公理驗證 = 窮舉,這在紙上數學反而做不到(太繁瑣),Lean 卻一行搞定。
6.1.8 對照表:本章術語#
| 數學 | Lean / Mathlib |
|---|---|
| 群 \(G\) / 交換群 / 幺半群 | [Group G] / [CommGroup G] / [Monoid G] |
| 單位元 \(e\) 、反元素 \(a^{-1}\) | 1、a⁻¹ |
| 結合重排、交換群線性等式 | mul_assoc、abel tactic |
小結與練習#
小結:群 = 型別 + 運算 + 公理證明的包裹;typeclass 讓「 \(G\) 是群」成為編譯器自動查得到的假設;Semigroup → Monoid → Group 層級讓定理沿塔向上繼承;有限群的公理可以窮舉驗證。
練習(★ 越多越難)
- ★☆☆☆☆ 證明:
{G : Type*} [Group G] (a b : G) : a * (b * a⁻¹)⁻¹ = a * a * b⁻¹(提示:grouptactic 一行可解,但請先手動rw練習)。 - ★★☆☆☆ 證明群的單位元素唯一:若
h : e * a = a對所有a成立,則e = 1。 - ★★★☆☆ 在 6.1.7 的
T3上,補齊Groupinstance 中被all_goals exact inferInstance跳過的每個欄位,確認哪些是繼承來的、哪些要自己證。 - ★★★★☆ 定義 \(\mathbb{Z}/2 \times \mathbb{Z}/2\) (
ZMod 2 × ZMod 2)並證明它是交換群;再用decide驗證每個非單位元素的階都是 2。