CoQ中有充分根据的归纳法

CoQ中有充分根据的归纳法,coq,induction,Coq,Induction,假设我知道某些自然数是好的。我知道1是好的,如果n是好的,那么3n是好的,如果n是好的,那么n+5是好的,这些是构造好数字的唯一方法。在我看来,在Coq中,这一点的充分形式化是 Inductive good : nat -> Prop := | g1 : good 1 | g3 : forall n, good n -> good (n * 3) | g5 : forall n, good n -> good (n + 5). 然而,尽管很明显,0不好的事实似乎不

假设我知道某些自然数是好的。我知道1是好的,如果n是好的,那么3n是好的,如果n是好的,那么n+5是好的,这些是构造好数字的唯一方法。在我看来,在Coq中,这一点的充分形式化是

Inductive good : nat -> Prop :=
  | g1 : good 1
  | g3 : forall n, good n -> good (n * 3)
  | g5 : forall n, good n -> good (n + 5).
然而,尽管很明显,0不好的事实似乎不能用这个定义来证明(因为当我反转时,在g3的情况下,我只在假设中得到相同的东西)


现在,好的数字究竟是什么并不那么明显。我真的不需要为了知道0是不好的而完全描述它们。例如,我可以通过做几次反演就知道2不好。

这个问题需要归纳。归纳法需要一些谓词
P:nat->Prop
来处理。像
(fun=>~good 0)
这样的基本(常量)谓词不会给您带来太多:您将无法证明
1
(对应于构造函数
g1
)的基本情况,因为谓词“忘记”了它的参数

因此,您需要证明一些逻辑等价(或更强)的语句,这些语句很容易为您提供必要的谓词。 这种等价语句的一个例子是
forall n,good n->n>0
,您可以稍后使用它来反驳
good 0
。相应的谓词
P
(fun=>n>0)

以下是上述等效性的证明:

Lemma not_good0_gt_zero_equiv_not_good0 :
  (forall n, good n -> n > 0) <-> ~ good 0.
Proof.
  split; intros; firstorder.
  destruct n; [tauto | omega].
Qed.
现在,用来证明所有n,n=0->~good n的相应谓词是
fun=>n=0->False
。这可以通过手动应用Coq自动生成的
goal\u ind
归纳原则来显示:

Example not_good_0_manual : forall n, n = 0 -> ~ good n.
Proof.
  intros n Eq contra.
  generalize Eq.
  refine (good_ind (fun n => n = 0 -> False) _ _ _ _ _);
    try eassumption; intros; omega.
Qed.

generalize Eq.
引入
n=0
作为当前目标的前提。如果没有它,证明的目标将是
False
,相应的谓词将是无聊的
fun=>False

事实上
g3
在试图反驳
好0
时可以被应用无限次。这就是为什么我们认为这个证明需要
归纳法
(我们可以看到@AntonTrunov的解中需要的辅助引理使用归纳法)。同样的思想也被用于的定理
loop\u never\u stop


事实上,“x是3的幂”的正确定义应该是
exists n,n^3==x
Argh。当我试图为StackOverflow简化事情时,就会发生这种情况你的解决方案很好,但当然,问题比这更难:归纳类型中还有其他构造函数,因此它的特征化并不像“3的幂”那么简单。事实上,我不确定是否有一个简单的特征。@ejgallego“2的幂表示形式为2^n的数字,其中n是整数”(from),因此通过类比:
3^k
是3的幂
n^3
n
的立方体。哦,是的,真的很抱歉我的打字错误。@Veky,如果你在纸上都不确定,在你知道你想要什么之前(除非我们谈论一些特殊情况)尝试Coq没有什么意义。
记住0,因为n
是这个解决方案的关键组成部分。它将原始语句替换为
forall n,n=0->~good n.
。回答得好@Veky我找到了Sotware基金会讨论这个问题的确切段落(归纳归纳)。@Veky SF,v3.2:“问题在于,对
Prop
的归纳只能在
Prop
的完全通用实例上正常工作,即所有参数都是自由变量的实例。因此,它的行为更像是
destruct
,而不是
inversion
。当你想这样使用
归纳法时,这通常表明你需要证明一些更一般的东西。但在某些情况下,将任何具体的参数提取到单独的方程中就足够了,比如:
∀n、 n=1→漂亮的n
。有一种
记住
策略可以从原始的证明状态生成第二个证明状态。“@AntonTrunov谢谢。因此,唯一神秘的事情似乎是:在
n=1
的上下文中,证明
~美丽的n
的精确方式(这是
记住
要求你做的)”更一般“而不是证明
~beautiful 1
@AntonTrunov这正是我所指的段落,谢谢。指向旧版本的正确链接是。
Lemma not_good0_eq_zero_equiv_not_good0 :
  (forall n, n = 0 -> ~ good n) <-> ~ good 0.
Proof.
  split; intros; subst; auto.
Qed.
Example not_good_0_manual : forall n, n = 0 -> ~ good n.
Proof.
  intros n Eq contra.
  generalize Eq.
  refine (good_ind (fun n => n = 0 -> False) _ _ _ _ _);
    try eassumption; intros; omega.
Qed.
Require Import Omega.

Example not_good_0 : ~ good 0.
Proof.
  intros contra. remember 0 as n. induction contra.
  discriminate. apply IHcontra. omega. omega.
Qed.