这个问题的灵感来自软件基础,但不是练习。到目前为止我所知道的。
Imp章节(“简单命令式程序”)使用功能图(来自地图章节(“全部和部分地图”))来简化环境。[1]编程语言。
Inductive id : Type :=
| Id : string -> id.
Definition total_map (A:Type) := id -> A.
Definition t_empty {A:Type} (v : A) : total_map A :=
(fun _ => v).
Definition t_update {A:Type} (m : total_map A) (x : id) (v : A) :=
fun x' => if beq_id x x' then v else m x'.
关于Imp章节中的程序的推理需要操作t_update (t_update (...) x 4) y 12)
形式的程序状态,这变得乏味,因为状态随着每个赋值而增长,即使赋值是“实现”是现有变量的更新
从理论上讲,对于每个变量,应该可以将程序状态折叠为单t_update
个,而且我已经证明了几个朝着正确方向前进的引理。 / p>
Require Import Coq.Logic.FunctionalExtensionality.
Lemma swap_updates : forall A (m : total_map A) x vx y vy,
x <> y -> t_update (t_update m x vx) y vy = t_update (t_update m y vy) x vx.
Proof.
intros A m x vx y vy H. apply functional_extensionality. intros k.
unfold t_update. destruct (beq_id y k) eqn:Eqyk.
- destruct (beq_id x k) eqn:Eqxk.
+ apply beq_id_true_iff in Eqyk. apply beq_id_true_iff in Eqxk. subst.
contradiction.
+ reflexivity.
- destruct (beq_id x k) eqn:Eqxk; reflexivity.
Qed.
Lemma collapse_updates : forall A (m : total_map A) x v1 v2,
t_update (t_update m x v1) x v2 = t_update m x v2.
Proof.
intros A m x v1 v2. apply functional_extensionality. intros k.
unfold t_update. destruct (beq_id x k); reflexivity.
Qed.
但我不知道如何陈述(更不用说证明或使用)t_update (... (t_update (...) x 4) ...) x 27
等于t_update (...) x 27
的定理;即删除x
的无用绑定。
有什么想法吗?
[1]我刚看到这个。我要离开了,但是我正考虑很快从Coq度假。
答案 0 :(得分:3)
但我不知道如何陈述(更不用说证明或使用)
t_update (... (t_update (...) x 4) ...) x 27
等于t_update (...) x 27
的定理;即删除x
的无用绑定。
首先,没有必要陈述这样的定理,能够求解形式的方程式就足够了
t_update ... (t_update ...) = t_update ... (t_update ...)
实现您的目标。这就是以下自定义策略。
Require Import Coq.Logic.FunctionalExtensionality.
Ltac t_solve :=
intros; apply functional_extensionality; intros; unfold t_update;
repeat lazymatch goal with
|- context [beq_id ?v ?x] =>
case_eq (beq_id v x);
[rewrite beq_id_true_iff | rewrite beq_id_false_iff]; intros
end;
subst; (congruence || discriminate).
我们知道状态只是嵌套if beq_id ? ? then ... else ...
表达式的阶梯,所以如果我们使用beq_id ? ?
机制破坏所有context
子表达式,那么一些标准策略足够聪明,可以完成我们。如果变量上的数字足够大,但这个解决方案将不起作用,但应足以通过软件基础工作。
答案 1 :(得分:2)
执行此操作的一种方法是通过中间表示继续操作,以便我们可以更轻松地操作更新。我是通过根据(id, A)
对(l_update
)列表定义更新来实现的,然后证明我们可以添加到更新列表并替换任何现有更新(add_update
这个)。简化最终是一种策略,首先重写使用l_update
的所有内容,然后通过简化add_update
来计算更新列表(没有重复的ID),然后最终计算l_update
低至t_update
s(因为它恰好以这种方式定义)。在一个真正的开发中,它会更容易,因为你将使用字符串作为ID并且if string_dec "a" "b" then ... else ...
调用应该计算掉,而我必须使用重写,因为决策函数是一个公理。
Require Import Coq.Logic.FunctionalExtensionality.
Require Import List.
Variable id:Type.
Axiom id_eq_dec : forall (x y:id), {x=y}+{x<>y}.
Variable A:Type.
Definition total_map := id -> A.
Definition t_update (m : total_map) (x : id) (v : A) : total_map :=
fun x' => if id_eq_dec x x' then v else m x'.
Definition Updates := list (id*A).
Fixpoint l_update (m:total_map) (us:Updates) : total_map :=
match us with
| nil => m
| (x,a)::us' => t_update (l_update m us') x a
end.
Fixpoint add_update (us:Updates) x a : Updates :=
match us with
| nil => (x, a)::nil
| (x',a')::us' => if id_eq_dec x x' then
add_update us' x a
else (x',a') :: add_update us' x a
end.
Lemma t_update_neq : forall m x v x',
x <> x' ->
t_update m x v x' = m x'.
Proof.
unfold t_update; intros.
destruct (id_eq_dec x x'); congruence.
Qed.
Lemma t_update_eq : forall m x v,
t_update m x v x = v.
Proof.
unfold t_update; intros.
destruct (id_eq_dec x x); congruence.
Qed.
Hint Rewrite t_update_neq using (solve [ auto ] ) : upd.
Hint Rewrite t_update_eq : upd.
Ltac cmp_id x x' := destruct (id_eq_dec x x'); subst; simpl;
try autorewrite with upd;
try congruence; auto.
Lemma l_update_add_other_update: forall us x a m a' x',
x <> x' ->
l_update m (add_update us x a) x' = l_update m (add_update us x a') x'.
Proof.
induction us; simpl; intros.
autorewrite with upd; auto.
destruct a.
cmp_id x i.
cmp_id i x'.
Qed.
Hint Resolve l_update_add_other_update.
Lemma l_update_add_update : forall us m x a,
l_update m (add_update us x a) x = a.
Proof.
induction us; simpl; intros;
autorewrite with upd;
auto.
destruct a; simpl.
cmp_id x i.
Qed.
Hint Rewrite l_update_add_update : upd.
Lemma l_update_add_update_neq : forall us m x x' a,
x <> x' ->
l_update m (add_update us x a) x' = l_update m us x'.
Proof.
induction us; intros.
simpl; autorewrite with upd; auto.
destruct a; simpl.
cmp_id x i.
cmp_id i x'.
Qed.
Hint Rewrite l_update_add_update_neq using solve [ auto ] : upd.
Theorem l_update_add : forall us m x a,
t_update (l_update m us) x a =
l_update m (add_update us x a).
Proof.
induction us; intros; extensionality x'; simpl; auto.
destruct a; simpl in *.
rewrite IHus by auto.
cmp_id x i.
cmp_id i x'.
cmp_id x x'.
cmp_id i x'.
Qed.
Lemma if_id_eq_not : forall T (a b:T) i i',
i <> i' ->
(if id_eq_dec i i' then a else b) = b.
Proof.
intros.
destruct (id_eq_dec i i'); congruence.
Qed.
Lemma if_id_eq : forall T (a b:T) i,
(if id_eq_dec i i then a else b) = a.
Proof.
intros.
destruct (id_eq_dec i i); congruence.
Qed.
Ltac simplify_updates m :=
replace m with (l_update m nil) by auto;
repeat rewrite l_update_add;
repeat (simpl; rewrite ?if_id_eq_not, ?if_id_eq by auto).
Example update_chain1 : forall m x1 x2 x3 a1 a2 a3 a4 a5,
x1 <> x2 ->
x2 <> x3 ->
x1 <> x3 ->
t_update
(t_update
(t_update
(t_update
(t_update m x1 a1) x3 a2) x2 a3) x1 a4) x3 a5 =
t_update
(t_update
(t_update m x3 a5) x1 a4) x2 a3.
Proof.
intros.
etransitivity.
simplify_updates m.
auto.
auto.
Qed.
答案 2 :(得分:2)
这样的事情怎么样?
Definition almost_equal {A} x (m m' : total_map A) :=
forall y, x <> y -> m y = m' y.
Lemma update_almost_equal : forall A (m : total_map A) x v1,
almost_equal x (t_update m x v1) m.
Proof.
intros A m x v1 y H.
unfold t_update.
destruct (beq_id x y) eqn:Eqxy.
+ rewrite beq_id_true_iff in Eqxy. congruence.
+ reflexivity.
Qed.
Lemma update_preserves_almost_equal : forall A (m m' : total_map A) x y v,
almost_equal x m m' ->
almost_equal x (t_update m y v) (t_update m' y v).
Proof.
intros A m m' x y v H z H'.
unfold t_update.
destruct (beq_id y z); auto.
Qed.
Lemma collapse_updates : forall x A (m m' : total_map A) v,
almost_equal x m m' ->
t_update m x v = t_update m' x v.
Proof.
intros x A m m' v Hae. apply functional_extensionality. intros k.
unfold t_update.
destruct (beq_id x k) eqn:Heq.
+ reflexivity.
+ rewrite beq_id_false_iff in Heq.
apply Hae; exact Heq.
Qed.
您可以使用collapse_updates
重写,eauto
可以构建almost_equal
的证明。
Example ex1 :
forall A x y z (v1 v2 v3 v4 : A) m,
t_update (t_update (t_update (t_update m x v1) z v2) y v3) x v4
= t_update (t_update (t_update m z v2) y v3) x v4.
Proof.
intros.
erewrite collapse_updates by eauto using update_almost_equal, update_preserves_almost_equal.
reflexivity.
Qed.
Example ex2 :
forall A x y z (v1 v2 v3 v4: A) m,
t_update (t_update (t_update (t_update m y v1) z v2) y v3) x v4
= t_update (t_update (t_update m z v2) y v3) x v4.
Proof.
intros.
erewrite (collapse_updates y) by eauto using update_almost_equal, update_preserves_almost_equal.
reflexivity.
Qed.
缺点是您必须提及要简化的变量,例如:上面collapse_updates y
。我想这是因为rewrite
没有回溯不同的子项选择,所以如果你没有提到变量,它将尝试最外面的变量,然后放弃,如果失败。这意味着我无法想出任何方式将其用作autorewrite
提示,尽管您可以编写一个尝试所有不同变量的Ltac:
Ltac simpl_updates :=
repeat match goal with
| [ |- context C1[t_update _ ?X _] ] =>
erewrite (collapse_updates X) by eauto using update_almost_equal, update_preserves_almost_equal
end.
Example ex3 :
forall A x y z w (v1 v2 v3 v4 v5 v6 v7 v8: A) m,
t_update (t_update (t_update (t_update (t_update (t_update (t_update m x v1) y v2) z v3) x v4) y v5) w v6) y v7
= t_update (t_update (t_update (t_update m z v3) x v4) w v6) y v7.
Proof.
intros.
simpl_updates.
reflexivity.
Qed.