Coq 关于正则表达式的简单证明

Coq 关于正则表达式的简单证明,coq,Coq,我试图用Coq形式化正则表达式(REs)的一些属性。但是,要证明一个相当简单的属性,我遇到了一些麻烦: 对于所有字符串s,如果s的语言为(epsilon)*RE,则s= “”,其中epsilon和*表示空字符串RE和Kleene星 手术 这似乎是归纳/倒装策略的一个明显应用,但我无法让它起作用 带有问题引理的最小工作代码如下所示。 任何关于我应该如何进行的提示都将不胜感激 编辑: 我的一次尝试是: Lemma star_lemma : forall s, s <<- (#1 ^*)

我试图用Coq形式化正则表达式(REs)的一些属性。但是,要证明一个相当简单的属性,我遇到了一些麻烦:

对于所有字符串s,如果s的语言为(epsilon)*RE,则s= “”,其中epsilon和*表示空字符串RE和Kleene星 手术

这似乎是归纳/倒装策略的一个明显应用,但我无法让它起作用

带有问题引理的最小工作代码如下所示。 任何关于我应该如何进行的提示都将不胜感激

编辑

我的一次尝试是:

Lemma star_lemma : forall s, s <<- (#1 ^*) -> s = "".
Proof.  
  intros s H.
  inverts* H.
  inverts* H2.
  inverts* H1.
  inverts* H1.
  inverts* H2.
  simpl in *.
  -- stuck here
而不是

inverts* H

我有一些(至少对我来说)毫无意义的目标。在Idris/Agda中,这样的证明只是通过模式匹配和s结构上的递归来进行的。I在_regex谓词中稍微修改了
的定义:

Inductive in_regex : string -> regex -> Prop :=
| InEps
  : "" <<- #1
| InChr
  : forall c
  , (String c EmptyString) <<- ($ c)
| InCat
  :  forall e e' s s' s1
  ,  s <<- e
  -> s' <<- e'
  -> s1 = s ++ s'
  -> s1 <<- (e @ e')
| InLeft
  :  forall s e e'
  ,  s <<- e
  -> s <<- (e :+: e')
| InRight
  :  forall s' e e'
  ,  s' <<- e'
  -> s' <<- (e :+: e')
| InStarLeft
  : forall e
  , "" <<- (e ^*)
| InStarRight
  :  forall s s' e
  ,  s <<- e
  -> s' <<- (e ^*)
  -> (s ++ s') <<- (e ^*)
where "s '<<-' e" := (in_regex s e).
inclusive in_regex:string->regex->Prop:=
|伊内普斯

:“”以下是原始问题的一种可能解决方案:

Lemma star_lemma : forall s,
    s <<- (#1 ^*) -> s = "".
Proof.
  refine (fix star_lemma s prf {struct prf} : s = "" := _).
  inversion_clear prf; subst.
  inversion_clear H; subst.
  - now inversion H0.
  - inversion_clear H0; subst. inversion_clear H; subst.
    rewrite (star_lemma s' H1).
    reflexivity.
Qed.
引理星引理:对于所有的s,
这个问题困扰了我一个星期,我终于找到了一个我觉得很优雅的解决方案

我已经读过,当归纳法原理不适合你的需要时,你可以写下并证明另一个更适合你的问题的原理。这就是我在这个案件中所做的。我们想要的是在使用中给出的更自然的定义时得到的定义。通过这样做,我们可以更容易地保持相同的定义(例如,如果更改它意味着太多更改)和理由

这里是归纳原理的证明(我使用一个节来精确地指定隐式参数,因为否则我会观察到它们的奇怪行为,但这里根本不需要节机制)


你在理论上证明了更简单的性质了吗?什么时候失败了?你做过任何研究吗?我从
归纳H
开始尝试,并能用
subst证明每个子目标;自反性
除了一个,情况是
inChr
。当我尝试
感应s
时,我也陷入了同样的境地。有没有可能这个表示法不符合预期?我认为你的定理有点太专业化了。Coq不能很好地处理不是“所有变量”的术语的归纳。这里你的@Vinz问题是,在归纳假设中,
r
变成了
1:+:((#1@(#1^*)
,所以你有一个先决条件,虚假的
#1:+:(#1@(#1^*)=(#1^*))
这意味着它不能再使用了。另外,
依赖归纳法
将引入对
JMeq
公理的依赖。原始问题的证明是:)(1)很高兴在Idris中证明引理(与Coq相比)。(2)我想知道是否有更快的方法(不修改数据结构)很好!我真的不知道如何使用手工制作的不动点来证明它。在你的例子中,通过<代码> StasyOple < /Cult>引号,它表示如果<代码> s @ GARAAIS非常好的点!请考虑把你的评论变成一个答案——我听到评论不太可靠。你也可以使用<代码> NAT。使用
ntimes
的ead将代码缩短:
存在感谢@gallais和@Anton Trunov的伟大回答。我从未想过使用refine来证明这样的引理!而且,基于
ntimes
的解决方案非常好!感谢您的时间,@eponier!您创建新的自定义归纳原理的想法非常好而且,我相信,将军,因为它可以适应其他问题。那太棒了!顺便说一下,当我“测量”使用
time coqc regex.v的性能
在测试代码时,我得到了
0,85s用户
的平均值,在
in regex\u ind2
中将
反转
替换为
反转
时,我得到了
0,70s用户
的平均值(第一次和第三次出现的情况都很重要,第二次出现的情况可以预料不重要)@Zimmi48我不完全确定这是一个问题还是一个请求。我相应地更新了第二个证明。@AntonTrunov这很有趣。我认为
inversion\u clear
或多或少是一种语法上的糖分,但在这里似乎有所不同。使用
时间Qed.
,我用
inversion
得到0.220秒,用得到0.120秒实际上,两个证明项是相等的(分别是
inversion\u clear
inversion;clear
)。
Inductive in_regex : string -> regex -> Prop :=
| InEps
  : "" <<- #1
| InChr
  : forall c
  , (String c EmptyString) <<- ($ c)
| InCat
  :  forall e e' s s' s1
  ,  s <<- e
  -> s' <<- e'
  -> s1 = s ++ s'
  -> s1 <<- (e @ e')
| InLeft
  :  forall s e e'
  ,  s <<- e
  -> s <<- (e :+: e')
| InRight
  :  forall s' e e'
  ,  s' <<- e'
  -> s' <<- (e :+: e')
| InStarLeft
  : forall e
  , "" <<- (e ^*)
| InStarRight
  :  forall s s' e
  ,  s <<- e
  -> s' <<- (e ^*)
  -> (s ++ s') <<- (e ^*)
where "s '<<-' e" := (in_regex s e).
Lemma star_lemma : forall s, s <<- (#1 ^*) -> s = "".
Proof.
  intros s H.
  remember (#1 ^*) as r.
  induction H; inversion Heqr; clear Heqr; trivial.
  subst e.
  rewrite IHin_regex2; trivial.
  inversion H; trivial.
Qed.
Lemma star_lemma : forall s,
    s <<- (#1 ^*) -> s = "".
Proof.
  refine (fix star_lemma s prf {struct prf} : s = "" := _).
  inversion_clear prf; subst.
  inversion_clear H; subst.
  - now inversion H0.
  - inversion_clear H0; subst. inversion_clear H; subst.
    rewrite (star_lemma s' H1).
    reflexivity.
Qed.
Section induction_principle.

Context (P : string -> regex -> Prop)
  (H_InEps : P "" #1)
  (H_InChr : forall c, P (String c "") ($ c))
  (H_InCat : forall {e e' s s' s1}, s <<- e -> P s e -> s' <<- e' ->
    P s' e' -> s1 = s ++ s' -> P s1 (e @ e'))
  (H_InLeft : forall {s e e'}, s <<- e -> P s e -> P s (e :+: e'))
  (H_InRight : forall {s' e e'}, s' <<- e' -> P s' e' -> P s' (e :+: e'))
  (H_InStar_Eps : forall e, P "" (e ^*))
  (H_InStar_Cat : forall {s1 s2 e}, s1 <<- e -> s2 <<- (e ^*) ->
    P s1 e -> P s2 (e ^*) -> P (s1++s2) (e ^*)).

Arguments H_InCat {_ _ _ _ _} _ _ _ _ _.
Arguments H_InLeft {_ _ _} _ _.
Arguments H_InRight {_ _ _} _ _.
Arguments H_InStar_Cat {_ _ _} _ _ _ _.

Definition in_regex_ind2 : forall (s : string) (r : regex), s <<- r -> P s r.
Proof.
  refine (fix in_regex_ind2 {s r} prf {struct prf} : P s r :=
    match prf with
    | InEps => H_InEps
    | InChr c => H_InChr c
    | InCat prf1 prf2 eq1 =>
        H_InCat prf1 (in_regex_ind2 prf1) prf2 (in_regex_ind2 prf2) eq1
    | InLeft _ prf => H_InLeft prf (in_regex_ind2 prf)
    | InRight _ prf => H_InRight prf (in_regex_ind2 prf)
    | InStar prf => _
    end).
  inversion prf; subst.
  - inversion H1. apply H_InStar_Eps.
  - inversion H1; subst.
    apply H_InStar_Cat; try assumption; apply in_regex_ind2; assumption.
Qed.

End induction_principle.
Lemma star_lemma : forall s, s <<- (#1 ^*) -> s = "".
Proof.
  intros s H. remember (#1 ^*) as r.
  induction H using in_regex_ind2; try discriminate.
  - reflexivity.
  - inversion Heqr; subst.
    inversion H. rewrite IHin_regex2 by reflexivity. reflexivity.
Qed.