有没有办法通过重写步骤自动化 Coq 证明?
Is there a way to automate a Coq proof with rewrite steps?
我正在做一个证明,我的一个子目标看起来有点像这样:
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 等)上略有不同),假设的数量(有时会有一个或两个额外的归纳假设)和最后的布尔公式。我认为,如果我可以使用自动化来解决这个问题,我的整体证明脚本会更加简洁和健壮。
edit:如果其中一个假设中存在 forall 怎么办?
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
这个特定的目标可以这样解决:
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.
以上是根据 destr_bool
策略建模的,在 Coq.Bool.Bool
:
中定义
Ltac destr_bool :=
intros; destruct_all bool; simpl in *; trivial; try discriminate.
您也可以尝试使用
destr_bool; intuition.
在更简单的 destr_bool
之后点燃强大的 intuition
。
now
在Coq.Init.Tactics
中定义如下
Tactic Notation "now" tactic(t) := t; easy.
easy
定义在它的正上方(顾名思义)可以解决简单的目标。
intuition
可以解决需要应用(直觉)逻辑定律的目标。例如。问题原始版本的以下两个假设需要应用 modus ponens 法则。
H1 : p -> false = true
H2 : p
auto
,另一方面,默认情况下不这样做,它也不解决矛盾。
如果您的假设包含一些一阶逻辑语句,firstorder
策略可能就是答案(就像在这种情况下一样)——只需用它替换 intuition
。
当您在证明某些引理的过程中发现重复模式时,您通常可以定义自己的策略来自动进行证明。
在您的具体情况下,您可以编写以下内容:
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。
我正在做一个证明,我的一个子目标看起来有点像这样:
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 等)上略有不同),假设的数量(有时会有一个或两个额外的归纳假设)和最后的布尔公式。我认为,如果我可以使用自动化来解决这个问题,我的整体证明脚本会更加简洁和健壮。
edit:如果其中一个假设中存在 forall 怎么办?
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
这个特定的目标可以这样解决:
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.
以上是根据 destr_bool
策略建模的,在 Coq.Bool.Bool
:
Ltac destr_bool :=
intros; destruct_all bool; simpl in *; trivial; try discriminate.
您也可以尝试使用
destr_bool; intuition.
在更简单的 destr_bool
之后点燃强大的 intuition
。
now
在Coq.Init.Tactics
中定义如下
Tactic Notation "now" tactic(t) := t; easy.
easy
定义在它的正上方(顾名思义)可以解决简单的目标。
intuition
可以解决需要应用(直觉)逻辑定律的目标。例如。问题原始版本的以下两个假设需要应用 modus ponens 法则。
H1 : p -> false = true
H2 : p
auto
,另一方面,默认情况下不这样做,它也不解决矛盾。
如果您的假设包含一些一阶逻辑语句,firstorder
策略可能就是答案(就像在这种情况下一样)——只需用它替换 intuition
。
当您在证明某些引理的过程中发现重复模式时,您通常可以定义自己的策略来自动进行证明。
在您的具体情况下,您可以编写以下内容:
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。