上一章介绍了如何对含有命题逻辑连结词的断言构造证明。 这一章我们将扩充构造命题逻辑公式的命令,使其囊括 全称量词、存在量词以及相等关系。
4.1. 全称量词 The Universal Quantifier
对于任意类型 α,
α 上的一元谓词 p 可被视作类型为 α → Prop 的对象,
如此 x : α, p x 就表示断言“p 在 x 上成立”;类似地
对象 r : α → α → Prop 代表一个 α 上的二元关系,
给定 x y : α,r x y 就表示断言“x 与 y 相关联”。
全称量词 ∀ x : α, p x 表示的断言是
“对每一个 x : α 都会有 p x 成立”。
类似命题连结词,“forall”在自然演绎系统中
也受引入和消去规则支配。非正式地,
引入规则宣称:
若已有
p x的证明,且语境中x : α都是任意的, 则可得∀ x : α, p x的证明。
对任何项
t : α,若已有∀ x : α, p x的证明, 则可得p t的证明。
正如处理蕴含时一样,“命题即类型”释义再次发挥作用。 回想一下依值箭头类型的引入和消去规则:
若已有类型为
β x的项t,且语境中x : α都是任意的, 则可得(fun x : α => t) : (x : α) → β x。
消去规则宣称:
对任何项
t : α,若已有项s : (x : α) → β x则可得s t : β t。
对于 p x 具有 Prop 类型的情形下,
如果将 (x : α) → β x 替换为 ∀ x : α, p x,
那么我们就可以将它们解读为
构造涉及全称量词的证明的正确规则。
因此构造演算便以这种方式将依值箭头类型与全称表达式对应起来。
如果 p 为任意表达式,那么 ∀ x : α, p 不过是 (x : α) → p 的一种替代记法罢了,
并且在 p 为命题的情况下前者比后者更自然。
通常表达式 p 会依赖于 x : α。回想一下,对于普通函数空间,
我们可以将函数类型 α → β 解释为 (x : α) → β 的一种特殊情形——即 β 不依赖于 x 的情况。类似地,
我们可以将命题蕴含 p → q 看作是 ∀ x : p, q 的一种特殊情形——即 q 不依赖于 x 的情况。
下面的例子演示了“命题即类型”是如何在实际应用中发挥作用的。
| |
作为一种书写约定,我们赋予全称量词尽可能大的作用域。
因此对于上方例子中的假设我们需要用括号限定 x 的量词的作用范围;
证明 ∀ y : α, p y 的规范方法是先取任意的 y 再证明 p y,这是引入规则;
已知 h 的类型为 ∀ x : α, p x ∧ q x 则表达式 h y 的类型即为 p y ∧ q y,这是消去规则;
取合取的左侧部分便可获得所需结论 p y。
请记住,如果表达式之间的差异仅在于
其中一个是对另一个里所有约束变量的重命名,
那么它们就可以被视作是等价的。因此
我们就可以在假设和结论中使用相同的变量 x,
并在证明中用其他变量(比如 z)来实例化它,见下:
| |
再举一个例子:下面展示了该
如何描述一个关系 r 具有传递性 Transitivity:
| |
思考一下到底发生了什么。在用值 a、b、c 实例化 trans_r 后
我们会得到 r a b → r b c → r a c 的证明;将此应用于“假设” hab : r a b 后
我们便得到 r b c → r a c 的一个证明;最后将其应用到假设 hbc 上
便会有结论 r a c 的证明。
在上例的情形中,显示地写出参数 a、b、c 会很繁琐
——如果它们可以从 hab hbc 中推断出来的话。
因此它们通常会被设置为隐式参数:
| |
这样做的优点是我们可以简单地写下 trans_r hab hbc 作为 r a c 的证明。
但有一个缺点:Lean 没有足够的信息来推断表达式 trans_r 和 trans_r hab 中参数的类型。
第一个 #check 命令的输出是 r ?m.1 ?m.2 → r ?m.2 ?m.3 → r ?m.1 ?m.3,
说明在本例中的隐式参数未被指定。
下面的例子展示了如何使用等价关系进行基本推理:
| |
要想熟悉使用全称量词, 你应该试试本节末尾的一些练习。
依值箭头类型的类型规则,尤其是全称量词,
体现了 Prop 类型与其他对象的类型的不同之处:
假设我们有 α : Sort i 和 β : Sort j——
其中表达式 β 可能依赖于变量 x : α,
那么 (x : α) → β 便是 Sort (imax i j) 的一个元素,
其中 imax i j 是 i 和 j 在 j 不为 0 时的最大值,否则为 0。
其思路如下:
如果 j 不是 0,
那么 (x : α) → β 便是类型 Sort (max i j) 的一个元素,也就是说
类型为 α 到 β 的依值函数“活在”指数为 i 和 j 两者最大值的宇宙中。然而,
假如 β 属于 Sort 0——即 Prop 的一个元素,
那么 (x : α) → β 也是 Sort 0 的一个元素——
无论 α 生活在哪种类型的宇宙中,也就是说
如果 β 是一个依赖于 α 的命题,
那么 ∀ x : α, β 仍然是一个命题。
这反映出 Prop 被解释为一种命题的类型而非数据类型,同时
这也使得 Prop 具有“非直谓性 impredicative”。
“直谓性”一词源于二十世纪初期的数学基础研究。
当时如庞加莱和罗素之类的逻辑学家
将集合论的悖论归咎于“恶性循环”——比如
某个属性是通过量化一个类来定义的,
而这个类又包含了待定义的属性。
会发现:如果 α 是任意类型,
那么我们就可以在 α 上构造类型 α → Prop
来囊括所有与 α 相关的谓词(Prop 的“幂”)。
Prop 的非直谓性意味着
我们可以通过量化 α → Prop 来形成命题。特别地,
我们可以通过量化所有关于 α 的谓词来定义 α 上的谓词,
而这正是曾被认为是有问题的循环类型。
下面是一些练习题:
| |
(∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x)答:1 2 3 4 5 6 7 8 9 10 11 12variable (α : Type) (p q : α → Prop) (r : Prop) example : (∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x) :=Iff.intro (λ (h : ∀ x, p x ∧ q x) ↦ ⟨λ (x : α) ↦ (h x).left ,λ (x : α) ↦ (h x).right⟩) (λ (h : (∀ x, p x) ∧ (∀ x, q x)) ↦ λ (x : α) ↦ ⟨h.left x,(h.right x)⟩)(∀ x, p x → q x) → (∀ x, p x) → (∀ x, q x)答:1 2 3 4 5 6 7 8 9 10variable (α : Type) (p q : α → Prop) (r : Prop) example : (∀ x, p x → q x) → (∀ x, p x) → (∀ x, q x) :=(λ (hpq : ∀ x, p x → q x) ↦ λ (hp : ∀ x, p x) ↦ λ (x : α) ↦ (hpq x) (hp x))(∀ x, p x) ∨ (∀ x, q x) → ∀ x, p x ∨ q x答:1 2 3 4 5 6 7 8 9 10variable (α : Type) (p q : α → Prop) (r : Prop) example : (∀ x, p x) ∨ (∀ x, q x) → ∀ x, p x ∨ q x :=(λ (hpq : (∀ x, p x) ∨ (∀ x, q x)) ↦ λ (x : α) ↦ match hpq with | Or.inl hp => Or.inl (hp x) | Or.inr hq => Or.inr (hq x))
当公式的一个组件不依赖于量化变量时,通常可以将其移到全称量词之外。 尝试证明这些(其中第二个的一个方向需要经典逻辑)
| |
- 答:
1 2 3 4 5 6 7 8 9variable (α : Type) (p q : α → Prop) (r : Prop) example : α → (∀ _ : α, r) → r :=λ (x : α) ↦ λ (h : ∀ _ : α, r) ↦ h x (∀ x, p x ∨ r) ↔ (∀ x, p x) ∨ r答:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18variable (α : Type) (p q : α → Prop) (r : Prop) open Classical example : (∀ x, p x ∨ r) ↔ (∀ x, p x) ∨ r :=Iff.intro (λ (h : ∀ x, p x ∨ r) ↦ byCases (λ (hr : r) ↦ Or.inr hr) (λ (hnr : ¬r) ↦ Or.inl (λ (x : α) ↦ match (h x) with | Or.inl hl => hl | Or.inr hr => absurd hr hnr))) (λ (h :(∀ x, p x) ∨ r) ↦ match h with | Or.inl hl => (λ (x : α) ↦ Or.inl (hl x)) | Or.inr hr => (λ (_ : α) ↦ Or.inr hr))(∀ x, r → p x) ↔ (r → ∀ x, p x)答:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15variable (α : Type) (p q : α → Prop) (r : Prop) example : (∀ x, r → p x) ↔ (r → ∀ x, p x) :=Iff.intro (λ (hrp : ∀ x, r → p x) ↦ λ (hr : r) ↦ λ (x : α) ↦ hrp x hr) (λ (hrp : r → ∀ x, p x) ↦ λ (x : α) ↦ λ (hr : r) ↦ hrp hr x)
考虑“理发师悖论 Barber Paradox”: 小镇上有个男理发师,他只为所有不给自己刮胡子的男人刮胡子。请证明这是不可能的。
| |
- 答:借用上一章第 17 题的答案。
1 2 3 4 5 6 7 8 9 10 11 12 13variable (α : Type) (a : α) (p : α → α → Prop) theorem cache {p : Prop} : ¬(p ↔ ¬p) :=λ (hpnp : p ↔ ¬p) ↦ let hnp : p → False := λ (hp : p) ↦ hpnp.mp hp hp let hp : p := hpnp.mpr hnp hpnp.mp hp hp example : (∀ x : α, p a x ↔ ¬p x x) → False :=λ (h : ∀ x : α, p a x ↔ ¬p x x) ↦ cache (h a)
4.2. 相等 Equality
现在来看看 Lean 库中定义的最基本的关系之一——相等关系。 在归纳类型一章我们将解释相等在 Lean 的逻辑框架中是如何被定义的。 不过在此之前先介绍一下如何使用它。
当然,相等关系的基本性质之一 便是其构成一个等价关系:
| |
我们可以让输出变得更易读—— 只需告诉 Lean 不要插入隐式参数(这里显示为元变量)即可。
| |
标记 .{u} 告诉 Lean
在宇宙 u 上实例化常量。
如此我们便可将上一节中的例子 套到相等关系上:
| |
我们也可以使用投影记号:
| |
自反性 Reflexivity 比表面上更强大。回想一下, 在构造演算中每个项都有一个计算释义, 而所有能被规约为相同形式的项 在逻辑框架内都会被视作是相同的。 正因如此,一些看似非平凡的恒等式 也可以通过自反性来证明:
| |
这个特性非常重要,以至于库中
为 Eq.refl _ 专门定义了一个符号 rfl:
| |
然而相等不仅仅是一种等价关系,它还有一个重要的性质:每个断言都遵从等价性,
意味着可以在不改变真值的情况下对表达式做等价代换;也就是说,
给定 h1 : a = b 和 h2 : p a 我们就可以构造一个 p b 的证明——
使用代换 Eq.subst h1 h2 即可。
| |
第二个例子中的而三角形 ▸ 是一个
建立在 Eq.subst 和 Eq.symm 之上的宏,
你可以通过输入 \t 来打出它。
规则 Eq.subst 定义了一系列辅助规则以进行更显式的替换,
它们用于处理应用项 applicative term,即形如 s t 的项;具体来说:
congrArg 用于替换实参,
congrFun 用于替换函数,
congr 可同时替换两者。
| |
Lean 的库包含大量常用等式,比如:
| |
Nat.mul_add 和 Nat.add_mul 分别是
Nat.left_distrib 和 Nat.right_distrib 的别名。
上面的属性都是针对自然数类型 Nat 的。
下面关于计算自然数的例子 使用了代换外加自然数的结合律、交换律及分配律。
| |
注意到 Eq.subst 的第二个隐式参数
提供了将要发生代换的语境,其类型为 α → Prop;
这意味着推断这个谓词需要一个
高阶合一 High-Order Unification 的实例。
一般来说高阶合一器的存在性问题是不可判定的,
Lean 顶多只能提供不完美的和近似的解决方案,
因此 Eq.subst 并不总是能实现你想要的效果;
宏 h ▸ e 使用了更有效的启发式方法来计算这个隐式参数,
并且通常会在 Eq.subst 失效的情况下成功
由于等式推理是如此的普遍和重要, Lean 提供了许多机制以更有效地执行它。 下一节介绍的语法允许你以更自然和清晰的方式书写计算式证明。 但更重要的是,等式推理是由 项重写器 term rewriter、 简化器 simplifier 和 其他种类的自动化方法支持的。 项重写器和简化器将在下一节中简要描述, 而更多细节将在下一章中介绍。
4.3. 计算式证明 Calculational Proofs
计算式证明是一串中间结果,
这些结果通过如等式传递性这样的基本原理进行串联。
在 Lean 中计算式证明以关键字 calc 开始,语法如下:
| |
注意到 calc 下的每一对相等关系都使用了相同的缩进。
每个 <proof>_i 都是对 <expr>_{i-1} op_i <expr>_i 的证明。
我们也可以在第一对相等关系中使用 _(就在 <expr>_0 正后方),
如此便可将关系对/证明对对齐:
| |
下面是一个例子:
| |
这种书写证明的风格在与
simp 和
rewrite 策略结合使用时最为有效。
这些策略将在下一章中详细讨论。例如:若用缩写 rw 表示重写,
那么刚才的证明便可写成如下形式:
| |
rw 策略本质上会利用一个给定的等式
(可以是一个假设、一个定理名或者是一个复杂的项)来“重写”目标;
如果这样做能将目标简化为一种等式 t = t,
那么该策略就会应用自反性来证明它。
重写可以应用到一连串等式上, 因此刚才的证明可以简化为如下:
| |
甚至还可以更简洁:
| |
相反,simp 策略可以
以任意顺序
在项中任何适用的地方
重复应用给定的等式
来重写目标。它
还可以使用之前声明给系统的其他规则,且
还可以明智地应用交换性以避免陷入死循环。
如此我们便可如下证明定理:
| |
我们将在下一章讨论 rw 和 simp 的变体。
calc 命令可以针对任何支持某种形式传递性的关系进行配置。
它甚至可以组合不同的关系。
| |
你还可以“教会” calc 新的传递性定理——
只需加入 Trans 类型类下的新实例即可。
类型类会在后面介绍。
下面的小例子将演示
如何使用新的 Trans 实例
扩展 calc 表示法。
| |
上面的例子清楚地表明:
即便关系式中没有中缀符号,
你也依然可以使用 calc。
由于 Lean 已经包含了除法对应的标准 Unicode 符号
(即 ∣,可以通过输入 \dvd 或 \mid 来打出它),
上述例子采用的是普通的竖线以避免冲突;
但在实际使用中这可不是个好主意,
因为它可能会和 match ... with 表达式中的 ASCII | 混淆。
有了 calc 我们就可以以一种
更自然、更清晰的方式写出上一节的证明。
| |
这里值得考虑另一种 calc 表示法。当第一个表达式占用这么多空间时,
在第一个关系中使用 _ 自然会对齐所有关系式:
还有一种 calc 记法值得考虑:
当第一个表达式占用很多空间时,
在第一对关系中使用 _ 便可以自然地对齐所有关系式:
| |
rw[←Nat.add_assoc] 中 ← 存在与否的区别 | |
这里 Nat.add_assoc 之前的左箭头(可以输入 \l 或者是对应的 ASCII 码 <-)
指示 rewrite以相反的方向应用该等式。如果追求简洁,
那么 rw 和 simp 各自都可以单独完成这项任务:
| |
下面是一些与等式有关的练习:
记住:在没有任何参数的情况下,Prop 类型的表达式只是一个断言。请
填写下面 prime 和 Fermat_prime 的定义并
构造每个给定的断言。举个例子:你可以通过声称
对每个自然数 n 都存在一个大于 n 的素数来表示素数有无穷多个。
哥德巴赫弱猜想 Goldbach’s weak conjecture声称
每个大于 5 的奇数都可以表示为三个素数之和。如果有必要,
请查阅费马素数 Fermat prime 的定义或任何其他陈述。
| |
- 答:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29def divides (n m : Nat) : Prop := ∃ (k : Nat), k * n = m def even (n : Nat) : Prop := divides 2 n def prime (n : Nat) : Prop := ∀ (k : Nat), k != n ∧ k != n → ¬(divides k n) def infinitely_many_primes : Prop := ∀ (n : Nat), ∃ (k : Nat), k > n ∧ prime k def Fermat_prime (n : Nat) : Prop := prime n ∧ ∃ (k : Nat), (2^k + 1= n) def infinitely_many_Fermat_primes : Prop := ∀ (n : Nat), ∃ (k : Nat), k > n ∧ Fermat_prime k def goldbach_conjecture : Prop := ∀ (n : Nat), n > 2 ∧ even n → ∃ (p q : Nat), prime p ∧ prime q ∧ p + q = n def Goldbach's_weak_conjecture : Prop := ∀ (n : Nat), n > 2 ∧ even n → ∃ (p q r : Nat), prime p ∧ prime q ∧ prime r ∧ p + q + r = n def Fermat's_last_theorem : Prop := ∀ (n : Nat), n > 2 → ¬∃ (a b c : Nat), a^n + b^n = c^n
4.4. 存在量词 The Existential Quantifier
最后我们来看看存在量词:其可以写成
exists x : α, p x,也可以写成
∃ x : α, p x。
这两种写法其实都是一个更冗长的表达式的缩写,即
Exists (fun x : α => p x),定义位于 Lean 库中。
如你所想的那样,Lean 库中包含了
一个引入规则和
一个消去规则。
引入规则很直白:
要想证明 ∃ x : α, p x,
只需提供一个合适的项 t 以及 p t 的证明即可。
下面是一些例子:
| |
我们可以用匿名构造子表示法 ⟨t, h⟩ 代替 Exists.intro t h,
如果类型可从语境中推断出的话:
| |
注意到 Exists.intro 有隐式参数:
Lean 必须在结论 ∃ x, p x 中推断出谓词 p : α → Prop,而这并非易事;例如,
如果我们有 hg : g 0 0 = 0 并且写下 Exists.intro 0 hg,
那么谓词 p 就会有许多可能的取值,比如分别对应于命题
∃ x, g x x = x,
∃ x, g x x = 0,
∃ x, g x 0 = x,等等。
Lean 会利用语境来推断出哪个是合适的,
下面的例子对此进行了说明:当中
我们将选项 pp.explicit 设置为 true
以要求 Lean 美观显示隐式参数。
| |
我们可以将 Exists.intro 视为某种信息隐藏操作,
因为它将断言的具体实例隐藏起来并用存在量词代替。
存在消去规则 Exists.elim 则执行相反的操作,
它允许我们从 ∃ x : α, p x 证明一个命题 q;
这是通过展示对任意 w p w 都能推出 q 来实现的。粗略地说,
既然知道存在一个 x 满足 p x,
那么我们可以给它起个名字,比如 w。
如果 q 没有提到 w,
那么展示“p w 能推出 q”就等同
于展示“q 可以从任何这样的 x 的存在性而推得”。
下面是一个例子:
| |
将存在消去规则和析取消去规则进行比较可能会带来一些帮助。
命题 ∃ x : α, p x 可以看成一个关于命题 p a 的大型析取,
其中 a 遍历所有 α 中的元素。注意到
匿名构造子 ⟨w, hw.right, hw.left⟩ 是
嵌套的构造子 ⟨w, ⟨hw.right, hw.left⟩⟩ 的缩写。
带存在量词的命题与
Sigma 类型
很相似,后者在依值类型一节中提到过。
区别在于前者是命题,后者是类型。
不然的话它们非常相似。
给定谓词 p : α → Prop 和一族类型 β : α → Type,
对于项 a : α、h : p a、h' : β a 而言
项 Exists.intro a h 的类型是 (∃ x : α, p x) : Prop,而
项 Sigma.mk a h' 的类型是 (Σ x : α, β x) : Type。
∃ 和 Σ 之间的相似性是 Curry-Howard 同构的另一例子。
Lean 提供一个更加方便的消去存在量词的途径,
那就是通过 match 表达式:
| |
match 表达式是 Lean 函数定义系统的一部分,
其提供了方便且富有表达力的方式来定义复杂函数。
Curry-Howard 同构又一次让我们能够采用这种机制来编写证明。
match 语句会将带有存在量词的命题“解构”到组件 w 和 hw 中,
后者可以在语句体中被引用以用于证明命题。
我们还可以对 match 添加类型注释以使代码变得更清晰:
| |
甚至还可以在 match 语句中把合取也顺便解构掉:
| |
Lean 还提供了一个支持模式匹配的 let 表达式:
| |
这实际上是上面的 match 结构的替代记法。
Lean 还允许我们在 fun 表达式中使用隐式的 match:
| |
我们将在归纳和递归一章看到: 所有这些变体其实都是更一般的模式匹配构造的实例。
在下面的例子中,我们将 is_even a 定义为 ∃ a', a = 2 * a',
然后证明两个偶数的和是偶数。
| |
使用本章提到的各种小工具——
match 语句、
匿名构造子和
rewrite 策略,
我们可以简洁地写出如下证明:
| |
正如
构造主义的“或”比古典的“或”强,
构造主义的“存在”也会比古典的“存在”强。
例如下面的推论就需要经典推理:
因为从构造主义的角度来看,
知道“并不是每一个 x 都满足 ¬p”并不等同于
知道“有一个特定的 x 能满足 p”。
| |
下面是一些涉及到存在量词的常见等式。在下面的练习中, 我们鼓励你写出尽可能多的证明。 至于当中哪些是非构造主义的,需要你自己判断。 因此需要用到一些经典逻辑。
| |
注意到
第二个例子和
最后两个例子
要求假设至少有一个类型为 α 的元素 a。
以下是两个比较困难的问题的解:
| |
- 答:
简单版:
1 2 3 4 5 6 7 8variable (α : Type) (p q : α → Prop) (r : Prop) example : (∃ _ : α, r) → r :=λ (h : ∃ _ : α, r) ↦ match h with | Exists.intro _ hr => hr复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a example : (∃ _ : α, r) → r :=show (∃ _ : α, r) → r from fun -- → 引入 (h : ∃ _ : α, r) => -- (show r from Exists.elim -- ∃ 消去 (show ∃ _ : α, r from h) -- (show ∀ _ : α, r → r from fun -- ∀ 引入 (_ : α) => -- (show r → r from fun -- → 引入 (hr : r) => -- (show r from hr)))) -- - 答:
简单版:
1 2 3 4 5 6 7 8variable (α : Type) (p q : α → Prop) (r : Prop) example (a : α) : r → (∃ _ : α, r) :=λ (hr : r) ↦ ⟨a, hr⟩复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a example (a : α) : r → (∃ _ : α, r) :=show r → (∃ _ : α, r) from fun -- → 引入 (hr : r) => -- (show ∃ _ : α, r from Exists.intro -- ∃ 引入 (a : α) -- (show r from hr)) -- (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r答:简单版:
1 2 3 4 5 6 7 8 9 10 11variable (α : Type) (p q : α → Prop) (r : Prop) example : (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r :=Iff.intro (λ (h : ∃ x, p x ∧ r) ↦ match h with | ⟨w, hw⟩ => ⟨⟨w, hw.left⟩, hw.right⟩) (λ (h : (∃ x, p x) ∧ r) ↦ match h with | ⟨⟨w, hw⟩, hr⟩ => ⟨w, hw, hr⟩)复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a example : (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r :=Iff.intro (show (∃ x, p x ∧ r) → (∃ x, p x) ∧ r from fun -- → 引入 (h : ∃ x, p x ∧ r) => -- (show (∃ x, p x) ∧ r from Exists.elim -- ∃ 消去 (show ∃ x, p x ∧ r from h) -- (show ∀ x, p x ∧ r → (∃ x, p x) ∧ r from fun -- ∀ 引入 (x : α) => -- (show p x ∧ r → (∃ x, p x) ∧ r from fun -- → 引入 (hw : p x ∧ r) => -- (show (∃ x, p x) ∧ r from And.intro -- ∧ 引入 (show ∃ x, p x from Exists.intro -- ∃ 引入 (x : α) -- (show p x from And.left -- ∧ 消去 (show p x ∧ r from hw))) -- (show r from And.right -- ∧ 消去 (show p x ∧ r from hw))))))) -- (show (∃ x, p x) ∧ r → (∃ x, p x ∧ r) from fun -- → 引入 (h : (∃ x, p x) ∧ r) => -- (show ∃ x, p x ∧ r from Exists.elim -- ∃ 消去 (show ∃ x, p x from And.left -- ∧ 消去 (show (∃ x, p x) ∧ r from h)) -- (show ∀ x, p x → ∃ x, p x ∧ r from fun -- ∀ 引入 (x : α) => -- (show p x → ∃ x, p x ∧ r from fun -- → 引入 (hw : p x) => -- (show ∃ x, p x ∧ r from Exists.intro -- ∃ 引入 (x : α) -- (show p x ∧ r from And.intro -- ∧ 引入 (show p x from hw) -- (show r from And.right -- ∧ 消去 (show (∃ x, p x) ∧ r from h)))))))) --(∃ x, p x ∨ q x) ↔ (∃ x, p x) ∨ (∃ x, q x)答:简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13variable (α : Type) (p q : α → Prop) (r : Prop) example : (∃ x, p x ∨ q x) ↔ (∃ x, p x) ∨ (∃ x, q x) :=Iff.intro (λ (h : ∃ x, p x ∨ q x) ↦ match h with | ⟨x, Or.inl hp⟩ => Or.inl ⟨x, hp⟩ | ⟨x, Or.inr hq⟩ => Or.inr ⟨x, hq⟩) (λ (h : (∃ x, p x) ∨ (∃ x, q x)) ↦ match h with | Or.inl ⟨x, hp⟩ => ⟨x, Or.inl hp⟩ | Or.inr ⟨x, hq⟩ => ⟨x, Or.inr hq⟩)复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a example : (∃ x, p x ∨ q x) ↔ (∃ x, p x) ∨ (∃ x, q x) :=Iff.intro (show (∃ x, p x ∨ q x) → (∃ x, p x) ∨ (∃ x, q x) from fun -- → 引入 (h : ∃ x, p x ∨ q x) => -- show (∃ x, p x) ∨ (∃ x, q x) from Exists.elim -- ∃ 消去 (show ∃ x, p x ∨ q x from h) -- (show ∀ x, p x ∨ q x → (∃ x, p x) ∨ (∃ x, q x) from fun -- ∀ 引入 (x : α) => -- (show p x ∨ q x → (∃ x, p x) ∨ (∃ x, q x) from fun -- → 引入 (hpq : p x ∨ q x) => -- (show (∃ x, p x) ∨ (∃ x, q x) from Or.elim -- ∨ 消去 (show p x ∨ q x from hpq) -- (show p x → (∃ x, p x) ∨ (∃ x, q x) from fun -- → 引入 (hp : p x) => -- show (∃ x, p x) ∨ (∃ x, q x) from Or.inl -- ∨ 引入 (show ∃ x, p x from ⟨x, hp⟩)) -- (show q x → (∃ x, p x) ∨ (∃ x, q x) from fun -- → 引入 (hq : q x) => -- show (∃ x, p x) ∨ (∃ x, q x) from Or.inr -- ∨ 引入 (show ∃ x, q x from ⟨x, hq⟩)))))) -- (show (∃ x, p x) ∨ (∃ x, q x) → (∃ x, p x ∨ q x) from fun -- → 引入 (h : (∃ x, p x) ∨ (∃ x, q x)) => -- (show (∃ x, p x ∨ q x) from Or.elim -- ∨ 消去 (show (∃ x, p x) ∨ (∃ x, q x) from h) -- (show (∃ x, p x) → (∃ x, p x ∨ q x) from fun -- → 引入 (hp : ∃ x, p x) => -- (show ∃ x, p x ∨ q x from Exists.elim -- ∃ 消去 (show ∃ x, p x from hp) -- (show ∀ x, p x → (∃ x, p x ∨ q x) from fun -- ∀ 引入 (x : α) => -- (show p x → (∃ x, p x ∨ q x) from fun -- → 引入 (hp : p x) => -- (show ∃ x, p x ∨ q x from Exists.intro -- ∃ 引入 (x : α) -- (show p x ∨ q x from Or.inl -- ∨ 引入 (show p x from hp))))))) (show (∃ x, q x) → (∃ x, p x ∨ q x) from fun -- → 引入 (hq : ∃ x, q x) => -- (show ∃ x, p x ∨ q x from Exists.elim -- ∃ 消去 (show ∃ x, q x from hq) -- (show ∀ x, q x → (∃ x, p x ∨ q x) from fun -- ∀ 引入 (x : α) => -- (show q x → (∃ x, p x ∨ q x) from fun -- → 引入 (hq : q x) => -- (show ∃ x, p x ∨ q x from Exists.intro -- ∃ 引入 (x : α) -- (show p x ∨ q x from Or.inr -- ∨ 引入 (show q x from hq))))))))) --- 答:
简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30variable (α : Type) (p q : α → Prop) (r : Prop) open Classical example : (∀ x, p x) ↔ ¬(∃ x, ¬p x) := Iff.intro (λ (hall : ∀ x, p x) ↦ λ (hext : ∃ x, ¬p x) ↦ match hext with | ⟨x, hn⟩ => hn (hall x)) (λ (h : ¬ (∃ x, ¬p x)) ↦ λ (a : α) ↦ byContradiction λ (hn : ¬p a) ↦ h ⟨a, hn⟩) -- 这里附上 (p ∧ q) ↔ ¬(¬p ∨ ¬q) 的证明作为对比 variable (p q : Prop) example : (p ∧ q) ↔ ¬(¬p ∨ ¬q) :=Iff.intro (λ (hpq : p ∧ q) ↦ λ (hnpq : ¬p ∨ ¬q) ↦ match hnpq with | Or.inl hnp => hnp hpq.left | Or.inr hnq => hnq hpq.right) (λ (hnnpq : ¬(¬p ∨ ¬q)) ↦ And.intro (byContradiction (λ (hnp : ¬p) ↦ hnnpq (Or.inl hnp))) (byContradiction (λ (hnq : ¬q) ↦ hnnpq (Or.inr hnq))))复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a open Classical example : (∀ x, p x) ↔ ¬(∃ x, ¬p x) :=Iff.intro -- ↔ 引入 (show (∀ x, p x) → ¬(∃ x, ¬p x) from fun -- → 引入 (hall : ∀ x, p x) => -- (show ¬(∃ x, ¬p x) from fun -- ¬ 引入 (hext : ∃ x, ¬p x) => -- (show False from Exists.elim -- ∃ 消去 (show ∃ x, ¬p x from hext) -- (show ∀ x, ¬p x → False from fun -- ∀ 引入 (x : α) => -- (show ¬p x → False from fun -- → 引入 (hn : ¬p x) => -- (show False from To.elim -- ¬ 消去 (show ¬p x from hn) -- (show p x from All.elim -- ∀ 消去 (show ∀ x, p x from hall) -- (x : α)))))))) -- (show ¬(∃ x, ¬p x) → (∀ x, p x) from fun -- → 引入 (hextn : ¬(∃ x, ¬p x)) => -- (show ∀ x, p x from fun -- ∀ 引入 (x : α) => -- (show p x from To.elim -- → 消去 (show ¬¬p x → p x from dne) -- (show ¬p x → False from fun -- → 引入 (hn : ¬p x) => -- (show False from To.elim -- ¬ 消去 (show ¬(∃ x, ¬p x) from hextn) -- (show ∃ x, ¬p x from Exists.intro -- ∃ 引入 (x : α) -- (show ¬p x from hn))))))) -- - 答:
简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32variable (α : Type) (p q : α → Prop) (r : Prop) open Classical example : (∃ x, p x) ↔ ¬(∀ x, ¬p x) :=Iff.intro (λ (hext : ∃ x, p x) ↦ λ (hall : ∀ x, ¬p x) ↦ match hext with | ⟨x, hp⟩ => (hall x) hp) (λ (halln : ¬(∀ x, ¬p x)) ↦ byContradiction λ (hextn : ¬(∃ x, p x)) ↦ halln (λ (a : α) ↦ λ (hp : p a) ↦ hextn ⟨a, hp⟩)) -- 这里附上 (p ∨ q) ↔ ¬(¬p ∧ ¬q) 的证明作为对比 variable (p q : Prop) example : (p ∨ q) ↔ ¬(¬p ∧ ¬q) :=Iff.intro (λ (hpq : p ∨ q) ↦ λ (hnpnq : ¬p ∧ ¬q) ↦ match hpq with | Or.inl hp => (hnpnq.left) hp | Or.inr hq => (hnpnq.right) hq) (λ (hnnpnq : ¬(¬p ∧ ¬q)) ↦ byContradiction λ (hnpq : ¬(p ∨ q)) ↦ hnnpnq (And.intro (λ (hp : p) ↦ hnpq (Or.inl hp)) (λ (hq : q) ↦ hnpq (Or.inr hq))))复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a open Classical theorem dne {p : Prop} : ¬¬p → p :=λ (hnnp : ¬¬p) ↦ byCases (λ (hp : p) ↦ hp) (λ (hnp : ¬p) ↦ absurd hnp hnnp) example : (∃ x, p x) ↔ ¬(∀ x, ¬p x) :=Iff.intro -- ↔ 引入 (show (∃ x, p x) → ¬(∀ x, ¬p x) from fun -- → 引入 (hext : ∃ x, p x) => -- (show (∀ x, ¬p x) → False from fun -- ¬ 引入 (hall : ∀ x, ¬p x) => -- (show False from Exists.elim -- ∃ 消去 (show ∃ x, p x from hext) -- (show ∀ x, p x → False from fun -- ∀ 引入 (x : α) => -- (show p x → False from fun -- → 引入 (hp : p x) => -- (show False from To.elim -- → 消去 (show ¬p x from All.elim -- ∀ 消去 (show ∀ x, ¬p x from hall) -- (x : α)) -- (show p x from hp))))))) -- (show ¬(∀ x, ¬p x) → (∃ x, p x) from fun -- → 引入 (halln : ¬(∀ x, ¬p x)) => -- (show ∃ x, p x from To.elim -- → 消去 (show ¬¬(∃ x, p x) → ∃ x, p x from dne) -- (show ¬(∃ x, p x) → False from fun -- ¬ 引入 (hextn : ¬(∃ x, p x)) => -- (show False from To.elim -- ¬ 消去 (show ¬(∀ x, ¬p x) from halln) -- (show ∀ x, ¬p x from fun -- ∀ 引入 (x : α) => -- (show p x → False from fun -- ¬ 引入 (hp : p x) => -- (show False from To.elim -- ¬ 消去 (show ¬(∃ x, p x) from hextn) -- (show ∃ x, p x from Exists.intro-- ∃ 引入 (x : α) -- (show p x from hp))))))))) -- - 答:
简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29variable (α : Type) (p q : α → Prop) (r : Prop) example : ¬(∃ x, p x) ↔ (∀ x, ¬p x) :=Iff.intro (λ (hextn : ¬∃ x, p x) ↦ λ (x : α) ↦ λ (hp : p x) ↦ hextn ⟨x, hp⟩) (λ (halln : ∀ x, ¬p x) ↦ λ (hext : ∃ x, p x) ↦ Exists.elim hext halln) -- 这里附上 ¬(p ∨ q) ↔ ¬p ∧ ¬q 的证明作为对比(见上一章练习第 9 题) variable (p q : Prop) example : ¬(p ∨ q) ↔ ¬p ∧ ¬q :=Iff.intro (λ (hnpq : ¬(p ∨ q)) ↦ ⟨(λ (hp : p) ↦ hnpq (Or.inl hp)), (λ (hq : q) ↦ hnpq (Or.inr hq))⟩) (λ (hnpnq : ¬p ∧ ¬q) ↦ λ (hpq : p ∨ q) ↦ match hpq with -- 对应 Or.elim | Or.inl hp => (hnpnq.left) hp | Or.inr hq => (hnpnq.right) hq)复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a example : (¬∃ x, p x) ↔ (∀ x, ¬p x) :=Iff.intro (show (¬∃ x, p x) → (∀ x, ¬p x) from fun -- → 引入 (hextn : ¬∃ x, p x) => -- (show ∀ x, ¬p x from fun -- ∀ 引入 (x : α) => -- (show p x → False from fun -- ¬ 引入 (hp : p x) => -- show False from To.elim -- ¬ 消去 (show ¬∃ x, p x from hextn) -- (show ∃ x, p x from Exists.intro -- ∃ 引入 (x : α) -- (show p x from hp))))) -- (show (∀ x, ¬p x) → (¬∃ x, p x) from fun -- → 引入 (hall : ∀ x, ¬p x) => -- (show ¬∃ x, p x from fun -- ¬ 引入 (hext : ∃ x, p x) => -- (show False from Exists.elim -- ∃ 消去 (show ∃ x, p x from hext) -- (show ∀ x, p x → False from hall)))) -- - 答:
简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32variable (α : Type) (p q : α → Prop) (r : Prop) open Classical example : (¬∀ x, p x) ↔ (∃ x, ¬p x) :=Iff.intro (λ (halln : ¬(∀ x, p x)) ↦ byContradiction (λ (hextn : ¬(∃ x, ¬p x)) ↦ halln (λ (a : α) ↦ byContradiction (λ (hnp : ¬p a) ↦ hextn ⟨a, hnp⟩)))) (λ (hext : ∃ x, ¬p x) ↦ λ (hall : ∀ x, p x) ↦ match hext with | ⟨w, hnpw⟩ => hnpw (hall w)) -- 这里附上 ¬(p ∧ q) ↔ (¬p ∨ ¬q) 的证明作为对比(见上一章练习第 20 题和第 10 题) variable (p q : Prop) example : ¬(p ∧ q) ↔ (¬p ∨ ¬q) :=Iff.intro (λ (hnpq : ¬(p ∧ q)) ↦ byCases (λ (hp : p) ↦ Or.inr (λ (hq : q) ↦ hnpq ⟨hp, hq⟩)) (λ (hnp : ¬p) ↦ Or.inl hnp)) (λ (hnpnq : ¬p ∨ ¬q) ↦ λ (hpq : p ∧ q) ↦ match hnpnq with -- 对应 Or.elim | Or.inl hnp => hnp (And.left hpq) | Or.inr hnq => hnq (And.right hpq))复杂版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56variable (α : Type) (p q : α → Prop) (r : Prop) def To.elim {p q : Prop} : (p → q) → p → q :=λ (hpq : p → q) (hp : p) ↦ hpq hp def All.elim {α : Type} {p : α → Prop} : (∀ x : α, p x) → (a : α) → p a -- (a : α) → p a 相当于 ∀ (a : α), p a :=λ (h : ∀ x : α, p x) (a : α) ↦ h a open Classical theorem dne {p : Prop} : ¬¬p → p :=λ (hnnp : ¬¬p) ↦ byCases (λ (hp : p) ↦ hp) (λ (hnp : ¬p) ↦ absurd hnp hnnp) example : (¬∀ x, p x) ↔ (∃ x, ¬p x) :=Iff.intro -- ↔ 引入 (show (¬∀ x, p x) → (∃ x, ¬p x) from fun -- → 引入 (halln : ¬(∀ x, p x)) => -- (show ∃ x, ¬p x from To.elim -- → 消去 (show ¬¬(∃ x, ¬p x) → (∃ x, ¬p x) from dne) -- (show ¬(∃ x, ¬p x) → False from fun -- → 消去 (hextn : ¬(∃ x, ¬p x)) => -- let hall := -- show ∀ x, p x from fun -- ∀ 引入 (x : α) => -- (show p x from To.elim -- → 消去 (show ¬¬p x → p x from dne) -- (show ¬p x → False from fun -- (hnp : ¬p x) => -- (show False from To.elim -- → 消去 (show ¬(∃ x, ¬p x) from hextn) -- (show ∃ x, ¬p x from Exists.intro -- ∃ 引入 (x : α) -- (show ¬p x from hnp))))) -- (show False from To.elim -- → 消去 (show ¬(∀ x, p x) from halln) -- (show ∀ x, p x from hall))))) -- (show (∃ x, ¬p x) → (¬∀ x, p x) from fun -- → 引入 (hext : ∃ x, ¬p x) => -- (show (∀ x, p x) → False from fun -- ¬ 引入 (hall : ∀ x, p x) => Exists.elim -- ∃ 消去 (show ∃ x, ¬p x from hext) -- (show ∀ x, ¬p x → False from fun -- ∀ 引入 (x : α) => -- (show ¬p x → False from fun -- → 引入 (hnp : ¬p x) => -- (show False from To.elim -- → 消去 (show ¬p x from hnp) -- (show p x from All.elim -- ∀ 消去 (show ∀ x, p x from hall) -- (x : α))))))) -- (∀ x, p x → r) ↔ (∃ x, p x) → r答:简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14variable (α : Type) (p q : α → Prop) (r : Prop) example : (∀ x, p x → r) ↔ ((∃ x, p x) → r) :=Iff.intro (λ (hallpr : ∀ x, p x → r) ↦ λ (hextp : ∃ x, p x) ↦ match hextp with | ⟨x, hp⟩ => hallpr x hp) (λ (hextpr : (∃ x, p x) → r) ↦ λ (x : α) ↦ λ (hp : p x) ↦ hextpr ⟨x , hp⟩)复杂版:
懒得写了。略。
α → ((∃ x, p x → r) ↔ (∀ x, p x) → r)答:简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20variable (α : Type) (p q : α → Prop) (r : Prop) open Classical example : (∃ x, p x → r) → (∀ x, p x) → r :=λ (hextpr : ∃ x, p x → r) ↦ λ (hallp : ∀ x, p x) ↦ match hextpr with | ⟨x, hpr⟩ => hpr (hallp x) example : α → ((∀ x, p x) → r) → (∃ x, p x → r) :=λ (x : α) ↦ λ (hallpr : (∀ x, p x) → r) ↦ byContradiction (λ (hnex : ¬(∃ x, p x → r)) ↦ (let hallp : ∀ x, p x :=λ (x : α) ↦ byContradiction (λ (hnpx : ¬p x) ↦ hnex ⟨x, λ (hp : p x) ↦ absurd hp hnpx⟩) hnex ⟨x, λ (_ : p x) ↦ hallpr hallp⟩))复杂版:
懒得写了。略。
α → ((∃ x, r → p x) ↔ (r → ∃ x, p x))答:简单版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17variable (α : Type) (p q : α → Prop) (r : Prop) open Classical example : (∃ x, r → p x) → (r → ∃ x, p x) :=(λ (h : ∃ x, r → p x) ↦ λ (hr : r) ↦ match h with | ⟨x, hrp⟩ => ⟨x, hrp hr⟩) example (x : α) : (r → ∃ x, p x) → (∃ x, r → p x) :=λ (hrextp : r → ∃ x, p x) ↦ byCases (λ (hr : r) ↦ match (hrextp hr) with | ⟨x, hp⟩ => ⟨x, λ (_: r) ↦ hp⟩) (λ (hnr : ¬r) ↦ ⟨x, (λ (hr : r) ↦ absurd hr hnr)⟩)复杂版:
懒得写了。略。
4.5. 再来些证明语法 More on the Proof Language
我们已经看到:像 fun、have、show 这样的关键字
可使得形式化的证明项能够反映出非正式数学证明的结构。
本节我们将讨论证明语言的一些附加特性,它们会在实际使用中带来便利。
首先我们可以使用 have 表达式引入匿名的辅助目标。
若是想引用最后一个以此方式引入的表达式,
则可以考虑使用关键字 this:
| |
由于证明通常是从一个事实转移到另一个事实, 因此这可以有效地消除大量杂乱标签。
当目标是可被推断的时,我们也可以让 Lean 自己补充证明——只需写下 by assumption:
| |
这会让 Lean 使用 assumption 策略——
即通过在局部语境中找到合适的假设来证明目标。
我们将在下一章中
学到更多关于 assumption 策略的内容。
我们也可以通过写下 ‹p› 来要求 Lean 填写证明:
其中 p 是命题,我们希望 Lean 能在语境中找到它的证明。
你可以分别使用 \f< 和 \f> 来输入这些角引号。
字母“f”表示“French”,因为对应的 unicode 符号也可以作为法语引号。
这个符号在 Lean 中的定义其实是这样的:
| |
这种方法比使用 by assumption 更稳健,
因为需要推断的假设类型是显式给出的。
它还使证明更具可读性。这里有一个更详细的例子:
| |
请留意:法语引号可用来指代语境中的“任何东西”, 而非仅局限于通过匿名方式引入的东西。 它的使用也并非局限于命题—— 尽管将其用于其他数据类型看起来可能会有点怪:
| |
接下来我们将展示如何使用 Lean 中的宏系统扩展证明语言。
索引 Index
术语
ID 使用 term:<中文术语>。
- 全称引入 Universal Quantifier Introduction
- 全称消去 Universal Quantifier Elimination
- 非直谓性 Impredicative
- 传递性 Transitivity
- 等号引入 Equality Introduction,即自反性 Transitivity
- 等号消去 Equality Elimination,即代换性
- 高阶合一 High-Order Unification
- 存在引入 Existential Quantifier Introduction
- 存在消去 Existential Quantifier Elimination
- 理发师悖论 Barber Paradox
- 哥德巴赫弱猜想 Weak Goldbach Conjecture
- 费马素数 Fermat Prime
语法
ID 使用 synt:<关键字>。
- 语法
... ▸ ... - 策略
calc[...] - 策略
simp[...] - 策略
rw[...] - 语法
rw[←...] - 语法
match ... with ... - 语法
this - 策略
assumption - 语法
‹...›
代码块
ID 使用 S<小节>.code<编号>。
S04-01-code01.lean:创建例子(∀ x : α, p x ∧ q x) → (∀ x : α, p x)S04-01-code02.lean:创建例子(∀ x : α, p x ∧ q x) → (∀ x : α, p x)(约束变量重命名)S04-01-code03.lean:检查命题 二元关系r的传递性(显示参数)S04-01-code04.lean:检查命题 二元关系r的传递性(隐式参数)S04-01-code05.lean:创建例子 等价关系r可推出r a bS04-02-code01.lean:检查命题 相等关系Eq的自反/对称/传递性S04-02-code02.lean:检查命题 相等关系Eq的自反/对称/传递性(使用宇宙变量)S04-02-code03.lean:创建例子a = b(使用等号规则)S04-02-code04.lean:创建例子a = b(使用等号规则(投影))S04-02-code05.lean:创建例子 一些平凡命题(使用等号引入)S04-02-code06.lean:创建例子 一些平凡命题(使用等号引入(rfl))S04-02-code07.lean:创建例子p a = p b(使用等号消去(▸))S04-02-code08.lean:创建例子 一些平凡命题(使用等号消去的推论(congr、congrArg、congrFun))S04-02-code09.lean:创建例子 一些平凡命题(使用自然数算术相关定理)S04-02-code10.lean:创建例子 和平方的展开(使用自然数算术相关定理以及等号消去(▸))S04-03-code01.lean:介绍calc语法(第一种形式)S04-03-code02.lean:介绍calc语法(第二种形式)S04-03-code03.lean:创建定理a = e(使用calc)S04-03-code04.lean:创建定理a = e(使用calc和rw)S04-03-code05.lean:创建定理a = e(使用calc和rw,更简洁的版本)S04-03-code06.lean:创建定理a = e(使用rw)S04-03-code07.lean:创建定理a = e(使用simp)S04-03-code08.lean:创建定理a < d(使用calc)S04-03-code09.lean:创建定理(x | y) ∧ (y = z) → (x | 2*z)(使用calc)S04-03-code10.lean:创建例子 和平方的展开(使用calc)S04-03-code11.lean:创建例子 和平方的展开(使用calc,第二种形式)S04-03-code12.lean:创建例子 和平方的展开(使用rw和simp)S04-04-code01.lean:创建例子 一些平凡命题(使用存在引入)S04-04-code02.lean:创建例子 一些平凡命题(使用存在引入(匿名构造子))S04-04-code03.lean:打印例子 存在引入的模式匹配S04-04-code04.lean:创建例子∃ x, p x ∧ q x → ∃ x, q x ∧ p x(使用存在消去和合取消去)S04-04-code05.lean:创建例子∃ x, p x ∧ q x → ∃ x, q x ∧ p x(使用存在消去(match解构∃)和合取消去)S04-04-code06.lean:创建例子∃ x, p x ∧ q x → ∃ x, q x ∧ p x(使用存在消去(match解构∃,附类型注释)和合取消去)S04-04-code07.lean:创建例子∃ x, p x ∧ q x → ∃ x, q x ∧ p x(使用存在消去和合取消去(match解构∃和∧))S04-04-code08.lean:创建例子∃ x, p x ∧ q x → ∃ x, q x ∧ p x(使用存在消去和合取消去(let解构∃和∧))S04-04-code09.lean:创建例子∃ x, p x ∧ q x → ∃ x, q x ∧ p x(使用存在消去和合取消去(隐式match解构∃和∧))S04-04-code10.lean:创建定理 偶数的和是偶数(使用存在规则)S04-04-code11.lean:创建定理 偶数的和是偶数(使用存在规则(match))S04-04-code12.lean:创建例子¬∀ x, ¬p x -> ∃ x, p x(使用存在规则和经典逻辑)S04-04-code13.lean:练习 5 题目S04-05-code01.lean:创建例子f 0 ≤ f 3(使用have(匿名)并用this调用S04-05-code02.lean:创建例子f 0 ≤ f 3(使用have(匿名)并用by assumption调用)S04-05-code03.lean:‹...›的定义S04-05-code04.lean:创建例子f 0 ≤ f 3(使用have(匿名)并用‹...›调用)S04-05-code05.lean:创建例子Nat → Nat(对任何类型使用‹...›)S04-06-code01.lean:练习 1 题目S04-06-code02.lean:练习 2 题目S04-06-code03.lean:练习 3 题目S04-06-code04.lean:练习 4 题目
练习
ID 使用 exer<编号>。
第一部分(全称量词与合取、蕴含、析取的关系):
(∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x)(∀ x, p x → q x) → (∀ x, p x) → (∀ x, q x)(∀ x, p x) ∨ (∀ x, q x) → ∀ x, p x ∨ q x
第二部分(全称量词的删去):
第三部分(理发师悖论):
第四部分(自然数与等式):
第五部分(存在量词):
(∃ x : α, r) → rα → r → (∃ x : α, r)(∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r(∃ x, p x ∨ q x) ↔ (∃ x, p x) ∨ (∃ x, q x)(∀ x, p x) ↔ ¬(∃ x, ¬p x)(∃ x, p x) ↔ ¬(∀ x, ¬p x)¬(∃ x, p x) ↔ (∀ x, ¬p x)¬(∀ x, p x) ↔ (∃ x, ¬p x)(∀ x, p x → r) ↔ (∃ x, p x) → rα → ((∃ x, p x → r) ↔ (∀ x, p x) → r)α → ((∃ x, r → p x) ↔ (r → ∃ x, p x))
微信