我想用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
的例子,但我不明白这个程序。
最后,如果我的引理依赖于几种归纳类型并且我仍想覆盖所有情况,会发生什么?
答案 0 :(得分:9)
如何丢弃不可能的案件?嗯,前两个义务无法证明是正确的,但请注意它们有相互矛盾的假设(分别为zero <> zero
和one <> 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 P
从P
和~P
中推断出任何目标。如果有一个特定的假设是矛盾的,contradict H
会将目标设定为~H
,或者假设是否为~A
,那么目标将是A
(强于~ ~A
但通常更方便)。如果一个特定的假设显然是矛盾的,contradiction H
或只是contradiction
将证明任何目标。
有许多涉及归纳类型假设的策略。确定使用哪一个主要是经验问题。这是主要的(但你会遇到很快没有涉及的案例):
destruct
简单地将假设分解为几个部分。它会丢失有关依赖项和递归的信息。一个典型的例子是destruct H
其中H
是一个H : A /\ B
,它将H
拆分为两个独立的假设类型A
和B
;或destruct H
其中H
是一个分离H : A \/ B
,它将证明分为两个不同的子证据,一个假设A
,另一个假设B
case_eq
与destruct
类似,但保留了假设与其他假设的联系。例如,destruct n
其中n : nat
将证明分为两个子证明,一个用于n = 0
,另一个用于n = S m
。如果n
用于其他假设(即您有H : P n
),则可能需要记住,您销毁的n
与这些假设中使用的n
相同假设:case_eq n
这样做。inversion
对假设的类型进行案例分析。当destruct
会忘记的假设类型存在依赖关系时,它尤其有用。您通常会在case_eq
(相关性相关)和Set
假设inversion
(具有非常依赖类型)的假设中使用Prop
。 inversion
策略背后留下了很多平等,而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
的情况是对称的;最后一种情况,其中one
为a
,反身性很明显。)
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
。所以False
是H0
的结论:
apply H0.
现在我们需要证明zero=zero
,这是
reflexivity.
现在我们证明了False
的断言。剩下的就是证明False
暗示了我们的目标。好吧,False
意味着任何目标,这就是它的定义(False
被定义为归纳类型,为0)。
destruct F.