Library HOC06FreshLemmas


Require Import HOC01Defs.
Require Import HOC02BaseLemmas.
Require Import HOC03CanonicalLemmas.
Require Import HOC04DefLTS.
Require Import HOC05WFProcesses.


Lemma wfp_gfresh_Abs : a X Y p, X # (wfp_Abs a Y p) = (X = Y X # p).
Proof with (try solve [fresh_solve]; jauto).
  introv; simpl; unfold Abs.
  rewrite gfresh_receive.
  tests : (X = Y); rew_logic; splits; intro Hyp...
Qed.



Lemma wfp_cfresh_par_iff : m p q,
  m ### wfp_Par p q = (m ### p m ### q).
Proof.
  introv; simpl; rewrite× cfresh_par_iff.
Qed.

Lemma wfp_cfresh_Abs : a m X p,
  m ### (wfp_Abs a X p) = (m ### p a m).
Proof.
  introv; simpl; unfold Abs; simpl.
  rewrite cfresh_receive.

  assert ( x X p, CHS ([Lvar x//X]p) = (CHS p)).
    clear; induction p; introv; simpls~; try rewrite¬ IHp.
    cases_if¬.
    rewrite IHp1, IHp2; auto.

  unfolds fresh_chan; rewrite H; tauto.
Qed.

Lemma wfp_cfresh_pipe : a m xs (p : wfprocess),
  m ### p a mm ### (wfp_pipe a xs p).
Proof.
  induction xs; introv H.
    simpls×.
    rewrite wfp_pipe_to_Abs. rewrite wfp_cfresh_Abs; split×.
Qed.

Lemma wfp_cfresh_pipe_cons : xs a m x p,
  m ### (wfp_pipe a (x :: xs) p)m###p am.
Proof with
  (try rewrite wfp_pipe_to_Abs in *;
   try rewrite wfp_pipe_nil_eq in *;
   try rewrite wfp_cfresh_Abs in *; jauto).

  induction xs; introv Hf; simpl...
    applys× IHxs.
Qed.


Lemma wfp_cfresh_swap_inv : (p : wfprocess) m X Y, m ### p = m ### wfp_swap X Y p.
Proof.
  inductions p; simpl; rename proc into p; clear wf_cond.
  inductions p; introv; unfolds fresh_chan; simpls;
  unfold notin in *; repeat (rewrite in_union in *; rew_logic in × );
   try solve [rewrites¬ <- IHp; try reflexivity; intuition]; auto.
   rewrites¬ <- IHp1; rewrites¬ <- IHp2. tauto.
Qed.

Lemma wfp_cfresh_subst_in : m Y (p q : wfprocess),
  m ### pm ### qm ### (wfp_subst q Y p).
Proof with freshen_up.
  induction p using wfp_ind_gen; introv Hf1 Hf2;
    try solve [simpls; try cases_if~; freshen_up].
  rewrite wfp_cfresh_Abs in Hf1; destruct Hf1 as (Hf1 & Hneq).
  tests : (X = Y).
    rewrite wfp_eq_subst_abs1. rewrite× wfp_cfresh_Abs.
    lets (Z & Hfz) : find_fresh (Gvar Y :: proc p :: proc q :: nil).
    rewrite Forall_to_conj_3 in Hfz. rewrite gfresh_gvar in Hfz.
    rewrite wfp_eq_subst_abs3 with (Z := Z); jauto.
    rewrite wfp_cfresh_Abs; splits×. applys× H.
      rewrite× wfp_gfresh_subst_is_swap.
      rewrite¬ <- wfp_cfresh_swap_inv.
Qed.

Lemma wfp_cfresh_subst_from1 : m X p q,
  m ### wfp_subst q X pm ### p.
Proof with freshen_up.
  inductions p; simpl; rename proc into p; clear wf_cond.
  induction p; simpls~; introv H...
Qed.

Lemma wfp_cfresh_msubst_from : m xs p rs,
  length rs = length xsm ### wfp_multisubst (combine xs rs) pm ### p.
Proof.
  induction xs.
    simpls¬.
    introv Hl; lets Hl´ : Hl; rew_length in Hl; apply lengthn in Hl.
    destruct Hl as (y & ys & Hys); subst; rew_length in Hl´.
    introv Hf; simpl wfp_multisubst in Hf; apply wfp_cfresh_subst_from1 in Hf; jauto.
Qed.

Lemma wfp_cfresh_subst_from2 : (p : wfprocess) m X q, X \in GV p
  m ### (wfp_subst q X p)m ### q.
Proof with freshen_up.
  induction p using wfp_ind_gen; introv Hgv Hfr; rewrite_wfp_subst; simpl in Hgv.
    eapply IHp. apply Hgv. simpls...

    tests : (X # p).
      rewrite¬ gfresh_subst_rewrite in Hgv.
      tests : (X = X0).
        lets (Z & Hfz) : find_fresh (Gvar X0 :: proc p :: proc q :: nil).
        rewrite Forall_to_conj_3 in Hfz. rewrite gfresh_gvar in Hfz.
        rewrite wfp_eq_subst_abs3 with (Z := Z) in Hfr; jauto.
        rewrite wfp_cfresh_Abs in Hfr. inverts Hfr.
        apply H in H0; jauto.
        rewrite¬ wfp_gfresh_subst_rewrite.
      rewrite¬ GV_subst in Hgv; simpl in Hgv. rewrite union_empty_r in Hgv.
      rewrite in_remove in Hgv; inverts Hgv as (Hgv & Hneq).
        lets (Z & Hfz) : find_fresh (Gvar X0 :: proc p :: proc q :: nil).
        rewrite Forall_to_conj_3 in Hfz. rewrite gfresh_gvar in Hfz.
        rewrite wfp_eq_subst_abs3 with (Z := Z) in Hfr; jauto.
        rewrite wfp_cfresh_Abs in Hfr. inverts Hfr.
        apply H in H0; jauto.
        simpl; rewrite¬ GV_subst; rewrite in_union; left.
        rewrite× in_remove.
        rewrite¬ notin_singleton in H2.

    rewrite in_singleton in Hgv. cases_if¬.
    rewrite in_union in Hgv; inverts Hgv; [eapply IHp1 | eapply IHp2];
      try apply H; simpls; rewrite× cfresh_par_iff in Hfr.
    rewrite in_empty in Hgv. false.
Qed.


Lemma wfp_fresh_cp : (r : wfprocess), closed_process r X:var, X#r.
Proof.
  introv H. introv. unfolds in H. applys¬ fresh_GV.
Qed.

Lemma wfp_fresh_Msubst : xs rs X (p : wfprocess),
  X#plength xs = length rsclosed_proc_list_wfp rsX # (wfp_multisubst (combine xs rs) p).
Proof.
  induction xs; introv Hf Hls Hcp.
    simpls¬.
    rewrite length_cons in Hls. symmetry in Hls. lets (y & ys & H): (lengthn rs Hls).
    subst. simpls. apply gfresh_in_subst_p_q. applys× IHxs.
      rewrite length_cons in Hls. nat_math.
    unfolds. destruct Hcp. unfolds in H. rewrite H. apply notin_empty.
Qed.

Lemma wfp_fresh_chan_cswap : (p : wfprocess) m n a,
  a ### p({{|m,n|}}a) ### wfp_swap_chan m n p.
Proof with freshen_up.
  induction p; simpl; rename proc into p; clear wf_cond.
  induction p; simpl; intros...
    rewrite cfresh_send in ×. split×.
      unfolds swap_name; repeat cases_if~; substs×.
    rewrite cfresh_receive in ×. split×.
      unfolds swap_name; repeat cases_if~; substs×.
Qed.

Lemma wfp_fresh_chan_gswap: (p : wfprocess) m X Y, m ### pm ### wfp_swap X Y p.
Proof with freshen_up.
  induction p; simpl; rename proc into p; clear wf_cond.
  induction p; introv Hf; simpls¬...
Qed.

Lemma wfp_fresh_gvar_cswap: (p : wfprocess) m n X, X # pX # wfp_swap_chan m n p.
Proof.
  induction p; simpl; rename proc into p; clear wf_cond.
  induction p; introv Hf; simpls~; unfolds fresh_gvar; simpls¬.
Qed.

Lemma wfp_fresh_inst_Abs : p fp a X Y, {{p -- LabIn a ->> AA fp}}X # pX YX # wfp_inst_Abs fp (wfp_Gvar Y).
Proof with freshen_up.
  introv Ht; inductions Ht; simpls; intros...
  tests : (X = X0).
    fresh_solve.
    unfold Abs in H; rewrite gfresh_receive in H.
    apply¬ gfresh_in_subst_p_q... fresh_solve.
  destruct ap; inverts x; simpl; rewrite gfresh_par_iff in *; splits×.
  destruct aq; inverts x; simpl; rewrite gfresh_par_iff in *; splits×.
Qed.


Lemma wfp_cfresh_in: a m (p : wfprocess) f,
  m ### p{{p--LabIn a->>(AA f)}} (q : wfprocess), m###qm ### (wfp_inst_Abs f q).
Proof with freshen_up.
  introv Hfm Ht; gen m. inductions Ht; introv Hf1 Hf2.
    rewrite wfp_cfresh_Abs in Hf1. destruct Hf1. simpl wfp_inst_Abs; apply¬ wfp_cfresh_subst_in.
    destruct ap; inverts x. simpls...
    destruct aq; inverts x. simpls...
Qed.

Lemma wfp_cfresh_out: (a m : chan) (p : wfprocess) p´´,
  m###p{{p -- LabOut a p´´ ->> (AP )}}
    a m m ### m ### p´´.
Proof with freshen_up.
  introv Hf Ht; gen m; inductions Ht; introv Hf.
    simpls; splits...
    destruct ap; inverts x...
    simpls; rewrite cfresh_par_iff in ×. rewrite and_assoc.
      splits*; try eapply IHHt; jauto.
    destruct aq; inverts x...
    simpls; rewrite cfresh_par_iff in ×. rewrite and_assoc.
      splits*; try eapply IHHt; jauto.
Qed.

Lemma wfp_cfresh_rem: a X (p : wfprocess) , a###p{{p--LabRem X->>(AP )}}a###.
Proof with freshen_up.
  introv Hf Ht; gen a; introv Hf; inductions Ht; simpls...
    destruct ap; inverts x; simpls...
    destruct aq; inverts x; simpls...
Qed.

Lemma wfp_cfresh_tau: m (p : wfprocess) , m###p{{p--Tau->>(AP )}}m###.
Proof with freshen_up.
  introv Hf Ht; gen m; inductions Ht; introv Hf; simpls...
    destruct ap; inverts x; simpl...
    destruct aq; inverts x; simpl...
    clear IHHt1 IHHt2.
    rename p´0 into .
    rewrite cfresh_par_iff in *; split.
      apply wfp_cfresh_out with (m := m) in Ht1; intuition.
      eapply wfp_cfresh_in; try eassumption; jauto.
      eapply wfp_cfresh_out; try eassumption; jauto.
    clear IHHt1 IHHt2.
    rewrite cfresh_par_iff in *; split.
      apply wfp_cfresh_out with (m := m) in Ht2; intuition.
      apply wfp_cfresh_in with (m := m) (q := q´´) in Ht1; auto.
      apply wfp_cfresh_out with (m := m) in Ht2; jauto.
Qed.

Lemma wfp_cfresh_Msubst1 : (XS : list var) m ms (p : wfprocess),
  m###plength XS = length msForall ( m) ms
  m###(wfp_multisubst (combine XS (¬¬ms)) p).
Proof.
  induction XS; introv Hf Hls Hd.
    simpls¬.
    lets Hls´: Hls.
    rewrite length_cons in Hls. symmetry in Hls. apply lengthn in Hls.
    destruct Hls as ( & ms´ & Hys). subst. inverts Hd.
    simpl wfp_multisubst; applys¬ wfp_cfresh_subst_in.
    unfolds. simpls. rewrite notin_union. split¬. rewrite¬ notin_singleton.
Qed.


Lemma wfp_cfresh_out_inv : (a :chan) p p´´,
  {{p -- LabOut a p´´ ->> AP }}¬ a ### p.
Proof with (freshen_up; try solve_wfp_size).
  induction p using (measure_induction wfp_size).
  introv Ht; inverts Ht; simpls.
    unfolds fresh_chan; simpl.
    unfold notin; rewrite in_union; rewrite¬ in_singleton.

    rewrite cfresh_par_iff; rew_logic; left.
    destruct ap; inverts H0; simpl...
    eapply H... eassumption.

    rewrite cfresh_par_iff; rew_logic; right.
    destruct aq; inverts H0; simpl...
    eapply H... eassumption.
Qed.