探索归纳的奥秘


从初中开始我们就使用数学归纳法证明数学题,我们首先需要确定归纳的基础,在n=1或n=1,n=2时式子成立,然后在此基础上假设n=k-1时所证内容成立,从而推导出n=k时成立,命题得证,实际上归纳是数学的基础之一,我们利用归纳定义了自然数,定义了布尔表达式,在机器证明系统中归纳法也有着不可磨灭的作用,本文将介绍集合论中归纳法的应用,以及归纳法在coq证明系统中的应用。
首先要明确归纳法的核心 归纳基础构造算子

集合论中的归纳法

这里的归纳法都基于集合,那么我们先从集合的构造讲起(这部分内容在集合论(二)中有涉及,但是笔者觉得和induction结合在一起更容易理解)

集合的构造——从有限到无限

从1到自然数

😈 Power Set
对于每个集合S,存在一个集合,该集合的元素正好是集合S的子集合,称之为S的幂集合,记为℘(S),或者2^s
幂集合的基数
😈 自然数的构造
|O:base
|S:nat→nat
比如这样一种归纳:

Inductive nat:Set:=
|Lilghost
|Darling (n:nat).
Check Darling(Lilghost).

利用空集合构造自然数
在这里插入图片描述
在这里插入图片描述

从序偶到多元组

😈 序偶是两个元素组成的对象,(第一分量,第二分量)
将序偶理解为(a,b)=(a,{a,b})表示两个元素不等价,不在一个次元
证明(a,b)=(a’,b’)的充要条件(这里仅证明必要性)

Theorem equl:forall a b m n:nat,
a=m->b=n->(a,b)=(m,n).
Proof.
  intros.
  rewrite H0.
  rewrite H.
  reflexivity.
Qed.

😈 n-tuple n元组
多元函数运用到高阶函数(维基百科)
设 (a1; a2; : : : ; an) (n >= 2) 是 n 元组,则 n + 1 元组定义
为 (a1; a2; : : : an; a) ≜ ((a1; a2; : : : an); a).
😈 字符串的归纳定义

在这里插入图片描述
当集合Σ为任意集合时,就是我们定义的链表。(见coq-list部分)
😈连接运算
在这里插入图片描述

计算机中的归纳思想

  • 归纳定义从最小的元素开始按照归纳条款有限步骤内逐步增长到被定义的集合
  • 根据可计算性理论,计算机处理的对象一定是具有归纳结构的集合
  • 数据结构的链表,栈和树等等

利用归纳法证明

😈结构归纳法:
在这里插入图片描述

coq:Induction

Require export

from LP require export basic这条语句表示从有前缀LP相关的目录中导入basic.vo相关的内容

Proof by Induction

😈 证明0是一个neutral element for +
第一反应的证明:

Theorem neutral_0 : forall n:nat,
n+0=n.
Proof.
 intros.
 simpl.
 reflexivity.
Qed.

但是coq中的simpl只能简化一些确定的值,如1+2=3这类简化,n是未知的,就好像是n+1不能看作(n+1)一样,前者的加是运算符,后者是一个整体的数字,所以我们必须使用枚举法标识出n所有可能的情况,但是当n很大时,显然使用destruct分类很不明智,我们就要考虑到归纳法
归纳基础:n=0时成立
证明当n=k-1时成立,从而证明n=k时成立
我们先来看看coq代码是怎样实现的:

Theorem netrul :forall n,n+0=n.`对定理的描述`
Proof.
  intros.
  induction n as [|n' HL].`将n析构为0和n’,但是同时给出条件HL作为归纳假设,表示当n’时上式成立`
  -reflexivity.
  -simpl. rewrite HL. reflexivity.`要证明的式子为:S n’=S n’+0,simpl后变为S n’=S(n’+0),代入归纳假设得证`
Qed.

关于S n’+0=S(n’+0),这里体现了之前介绍一进制数字加法的基本规则,比如A+B,相当于A+B的前驱再取后继。
induction规则能自动执行intros的效果,但是笔者的coq笔记主要讲述离散数学中的基本思想,对于基本语法关注较少。

Proofs within proofs

我们在证明一个定理时,通常需要用到其他的定理,这时我们就有一个关于定理的结构,哪个定理是需要证明的主要定理,哪个是他的子定理,为了方便起见,我们用assert描述需要用到的子定理,更清晰的展现定理之间的关系。
😈

Theorem mult_0_plus' : forall n m : nat,
  (0 + n) * m = n * m.
Proof.
  intros n m.
  assert (H: 0 + n = n). { reflexivity. } 
  rewrite -> H.
  reflexivity. 
Qed.

通过逐步运行,发现assert会产生两个子目标,一个是证明我们需要的前提,另一个是我们利用前提证明的定理。用{}表示对assert的证明过程。
😈 rewrite功能的局限
在之前的博客中我们证明了析取运算的交换律,发现了一些问题。

Theorem andb_commutative : forall b c,  (b & c) =  (c & b).
Proof.
  intros b c. destruct b.
  - destruct c.
    + reflexivity.
    + reflexivity.
  - destruct c.
    + reflexivity.
    + reflexivity.
Qed.

Theorem andb_assoc: forall b c d : bool, (b & c & d) = ((b & c) & d). 
Proof.
  intros.
  destruct b.
  - destruct c.
    + destruct d.
      * reflexivity.
      * reflexivity.
    + destruct d; reflexivity.
  - destruct c; destruct d; reflexivity.
Qed.

Theorem andb_permute: forall b c d, (b & c & d) = (d & c & b).
Proof.
  intros.
  rewrite andb_commutative.//之前规定了是右结合,所以这个会应用到左式最右边的与运算,所以下边使用函数化运用交换律,此时交换律运用到参数b0
  pattern (c & d).
  rewrite andb_commutative.
  symmetry.//rewrite只能从左到右替换,选择交换。
  apply andb_assoc.
Qed.

在这里插入图片描述
rewrite在面临多个运算符时,会优先考虑到括号外的运算符。(由于coq很多定理证明需要之前的定理,为了节约阅读时间,只展示主定理证明过程)

Theorem plus_rearrange_firsttry : 
forall n m p q : nat,
  (n + m) + (p + q) = (m + n) + (p + q).
Proof.
  intros n m p q.
  (* We just need to swap (n + m) for (m + n)... seems
     like plus_comm should do the trick! *)
  rewrite -> plus_comm.
  (* Doesn't work...Coq rewrites the wrong plus! *)
Abort.

assert可以对我们这里需要用到的m+n=n+m进行特指的证明。

Theorem plus_rearrange_firsttry : 
forall n m p q : nat,
  (n + m) + (p + q) = (m + n) + (p + q).
Proof.
  intros n m p q.
  assert (H:n+m=m+n).  { rewrite plus_comm. reflexivity. }
  rewrite -> H.
  reflexivity.
Qed.

应用举例:list的构造

Pairs of Numbers

😈 Inductive接受多个参数
⭐ 两个参数

Inductive natprod:Type :=
|pair (n1 n2:nat).
Check pair 3 5.
Definition fst (p:natprod):nat:=
match p with
|pair x y=>x
end.
Definition snd (p:natprod):nat:=
match p with
|pair x y=>y
end.
Compute fst (pair 3 5).
Notation "( x , y )":=(pair x y).
Compute fst (3,5).
Definition swap_pair (p:natprod):natprod:=
match p with
|(x,y)=>(y,x)
end.
Compute swap_pair (3,5).

pair两种表示方式的不同证明:

Theorem surjective_pairing' : 
forall (n m : nat),
  (n,m) = (fst (n,m), snd (n,m)).
Proof.
  reflexivity. 
Qed.

Theorem surjective_pairing_stuck : 
forall (p : natprod),
  p = (fst p, snd p).
Proof.
  intros.
  destruct p as [n m].
  simpl. reflexivity. 
Qed.

😈 list of numbers
定义链表:

Inductive natlist :Type:=
|nil
|cons (a:nat) (l:natlist).
Definition mylist:=cons 1(cons 2(cons 3 nil)).
Notation "[ ]":=nil.
Notation "[ a ; .. ; b ]" := (cons a .. (cons b nil) .. ).

利用递归函数求解链表的一些问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值