我如何在 Coq 的证明中自动计数?
How can I automate counting within proofs in Coq?
我有一个函数 count
,它计算给定谓词在应用于列表元素时可证明的次数。定义如下:
Parameter T : Type.
Parameter dec: forall (p: T -> Prop) (w: T), {p w} + {~ (p w)}.
Fixpoint count (p: T -> Prop) (l: list T) := match l with
| nil => 0
| (cons head tail) => if (dec p head) then (1 + (count p tail)) else (count p tail)
end.
然后我使用这个函数来陈述引理,如下所示:
Parameter a b c: T.
Parameter q: T -> Prop.
Axiom Aa: (q a).
Axiom Ab: (q b).
Axiom Ac: ~ (q c).
Lemma example: (count q (cons a (cons b (cons c nil)))) = 2.
我对此类引理的证明往往很乏味:
Lemma example: (count q (cons a (cons b (cons c nil)))) = 2.
Proof.
unfold count.
assert (q a); [apply Aa| auto].
assert (q b); [apply Ab| auto].
assert (~ (q c)); [apply Ac| auto].
destruct (dec q a); [auto | contradiction].
destruct (dec q b); [auto | contradiction].
destruct (dec q c); [contradiction | auto].
Qed.
我可以做些什么来使用我的 count
函数自动执行这些涉及计算的繁琐证明?
让我们创建自定义提示数据库并在其中添加您的公理:
Hint Resolve Aa : axiom_db.
Hint Resolve Ab : axiom_db.
Hint Resolve Ac : axiom_db.
现在,firstorder
策略可以利用提示数据库:
Lemma example: count q (cons a (cons b (cons c nil))) = 2.
Proof.
unfold count.
destruct (dec q a), (dec q b), (dec q c); firstorder with axiom_db.
Qed.
我们可以使用以下 Ltac 自动化我们的解决方案:
Ltac solve_the_probem :=
match goal with
|- context [if dec ?q ?x then _ else _] =>
destruct (dec q x);
firstorder with axioms_db;
solve_the_probem
end.
那么,unfold count; solve_the_probem.
就可以证明引理了。
在这种情况下,您最好通过反思来证明事情。看看事情进展如何顺利(当然我修改了你的例子以避免所有这些公理):
Require Import List.
Import ListNotations.
Fixpoint count {T : Type} (p : T -> bool) (l : list T) :=
match l with
| [] => 0
| h :: t => if p h then S (count p t) else (count p t)
end.
Inductive T := a | b | c.
Definition q x :=
match x with
| a => true
| b => true
| c => false
end.
Lemma example: (count q [a; b; c]) = 2.
Proof.
reflexivity.
Qed.
我意识到你对 count
的定义是在类型 T 上采用命题谓词(但假设类型 T 上的所有谓词都是可判定的)并且我建议将 count
定义为取一个布尔谓词。但是你可能会意识到,拥有一个可判定的命题谓词或拥有一个布尔谓词实际上是等价的。
例如根据您的公理,我可以定义一个函数,将任何命题谓词转换为布尔谓词:
Parameter T : Type.
Parameter dec: forall (p: T -> Prop) (w: T), {p w} + {~ (p w)}.
Definition prop_to_bool_predicate (p : T -> Prop) (x : T) : bool :=
if dec p x then true else false.
当然,由于您的示例中涉及公理,因此实际上无法使用布尔谓词进行计算。但我假设您为了示例的目的而放置了所有这些公理,而您的实际应用程序没有它们。
回复您的评论
正如我告诉过你的,一旦你根据公理(或 Parameter
定义了一些函数,因为这是同一件事),你就无法再用它来计算了.
然而,这里有一个解决方案,其中命题谓词 p
的可判定性是一个引理。我用 Defined
instead of Qed
结束了引理的证明,以允许用它进行计算(否则,它不会比公理更好)。如您所见,我还重新定义了 count
函数以获取谓词及其可判定性证明。在这种情况下,反射证明仍然有效。没有bool
但严格等价
Require Import List.
Import ListNotations.
Fixpoint count {T : Type}
(p : T -> Prop) (dec : forall (w: T), {p w} + {~ (p w)}) (l : list T) :=
match l with
| [] => 0
| h :: t => if dec h then S (count p dec t) else (count p dec t)
end.
Inductive T := a | b | c.
Definition p x := match x with | a => True | b => True | c => False end.
Lemma dec_p: forall (w: T), {p w} + {~ (p w)}.
Proof.
intros []; simpl; auto.
Defined.
Lemma example2: (count p dec_p [a; b; c]) = 2. Proof. reflexivity. Qed.
我有一个函数 count
,它计算给定谓词在应用于列表元素时可证明的次数。定义如下:
Parameter T : Type.
Parameter dec: forall (p: T -> Prop) (w: T), {p w} + {~ (p w)}.
Fixpoint count (p: T -> Prop) (l: list T) := match l with
| nil => 0
| (cons head tail) => if (dec p head) then (1 + (count p tail)) else (count p tail)
end.
然后我使用这个函数来陈述引理,如下所示:
Parameter a b c: T.
Parameter q: T -> Prop.
Axiom Aa: (q a).
Axiom Ab: (q b).
Axiom Ac: ~ (q c).
Lemma example: (count q (cons a (cons b (cons c nil)))) = 2.
我对此类引理的证明往往很乏味:
Lemma example: (count q (cons a (cons b (cons c nil)))) = 2.
Proof.
unfold count.
assert (q a); [apply Aa| auto].
assert (q b); [apply Ab| auto].
assert (~ (q c)); [apply Ac| auto].
destruct (dec q a); [auto | contradiction].
destruct (dec q b); [auto | contradiction].
destruct (dec q c); [contradiction | auto].
Qed.
我可以做些什么来使用我的 count
函数自动执行这些涉及计算的繁琐证明?
让我们创建自定义提示数据库并在其中添加您的公理:
Hint Resolve Aa : axiom_db.
Hint Resolve Ab : axiom_db.
Hint Resolve Ac : axiom_db.
现在,firstorder
策略可以利用提示数据库:
Lemma example: count q (cons a (cons b (cons c nil))) = 2.
Proof.
unfold count.
destruct (dec q a), (dec q b), (dec q c); firstorder with axiom_db.
Qed.
我们可以使用以下 Ltac 自动化我们的解决方案:
Ltac solve_the_probem :=
match goal with
|- context [if dec ?q ?x then _ else _] =>
destruct (dec q x);
firstorder with axioms_db;
solve_the_probem
end.
那么,unfold count; solve_the_probem.
就可以证明引理了。
在这种情况下,您最好通过反思来证明事情。看看事情进展如何顺利(当然我修改了你的例子以避免所有这些公理):
Require Import List.
Import ListNotations.
Fixpoint count {T : Type} (p : T -> bool) (l : list T) :=
match l with
| [] => 0
| h :: t => if p h then S (count p t) else (count p t)
end.
Inductive T := a | b | c.
Definition q x :=
match x with
| a => true
| b => true
| c => false
end.
Lemma example: (count q [a; b; c]) = 2.
Proof.
reflexivity.
Qed.
我意识到你对 count
的定义是在类型 T 上采用命题谓词(但假设类型 T 上的所有谓词都是可判定的)并且我建议将 count
定义为取一个布尔谓词。但是你可能会意识到,拥有一个可判定的命题谓词或拥有一个布尔谓词实际上是等价的。
例如根据您的公理,我可以定义一个函数,将任何命题谓词转换为布尔谓词:
Parameter T : Type.
Parameter dec: forall (p: T -> Prop) (w: T), {p w} + {~ (p w)}.
Definition prop_to_bool_predicate (p : T -> Prop) (x : T) : bool :=
if dec p x then true else false.
当然,由于您的示例中涉及公理,因此实际上无法使用布尔谓词进行计算。但我假设您为了示例的目的而放置了所有这些公理,而您的实际应用程序没有它们。
回复您的评论
正如我告诉过你的,一旦你根据公理(或 Parameter
定义了一些函数,因为这是同一件事),你就无法再用它来计算了.
然而,这里有一个解决方案,其中命题谓词 p
的可判定性是一个引理。我用 Defined
instead of Qed
结束了引理的证明,以允许用它进行计算(否则,它不会比公理更好)。如您所见,我还重新定义了 count
函数以获取谓词及其可判定性证明。在这种情况下,反射证明仍然有效。没有bool
但严格等价
Require Import List.
Import ListNotations.
Fixpoint count {T : Type}
(p : T -> Prop) (dec : forall (w: T), {p w} + {~ (p w)}) (l : list T) :=
match l with
| [] => 0
| h :: t => if dec h then S (count p dec t) else (count p dec t)
end.
Inductive T := a | b | c.
Definition p x := match x with | a => True | b => True | c => False end.
Lemma dec_p: forall (w: T), {p w} + {~ (p w)}.
Proof.
intros []; simpl; auto.
Defined.
Lemma example2: (count p dec_p [a; b; c]) = 2. Proof. reflexivity. Qed.