gpt4 book ai didi

coq - 几乎只使用重写来证明 Coq 中的定理 - 没有 "cleverness"

转载 作者:行者123 更新时间:2023-12-04 13:43:25 25 4
gpt4 key购买 nike

我正在尝试制定一个问题,以便只有重写就足够了
来证明目标。我想避免“聪明”地使用命题,而是使用
可以由 Coq 计算的 bool 值。

我定义了一个 bool 测试函数 member如果元素在列表中,则返回 true,
different如果两个列表中都没有元素,则返回 true。

我想证明我可以重写different转换成仅使用 member 的表达式.

Theorem different_member:  forall xs ys y,
different xs ys = ((negb (member y ys)) || negb (member y xs)).

( (negb X || Y) 形式是 bool 含义)。

作为热身和现实检查,我想证明
Theorem diff_mem:
forall xs ys,
different xs ys = true -> forall y, member y xs = true -> ~ member y ys = true.

继续的方法是对 xs 进行归纳,但我一直在最后一步搞砸。

非常感谢对这两个定理的帮助!这是开发的相关部分。
Require Import Arith.
Require Import List.
Require Import Bool.
Import List.ListNotations.
Open Scope list.
Open Scope bool.

Fixpoint member x ys :=
match ys with
| [] => false
| y :: ys' => (beq_nat x y) || (member x ys')
end.

Lemma mem1: forall x, member x [] = false.
Proof. auto. Qed.
Lemma mem2: forall x y l, member x (y::l) = (beq_nat x y) || (member x l).
Proof. auto. Qed.

Fixpoint different xs ys :=
match xs with
| [] => true
| x::xs' => (negb (member x ys)) && (different xs' ys)
end.

Lemma diff1: forall ys, different [] ys = true.
Proof. auto. Qed.
Lemma diff2: forall x xs ys,
different (x::xs) ys = (negb (member x ys)) && (different xs ys).
Proof. auto. Qed.


Theorem diff_mem1: forall xs ys, different xs ys = true -> forall y, member y xs = true -> ~ member y ys = true.

Proof.
Abort.

Theorem different_member:
forall xs ys y, different xs ys =
((negb (member y ys)) || negb (member y xs)).
Proof.
Abort.

编辑:

这是 diff_mem1的证明定理。 (睡在它上面,在开始在 ProofGeneral 中敲击它之前思考有时会有所帮助......)。另一个定理的证明遵循相同的结构。

但是,问题和最终目标仍然是如何完全通过重写和提示来解决它,以便(几乎)可以做到 induction xs; auto. .
Theorem diff_mem1: forall xs ys, 
different xs ys = true -> forall y, member y xs = true -> ~ member y ys = true.

Proof.
induction xs as [|a xs]; intros ys Hdiff y Hxs Hys.
- inversion Hxs.
- (* we assume y is a member of ys, and of (a::xs) *)
(* it is also assumed that (a::xs) is different from ys *)
(* consider the cases y=a and y<>a *)
remember (beq_nat y a) as Q; destruct Q.
+ (* this case is absurd since y is a member of both ys and (y::xs) *)
apply eq_sym in HeqQ; apply beq_nat_true in HeqQ.
subst a.
simpl in Hdiff.
rewrite Hys in Hdiff.
inversion Hdiff.
+ (* this case is also absurd since y is a member of both ys and xs *)
simpl in Hdiff, Hxs.
rewrite <- HeqQ in Hxs.
simpl in Hxs.
rewrite Bool.andb_true_iff in Hdiff; destruct Hdiff as [_ Hdiff1].
destruct (IHxs ys Hdiff1 y Hxs Hys).
Qed.

编辑2:

我将关闭它,因为@Arthur 给出了我为什么在最初的尝试中失败的正确答案,但为了完整起见,我想添加一个符合我的目标的解决方案。

我写了一个 Ltac 策略 my_simple_rewrite这做了许多 try rewrite with lemma_x in * (大约 20 个不同的引理,仅从左到右重写)。它们是关于 bool 的简单引理s 和 mem1 , mem2 , diff1 , 和 diff2从上面。为了证明定理我用了它,只指定了归纳变量 xs其中 bool对表达式进行案例分析(使用自制的 Ltac bool_destruct),得到如下证明。
Theorem different_member:
forall xs ys, different xs ys = true ->
forall y, ((negb (member y ys)) || negb (member y xs)) = true.
Proof.
induction xs as [| a xs]; intros; my_simple_rewrite.
- congruence.
- try
match goal with
| [ HH:_ |- _] => (generalize (IHxs ys HH y); intro IH)
end;
bool_destruct (member a ys);
bool_destruct (member y ys);
bool_destruct (member a xs);
bool_destruct (member y xs);
bool_destruct (beq_nat y a);
my_simple_rewrite;
congruence.
Qed.

这个想法是这几乎可以自动化。选择要破坏的术语可以自动进行,并注意它试图用任何它可以抛出的东西来实例化归纳假设 - (“如果它有效,那很好!否则尝试下一个选择......”)。

以供将来引用,完整的开发在 https://gist.github.com/larsr/10b6f4817b5117b335cc

最佳答案

你的结果的问题是它不成立。例如,尝试

Compute different [2] [1; 2]. (* false *)
Compute (negb (member 1 [2]) || negb (member 1 [1; 2])). (* true *)

发生这种情况是因为,为了获得相反的结果,我们需要右侧对所有 y 都有效。 .正确的形式是:
forall xs ys,
different xs ys = true <->
(forall y, negb (member y xs) || negb (member x xs)).

尽管如此,将某些结果指定为 bool 方程会使它们在许多情况下更方便使用,这是对的。这种样式被大量使用,例如,在 Ssreflect 中图书馆,他们在那里写定理,例如:
eqn_leq : forall m n, (m == n) = (m <= n) && (n <= m)

在这里, ==<=运算符是 bool 函数,用于测试自然数的相等性和顺序。第一个是泛型​​的,适用于任何用 bool 相等函数声明的类型,称为 eqType在 Ssreflect 中。

这是使用 Ssreflect 的定理版本:
Require Import Ssreflect.ssreflect Ssreflect.ssrfun Ssreflect.ssrbool.
Require Import Ssreflect.ssrnat Ssreflect.eqtype Ssreflect.seq.

Section Different.

Variable T : eqType.
Implicit Types xs ys : seq T.

Fixpoint disjoint xs ys :=
match xs with
| [::] => true
| x :: xs' => (x \notin ys) && disjoint xs' ys
end.

Lemma disjointP xs ys :
reflect (forall x, x \in xs -> x \notin ys)
(disjoint xs ys).
Proof.
elim: xs=> [|x xs IH] /=; first exact: ReflectT.
apply/(iffP andP)=> [[x_nin /IH {IH} IH] x'|xsP].
by rewrite inE=> /orP [/eqP ->|] //; auto.
apply/andP; rewrite xsP /= ?inE ?eqxx //.
apply/IH=> x' x'_in; apply: xsP.
by rewrite inE x'_in orbT.
Qed.

End Different.

我已改名 differentdisjoint ,并使用了 Ssreflect 列表成员运算符 \in\notin ,可用于包含任何元素的列表 eqType .注意 disjointP的声明具有来自 bool 的隐式转换至 Prop (将 b 映射到 b = true ),并且用 reflect 表示谓词,您可以将其视为“当且仅当”连接词,但与 Prop 相关到 bool .

Ssreflect 广泛使用了 reflect谓词和 View 机制(您在证明脚本上看到的 / 标志)在同一事实的 bool 语句和命题语句之间进行转换。因此,虽然我们不能用简单的 bool 相等来说明等价,但我们可以保持 reflect 的许多便利性。谓词。例如:
Goal forall n, n \in [:: 1; 2; 3] -> n \notin [:: 4; 5; 6].
Proof. by apply/disjointP. Qed.

这里发生的事情是 Coq 使用了 disjointP将上述目标转换为 disjoint [:: 1; 2; 3] [:: 4; 5; 6] ( [:: ... ] 只是列表的 Ssreflect 符号),并且可以通过计算发现该目标是正确的。

关于coq - 几乎只使用重写来证明 Coq 中的定理 - 没有 "cleverness",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33315458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com