当前目标:a * b * c = b * (a * c)
↓
rw [mul_comm a b] -- 用 a*b = b*a 替换
↓
新目标:b * a * c = b * (a * c)
↓
rw [mul_assoc b a c] -- 用 b*a*c = b*(a*c) 替换
↓
目标解决!
mul_comm 和 mul_assoc 是什么?
mul_comm a b 是定理 a * b = b * a(乘法交换律)
mul_assoc a b c 是定理 a * b * c = a * (b * c)(乘法结合律)
这些是 Lean 中已注册的引理,可直接在 rw 中使用
rw 的三种用法
-- 1. 完全指定参数rw [mul_comm a b] -- 只替换涉及 a 和 b 的项-- 2. 部分指定rw [mul_comm a] -- 匹配 a * ? → ? * a-- 3. 不指定rw [mul_comm] -- 自动匹配第一个找到的模式
反向重写
rw [← mul_assoc] 中的 ← 表示反向使用等式。
如果 mul_assoc : a * b * c = a * (b * c),
那么 rw [← mul_assoc] 会把 a * (b * c) 替换成 a * b * c。
1 goalx y : ℕ, -- 变量h₁ : Prime x, -- 假设h₂ : ¬Even x,h₃ : y > x⊢ y ≥ 4 -- 目标(需要证明的东西)
关键符号:
⊢ 表示”需要证明”
假设可以是等式、不等式、否定等任何命题
变量和假设都有名字,可以在证明中引用
calc 证明链
calc 让你写出结构化的计算步骤:
variable (a b : ℝ)example : (a + b) * (a + b) = a * a + 2 * (a * b) + b * b := calc (a + b) * (a + b) = a * a + b * a + (a * b + b * b) := by rw [mul_add, add_mul, add_mul] -- mul_add : (a + b) * c = a * c + b * c -- add_mul : a * (b + c) = a * b + a * c _ = a * a + (b * a + a * b) + b * b := by rw [← add_assoc, add_assoc (a * a)] -- add_assoc : (x + y) + z = x + (y + z),调整括号位置 _ = a * a + 2 * (a * b) + b * b := by rw [mul_comm b a, ← two_mul] -- mul_comm b a : b * a = a * b -- two_mul : 2 * x = x + x,所以 a * b + a * b = 2 * (a * b)
calc 的语法要点
开头不写 by:calc 本身是一个证明项,不是 tactic
下划线 _:表示”上一行的右边”
对齐很重要:Lean 用缩进来判断结构
每步都要有 := 和证明
calc 的调试技巧
先用 sorry 占位,确保骨架正确:
calc lhs = step1 := by sorry _ = step2 := by sorry _ = rhs := by sorry
确认 Lean 接受后,再逐个填充证明。
ring 战术:自动代数
ring 能自动证明交换环中的恒等式:
example : c * b * a = b * (a * c) := by ringexample : (a + b) * (a - b) = a ^ 2 - b ^ 2 := by ring
ring 的限制
只处理纯代数恒等式
不能使用局部假设(context 中的 h)
只适用于交换环(CommRing)
如果需要使用假设,先 rw 再 ring:
variable (a b c d : ℝ)example (hyp : c = d * a + b) (hyp' : b = a * d) : c = 2 * a * d := by rw [hyp, hyp'] -- 代入 c 和 b:d*a + a*d = 2*a*d ring -- 自动整理
nth_rw:指定位置重写
当表达式中有多个相同子表达式时:
example (a b c : ℕ) (h : a + b = c) : (a + b) * (a + b) = a * c + b * c := by nth_rw 2 [h] -- 只替换第二个 (a + b) rw [add_mul]
2.2 Proving Identities in Algebraic Structures
核心思想
从具体(ℝ)到抽象(Ring)。Lean 的强大之处在于泛化推理。
环的公理
variable (R : Type*) [Ring R]-- 加法公理#check (add_assoc : ∀ a b c : R, a + b + c = a + (b + c))#check (add_comm : ∀ a b : R, a + b = b + a)#check (zero_add : ∀ a : R, 0 + a = a)#check (neg_add_cancel : ∀ a : R, -a + a = 0)-- 乘法公理#check (mul_assoc : ∀ a b c : R, a * b * c = a * (b * c))#check (mul_one : ∀ a : R, a * 1 = a)#check (one_mul : ∀ a : R, 1 * a = a)-- 分配律#check (mul_add : ∀ a b c : R, a * (b + c) = a * b + a * c)#check (add_mul : ∀ a b c : R, (a + b) * c = a * c + b * c)
泛化的力量
-- 在任意交换环中成立variable (R : Type*) [CommRing R]example (a b : R) : (a + b) * (a - b) = a ^ 2 - b ^ 2 := by ring-- 自动适用于 ℤ, ℚ, ℂ, 矩阵环等-- CommRing 的实例:ℤ, ℚ, ℂ-- Ring 但非 CommRing 的实例:n×n 矩阵
-- add_left_cancel:若 a + b = a + c,则 b = c(加法消去律)#check (add_left_cancel : a + b = a + c → b = c)theorem mul_zero (a : R) : a * 0 = 0 := by have h : a * 0 + a * 0 = a * 0 + 0 := by rw [← mul_add, add_zero, add_zero] rw [add_left_cancel h] -- 消去两边的 a * 0,得 a * 0 = 0
工作流程:
have h : P := by ... 引入一个新目标 P
在缩进块中证明 P
证明完成后,h 可以作为假设使用
回到原来的证明
have 的使用场景
当直接证明目标太难时,先证明一个中间结论
当需要复用某个事实时
让证明更模块化和可读
隐式参数
-- 花括号表示隐式参数theorem add_left_cancel {a b c : R} (h : a + b = a + c) : b = c := by ...-- 使用时不需要提供 a, b, cadd_left_cancel h -- Lean 从 h 的类型推断出 a, b, c
隐式 vs 显式
(a : R) 显式:调用时必须提供
{a : R} 隐式:Lean 自动推断
选择原则:如果参数能从其他参数推断,就用隐式
rfl:定义相等
-- 在 ℝ 上,减法定义为加负数example (a b : ℝ) : a - b = a + -b := rfl-- rfl 能证明"定义上相等"的等式-- Lean 会展开定义检查两边是否相同
2.3 Using Theorems and Lemmas
核心思想
不只是等式,不等式、蕴含、存在都需要 apply 和 exact。
apply vs exact
先看两个核心定理的含义:
#check (le_refl : ∀ a, a ≤ a) -- ≤ 的自反性:任何数 ≤ 自己#check (le_trans : a ≤ b → b ≤ c → a ≤ c) -- ≤ 的传递性
exact 用于直接提供完整证明,apply 用于匹配结论、拆分目标:
variable (x y z : ℝ) (h₀ : x ≤ y) (h₁ : y ≤ z)-- exact:提供的项完全匹配目标,直接关闭example : x ≤ x := by exact le_refl x -- le_refl x 的类型正好是 x ≤ x-- apply:匹配结论,剩余前提成为新目标example : x ≤ z := by apply le_trans -- le_trans 的结论是 a ≤ c,匹配 x ≤ z -- 剩余两个前提 a ≤ b 和 b ≤ c 成为子目标 · exact h₀ -- 证明 x ≤ y · exact h₁ -- 证明 y ≤ z
#check (le_refl : ∀ a, a ≤ a) -- a ≤ a#check (le_trans : a ≤ b → b ≤ c → a ≤ c) -- 传递性#check (lt_of_le_of_lt : a ≤ b → b < c → a < c) -- 混合传递#check (lt_trans : a < b → b < c → a < c) -- < 传递性
add_le_add:加法保持不等式
-- add_le_add:若 a ≤ b 且 c ≤ d,则 a + c ≤ b + d#check (add_le_add : a ≤ b → c ≤ d → a + c ≤ b + d)variable (a b c : ℝ) (h : b ≤ c)example : a + Real.exp b ≤ a + Real.exp c := by apply add_le_add (le_refl a) -- a ≤ a 来自自反性 apply Real.exp_le_exp.mpr -- exp 单调增:b ≤ c ↔ exp b ≤ exp c exact h