我想用这种destruct
策略来证明案件的陈述.我在线阅读了几个例子,我很困惑.有人能更好地解释一下吗?
这是一个小例子(有其他方法可以解决它,但尝试使用destruct
):
Inductive three := zero
| one
| two.
Lemma has2b2: forall a:three, a<>zero /\ a<>one -> a=two.
Run Code Online (Sandbox Code Playgroud)
现在一些在线示例建议执行以下操作:
intros. destruct a.
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我得到:
3 subgoals H : zero <> zero /\ zero <> one
______________________________________(1/3)
zero = two
______________________________________(2/3)
one = two
______________________________________(3/3)
two = two
Run Code Online (Sandbox Code Playgroud)
所以,我想证明前两种情况是不可能的.但机器将它们列为子目标,并希望我证明它们......这是不可能的.
摘要:如何准确丢弃不可能的案例?
我看过一些使用的例子,inversion
但我不明白这个程序.
最后,如果我的引理依赖于几种归纳类型并且我仍想覆盖所有情况,会发生什么?
如何丢弃不可能的案件?确实,前两个义务是不可能证明的,但请注意它们有相互矛盾的假设(zero <> zero
和one <> one
分别).因此,您将能够证明这些目标tauto
(如果您感兴趣,还有更多原始战术可以解决这个问题).
inversion
是一个更高级的破坏版本.除了"破坏"归纳法之外,它有时会产生一些平等(你可能需要).它本身就是一个简单版本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.
Run Code Online (Sandbox Code Playgroud)
如果你看到一个不可能实现的目标,那么有两种可能性:你在证明策略中犯了错误(也许你的引理是错误的),或者假设是矛盾的.
如果您认为这些假设是矛盾的,那么您可以设定目标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
打破了证明分为两个subproofs,一个是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
where n : nat
表示您将执行整数归纳并证明基本情况(n
替换为0
)和归纳情况(n
替换为m+1
).你的例子很简单,你可以证明它"通过案例分析很明显a
".
Lemma has2b2: forall a:three, a<>zero/\a<>one ->a=two.
Proof. destruct a; tauto. Qed.
Run Code Online (Sandbox Code Playgroud)
但是让我们看一下destruct
战术产生的案例,即仅仅是intros; destruct a.
.(其中,该情况下a
是one
对称;后一种情况,其中a
是two
,很明显通过自反).
H : zero <> zero /\ zero <> one
============================
zero = two
Run Code Online (Sandbox Code Playgroud)
目标看起来不可能.我们可以告诉Coq,在这里它可以自动发现矛盾(zero=zero
很明显,其余的是由tauto
策略处理的一阶重言式).
elimtype False. tauto.
Run Code Online (Sandbox Code Playgroud)
事实上,tauto
即使你没有开始告诉Coq不要担心目标,并且tauto
没有第elimtype False
一个(IIRC它没有在旧版本的Coq中没有写),它就开始工作了.你可以tauto
通过写作来了解Coq正在采取的策略info tauto
.Coq会告诉你tauto
战术生成的证明脚本.这不是很容易理解,所以让我们看看这个案例的手动证明.首先,让我们将假设(这是一个结合)分成两部分.
destruct H as [H0 H1].
Run Code Online (Sandbox Code Playgroud)
我们现在有两个假设,其中一个假设是zero <> zero
.这显然是错误的,因为它的否定zero = zero
显然是正确的.
contradiction H0. reflexivity.
Run Code Online (Sandbox Code Playgroud)
我们可以更详细地了解contradiction
战术的作用.(info contradiction
会揭示现场发生的事情,但同样不是新手友好的).我们声称目标是正确的,因为假设是矛盾的,所以我们可以证明任何事情.所以让我们设定中间目标False
.
assert (F : False).
Run Code Online (Sandbox Code Playgroud)
运行red in H0.
以查看这zero <> zero
是真正的符号~(zero=zero)
,反过来将其定义为含义zero=zero -> False
.所以,False
是的结论H0
:
apply H0.
Run Code Online (Sandbox Code Playgroud)
现在我们需要证明zero=zero
,这是
reflexivity.
Run Code Online (Sandbox Code Playgroud)
现在我们已经证明了我们的主张False
.剩下的就是证明这False
意味着我们的目标.嗯,False
暗示任何目标,这是它的定义(False
被定义为具有0个案例的归纳类型).
destruct F.
Run Code Online (Sandbox Code Playgroud)