IndProp章节中pumping lemma的证明

software foundations–Logic foudations–IndProp中,有一个证明pumping lemma的练习,本文介绍了一种证明方法。

辅助引理

为了证明pumping lemma,除了software foundations–Logic foudations–IndProp中已经给出的引理外(napp_star, pumping_constant_0_false ),还使用了下边两个新定义的引理。

le_plus_both

Lemma le_plus_both: forall (a b c d : nat), a <= c -> b <= d -> a + b <= c + d.
Proof.
  intros a.
  induction a.
  -intros b c d H1 H2. simpl. apply le_trans with (n := d). apply H2. 
  rewrite -> plus_comm. apply le_plus_l.
  -intros b c d H1 H2. destruct c.
  --inversion H1.
  --simpl. apply n_le_m__Sn_le_Sm. apply Sn_le_Sm__n_le_m in H1. 
  apply (IHa b c d H1) in H2. apply H2.
Qed.

le_false_rev

Lemma le_false_rev: forall (a b : nat), (a <=? b = false) -> b <= a.
Proof.
  intros a.
  induction a.
  -intros b H. simpl in H. discriminate.
  -intros b H. destruct b.
  --simpl in H. apply O_le_n.
  --simpl in H. apply n_le_m__Sn_le_Sm. apply IHa. apply H.
Qed.

证明思路

pumping lemma的表述如下

Lemma pumping : forall T (re : reg_exp T) s,
  s =~ re ->
  pumping_constant re <= length s ->
  exists s1 s2 s3,
    s = s1 ++ s2 ++ s3 /\
    s2 <> [] /\
    length s1 + length s2 <= pumping_constant re /\
    forall m, s1 ++ napp m s2 ++ s3 =~ re.

可以看到,基本思路是对s =~ re的可能情况进行归纳证明。

在归纳证明的过程中,MEmpty, MChar, MStar0的可能情况证明很简单,MUinonLMUnionR稍微困难一些,MAddMStar是最困难的部分。 我们首先讨论Madd的证明思路。

MAdd

Madd子目标如下

pumping_constant re1 + pumping_constant re2 <= length (s1 ++ s2) ->
exists s0 s3 s4 : list T,
  s1 ++ s2 = s0 ++ s3 ++ s4 /\
  s3 <> [ ] /\
  length s0 + length s3 <= pumping_constant re1 + pumping_constant re2 /\
  (forall m : nat, s0 ++ napp m s3 ++ s4 =~ App re1 re2)

可以看到,我们可以使用的假设为pumping_constant re1 + pumping_constant re2 <= length (s1 ++ s2), 然后存在两个归纳假设

Hmatch1 : s1 =~ re1
Hmatch2 : s2 =~ re2
IH1 : pumping_constant re1 <= length s1 ->
      exists s2 s3 s4 : list T,
        s1 = s2 ++ s3 ++ s4 /\ s3 <> [ ] /\ length s2 + length s3 <= pumping_constant re1 /\ (forall m : nat, s2 ++ napp m s3 ++ s4 =~ re1)
IH2 : pumping_constant re2 <= length s2 ->
      exists s1 s3 s4 : list T,
        s2 = s1 ++ s3 ++ s4 /\ s3 <> [ ] /\ length s1 + length s3 <= pumping_constant re2 /\ (forall m : nat, s1 ++ napp m s3 ++ s4 =~ re2)

为了利用归纳假设,我们需要构建出pumping_constant re1 <= length s1或者pumping_constant re2 <= length s2这样的假设来。根据pumping_constant re1 + pumping_constant re2 <= length (s1 ++ s2),以及本章前部分证明的add_le_case引理,可以得到如下假设。

H : pumping_constant re1 <= length s1 \/ pumping_constant re2 <= length s2

之后进行分类讨论,分别在pumping_constant re1 <= length s1pumping_constant re2 <= length s2的完成证明。

pumping_constant re1 <= length s1

根据该假设(pumping_constant re1 <= length s1)以及归纳假设IH1,可以得到归纳假设的结论部分(注意这里面只有s1是一个具体的值,其他都是未确定的遍历),假设其为H3.

H3: exists s2 s3 s4 : list T,
        s1 = s2 ++ s3 ++ s4 /\ s3 <> [ ] /\ length s2 + length s3 <= pumping_constant re1 /\ (forall m : nat, s2 ++ napp m s3 ++ s4 =~ re1)

我们给其指定具体值x, x0, x1,则得到

H3: s1 = x ++ x0 ++ x1 /\ x0 <> [ ] /\ length x + length x0 <= pumping_constant re1 /\ (forall m : nat, x ++ napp m x0 ++ x1 =~ re1)

我们基于这个结论来构造我们的目标

exists s0 s3 s4 : list T,
  s1 ++ s2 = s0 ++ s3 ++ s4 /\
  s3 <> [ ] /\
  length s0 + length s3 <= pumping_constant re1 + pumping_constant re2 /\
  (forall m : nat, s0 ++ napp m s3 ++ s4 =~ App re1 re2)

首先根据MApp的规则,s1 =~ re1, s2 =~ re2 -> s1 ++ s2 =~ App re1 re2,在H3中我们已经有x ++ napp m x0 ++ x1 =~ re1, 并且s2=~ re2. 因此我们指定目标中s0 = x, s3 = x0, s4 = x1 + s2. 后续证明就较为简单了.

pumping_constant re2 <= length s2

根据该假设(pumping_constant re2 <= length s2)以及归纳假设IH2,同样可以得到归纳假设的结论部分(注意这里面只有s2是一个具体的值,其他都是未确定的遍历),假设其为H4.

H4 : exists s1 s3 s4 : list T,
        s2 = s1 ++ s3 ++ s4 /\ s3 <> [ ] /\ length s1 + length s3 <= pumping_constant re2 /\ (forall m : nat, s1 ++ napp m s3 ++ s4 =~ re2)

同样给其指定具体值x, x0, x1得到

H4: s2 = x ++ x0 ++ x1 /\ x0 <> [ ] /\ length x + length x0 <= pumping_constant re2 /\ (forall m : nat, x ++ napp m x0 ++ x1 =~ re2)

这里的x ++ napp m x0 ++ x1 =~ re2,因此根据MApp的规则,和pumping_constant re1 <= length s1的情况不同, 我们需要指定目标中s0 = s1 ++ x, s3 = x0, s4 = x1. 然而,后续的证明还是存在问题,因为我们难以证明

length (s1 ++ x) + length x0 <= pumping_constant re1 + pumping_constant re2

根据已有的结论length x + length x0 <= pumping_constant re2, 我们可以将该目标转换为证明length s1 <= pumping_constant re1. 但显然,这个结论是证明不了的,因此按照这种方式进行证明存在一定问题。

从上述分析中可以看到,length s1 <= pumping_constant re1是否成立影响了证明过程,我们可以考虑对其进行分类讨论。

如果length s1 <= pumping_constant re1成立,则我们可以继续上述证明过程,后续证明类似对pumping_constant re1 <= length s1情况的证明。

如果length s1 <= pumping_constant re1不成立,则必有pumping_constant re1 <= length s1成立(根据辅助引理小节证明的le_false_rev引理可以得到)。在这种情况下,则可以按照和前一小节pumping_constant re1 <= length s1完全一致的方法完成证明。

按照这个分类讨论的思路,即可在pumping_constant re2 <= length s2成立的情况下完成证明。分类讨论的具体方法,则是使用assert引入如下假设H并进行证明,然后再使用destruct对该假设进行分类讨论。

-- assert(H : (pumping_constant re1 <=? length s1) = true \/ (length s1 <=? pumping_constant re1) = true).
{   
    destruct (pumping_constant re1 <=? length s1) eqn:E.
    * left. reflexivity.
    * right. apply le_false_rev in E. rewrite -> leb_iff. apply E.
}

MStar

MStar子目标中存在如下假设

Hmatch1 : s1 =~ re
Hmatch2 : s2 =~ Star re
IH1 : pumping_constant re <= length s1 ->
      exists s2 s3 s4 : list T,
        s1 = s2 ++ s3 ++ s4 /\
        s3 <> [ ] /\
        length s2 + length s3 <= pumping_constant re /\
        (forall m : nat, s2 ++ napp m s3 ++ s4 =~ re)
IH2 : pumping_constant (Star re) <= length s2 ->
      exists s1 s3 s4 : list T,
        s2 = s1 ++ s3 ++ s4 /\
        s3 <> [ ] /\
        length s1 + length s3 <= pumping_constant (Star re) /\
        (forall m : nat, s1 ++ napp m s3 ++ s4 =~ Star re)

目标如下

pumping_constant (Star re) <= length (s1 ++ s2) ->
exists s0 s3 s4 : list T,
  s1 ++ s2 = s0 ++ s3 ++ s4 /\
  s3 <> [ ] /\
  length s0 + length s3 <= pumping_constant (Star re) /\
  (forall m : nat, s0 ++ napp m s3 ++ s4 =~ Star re)

根据IndProp前边部分已经证明的引理napp_star我们可以看到指定s0 = [], s3 = s1, s4 = s2即可证明forall m : nat, s0 ++ napp m s3 ++ s4 =~ Star re. 然而,这其中困难的地方在于我们难以证明s1 <> [],因此需要对s1进行分类讨论,讨论s1 = []s1 <> [](s1 = x :: t)的情况。(使用destruct)。

s1 = []

该情况下目标可以转换为

pumping_constant (Star re) <= length  s2 ->
exists s0 s3 s4 : list T,
  s2 = s0 ++ s3 ++ s4 /\
  s3 <> [ ] /\
  length s0 + length s3 <= pumping_constant (Star re) /\
  (forall m : nat, s0 ++ napp m s3 ++ s4 =~ Star re)

这同归纳假设IH2是完全一致的,因此使用apply IH2即可证明。

s1 = x :: t

该情况可以继续上述证明思路,我们继续指定目标中s0 = [], s3 = s1, s4 = s2. 此时很容易证明s1 <> [],然而无法证明

length s1 <= pumping_constant (Star re)

上述目标化简得到

length s1 <= pumping_constant re

因此,我们同样考虑使用分类讨论的方法来完成证明,即分为length s1 <= pumping_constant re成立和pumping_constant re <= length s1成立两种情况来进行证明。

length s1 <= pumping_constant re

该情况成立时,可以继续按照指定目标中s0 = [], s3 = s1, s4 = s2的方法来完成后续证明,后续证明较为容易。

pumping_constant re <= length s1

该情况成立时,不能按照指定目标中s0 = [], s3 = s1, s4 = s2的方法来进行证明,因此,我们给目标中存在量词修饰的变量指定具体值的时机不能在对length s1 <= pumping_constant re是否成立进行分类讨论之前

该情况成立时的证明过程同上述MApp小节证明过程中pumping_constant re1 <= length s1的情况几乎一致,唯一的区别是最后使用MStarApp规则来构建x + napp m x0 + x1 + s2 = Start re(因为x + napp m x0 + x1 =~ re, 并且re2 =~ re).

分类讨论的方法还是同MApp小节的pumping_constant re2 <= length s2的情况中使用的方法一致,使用assert引入新假设来并使用destruct来实现。

assert(Hd : (pumping_constant re <=? length s) = true \/ (length s <=? pumping_constant re) = true).
{   
    destruct (pumping_constant re <=? length s) eqn:E.
    *left. reflexivity.
    *right. apply le_false_rev in E. rewrite -> leb_iff. apply E.
}

其他情况

其他子目标的证明可以在coq中运行如下证明过程来详细了解,记得将辅助引理部分的引理加入。

证明

Lemma pumping : forall T (re : reg_exp T) s,
  s =~ re ->
  pumping_constant re <= length s ->
  exists s1 s2 s3,
    s = s1 ++ s2 ++ s3 /\
    s2 <> [] /\
    length s1 + length s2 <= pumping_constant re /\
    forall m, s1 ++ napp m s2 ++ s3 =~ re.

Proof.
  intros T re s Hmatch.
  induction Hmatch
    as [ | x | s1 re1 s2 re2 Hmatch1 IH1 Hmatch2 IH2
       | s1 re1 re2 Hmatch IH | re1 s2 re2 Hmatch IH
       | re | s1 s2 re Hmatch1 IH1 Hmatch2 IH2 ].
  (* MEmpty *)
  - simpl. intros contra. inversion contra.
  (* MChar *)
  - simpl. intros contra. inversion contra. inversion H0.
  (* MAdd *)
  - simpl. intros H. rewrite -> app_length in H. apply add_le_cases in H.
    destruct H as [H1 | H2].
  (* MAdd-1 pumping_constant re1 <= length s1 *)
  -- apply IH1 in H1.  destruct H1 as (x & x0 & x1 & H). destruct H as (H1 & H2 & H3 & H4).
  exists x. exists x0. exists (x1 ++ s2). split;[|split ;[|split]].
    * rewrite -> app_assoc. rewrite -> app_assoc. rewrite <- (app_assoc T x x0 x1).
      rewrite <- H1. reflexivity.
    * apply H2.
    * apply le_trans with (o := pumping_constant re1 + pumping_constant re2) in H3. apply H3. 
      apply le_plus_l. 
    * intros m. rewrite -> app_assoc. rewrite -> app_assoc.
      rewrite <- (app_assoc T x (napp m x0) x1). apply MApp. apply H4. apply Hmatch2.
  (* MAdd-2 pumping_constant re2 <= length s2 *)
  (* 引入一个假设,进行分类讨论 *)
  -- assert(H : (pumping_constant re1 <=? length s1) = true \/ (length s1 <=? pumping_constant re1) = true).
     {   
       destruct (pumping_constant re1 <=? length s1) eqn:E.
       * left. reflexivity.
       * right. apply le_false_rev in E. rewrite -> leb_iff. apply E.
     }
     destruct H as [H3 | H4].
     (* 和MAdd-1完全一致 pumping_constant re1 <= length s1 *)
     * apply leb_iff in H3. apply IH1 in H3.  destruct H3 as (x & x0 & x1 & H). destruct H as (H3 & H4 & H5 & H6).
       exists x, x0, (x1 ++ s2). split;[|split ;[|split]].
     ** rewrite -> app_assoc. rewrite -> app_assoc. rewrite <- (app_assoc T x x0 x1).
        rewrite <- H3. reflexivity.
     ** apply H4. 
     ** apply le_trans with (o := pumping_constant re1 + pumping_constant re2) in H5. apply H5. 
        apply le_plus_l. 
     ** intros m. rewrite -> app_assoc. rewrite -> app_assoc.
        rewrite <- (app_assoc T x (napp m x0) x1). apply MApp. apply H6. apply Hmatch2.
     (* length s1 <= pumping_constant re1 && pumping_constant re2 <= length s2 *)  
     * apply leb_iff in H4. apply IH2 in H2. destruct H2 as (x & x0 & x1 & H). destruct H as (H1 & H2 & H3 & H5).
       exists (s1 ++ x), x0, x1. split;[|split ;[|split]].
     ** rewrite <- app_assoc. rewrite <- H1. reflexivity.
     ** apply H2.
     ** rewrite -> app_length. rewrite <- plus_assoc. apply le_plus_both.
        apply H4. apply H3.
     ** intros m. rewrite <- app_assoc. apply MApp. apply Hmatch1. apply H5.
  (* MUninoL *)
  - simpl. intros H. apply plus_le in H. destruct H as [H1 H2]. apply IH in H1.
    destruct H1. destruct H. destruct H. destruct H as [H3 [H4 H5]]. 
    exists x. exists x0. exists x1. split. apply H3. split. apply H4. split. destruct H5 as [H6 H7].
    * apply le_trans with (o := pumping_constant re1 + pumping_constant re2) in H6. apply H6. apply le_plus_l. 
    * intros m. apply MUnionL. apply H5.
  (* MUninoR *)
  - simpl. intros H. apply plus_le in H. destruct H as [H1 H2]. apply IH in H2.
    destruct H2 as (x & x0 & x1 & H). destruct H as (H3 & H4 & H5 & H6). 
    exists x, x0, x1. split. apply H3. split. apply H4. split. 
    * apply le_trans with (o := pumping_constant re1 + pumping_constant re2) in H5. apply H5. 
      rewrite -> plus_comm. apply le_plus_l. 
    * intros m. apply MUnionR. apply H6.
  (* MStar0 *)
  - simpl. intros H. inversion H. apply pumping_constant_0_false in H1. destruct H1.
  (* MStarApp *)
  - simpl. destruct s1.
  -- simpl. apply IH2.
  -- intros H. remember (x::s1) as s. simpl in H.
     (* 引入一个假设,进行分类讨论 *)
     assert(Hd : (pumping_constant re <=? length s) = true \/ (length s <=? pumping_constant re) = true).
     {   
       destruct (pumping_constant re <=? length s) eqn:E.
       *left. reflexivity.
       *right. apply le_false_rev in E. rewrite -> leb_iff. apply E.
     }
     destruct Hd as [Ha | Hb].
     * apply leb_iff in Ha. apply IH1 in Ha. destruct Ha as (x0 & x1 & x2 & Ha & Hb & Hc & Hd).
       exists x0, x1, (x2 ++ s2). split. rewrite -> app_assoc. rewrite -> app_assoc. 
       rewrite <- (app_assoc T x0 x1 x2). rewrite <- Ha. reflexivity. split. apply Hb.
       split. apply Hc. intros m. rewrite -> app_assoc. rewrite -> app_assoc. 
       rewrite <- (app_assoc T x0 (napp m x1) x2). apply MStarApp. apply Hd. apply Hmatch2.
     * apply leb_iff in Hb. exists nil, s, s2. simpl. split. reflexivity. split.
     ** unfold not. intros Hfalse. rewrite -> Heqs in Hfalse. discriminate.
     ** split. apply Hb. intros m. apply napp_star. apply Hmatch1. apply Hmatch2.
Qed.
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值