我可以告诉Coq从n到n + 2进行归纳吗?

时间:2019-01-01 21:14:30

标签: coq induction

我正在尝试是否有可能从https://softwarefoundations.cis.upenn.edu/lf-current/Logic.html中证明evenb n = true <-> exists k, n = double k而根本不涉及奇数。我尝试了以下操作:

Theorem evenb_double_k : forall n,
  evenb n = true -> exists k, n = double k.
Proof.
  intros n H. induction n as [|n' IHn'].
  - exists 0. reflexivity.
  - (* stuck *)

但是,归纳法一次只能处理一个自然数,exists k : nat, S n' = double k显然是不可证明的。

n' : nat
H : evenb (S n') = true
IHn' : evenb n' = true -> exists k : nat, n' = double k
______________________________________(1/1)
exists k : nat, S n' = double k

有没有办法使感应从n变到n + 2?

2 个答案:

答案 0 :(得分:7)

是的,绝对!让我们使用doc中的归纳原理。

From Coq Require Import Arith.

Lemma pair_induction (P : nat -> Prop) :
  P 0 -> P 1 ->
  (forall n, P n -> P (S n) -> P (S (S n))) ->
  forall n, P n.
Proof.
  intros H0 H1 Hstep n.
  enough (P n /\ P (S n)) by easy.
  induction n; intuition.
Qed.

现在,我们可以像这样使用新原理(我将非标准函数与其stdlib对应项进行了交换,以便所有内容都能编译):

Theorem evenb_double_k : forall n,
  Nat.even n = true -> exists k, n = Nat.double k.
Proof.
  intros n Ev.
  induction n as [| |n IHn _] using pair_induction.
  (* the rest of the proof has been removed to not spoil the fun *)
Qed.

答案 1 :(得分:7)

有一种名为fix的策略。我会尝试从较高的角度解释正在发生的事情,因为我认为这是一个很酷的技巧,但请注意,fix是一把双刃剑,通常不建议使用:它取决于真正的Coq的详细级别,使证明非常脆弱,并且当它们损坏时,错误消息也很难理解。

fix foo i,其中foo是一个新鲜变量,而i是一个整数,是一种策略,适用于至少有i个自变量的目标(例如,forall n, evenb n = true -> ...有两个:n和证明evenb n = true),并且假定您要证明的目标,并命名新的假设{{1 }}。 (是的,您没看错。)

foo

当然有一个陷阱:必须将假设应用于Theorem evenb_double_k : forall n, evenb n = true -> exists k, n = double k. Proof. fix self 1. (* 1 subgoal (ID 17) self : forall n : nat, evenb n = true -> exists k : nat, n = double k ============================ forall n : nat, evenb n = true -> exists k : nat, n = double k *) 的适当子项(这是目标的 first 自变量,这就是n的number参数的含义,我们说第一个参数是递减参数)。 fix self 1的适当子项是什么?您只能通过破坏n至少一次来获得该值。

请注意,如果您仍然决定直接应用假设nself本身不是适当的子术语),Coq不会立即提出投诉。 Coq仅检查n上的“ subterm”要求。 EDIT :您也可以随时使用命令Qed进行检查。

Guarded

您可以近似地将 apply self. (* seems fine, all goals done. *) Qed. (* ERROR! *) 想象为强归纳的一种形式,其中归纳假设(fix)用于所有小于当前归纳的术语,而不仅是直接的前任。但是,此“子项”关系实际上并未出现在self的语句中。 (这种特殊性使self成为一种低级的危险策略。)

fix之后,您通常需要fix递减参数。这是destruct允许您的证明遵循fix的结构的地方。下面,我们在evenb情况下立即再次销毁。因此我们得到三种情况:Sn = On = S O

第一种情况很容易,第二种情况是虚无,而第三种情况是您需要在n = S (S n')处使用“归纳假设” n' : nat

self

其中的某些推理是相当通用的,甚至可以将其引入自定义的归纳原理,甚至n' ,具体来说就是另一个Proof. fix self 1. intros n. destruct n as [| [| n']]. - exists 0; reflexivity. - discriminate. - simpl. intro H. apply self in H. destruct H as [k Hk]. exists (S k). rewrite Hk; reflexivity. Qed. 。 / p>

nat

将其与Theorem的标准归纳原理进行比较,它实际上也是一个定理,名为Theorem even_ind : forall (P : nat -> Prop), P O -> (forall n, evenb n = true -> P n -> P (S (S n))) -> forall n, evenb n = true -> P n. 。这就是nat策略在幕后使用的方式。

nat_ind

induction中的归纳步骤从About nat_ind. (* nat_ind : forall P : nat -> Prop, P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n *) nat_ind,而n的归纳步骤从S neven_ind,并且有一个额外的假设说我们的数字是偶数。

n的证明与S (S n)相似,但它更为抽象,因为它可以概括even_ind上的所有谓词{{​​1}}。

evenb_double_k

这里的另一种方法是根本不使用P(因为应该避免使用),而是将nat用作证明替代Proof. intros P HO HSS. fix self 1. intros n. destruct n as [| [| n']]. - intro; apply HO. - discriminate. - intros H. apply HSS. + apply H. + apply self. apply H. Qed. 原理的原始方法。这对于fix很好,但是对于某些复杂的归纳类型,默认归纳原理太弱了,手写induction是唯一的方法。

最后,回到even_ind,我们可以对nat使用新的归纳原理,而不是fixevenb_double_k。现在,我们只得到两个有意义的情况,apply even_indfix,其中induction是偶数。

O

此答案中使用的定义:

S (S n')