5-8年后回到Coq验证人:如何证明(对于所有n,m:n,(n-(S m))=pred(n-m))?

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

大约在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的细心读者可能已经发现了旧证据的问题:第二行

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。不管怎样,它现在起作用了。对你的帮助,我真诚而深切的感谢。“如果没有它,我会被完全卡住的。”阿辛尼耶夫说