如何在Coq中使用归纳型案例

时间:2011-07-25 22:47:04

标签: logic coq

我想用destruct策略来证明案件的陈述。我在线阅读了几个例子,我很困惑。有人可以更好地解释一下吗?

这是一个小例子(有其他方法可以解决它,但尝试使用destruct):

 Inductive three := zero 
                  | one 
                  | two.
 Lemma has2b2: forall a:three, a<>zero /\ a<>one -> a=two.

现在网上的一些例子建议做以下事情:

intros. destruct a.

在这种情况下,我得到:

3 subgoals H : zero <> zero /\ zero <> one
______________________________________(1/3) 
zero = two

______________________________________(2/3) 
one = two

______________________________________(3/3) 
two = two

所以,我想证明前两种情况是不可能的。但机器将它们列为子目标,并希望我证明它们......这是不可能的。

要点: 如何准确地丢弃不可能的案件?

我看过一些使用inversion的例子,但我不明白这个程序。

最后,如果我的引理依赖于几种归纳类型并且我仍想覆盖所有情况,会发生什么?

2 个答案:

答案 0 :(得分:9)

如何丢弃不可能的案件?嗯,前两个义务无法证明是正确的,但请注意它们有相互矛盾的假设(分别为zero <> zeroone <> one)。所以你将能够用tauto来证明这些目标(如果你有兴趣的话,还有更多原始战术可以解决这个问题。)

inversion是更高级的destruct版本。除了“破坏”之外归纳,它有时会产生一些平等(你可能需要)。它本身是induction的简单版本,它还会为您生成一个归纳假设。

如果你的目标中有几种归纳类型,你可以逐个destruct/invert

更详细的演练:

Inductive three := zero | one | two .

Lemma test : forall a, a <> zero /\ a <> one -> a = two.
Proof.
  intros a H.
  destruct H. (* to get two parts of conjunction *)
  destruct a. (* case analysis on 'a' *)
(* low-level proof *)
  compute in H. (* to see through the '<>' notation *)
  elimtype False. (* meaning: assumptions are contradictory, I can prove False from them *)
  apply H.
  reflexivity.
(* can as well be handled with more high-level tactics *)
  firstorder.
(* the "proper" case *)
  reflexivity.
Qed.

答案 1 :(得分:8)

如果你看到一个不可能实现的目标,那么有两种可能性:你在证明策略中犯了错误(也许你的引理是错误的),或者假设是矛盾的。

如果您认为这些假设是矛盾的,您可以将目标设置为False,以避免一些复杂性。 elimtype False实现了这一目标。通常,您通过证明命题False及其否定P来证明~P;策略absurd PP~P中推断出任何目标。如果有一个特定的假设是矛盾的,contradict H会将目标设定为~H,或者假设是否为~A,那么目标将是A(强于~ ~A但通常更方便)。如果一个特定的假设显然是矛盾的,contradiction H或只是contradiction将证明任何目标。

有许多涉及归纳类型假设的策略。确定使用哪一个主要是经验问题。这是主要的(但你会遇到很快没有涉及的案例):

  • destruct简单地将假设分解为几个部分。它会丢失有关依赖项和递归的信息。一个典型的例子是destruct H其中H是一个H : A /\ B,它将H拆分为两个独立的假设类型AB;或destruct H其中H是一个分离H : A \/ B,它将证明分为两个不同的子证据,一个假设A,另一个假设B
  • case_eqdestruct类似,但保留了假设与其他假设的联系。例如,destruct n其中n : nat将证明分为两个子证明,一个用于n = 0,另一个用于n = S m。如果n用于其他假设(即您有H : P n),则可能需要记住,您销毁的n与这些假设中使用的n相同假设:case_eq n这样做。
  • inversion对假设的类型进行案例分析。当destruct会忘记的假设类型存在依赖关系时,它尤其有用。您通常会在case_eq(相关性相关)和Set假设inversion(具有非常依赖类型)的假设中使用Propinversion策略背后留下了很多平等,而subst后面常常会简化假设。 inversion_clear策略是inversion; subst的简单替代方法,但会丢失一些信息。
  • induction意味着您将通过对给定假设的归纳(=递归)来证明目标。例如,induction n其中n : nat表示您将执行整数归纳并证明基本情况(n替换为0)和归纳情况({{1} }替换为n)。

您的示例很简单,您可以通过m+1上的案例分析证明它“显而易见”。

a

但是让我们来看看Lemma has2b2: forall a:three, a<>zero/\a<>one ->a=two. Proof. destruct a; tauto. Qed. 策略产生的案例,即仅destruct之后。 (intros; destruct a.a的情况是对称的;最后一种情况,其中onea,反身性很明显。)

two

目标看起来不可能。我们可以告诉Coq,在这里它可以自动发现矛盾(H : zero <> zero /\ zero <> one ============================ zero = two 很明显,其余的是由zero=zero策略处理的一阶重言式。)

tauto

事实上elimtype False. tauto. 即使您没有开始告诉Coq不要担心目标,并且在没有tauto的情况下首先写了tauto({II} Coq的版本。通过编写elimtype False,您可以看到Coq正在使用tauto策略做什么。 Coq会告诉你info tauto策略产生的证明脚本。这不是很容易理解,所以让我们来看看这个案例的手动证明。首先,让我们将假设(这是一个连词)分成两部分。

tauto

我们现在有两个假设,其中一个是destruct H as [H0 H1]. 。这显然是错误的,因为它是zero <> zero的否定,这显然是正确的。

zero = zero

我们可以更详细地了解contradiction H0. reflexivity. 策略的作用。 (contradiction会揭示场景下发生的事情,但同样不是新手友好的)。我们声称目标是正确的,因为假设是矛盾的,所以我们可以证明任何事情。所以我们将中间目标设置为info contradiction

False

运行assert (F : False). ,看red in H0.zero <> zero的真正符号,而~(zero=zero)又定义为zero=zero -> False。所以FalseH0的结论:

apply H0.

现在我们需要证明zero=zero,这是

reflexivity.

现在我们证明了False的断言。剩下的就是证明False暗示了我们的目标。好吧,False意味着任何目标,这就是它的定义(False被定义为归纳类型,为0)。

destruct F.