功能映射中的“折叠”状态?

时间:2017-12-05 20:20:30

标签: coq

这个问题的灵感来自软件基础,但不是练习。到目前为止我所知道的。

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度假。

3 个答案:

答案 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.