5.4 把論文翻譯成 Lean:從陳述到證明的工程流程#
本節目標#
- 建立「定義即型別、陳述即定理」的核心心法
- 學會三段式工作流:proof sketch → tactic 骨架 → 填洞(
sorry) - 以 AM-GM 不等式為例,完整示範從論文語句到 Lean 程式碼的翻譯過程
- 掌握 Mathlib 的命名慣例(snake_case、縮寫表)
- 認識常見陷阱:classical vs constructive 推理、choice 函數
核心心法:定義即型別,陳述即定理#
把一篇數學論文翻譯成 Lean,本質上是一場語意壓縮:論文的自然語言裡,「設 G 是一個群」、「令 ε > 0」、「存在唯一的 x」這些句子,在 Lean 中全都有精確的型別表示:
| 論文語句 | Lean 表示 |
|---|---|
| 「設 M 是一個 monoid」 | {M : Type} [Monoid M] |
| 「存在唯一的 x 使得 P x」 | ∃! x, P x |
| 「定義 f 為……」 | def f : α → β := ... |
| 「定理 T:P 蘊含 Q」 | theorem T : P → Q := by ... |
兩條鐵律:
- 定義即型別:一個數學定義翻成 Lean 時,優先考慮「它是一個什麼型別的東西」,而不是「它是怎麼算出來的」
- 陳述即定理:先把定理的陳述(statement)一字不差地形式化並通過編譯,再開始寫證明。陳述錯了,證明再漂亮也是白工
三段式工作流:sketch → 骨架 → 填洞#
實務上把一個證明翻進 Lean 的標準流程:
flowchart LR
A["讀論文<br/>寫下 proof sketch"] --> B["陳述形式化<br/>statement 編譯通過"]
B --> C["tactic 骨架<br/>每步放 sorry"]
C --> D["逐洞填補<br/>消除所有 sorry"]
D --> E["清理重構<br/>命名與 docstring"]第一原則:先讓整個檔案的骨架通過編譯,再逐一消滅 sorry。sorry 是 Lean 的佔位證明——編譯器知道你在偷懶,會發出警告,但不阻擋你繼續工作。這讓你可以先確認全局推理路徑,再深入各個細節。
實戰示範:AM-GM 不等式#
論文語句(常見的初等敘述):
定理(算術幾何平均不等式):對任意實數 \(a_1, a_2, \dots, a_n \geq 0\) ,有 \(\dfrac{a_1 + a_2 + \cdots + a_n}{n} \leq \sqrt[n]{a_1 a_2 \cdots a_n}\) 。
第一步:翻譯陳述#
先選擇最簡的 \(n = 2\) 版本,把句子逐詞映射成 Lean:
theorem amgm_two (a b : ℝ) (ha : 0 ≤ a) (hb : 0 ≤ b) :
(a + b) / 2 ≤ Real.sqrt (a * b) := by
sorry
陳述寫好了,先編譯。若 Real.sqrt 的名字不對,此時就會發現——這正是「陳述先過編譯」的價值。
第二步:寫 proof sketch 與 tactic 骨架#
論文裡的證明可能是:「移項後兩邊平方,化為 \((a-b)^2 \geq 0\) 」。把這個意圖翻成骨架——先假設「兩邊非負可平方比較」這個引理存在,細節留成 sorry:
再細化第一個洞:「不等式兩邊非負,故可平方比較」:```lean
theorem amgm_two (a b : ℝ) (ha : 0 ≤ a) (hb : 0 ≤ b) :
(a + b) / 2 ≤ Real.sqrt (a * b) := by
have hsq : ((a + b) / 2) ^ 2 ≤ (Real.sqrt (a * b)) ^ 2 := by
sorry -- 兩邊展開:左 = (a+b)²/4,右 = a*b
have hnonneg : 0 ≤ (a + b) / 2 := by linarith
have hsqrtnonneg : 0 ≤ Real.sqrt (a * b) := Real.sqrt_nonneg _
have h := sq_le_sq' hsq hsqrtnonneg -- 骨架期先假設 Mathlib 有這個引理
linarith
第三步:填洞#
((a + b) / 2) ^ 2 ≤ (Real.sqrt (a * b)) ^ 2 這個洞化為代數恆等式:```lean have expand : ((a + b) / 2) ^ 2 = a * b + (a - b) ^ 2 / 4 := by field_simp ring have rsq : (Real.sqrt (a * b)) ^ 2 = a * b := by rw [Real.sq_sqrt (mul_nonneg ha hb)] linarith [expand, rsq]
最後得到無 `sorry` 的完整證明。實務中,這些現成的引理(如 `geom_mean_le_arith_mean2_weighted`)在 Mathlib 中早有部署——**先查 Mathlib 再自己證**,是貢獻者的第一美德。
## 命名慣例:snake_case 與縮寫表
Mathlib 的命名有一套近乎形式語法的規則,核心原則是「**讀陳述,猜名字**」:
- **snake_case**:`mul_assoc`、`add_comm`、`exists_eq_left`
- **依賴關係進名字**:定理 `a ≤ b → f a ≤ f b` 對單調 `f` 命名為 `f mono`,如 `Nat.add_le_add`
- **常用縮寫表**:
| 縮寫 | 全名 | 範例 |
|------|------|------|
| `assoc` | associative | `mul_assoc` |
| `comm` | commutative | `add_comm` |
| `le` / `lt` | ≤ / < | `le_of_lt` |
| `iff` | 若且唯若 | `mem_iff` |
| `nonneg` | nonnegative | `abs_nonneg` |
| `homo` / `anti` | 同調 / 反調 | `antitone_map` |
| `simpa` | simplify + assumption | (tactic) |
一致命名的回報是巨大的:`exact?`、`apply?` 這些自動搜尋工具,正因為命名有規律,才能「從陳述猜出引理」。
## 常見陷阱一:classical vs constructive
Lean 的底層是構造主義友善的,但**經典邏輯需要顯式開啟**,而多數數學論文默認排中律與選擇公理。Lean 用 `Classical` namespace 的引理與 `by_cases`、`push_neg` 等 tactic 提供它們:
```lean
-- 「不是假」在經典邏輯下就能得到真——構造邏輯下不成立
example (p : Prop) : ¬¬p → p := by
intro h
exact Classical.byContradiction h
陷阱在於:過度使用 classical 推理會讓定義「不可計算」(無法 #eval)。若目標包含可執行的演算法,應盡量在構造層面工作。
常見陷阱二:choice 函數#
選擇公理在 Lean 中透過 Classical.choice 實現,它讓你能寫出這種定義:
-- 「取一個滿足 P 的元素」——若 P 不決定唯一元素,這是 choice
noncomputable def some_big_element {α : Type} [Inhabited α]
(P : α → Prop) (h : ∃ x, P x) : α :=
Classical.choose h
陷阱:
- 用了 choice 的定義必須標記
noncomputable,且無法展開檢視其值——你只知道它滿足性質,不知道它是誰;每出現一次都值得自問一次 -
若論文說「取一個極大元素」,想想:真的需要 Zorn 嗎?很多時候有構造性的替代(如良序遞迴)
-
出現
noncomputable是正常訊號,每出現一次都值得自問一次 - 陷阱三:定義的「形狀」選錯。翻譯「序列收斂到 L」時,新手常自創
Prop,而 Mathlib 的標準形狀是Filter.Tendsto——先查庫裡的標準形狀,再決定自己的定義,自創定義是翻譯工作中最大的沉沒成本
小結與練習#
翻譯論文到 Lean 是一套可學習的工程流程:定義即型別、陳述先過編譯、sketch 對應 tactic 骨架、sorry 支援增量填洞、命名遵循「讀陳述猜名字」、對 classical 與 choice 保持警覺。這套流程正是大型專案(如 5.3 節的 liquid tensor experiment)能夠分工的基礎。
練習:
- 把 Lagrange 四平方定理的陳述翻成 Lean:對任意自然數 \(n\) ,存在 \(a, b, c, d\) 使 \(n = a^2 + b^2 + c^2 + d^2\) 。(提示:Mathlib 有
Nat.sum_four_squares,先試自己寫陳述,再比對) - 完成上面 AM-GM 證明的骨架版本,練習
sq_le_sq'與linarith的配合;再查 Mathlib 找官方版本引理名。 - 選一篇你熟悉論文的某個引理,寫出:論文原文語句 → Lean 陳述 → proof sketch 三段,不需要完成證明。