Library control


Defines control depence as an inductive type control_depsR_prog. Also defines keep_L_prog, the function computing the slice.

Require Export prog.
Require Export label.
Require Export set_prog.
Require Import quotient.
Require Import seq.
Require Import set_relation.
Require Import set_instance.

Inductive control_depsR_prog : prog relation label :=
  | CDP_here : s p l l', control_depsR_stmt s l l'
      control_depsR_prog (s;;p) l l'
  | CDP_after : s p l l', control_depsR_prog p l l'
      control_depsR_prog (s;;p) l l'
with control_depsR_stmt : stmt relation label :=
  | CDS_ifb_l : l b p1 p2 l' l'', control_depsR_prog p1 l' l''
      control_depsR_stmt (IFB << l >> b THEN p1 ELSE p2 FI) l' l''
  | CDS_ifb_r : l b p1 p2 l' l'', control_depsR_prog p2 l' l''
      control_depsR_stmt (IFB << l >> b THEN p1 ELSE p2 FI) l' l''
  | CDS_ifb_cond_l : l l' b p1 p2, label_first_inR_prog p1 l'
      control_depsR_stmt
        (IFB << l >> b THEN p1 ELSE p2 FI) l l'
  | CDS_ifb_cond_r : l l' b p1 p2, label_first_inR_prog p2 l'
      control_depsR_stmt
        (IFB << l >> b THEN p1 ELSE p2 FI) l l'
  | CDS_while : l b p l' l'', control_depsR_prog p l' l''
      control_depsR_stmt (WHILE << l >> b DO p END) l' l''
  | CDS_while_cond : l l' b p, label_first_inR_prog p l'
      control_depsR_stmt
        (WHILE << l >> b DO p END) l l'.

Scheme control_depsR_prog_mutual_ind :=
    Induction for control_depsR_prog Sort Prop
  with control_depsR_stmt_mutual_ind :=
    Induction for control_depsR_stmt Sort Prop.

Fixpoint keep_L_prog (p:prog) (L:set label) :=
  match p with
  | {{}}{{}}
  | s;;qif set_mem (stmt_get_label s) L then
              keep_L_stmt s L;;keep_L_prog q L
            else keep_L_prog q L
  end
with keep_L_stmt (s:stmt) (L:set label) :=
  match s with
  | SKIP << l >>SKIP << l >>
  | i::=a << l >>i ::= a << l >>
  | IFB << l >> b THEN p1 ELSE p2 FIIFB << l >> b THEN (keep_L_prog p1 L)
                                                      ELSE (keep_L_prog p2 L) FI
  | WHILE << l >> b DO p ENDWHILE << l >> b DO (keep_L_prog p L) END
  | ASSERT << l >> b =>> l'ASSERT << l >> b =>> l'
  end.

Lemma keep_L_prog_quotient : (p:prog) (L:set label),
  is_quotientR_prog p (keep_L_prog p L).
Proof.
  intros p L. revert p.
  prog_cases (apply (prog_mutual_ind
    (fun pis_quotientR_prog p (keep_L_prog p L))
    (fun sis_quotientR_stmt s (keep_L_stmt s L)))) Case; intros;
  try now constructor.
  - Case "P_cons". simpl. destruct (set_mem (stmt_get_label s) L).
    + apply IQP_stmt; assumption.
    + apply IQP_remove; assumption.
Qed.

Lemma include_rt : {A:Type} R R',
  inclusion A R R' inclusion A (clos_refl_trans A R) (clos_refl_trans A R').
Proof. unfold inclusion.
  intros. induction H0.
  - apply rt_step. apply H; assumption.
  - apply rt_refl.
  - apply rt_trans with (y:=y); assumption.
Qed.

Lemma control_ifb : s l',
  label_inR_stmt s l'
  clos_refl_trans label
    (control_depsR_stmt s) (stmt_get_label s) l'.
Proof.
  prog_cases (apply (stmt_mutual_ind
    (fun p l', label_inR_prog p l' s,
      label_first_inR_prog p (stmt_get_label s)
      clos_refl_trans label (control_depsR_prog p) (stmt_get_label s) l')
    (fun s l' : label, label_inR_stmt s l'
      clos_refl_trans label (control_depsR_stmt s) (stmt_get_label s) l')))
  Case; intros.
  - inversion H.
  - inversion H1.
    + s. apply H in H5. split.
      × apply LFP_here.
      × apply include_rt with (R':=control_depsR_prog (s;; p)) in H5.
        assumption. unfold inclusion; apply CDP_here.
    + apply H0 in H5. inversion H5 as [s2 H6]. s2. destruct H6. split.
      × apply LFP_after. assumption.
      × apply include_rt with (R':=control_depsR_prog (s;;p)) in H7. assumption.
        unfold inclusion; apply CDP_after.
  - inversion H. apply rt_refl.
  - inversion H. apply rt_refl.
  - inversion H1.
    + subst. apply rt_refl.
    + apply H in H7. inversion H7 as [s2 H8]. destruct H8.
      apply include_rt with
        (R':=control_depsR_stmt (IFB << l >> b THEN p ELSE p0 FI)) in H9.
      apply rt_trans with (y:=stmt_get_label s2). apply rt_step.
      apply CDS_ifb_cond_l. assumption.
      assumption.
      unfold inclusion; apply CDS_ifb_l.
    + apply H0 in H7. inversion H7 as [s2 H8]. destruct H8.
      apply include_rt with
        (R':=control_depsR_stmt (IFB << l >> b THEN p ELSE p0 FI)) in H9.
      apply rt_trans with (y:=stmt_get_label s2). apply rt_step.
      apply CDS_ifb_cond_r. assumption.
      assumption.
      unfold inclusion; apply CDS_ifb_r.
  - inversion H0.
    + subst. apply rt_refl.
    + apply H in H5. inversion H5 as [s2 H6]. destruct H6.
      apply include_rt with
        (R':=control_depsR_stmt (WHILE << l >> b DO p END)) in H7.
      apply rt_trans with (y:=stmt_get_label s2). apply rt_step.
      apply CDS_while_cond. assumption.
      assumption.
      unfold inclusion; apply CDS_while.
  - inversion H. apply rt_refl.
Qed.

Lemma set_stable_clos : L d,
  set_stable d L set_stable (clos_refl_trans label d) L.
Proof.
  unfold set_stable.
  intros.
  induction H1.
  - apply H in H1; assumption.
  - assumption.
  - apply IHclos_refl_trans1. apply IHclos_refl_trans2. assumption.
Qed.

Lemma control_stmt_get_label : s d L,
  set_stable d L
  inclusion label (control_depsR_stmt s) d
  set_mem (stmt_get_label s) L = false
  set_same (set_inter (set_of_labels_stmt s) L) empty_set.
Proof.
  intros.
  destruct s.
  - simpl in H1. simpl. apply set_inter_not_mem_empty. apply set_mem_complete1.
    assumption.
  - simpl in H1. simpl. apply set_inter_not_mem_empty. apply set_mem_complete1.
    assumption.
  - simpl in H1. simpl. unfold set_same. split.
    + unfold set_incl. intros.
       apply set_inter_elim in H2. destruct H2.
       apply set_stable_clos in H.
       assert (set_In l L).
       { unfold set_stable in H. apply H with (l':=a). assumption.
         apply include_rt in H0. apply H0.
         apply control_ifb.
         apply set_add_elim in H2. destruct H2.
         subst. apply LIS_ifb_cond.
         apply set_union_elim in H2.
         destruct H2. apply LIS_ifb_l.
         apply <- label_inR_prog_iff_in_set_of_labels.
         assumption. apply LIS_ifb_r.
         apply <- label_inR_prog_iff_in_set_of_labels. assumption.
       }
       apply set_mem_correct2 in H4.
       rewrite H1 in H4. inversion H4.
    + unfold set_incl. intros. inversion H2.
  - simpl in H1. simpl. unfold set_same. split.
    + unfold set_incl. intros.
       apply set_inter_elim in H2. destruct H2.
       apply set_stable_clos in H.
       assert (set_In l L).
       { unfold set_stable in H. apply H with (l':=a). assumption.
         apply include_rt in H0. apply H0.
         apply control_ifb.
         apply set_add_elim in H2. destruct H2.
         subst. apply LIS_while_cond. apply LIS_while_body.
         apply <- label_inR_prog_iff_in_set_of_labels.
         assumption.
       }
       apply set_mem_correct2 in H4.
       rewrite H1 in H4. inversion H4.
    + unfold set_incl. intros. inversion H2.
  - simpl in H1. simpl. apply set_inter_not_mem_empty. apply set_mem_complete1.
    assumption.
Qed.

Lemma keep_L_prog_label : (p:prog) (L:set label) d,
  set_stable d L
  inclusion label (control_depsR_prog p) d
  set_same (set_of_labels_prog (keep_L_prog p L)) (set_inter (set_of_labels_prog p) L).
Proof.
  intros p L d H. revert p.
  prog_cases (apply (prog_mutual_ind
    (fun pinclusion label (control_depsR_prog p) d
      set_same (set_of_labels_prog (keep_L_prog p L)) (set_inter (set_of_labels_prog p) L))
    (fun sinclusion label (control_depsR_stmt s) d
      set_same (set_of_labels_prog (keep_L_prog {{s}} L)) (set_inter (set_of_labels_stmt s) L))))
  Case; intros.
  - Case "P_nil". simpl. reflexivity.
  - Case "P_cons". simpl. destruct (set_mem (stmt_get_label s) L) eqn:Heqmem.
    rewrite set_inter_union_distr_l.
    simpl. apply set_same_union. simpl in H0. rewrite Heqmem in H0. apply H0. unfold inclusion.
    intros. apply H2. apply CDP_here; assumption.
    apply H1. unfold inclusion.
    intros. apply H2. apply CDP_after; assumption.
    rewrite set_inter_union_distr_l.
    assert (set_same (set_inter (set_of_labels_stmt s) L) empty_set).
    { apply control_stmt_get_label with (d:=d).
      assumption. unfold inclusion; intros. apply H2. apply CDP_here; assumption.
      assumption.
    }
    transitivity
      (set_union empty_set (set_inter (set_of_labels_prog p) L)).
    symmetry. rewrite set_same_union_empty_l. symmetry.
    apply H1. unfold inclusion; intros; apply H2; apply CDP_after; assumption.
    apply set_same_union. symmetry; assumption.
    reflexivity.
  - Case "S_skip". simpl. destruct (set_mem l L) eqn:Heqmem.
    + transitivity (set_singleton l). reflexivity.
      symmetry. apply set_inter_mem_singleton.
      apply set_mem_correct1; assumption.
    + simpl. symmetry. apply set_inter_not_mem_empty.
      apply set_mem_complete1; assumption.
  - Case "S_ass". simpl. destruct (set_mem l L) eqn:Heqmem.
    + transitivity (set_singleton l). reflexivity.
      symmetry. apply set_inter_mem_singleton.
      apply set_mem_correct1; assumption.
    + simpl. symmetry. apply set_inter_not_mem_empty.
      apply set_mem_complete1; assumption.
  - Case "S_ifb". simpl. destruct (set_mem l L) eqn:Heqmem.
    + simpl.
      rewrite set_same_union_empty_r.
      rewrite <- 2!set_same_union_add_singleton.
      rewrite 2!set_inter_union_distr_l.
      apply set_same_union.
      symmetry. apply set_inter_mem_singleton.
      apply set_mem_correct1; assumption.
      apply set_same_union.
      apply H0. unfold inclusion; intros. apply H2. apply CDS_ifb_l; assumption.
      apply H1. unfold inclusion; intros. apply H2. apply CDS_ifb_r; assumption.
    + simpl.
      remember (IFB << l >> b THEN p ELSE p0 FI) as s.
      assert (set_same (set_inter (set_of_labels_stmt s) L) empty_set).
      {
        apply control_stmt_get_label with (d:=d).
        assumption.
        assumption.
        rewrite Heqs. assumption.
      }
      rewrite Heqs in H3. simpl in H3.
      symmetry. assumption.
  - Case "S_while". simpl. destruct (set_mem l L) eqn:Heqmem.
    + simpl. rewrite <- 2!set_same_union_add_singleton.
      rewrite set_inter_union_distr_l.
      rewrite set_same_union_empty_r.
      apply set_same_union.
      symmetry. apply set_inter_mem_singleton.
      apply set_mem_correct1; assumption.
      apply H0. unfold inclusion; intros. apply H1. apply CDS_while; assumption.
    + remember (WHILE << l >> b DO p END) as s.
      assert (set_same (set_inter (set_of_labels_stmt s) L) empty_set).
      {
        apply control_stmt_get_label with (d:=d).
        assumption.
        assumption.
        rewrite Heqs. assumption.
      }
      rewrite Heqs in H2. simpl in H2.
      symmetry. assumption.
  - Case "S_assert". simpl. destruct (set_mem l L) eqn:Heqmem.
    + transitivity (set_singleton l). reflexivity.
      symmetry. apply set_inter_mem_singleton.
      apply set_mem_correct1; assumption.
    + simpl. symmetry. apply set_inter_not_mem_empty.
      apply set_mem_complete1; assumption.
Qed.

Lemma control_depsR_label_inR_prog : p l l',
  control_depsR_prog p l l'
  label_inR_prog p l'
  label_inR_prog p l.
Proof.
  apply (control_depsR_prog_mutual_ind
    (fun p l l' Hlabel_inR_prog p l' label_inR_prog p l)
    (fun s l l' Hlabel_inR_stmt s l' label_inR_stmt s l)); intros.
  - destruct H. split; apply LIP_here; assumption.
  - destruct H. split; apply LIP_after; assumption.
  - destruct H. split; apply LIS_ifb_l; assumption.
  - destruct H. split; apply LIS_ifb_r; assumption.
  - split.
    + apply LIS_ifb_l. apply label_first_label_inR_prog. assumption.
    + apply LIS_ifb_cond.
  - split.
    + apply LIS_ifb_r. apply label_first_label_inR_prog. assumption.
    + apply LIS_ifb_cond.
  - destruct H. split; apply LIS_while_body; assumption.
  - split.
    + apply LIS_while_body. apply label_first_label_inR_prog. assumption.
    + apply LIS_while_cond.
Qed.

Lemma trans_control_depsR_label_inR_prog : p l l',
  clos_refl_trans label (control_depsR_prog p) l l'
  label_inR_prog p l'
  label_inR_prog p l.
Proof.
  intros. induction H as [l l'|l|l l' l''].
  - apply control_depsR_label_inR_prog in H. destruct H; assumption.
  - assumption.
  - apply IHclos_refl_trans1. apply IHclos_refl_trans2.
    assumption.
Qed.

Lemma control_depsR_prog_stable : p,
  set_stable (control_depsR_prog p) (set_of_labels_prog p).
Proof. unfold set_stable.
  intros. apply label_inR_prog_iff_in_set_of_labels.
  apply control_depsR_label_inR_prog with (l':=l'). assumption.
Qed.

Fixpoint set_label_first_prog (p:prog) :=
  match p with
  | {{}}\emptyset
  | s;;qset_add (stmt_get_label s) (set_label_first_prog q)
  end.

Lemma set_label_first_prog_correct : p l,
  l \in set_label_first_prog p label_first_inR_prog p l.
Proof.
  intros p. induction p; intros.
  - simpl. split; intros; inversion H.
  - simpl. split; intros.
    + apply set_add_elim in H. destruct H.
      × subst l. apply LFP_here.
      × apply LFP_after. apply IHp. assumption.
    + inversion H.
      × apply set_add_intro2. reflexivity.
      × apply set_add_intro1. apply IHp. assumption.
Qed.

Fixpoint set_control_prog (p:prog) : set(label×label) :=
  match p with
  | {{}}\emptyset
  | s;;qset_control_stmt s \cup set_control_prog q
  end
with set_control_stmt (s:stmt) : set(label×label) :=
  match s with
  | SKIP << _ >>\emptyset
  | _ ::= _ << _ >>\emptyset
  | IFB << l >> _ THEN p1 ELSE p2 FI
      set_map (fun l'(l, l')) (set_label_first_prog p1 \cup set_label_first_prog p2)
      \cup set_control_prog p1 \cup set_control_prog p2
  | WHILE << l >> _ DO p END
      set_map (fun l'(l, l')) (set_label_first_prog p) \cup set_control_prog p
  | ASSERT << _ >> _ =>> _\emptyset
  end.

Lemma set_control_prog_correct : p l l',
  (l, l') \in set_control_prog p control_depsR_prog p l l'.
Proof.
  apply (prog_mutual_ind
    (fun p l l', (l, l') \in set_control_prog p control_depsR_prog p l l')
    (fun s l l', (l, l') \in set_control_stmt s control_depsR_stmt s l l'));
  intros; simpl; try (split; intros; inversion H; fail).
  - rewrite set_union_In. rewrite H, H0. split; intros.
    + destruct H1.
      × apply CDP_here; assumption.
      × apply CDP_after; assumption.
    + inversion H1.
      × left; assumption.
      × right; assumption.
  - rewrite 2!set_union_In. rewrite H, H0. split; intros.
    + decompose [or] H1; clear H1.
      × rewrite set_map_In in H2. destruct H2 as [a [H2 H3]]. inversion H3; subst.
        rewrite set_union_In in H2. { destruct H2.
        - apply CDS_ifb_cond_l. apply set_label_first_prog_correct. assumption.
        - apply CDS_ifb_cond_r. apply set_label_first_prog_correct. assumption. }
      × apply CDS_ifb_l; assumption.
      × apply CDS_ifb_r; assumption.
    + inversion H1; subst.
      × right; left. assumption.
      × right; right. assumption.
      × left. rewrite set_map_In. l'. split; try reflexivity.
        rewrite set_union_In. left. apply set_label_first_prog_correct; assumption.
      × left. rewrite set_map_In. l'. split; try reflexivity.
        rewrite set_union_In. right. apply set_label_first_prog_correct; assumption.
  - rewrite set_union_In. rewrite H. split; intros.
    + destruct H0.
      × rewrite set_map_In in H0. destruct H0 as [l'' [H0 H1]].
        inversion H1; subst. apply CDS_while_cond.
        apply set_label_first_prog_correct; assumption.
      × apply CDS_while; assumption.
    + inversion H0; subst.
      × right. assumption.
      × left. rewrite set_map_In. l'. split; try reflexivity.
        apply set_label_first_prog_correct; assumption.
Qed.