Library back_forth_bisim

Require Import base.
Require Import prelim.
Require Import lts_tau.
Require Import branch_bisim.

Require Import Arith.
Require Import Wf_nat.
Require Import Omega.

Module BF_BISIM.
Import LTS_TAU.
Import BRANCH_BISIM.
Section bf_bisim. Context {O:ObservationSystem}.

  Definition back X Y (R:run X -> run Y -> Prop) x y :=
      (forall a y', extended_run Y y' a y -> exists x', step_run X x' a x /\ R x' y').

  Definition forth X Y (R:run X -> run Y -> Prop) x y :=
      (forall a x', extended_run X x a x' -> exists y', step_run Y y a y' /\ R x' y').

  Definition back_forth := rtd_and forth back.

  Definition back' X Y (R:run X -> run Y -> Prop) x y :=
      (forall a y', step_run Y y' a y -> exists x', step_run X x' a x /\ R x' y').

  Definition forth' X Y (R:run X -> run Y -> Prop) x y :=
      (forall a x', step_run X x a x' -> exists y', step_run Y y a y' /\ R x' y').

  Definition back_forth' := rtd_and forth' back'.

  Definition back_forth_div X Y (R:run X -> run Y -> Prop) x y :=
    forall D, hdivergence_set X (fun _ => True) D -> D x ->
      exists x', exists y',
        D x' /\
        extended_run Y y None y' /\
        R x' y'.

  Definition back_forth_div' X Y (R:run X -> run Y -> Prop) x y :=
    forall D,
      hdivergence_set X (fun _ => True) D -> D x ->
      hdiverges Y (fun y' => exists x', D x' /\ R x' y') y.

  Lemma extended_run_push1 : forall X Y R x x' y,
    run_simulation forth X Y R ->
    R x y ->
    extended_run_star X x x' ->
    exists y',
      R x' y' /\
      extended_run_star Y y y'.

  Lemma extended_run_push2 : forall X Y R x y y',
    run_simulation back X Y R ->
    R x y ->
    extended_run_star Y y' y ->
    exists x',
      R x' y' /\
      extended_run_star X x' x.

  Lemma extended_run_step_run : forall Z z1 a z2,
    extended_run Z z1 a z2 ->
    step_run Z z1 a z2.

  Lemma back_sim'_sim : forall X Y R,
    run_simulation back' X Y R ->
    run_simulation back X Y R.

  Lemma forth_sim'_sim : forall X Y R,
    run_simulation forth' X Y R ->
    run_simulation forth X Y R.

  Lemma bf_sim'_sim : forall X Y R,
    run_simulation back_forth' X Y R ->
    run_simulation back_forth X Y R.

  Lemma back_sim_sim' : forall X Y R,
    run_simulation back X Y R ->
    run_simulation back' X Y R.

  Lemma forth_sim_sim' : forall X Y R,
    run_simulation forth X Y R ->
    run_simulation forth' X Y R.

  Lemma bf_sim_sim' : forall X Y R,
    run_simulation back_forth X Y R ->
    run_simulation back_forth' X Y R.

  Theorem bf_bisim_bisim' : forall X Y R,
    run_bisimulation back_forth X Y R <->
    run_bisimulation back_forth' X Y R.

  Lemma bf_sim_eq : forall X, run_simulation back_forth' X X eq.

  Lemma bf_bisim_eq : forall X, run_bisimulation back_forth' X X eq.

  Lemma bf_sim_comp : forall X Y Z R1 R2,
    run_simulation back_forth' X Y R1 ->
    run_simulation back_forth' Y Z R2 ->
    run_simulation back_forth' X Z (comp R1 R2).

  Lemma bf_bisim_comp : forall X Y Z R1 R2,
    run_bisimulation back_forth' X Y R1 ->
    run_bisimulation back_forth' Y Z R2 ->
    run_bisimulation back_forth' X Z (comp R1 R2).

  Lemma bf_bisimilar_simulation : forall X Y,
    run_simulation back_forth X Y (run_bisimilar back_forth X Y).

  Theorem bf_bisim_refl : forall X x,
    run_bisimilar back_forth X X x x.

  Theorem bf_bisim_trans : forall X Y Z x y z,
    run_bisimilar back_forth X Y x y ->
    run_bisimilar back_forth Y Z y z ->
    run_bisimilar back_forth X Z x z.

  Theorem bf_bisimilar_bisimulation : forall X Y,
    run_bisimulation back_forth X Y (run_bisimilar back_forth X Y).

  Definition Xclosure X Y (R:run X -> run Y -> Prop) x y :=
    exists x0, exists y0,
      step_run X x0 None x /\
      step_run Y y0 None y /\
      R x0 y /\
      R x y0.

  Definition Xproperty X Y R :=
    forall x0 y0 x y,
      step_run X x0 None x ->
      step_run Y y0 None y ->
      R x0 y ->
      R x y0 ->
      R x y.

  Lemma inv_Xclosure : forall X Y R,
    inv (Xclosure X Y R) = Xclosure Y X (inv R).

  Lemma Xclosure_property : forall X Y R,
    Xproperty X Y (Xclosure X Y R).

  Lemma Xclosure_incl : forall X Y (R:run X -> run Y -> Prop) x y,
    R x y -> Xclosure X Y R x y.

  Lemma Xclosure_back_sim' : forall X Y R,
    run_simulation back' X Y R ->
    run_simulation back X Y (Xclosure X Y R).

  Lemma Xclosure_forth_sim' : forall X Y R,
    run_simulation forth' X Y R ->
    run_simulation forth X Y (Xclosure X Y R).

  Lemma Xclosure_bf_sim' : forall X Y R,
    run_simulation back_forth' X Y R ->
    run_simulation back_forth X Y (Xclosure X Y R).

  Lemma Xclosure_bf_sim : forall X Y R,
    run_simulation back_forth X Y R ->
    run_simulation back_forth X Y (Xclosure X Y R).

  Lemma Xclosure_bf_bisim : forall X Y R,
    run_bisimulation back_forth X Y R ->
    run_bisimulation back_forth X Y (Xclosure X Y R).

  Section X_stutter.
    Variables X Y:LTS.
    Variable R : run X -> run Y -> Prop.

    Hypothesis HR : run_simulation back' X Y R.
    Hypothesis HRX : Xproperty X Y R.

    Lemma Xproperty_stutter : forall x y0 y y1,
      R x y0 ->
      R x y1 ->
      extended_run_star Y y0 y ->
      extended_run_star Y y y1 ->
      R x y.

    Lemma curr_path : forall (rx:run X) (ry1 ry2:run Y),
      extended_run_star Y ry1 ry2 ->
      R rx ry1 -> R rx ry2 ->
      path_where _ (steps_tau Y)
       (curr_rel X Y R (curr rx)) (curr ry1) (curr ry2).
  End X_stutter.

  Section bf_to_related_preruns.
    Lemma extended_star_length_le : forall Z z1 z2,
      extended_run_star Z z1 z2 ->
      length (prev z1) <= length (prev z2).

    Variables X Y:LTS.
    Variable R : run X -> run Y -> Prop.

    Hypothesis H : run_bisimulation back X Y R.
    Let R' := curr_rel X Y (Xclosure X Y R).

    Lemma related_runs_push : forall x y1 y2,
      Xclosure X Y R x y1 ->
      Xclosure X Y R x y2 ->
      extended_run_star Y y1 y2 ->
      related_runs X Y R' x y1 ->
      related_runs X Y R' x y2.

    Lemma bf_to_related_preruns :
      forall n
        (x : state X) (xs : prerun X) (gx : good_prerun X xs x)
        (y : state Y) (ys : prerun Y) (gy : good_prerun Y ys y),
        R {| curr := x; prev := xs; good_run := gx |}
          {| curr := y; prev := ys; good_run := gy |} ->
        n = length xs + length ys ->
        related_preruns X Y R' xs x ys y.
  End bf_to_related_preruns.

  Lemma bf_to_related_runs : forall X Y R x y,
    run_bisimulation back X Y R ->
    let R' := curr_rel X Y (Xclosure X Y R) in
    R x y ->
    related_runs X Y R' x y.

  Section bf_to_branch.
    Variables X Y:LTS.
    Variable R : run X -> run Y -> Prop.

    Hypothesis HR : run_simulation back_forth' X Y R.
    Hypothesis HRX : Xproperty X Y R.

    Lemma bf_to_branch_sim : simulation branch X Y (curr_rel X Y R).

  End bf_to_branch.

  Lemma back_related_runs : forall X Y R x y,
    related_runs X Y R x y ->
    back X Y (related_runs X Y R) x y.

  Section branch_to_bf.
    Variables X Y:LTS.
    Variable R : state X -> state Y -> Prop.

    Hypothesis HR : simulation branch X Y R.

    Lemma branch_to_bf_sim : run_simulation back_forth X Y (related_runs X Y R).

  End branch_to_bf.

  Lemma branch_to_bf_bisim : forall X Y R,
    bisimulation branch X Y R ->
    run_bisimulation back_forth X Y (related_runs X Y R).

  Lemma bf_to_branch_bisim : forall X Y R,
    run_bisimulation back_forth X Y R ->
    bisimulation branch X Y (curr_rel X Y (Xclosure X Y R)).

  Theorem bf_branch_related_runs : forall X Y x y,
    run_bisimilar back_forth X Y x y <->
    exists R,
      bisimulation branch X Y R /\
      related_runs X Y R x y.

  Theorem bf_branch_related_runs2 : forall X Y,
    run_bisimilar back_forth X Y =
    related_runs X Y (bisimilar branch X Y).

  Theorem branch_to_bf_bisimilar : forall X Y x y,
    bisimilar branch X Y x y ->
    run_bisimilar back_forth X Y (start_run X x) (start_run Y y).

  Theorem bf_to_branch_bisimilar : forall X Y x y,
    run_bisimilar back_forth X Y x y ->
    bisimilar branch X Y (curr x) (curr y).

  Definition bf_sim_div :=
    run_simulation (rtd_and back_forth back_forth_div).

  Definition bf_sim_div' :=
    run_simulation (rtd_and back_forth back_forth_div').

  Definition bf_bisim_div :=
    run_bisimulation (rtd_and back_forth back_forth_div).

  Definition bf_bisim_div' :=
    run_bisimulation (rtd_and back_forth back_forth_div').

  Definition bf_bisimilar_div :=
    run_bisimilar (rtd_and back_forth back_forth_div).

  Definition bf_bisimilar_div' :=
    run_bisimilar (rtd_and back_forth back_forth_div').

  Lemma bf_sim_div_div' : forall X Y R,
    bf_sim_div X Y R <-> bf_sim_div' X Y R.

  Lemma bf_bisim_div_div' : forall X Y R,
    bf_bisim_div X Y R <-> bf_bisim_div' X Y R.

  Lemma bf_sim_div_eq : forall X,
    bf_sim_div X X eq.

  Lemma bf_bisim_div_eq : forall X,
    bf_bisim_div X X eq.

  Lemma bf_sim_div_comp : forall X Y Z R1 R2,
    bf_sim_div X Y R1 ->
    bf_sim_div Y Z R2 ->
    bf_sim_div X Z (comp R1 R2).

  Lemma bf_bisim_div_comp : forall X Y Z R1 R2,
    bf_bisim_div X Y R1 ->
    bf_bisim_div Y Z R2 ->
    bf_bisim_div X Z (comp R1 R2).

  Theorem bf_bisimilar_div_refl : forall X x,
    bf_bisimilar_div X X x x.

  Theorem bf_bisimilar_div_trans : forall X Y Z x y z,
    bf_bisimilar_div X Y x y ->
    bf_bisimilar_div Y Z y z ->
    bf_bisimilar_div X Z x z.

  Lemma back_forth_div_Xclosure : forall X Y R,
    run_simulation back_forth_div X Y R ->
    run_simulation back_forth_div X Y (Xclosure X Y R).

  Theorem bf_related_runs : forall X Y R,
    simulation (td_and branch cond_D1) X Y R ->
    bf_sim_div X Y (related_runs X Y R).

  Theorem bf_branch_related_runs_div1 : forall X Y R,
    let R' := curr_rel X Y (Xclosure X Y R) in

    bf_sim_div X Y R ->
    simulation (td_and branch cond_D1) X Y R'.

  Theorem bf_branch_related_runs_div : forall X Y x y,
    bf_bisimilar_div X Y x y <->
    (exists R,
      bisimulation (td_and branch cond_D1) X Y R /\
      related_runs X Y R x y).

  Theorem bf_branch_related_runs_div2 : forall X Y,
    bf_bisimilar_div X Y =
    related_runs X Y (bisimilar (td_and branch cond_D1) X Y).

  Lemma remove_tau_prerun_cycle {Classic:EM} : forall X x z h,
    extended_run_star X (start_run X x) h ->
    prerun_cycle X z (prev h) ->
    steps_star X (curr h) z ->
    exists h',
      length (prev h') < length (prev h) /\
      extended_run_star X (start_run X x) h' /\
      curr h' = z /\
      related_runs X X (bisimilar (td_and branch cond_D1) X X) h' h.

  Lemma remove_tau_cycle {Classic:EM} : forall X x h,
    extended_run_star X (start_run X x) h ->
    run_cycle X (curr h) (prev h) ->
    exists h',
      length (prev h') < length (prev h) /\
      extended_run_star X (start_run X x) h' /\
      curr h = curr h' /\
      related_runs X X (bisimilar (td_and branch cond_D1) X X) h' h.

  Lemma step_run_remove_cycle {Classic:EM} : forall X x o h,
    step_run X (start_run X x) o h ->
    run_cycle X (curr h) (prev h) ->
    exists h',
      length (prev h') < length (prev h) /\
      step_run X (start_run X x) o h' /\
      related_runs X X (bisimilar (td_and branch cond_D1) X X) h' h.

  Lemma step_run_acyclic_bisimilar {Classic:EM} : forall X x o h,
    step_run X (start_run X x) o h ->
    exists h',
      acyclic_run X h' /\
      step_run X (start_run X x) o h' /\
      bf_bisimilar_div X X h' h.

  Lemma step_run_finite {Classic:EM} X :
    weak_image_finite X ->
    forall h o, exists l,
      (forall q, In q l -> step_run X h o q) /\
      (forall h', step_run X h o h' ->
        exists q, In q l /\ run_bisimilar (rtd_and back_forth back_forth_div) X X q h').

End bf_bisim.
End BF_BISIM.