5-8年后回到Coq验证人:如何证明(对于所有n,m:n,(n-(S m))=pred(n-m))?
大约在5年到8年前(可能是6年或7年),我在Coq中写了一个完整的冒泡排序形式化。最早被证明的引理之一是标题中的引理,我称之为“sub_such_r”(或者可能是标准名称?) 现在,回到那时,这是这个引理的非常简单的证明:5-8年后回到Coq验证人:如何证明(对于所有n,m:n,(n-(S m))=pred(n-m))?,coq,Coq,大约在5年到8年前(可能是6年或7年),我在Coq中写了一个完整的冒泡排序形式化。最早被证明的引理之一是标题中的引理,我称之为“sub_such_r”(或者可能是标准名称?) 现在,回到那时,这是这个引理的非常简单的证明: intros n m. induction n m using n_double_ind. simpl. auto. apply sub_0_r. Qed. “sub_0_r”是断言 forall n : nat, (n - 0)%nat = n 现在,同样熟悉现代Coq
intros n m.
induction n m using n_double_ind.
simpl.
auto.
apply sub_0_r.
Qed.
“sub_0_r”是断言
forall n : nat, (n - 0)%nat = n
现在,同样熟悉现代Coq的细心读者可能已经发现了旧证据的问题:第二行
induction n m
i、 e.两项同时归纳法不再有效,即使指定一项使用“n_double_ind”。
我一直在绞尽脑汁想如何证明这一点,先是n上的归纳,然后是m上的归纳,但我就是搞不懂
如果您想同时对两个变量应用归纳法,您需要使用逗号分隔符,或者Coq将
f t
识别为f
应用于t
,因此,当您编写nm
时,这实际上意味着n
是一个函数,您希望将其应用于m
。相反,请使用如下逗号:
induction n, m.
induction n, m; auto.
这将生成四个子目标。其中两个可以用auto证明,因此您可以要求Coq在归纳法生成的每个子目标上使用auto策略,使用分号如下:
induction n, m.
induction n, m; auto.
剩下的子目标很容易用你提到的引理和归纳假设来证明。因此,整个脚本如下所示:
Lemma sub_0_r : forall n : nat, (n - 0) = n.
Admitted.
Theorem sub_succ_r: forall n m : nat, (n - (S m)) = pred(n - m).
Proof.
induction n, m; auto.
- apply sub_0_r.
- apply IHn.
Qed.
还请注意,不需要使用%nat
但是正如你所看到的,我们只使用了IHn
,这意味着我们没有对m
使用归纳假设,因此我们不需要对m使用归纳
,只有自毁
策略才能起作用,更好的证明是:
induction n; destruct m; auto.
- apply sub_0_r.
- apply IHn.
这是最小的和优雅的。这确实有帮助,谢谢。然而,在
应用sub\u 0\r
之后,我只剩下归纳假设IHn:(n-S(sm))=pred(n-S(m))
和目标sn-S(sm)=pred(sn-sm)
。仅仅应用IHn是不够的,因为当我尝试这一点时,CoqIde(我想这是非常正确的)给出了一个错误。因此,我必须重新设计目标,使之类似于归纳假设,反之亦然。这可能真的很明显,我之所以错过它,只是因为我已经生锈了,但我似乎不知道如何从这里开始。对我来说,我提供的校对脚本完全完成了任务,使用了CoqIde 8.11.0。也许你遗漏了一些愚蠢的细节?是的,你是对的。我在归纳之前加了一个“intros n m”,就像8年前的原始证明一样。这给归纳假设增加了两个额外的“S”,使其IHn:(n-S(sm))=pred(n-(sm))
。省略介绍使归纳假设成为IHn:forall m:nat,(n-sm)=(n-m)
。我怀疑这使得证明检验者只需在归纳假设中的所有内容上加上一个“S”。也许所有m:nat的也有帮助,IDK。不管怎样,它现在起作用了。对你的帮助,我真诚而深切的感谢。“如果没有它,我会被完全卡住的。”阿辛尼耶夫说