我正在制作证据,我的一个子目标看起来有点像这样:
Goal forall
(a b : bool)
(p: Prop)
(H1: p -> a = b)
(H2: p),
negb a = negb b.
Proof.
intros.
apply H1 in H2. rewrite H2. reflexivity.
Qed.
证据不依赖于任何外部引理,只是在上下文中将一个假设应用于另一个假设,并使用已知假设进行重写步骤。
有没有办法实现自动化?我试过intros. auto.
,但没有效果。我怀疑这是因为auto
只能执行apply
步骤但没有rewrite
步骤,但我不确定。也许我需要一些更强大的策略?
我想要自动化的原因是,在我原来的问题中,我实际上有大量与这个非常相似的子目标,但假设名称(H1,H2等)的差异很小,假设的数量(有时还有一个额外的归纳假设或两个)和最后的布尔公式。我认为,如果我可以使用自动化来解决这个问题,那么我的整体校对脚本会更加简洁和强大。
编辑:如果其中一个假设存在错误怎么办?
Goal forall
(a b c : bool)
(p: bool -> Prop)
(H1: forall x, p x -> a = b)
(H2: p c),
negb a = negb b.
Proof.
intros.
apply H1 in H2. subst. reflexivity.
Qed
答案 0 :(得分:4)
当您在证明某些引理的方式中看到重复模式时,您通常可以定义自己的策略来自动化证明。
在您的具体情况下,您可以写下以下内容:
Ltac rewrite_all' :=
match goal with
| H : _ |- _ => rewrite H; rewrite_all'
| _ => idtac
end.
Ltac apply_in_all :=
match goal with
| H : _, H2 : _ |- _ => apply H in H2; apply_in_all
| _ => idtac
end.
Ltac my_tac :=
intros;
apply_in_all;
rewrite_all';
auto.
Goal forall (a b : bool) (p: Prop) (H1: p -> a = b) (H2: p), negb a = negb b.
Proof.
my_tac.
Qed.
Goal forall (a b c : bool) (p: bool -> Prop)
(H1: forall x, p x -> a = b)
(H2: p c),
negb a = negb b.
Proof.
my_tac.
Qed.
如果你想按照这种编写证据的方式,经常推荐的参考文献(但我还没读过)是Adam Chlipala的CPDT。
答案 1 :(得分:3)
这个特殊目标可以这样解决:
Goal forall (a b : bool) (p: Prop) (H1: p -> a = b) (H2: p),
negb a = negb b.
Proof.
now intuition; subst.
Qed.
或者,使用destruct_all
策略(假设您没有很多布尔变量):
intros; destruct_all bool; intuition.
上述内容是根据Coq.Bool.Bool
中定义的destr_bool
策略建模的:
Ltac destr_bool :=
intros; destruct_all bool; simpl in *; trivial; try discriminate.
你也可以尝试使用像
这样的东西destr_bool; intuition.
在更简单的intuition
之后启动强大的destr_bool
。
now
在Coq.Init.Tactics
中定义如下
Tactic Notation "now" tactic(t) := t; easy.
easy
正好位于它上方(顾名思义)可以解决简单的目标。
intuition
可以解决需要应用(直觉)逻辑定律的目标。例如。来自问题原始版本的以下两个假设需要应用 modus ponens 法律。
H1 : p -> false = true
H2 : p
另一方面, auto
默认不这样做,它也不能解决矛盾。
如果您的假设包含一些一阶逻辑语句,firstorder
策略可能就是答案(就像在这种情况下一样) - 只需用它替换intuition
。