Library Nom_Howe

Require Export Nom_Struct_congr.

Inductive howe {V:Set}: binary proc0 proc V proc V Prop :=
| howe_comp : Rel P Q R, howe Rel P R
      open_extension Rel R Q howe Rel P Q
| howe_nil : Rel, howe Rel PO PO
| howe_var : Rel x, howe Rel (pr_var x) (pr_var x)
| howe_par : Rel P Q P' Q', howe Rel P Q howe Rel P' Q'
      howe Rel (P // P') (Q // Q')
| howe_inp : Rel a P Q, @howe (incV V) Rel P Q
      howe Rel (a ? P) (a ? Q)
| howe_out : Rel a P Q P' Q', howe Rel P Q howe Rel P' Q'
      howe Rel (a!(P) P') (a !(Q) Q')
| howe_nu : Rel b c P Q, c `notin` fn (nu b, P)
      howe Rel P Q howe Rel (nu c, (swap b c P)) (nu b, Q)
.

Inductive howe' {V:Set}: binary proc0 proc V proc V nat Prop :=
| howe_comp' : Rel P Q R k, howe' Rel P R k
      open_extension Rel R Q howe' Rel P Q (S k)
| howe_nil' : Rel, howe' Rel PO PO 0
| howe_var' : Rel x, howe' Rel (pr_var x) (pr_var x) 0
| howe_par' : Rel P Q P' Q' k k', howe' Rel P Q k howe' Rel P' Q' k'
      howe' Rel (P // P') (Q // Q') (S(k+k'))
| howe_inp' : Rel a P Q k, @howe' (incV V) Rel P Q k
      howe' Rel (a ? P) (a ? Q) (S k)
| howe_out' : Rel a P Q P' Q' k k', howe' Rel P Q k howe' Rel P' Q' k'
      howe' Rel (a!(P) P') (a!(Q) Q') (S(k+k'))
| howe_nu' : Rel b c P Q k, c `notin` fn (nu b, P)
      howe' Rel P Q k howe' Rel (nu c, (swap b c P)) (nu b, Q) (S k)
.

Hint Constructors howe howe':howe.

Lemma howe_nu_same {V:Set}: Rel a (P Q: proc V),
    howe Rel P Q howe Rel (nu a, P) (nu a, Q).
Proof. intros. rewrite <- (swap_id _ a P) at 1; constructor; [simpl; auto | auto].
Qed.

Lemma howe'_nu_same {V:Set}: Rel a (P Q: proc V) k,
    howe' Rel P Q k howe' Rel (nu a, P) (nu a, Q) (S k).
Proof. intros. rewrite <- (swap_id _ a P) at 1; constructor; [simpl; auto | auto].
Qed.

Lemma howe_nu_aeq {V:Set} : b c (P : proc V),
    c `notin` fn (nu b, P) (nu c, (swap b c P) =A= nu b, P).
Proof. intros. destruct (b==c); simpls; subst; constructor; auto. simpl_swap.
  rewrite swap_sym. reflexivity. Qed.

Hint Resolve howe_nu_same howe'_nu_same:howe.

Lemma howe'_ind_size :
   Pr : ( V : Set, binary proc0 proc V proc V nat Prop),
   ( W (Rel : binary proc0) (P' Q':proc W) n', howe' Rel P' Q' n'
     ( (V : Set) (P Q: proc V) n, howe' Rel P Q n n < n'
          Pr V Rel P Q n) Pr W Rel P' Q' n')
    (V : Set) (b : binary proc0) (p p0 : proc V) (n : nat),
      howe' b p p0 n Pr V b p p0 n.
Proof.
  intros. gen V. induction n using TLC.LibNat.peano_induction; intros.
  apply H; auto.
Qed.


Lemma howe'_implies_howe {V:Set}: (P Q:proc V) Rel n,
    howe' Rel P Q n howe Rel P Q.
Proof.
  intros. induction H; eauto with howe.
Qed.

Lemma howe_implies_howe' {V:Set}: (P Q:proc V) (Rel:binary proc0),
    howe Rel P Q n, howe' Rel P Q n.
Proof.
  intros.
  induction H; try (destruct IHhowe as [n']);
    try (destruct IHhowe2 as [n2]); try (destruct IHhowe1 as [n1]);
    eexists; eauto with howe.
Qed.


Basic properties


Lemma howe_refl {V:Set}: Rel (P:proc V), howe Rel P P.
Proof. intros_all. induction P; eauto with howe. Qed.

Lemma howe'_refl {V:Set}: Rel (P:proc V), k, howe' Rel P P k.
Proof. intros_all. apply howe_implies_howe'. apply howe_refl. Qed.

Hint Resolve howe_refl howe'_refl :howe.

Lemma howe_genNu : V Rel L P Q,
    howe Rel P Q howe Rel (@genNu V L P) (genNu L Q).
Proof. intros V Rel L. induction L; intros; simpl; auto with howe. Qed.


Lemma howe'_swap {V:Set} : Rel (P Q : proc V) k b c,
    mod_aeq Rel mod_swap Rel howe' Rel P Q k
    howe' Rel (swap b c P) (swap b c Q) k.
Proof. intros. induction H1; simpl; auto with howe.
  - eapply howe_comp'. eauto with howe. apply oe_swap; auto.
  - rewrite swap_equivariance. constructor; auto. simpl_swap.
Qed.

Lemma mod_aeq_howe {V:Set} : Rel,
    refl Rel mod_aeq Rel mod_aeq (@howe V Rel).
Proof. introv ref maeq. intros_all. gen P' Q'.
  induction H; intros; simpl;
  try solve [inversion H0; inversion H1; auto with howe];
  try solve [inversion H1; inversion H2; auto with howe];
  forwards maeqoe: @mod_aeq_oe V Rel maeq.
  - apply howe_comp with R. apply IHhowe; auto; reflexivity.
    eapply maeqoe; eauto; reflexivity.
  - rewrite howe_nu_aeq in H1; auto.
    inversion H1; inversion H2; subst; auto with howe.
    + apply howe_comp with (nu b, (swap b c0 Q1)). auto with howe.
      eapply maeqoe; eauto. 2:constructor; eauto. apply oe_refl; auto.
    + rewrite <- (swap_invo _ b c0 Q0). constructor; auto. simpl; simpl_swap.
    + rewrite <- (swap_invo _ b c0 Q0). apply howe_comp with (nu b, (swap b c1 Q1)).
      constructor; auto. simpl; simpl_swap. eapply maeqoe. 3: reflexivity.
      apply oe_refl; auto. symmetry. constructor; auto. reflexivity.
Qed.

Lemma mod_aeq_left_howe' {V:Set} : Rel P Q P' k,
    refl Rel mod_aeq Rel howe' Rel P Q k
    P=A=P' @howe' V Rel P' Q k.
Proof. introv ref maeq. intros_all. gen P'.
  induction H; intros; simpl;
  try solve [inversion H0; auto with howe];
  try solve [inversion H1; auto with howe];
  forwards maeqoe: @mod_aeq_oe V Rel maeq.
  - apply howe_comp' with R. apply IHhowe'; auto; reflexivity. auto.
  - rewrite howe_nu_aeq in H1; auto. inversion H1; subst; auto with howe.
    rewrite <- (swap_invo _ b c0 Q0). constructor; auto. simpl; simpl_swap.
Qed.

Lemma howe_aeq {V:Set}: Rel (P Q:proc V),
    refl Rel mod_aeq Rel P=A=Q howe Rel P Q.
Proof. intros. forwards: @mod_aeq_howe V; eauto.
  eapply H2; eauto with howe; reflexivity. Qed.

Lemma howe_oe {V:Set}: Rel (P Q:proc V),
   open_extension Rel P Q howe Rel P Q.
Proof. intros. apply howe_comp with P; auto with howe. Qed.


Symmetry of the transitive closure


Lemma howe_clos_trans_par {V:Set}: Rel (P Q P' Q':proc V),
  tclosure (howe Rel) P Q tclosure (howe Rel) P' Q'
  tclosure (howe Rel) (P // P')(Q //Q').
Proof.
  intros. gen P' Q'.
  induction H.
  - intros. apply tclosure_trans with (y//P'). apply tclosure_once.
      apply howe_par; auto with howe.
    induction H0. apply tclosure_once. apply howe_par; auto with howe.
    eapply tclosure_trans; eauto.
  - intros. apply tclosure_trans with (y//P'). apply IHtclosure1.
      apply tclosure_once; auto with howe.
    apply IHtclosure2. apply H1.
Qed.

Lemma howe_clos_trans_inp {V:Set}: Rel (P Q:proc (incV V)) a,
  tclosure (howe Rel) P Q tclosure (howe Rel) (a ? P)(a ? Q).
Proof.
  intros.
  induction H.
  - apply tclosure_once. auto with howe.
  - eapply tclosure_trans; eauto with howe.
Qed.

Lemma howe_clos_trans_out {V:Set}: Rel (P Q P' Q':proc V) a,
  tclosure (howe Rel) P Q tclosure (howe Rel) P' Q'
  tclosure (howe Rel) (a !(P) P')(a !(Q) Q').
Proof.
  intros. gen P' Q'.
  induction H.
  - intros. apply tclosure_trans with (a!(y) P'). apply tclosure_once.
      apply howe_out; auto with howe.
    induction H0. apply tclosure_once. apply howe_out; auto with howe.
    eapply tclosure_trans; eauto.
  - intros. apply tclosure_trans with (a!(y) P'). apply IHtclosure1.
      apply tclosure_once; auto with howe. auto.
Qed.

Lemma howe_clos_trans_nu_same {V:Set}:
   (Rel:binary proc0) a (P Q:proc V),
  tclosure (howe Rel) P Q tclosure (howe Rel) (nu a, P) (nu a, Q).
Proof.
  intros. induction H.
  - apply tclosure_once. auto with howe.
  - eapply tclosure_trans; eauto with howe.
Qed.

Lemma howe_clos_trans_nu {V:Set}:
   (Rel:binary proc0) b c (P Q:proc V),
    tclosure (howe Rel) P Q c `notin` fn (nu b, P)
    tclosure (howe Rel) (nu c, (swap b c P)) (nu b, Q).
Proof. intros. induction H.
  - apply tclosure_once. auto with howe.
  - eapply tclosure_trans; eauto with howe. apply howe_clos_trans_nu_same; auto.
Qed.

Hint Resolve howe_clos_trans_par howe_clos_trans_inp howe_clos_trans_out: howe.
Hint Constructors tclosure:howe.

Lemma howe_sym {V:Set}: (Rel:binary proc0),
    refl Rel mod_aeq Rel sym Rel sym (tclosure (@howe V Rel)).
Proof.
  intros_all. induction H2.
  - induction H2; auto with howe.
    + eapply tclosure_trans; auto. apply tclosure_once.
      apply howe_oe; auto with howe. apply oe_sym; eauto.
    + eapply tclosure_r. eapply (howe_clos_trans_nu_same); eauto.
      apply howe_aeq; auto. symmetry. apply howe_nu_aeq. auto.
  - eapply tclosure_trans; eauto.
Qed.


Substitutivity


Lemma howe_mapV {V W:Set}: Rel (P Q:proc V) (f:VW),
    mod_aeq Rel howe Rel P Q howe Rel (mapV f P)(mapV f Q).
Proof.
  intros. gen W.
  induction H0; intros; simpl; try rewrite <- swap_mapV; auto with howe.
  eapply howe_comp; eauto. apply oe_mapV; auto.
  constructor; auto. simpl; simpl_swap.
Qed.

Hint Resolve howe_mapV:howe.

Lemma howe'_bind {V W:Set}: Rel (P Q:proc V) (f g:V proc W) N n,
    ( x, fn (f x) [<=] N) ( x, fn (g x) [<=] N)
    fn P [<=] N fn Q [<=] N refl Rel mod_aeq Rel mod_swap Rel
    howe' Rel P Q n ( x, k', howe' Rel (f x) (g x) k')
     k, howe' Rel (bind f N P) (bind g N Q) k.
Proof. introv inf ing inP inQ ref maeq swaprel howePQ howefg. gen W N.
  induction howePQ using howe'_ind_size.
  destruct howePQ; intros; unfold bind; simpl in *; foldbind; auto with howe.
  - forwards: H P R f g (union N (fn R)); eauto; try nat_math; try fsetdec;
    try solve [intro; try rewrite inf; try rewrite ing; fsetdec].
    destruct H1. (S x). apply howe_comp' with (bind g (union N (fn R)) R).
    eapply mod_aeq_left_howe'; eauto. apply aeq_bind_2; auto.
    intro; rewrite inf. 1-2:fsetdec.
    forwards maeqoe: @mod_aeq_oe maeq; auto.
    eapply maeqoe. 2: reflexivity. apply oe_bind; eauto. 4:apply aeq_bind_2; auto.
      fsetdec. 1,4:rewrite inQ; fsetdec. all:intro; rewrite ing; fsetdec.
  - forwards: H P Q; eauto; try nat_math; try fsetdec.
    forwards: H P' Q'; eauto; try nat_math; try fsetdec.
    destruct H0. destruct H1. (S x + x0). constructor; auto.
  - forwards: H P Q (liftV f) (liftV g) N; eauto. nat_math.
      1-3: intros [|x]; simpl; simpl_swap; try fsetdec; auto with howe.
      2-3: fsetdec. apply howe_implies_howe'. apply howe_mapV; auto with howe.
      destruct (howefg x). eapply howe'_implies_howe; eauto.
    destruct H0; eexists; constructor; eauto.
  - forwards: H P Q; eauto; try nat_math; try fsetdec.
    forwards: H P' Q'; eauto; try nat_math; try fsetdec.
    destruct H0. destruct H1. (S x + x0). constructor; auto.
  - destruct atom_fresh. foldbind. enough ( k0, howe' Rel ( bind f
      (add x N) (swap c x (swap b c P))) ( bind g (add x N) (swap b x Q)) k0)
      by (destruct H1; (S x0); auto with howe). simpl_swap in inP.
    rewrite <- swap_fs_notin in inP. 2-3:fsetdec.
    forwards: (@howe'_swap W) b x maeq howePQ; auto.
    forwards: H H1 (add x N); auto; try nat_math; try apply fnsaxp; auto;
      try solve [intro; try rewrite inf; try rewrite ing; fsetdec].
    destruct H2. (x0). eapply mod_aeq_left_howe'; eauto.
    symmetry. apply aeq_bind_3. apply fnsaxp; auto. rewrite swap_sym.
    symmetry. apply aeq_swap_cut_notin. intuition.
Qed.

Lemma howe_bind {V W:Set}: Rel (P Q:proc V) (f g:V proc W) N,
    ( x, fn (f x) [<=] N) ( x, fn (g x) [<=] N)
    fn P [<=] N fn Q [<=] N refl Rel mod_aeq Rel mod_swap Rel
    howe Rel P Q ( x, howe Rel (f x) (g x))
    howe Rel (bind f N P) (bind g N Q).
Proof.
  intros. apply howe_implies_howe' in H6. destruct H6. forwards: @howe'_bind V.
  exact H. exact H0. exact H1. exact H2. exact H3. exact H4. exact H5. exact H6.
  intros. apply howe_implies_howe'; auto.
  destruct H8. eapply howe'_implies_howe; eauto.
Qed.

Lemma howe_subst {V:Set}: Rel (P' Q' :proc V) P Q,
    refl Rel mod_aeq Rel mod_swap Rel
    howe Rel P Q howe Rel P' Q' howe Rel (subst P P')(subst Q Q').
Proof.
  introv ref maeq swaprel hPQ hPQ'. forwards maeqhowe: @mod_aeq_howe V maeq; auto.
  unfold subst. assert (fn P [<=] union (union (fn P) (fn P'))
    (union (fn Q) (fn Q'))) by fsetdec. assert (fn Q [<=] union (union (fn P)
    (fn P')) (union (fn Q) (fn Q'))) by fsetdec.
  eapply maeqhowe. 2-3:apply aeq_bind_2; eauto; try intros [|x]; simpl; fsetdec.
  apply howe_bind; auto; try intros [|x]; simpl; try fsetdec; auto with howe.
Qed.

Hint Resolve howe_subst howe_bind:howe.