Theory Weak_Late_Bisim

(* 
   Title: The pi-calculus   
   Author/Maintainer: Jesper Bengtson (jebe.dk), 2012
*)
theory Weak_Late_Bisim
  imports Weak_Late_Sim Strong_Late_Bisim
begin

lemma monoAux: "A ⊆ B ⟹ P ↝^<A> Q ⟶ P ↝^<B> Q"
by(auto intro: Weak_Late_Sim.monotonic)

coinductive_set weakBisim :: "(pi × pi) set"
where
  step: "⟦P ↝^<weakBisim> Q; (Q, P) ∈ weakBisim⟧ ⟹ (P, Q) ∈ weakBisim"
monos monoAux

abbreviation
  "weakBisimJudge" (infixr ‹≈› 65)  where "P ≈ Q ≡ (P, Q) ∈ weakBisim"

lemma weakBisimCoinductAux[case_names weakBisim, case_conclusion weakBisim step, consumes 1]:
  assumes p: "(P, Q) ∈ X"
  and step:  "⋀P Q. (P, Q) ∈ X ⟹ P ↝^<(X ∪ weakBisim)> Q ∧ ((Q, P) ∈ X ∨ Q ≈ P)"

  shows "P ≈ Q"
proof -
  have aux: "X ∪ weakBisim = {(P, Q). (P, Q) ∈ X ∨ P ≈ Q}" by blast

  from p show ?thesis
    by(coinduct, force dest: step simp add: aux)
qed

lemma weakBisimCoinduct[consumes 1, case_names cSim cSym]:
  fixes P :: pi
  and   Q :: pi

  assumes "(P, Q) ∈ X"
  and     "⋀P Q. (P, Q) ∈ X ⟹ P ↝^<(X ∪ weakBisim)> Q"
  and     "⋀P Q. (P, Q) ∈ X ⟹ (Q, P) ∈ X"

  shows "P ≈ Q"
using assms
by(coinduct rule: weakBisimCoinductAux) auto

lemma weak_coinduct[case_names weakBisim, case_conclusion weakBisim step, consumes 1]:
  assumes p: "(P, Q) ∈ X"
  and step:  "⋀P Q. (P, Q) ∈ X ⟹ P ↝^<X> Q ∧ (Q, P) ∈ X"

  shows "P ≈ Q"
using p
proof(coinduct rule: weakBisimCoinductAux)
  case (weakBisim P Q)
  from step[OF this] show ?case using Weak_Late_Sim.monotonic by blast
qed

lemma weakBisimWeakCoinduct[consumes 1, case_names cSim cSym]:
  fixes P :: pi
  and   Q :: pi

  assumes "(P, Q) ∈ X"
  and     "⋀P Q. (P, Q) ∈ X ⟹ P ↝^<X> Q"
  and     "⋀P Q. (P, Q) ∈ X ⟹ (Q, P) ∈ X"

  shows "P ≈ Q"
using assms
by(coinduct rule: weak_coinduct) auto
lemma monotonic: "mono(λp x1 x2. ∃P Q. x1 = P ∧ x2 = Q ∧ P ↝^<{(xa, x). p xa x}> Q ∧ Q ↝^<{(xa, x). p xa x}> P)"
by(auto intro: monoI Weak_Late_Sim.monotonic)

lemma unfoldE:
  fixes P :: pi
  and   Q :: pi

  assumes "P ≈ Q"
  
  shows "P ↝^<weakBisim> Q"
  and   "Q ≈ P"
using assms
by(auto intro: weakBisim.cases)

lemma unfoldI:
  fixes P :: pi
  and   Q :: pi
  
  assumes "P ↝^<weakBisim> Q"
  and     "Q ≈ P"

  shows "P ≈ Q"
using assms
by(auto intro: weakBisim.cases)

lemma eqvt:
  shows "eqvt weakBisim"
proof(auto simp add: eqvt_def)
  let ?X = "{x. ∃P Q (perm::name prm). P ≈ Q ∧ x = (perm ∙ P, perm ∙ Q)}"
  fix P Q
  fix perm::"name prm"
  assume PBiSimQ: "P ≈ Q"

  hence "(perm ∙ P, perm ∙ Q) ∈ ?X" by blast
  moreover have "⋀P Q perm::name prm. ⟦P ↝^<weakBisim> Q⟧ ⟹ (perm ∙ P) ↝^<?X> (perm ∙ Q)"
  proof -
    fix P Q
    fix perm::"name prm"
    assume "P ↝^<weakBisim> Q"

    moreover have "weakBisim ⊆ ?X"
    proof(auto)
      fix P Q
      assume "P ≈ Q"
      moreover have "P = ([]::name prm) ∙ P" and "Q = ([]::name prm) ∙ Q" by auto
      ultimately show "∃P' Q'. P' ≈ Q' ∧ (∃(perm::name prm). P = perm ∙ P' ∧ Q = perm ∙ Q')"
        by blast
    qed

    moreover have "eqvt ?X"
    proof(auto simp add: eqvt_def)
      fix P Q
      fix perm1::"name prm"
      fix perm2::"name prm"

      assume "P ≈ Q"
      moreover have "perm1 ∙ perm2 ∙ P = (perm1 @ perm2) ∙ P" by(simp add: pt2[OF pt_name_inst])
      moreover have "perm1 ∙ perm2 ∙ Q = (perm1 @ perm2) ∙ Q" by(simp add: pt2[OF pt_name_inst])

      ultimately show "∃P' Q'. P' ≈ Q' ∧ (∃(perm::name prm). perm1 ∙ perm2 ∙ P = perm ∙ P' ∧
                                                              perm1 ∙ perm2 ∙ Q = perm ∙ Q')"
        by blast
    qed

    ultimately show "(perm ∙ P) ↝^<?X> (perm ∙ Q)"
      by(rule Weak_Late_Sim.eqvtI)
    qed

    ultimately show "(perm ∙ P) ≈ (perm ∙ Q)" by(coinduct rule: weak_coinduct, blast dest: unfoldE)
qed

lemma eqvtI:
  fixes P :: pi
  and   Q :: pi
  and   perm :: "name prm"

  assumes "P ≈ Q"

  shows "(perm ∙ P) ≈ (perm ∙ Q)"
using assms
by(rule eqvtRelI[OF eqvt])

lemma weakBisimEqvt[simp]:
  shows "eqvt weakBisim"
by(auto simp add: eqvt_def eqvtI)

lemma strongBisimWeakBisim:
  fixes P :: pi
  and   Q :: pi

  assumes PSimQ: "P ∼ Q"

  shows "P ≈ Q"
proof -
  have "⋀P Q. P ↝[bisim] Q ⟹ P ↝^<(bisim ∪ weakBisim)> Q"
  proof -
    fix P Q
    assume "P ↝[bisim] Q"
    hence "P ↝^<bisim> Q" by(rule strongSimWeakSim)
    thus "P ↝^<(bisim ∪ weakBisim)> Q"
      by(blast intro: Weak_Late_Sim.monotonic)
  qed

  with PSimQ show ?thesis
    by(coinduct rule: weakBisimCoinductAux, force dest: Strong_Late_Bisim.bisimE symmetric)
qed

lemma reflexive:
  fixes P :: pi

  shows "P ≈ P"
proof -
  have "(P, P) ∈ Id" by simp
  then show ?thesis

  proof (coinduct rule: weak_coinduct)
    case (weakBisim P Q)
    have "(P, Q) ∈ Id" by fact
    thus ?case by(auto intro: Weak_Late_Sim.reflexive)
  qed
qed

lemma symmetric:
  fixes P :: pi
  and   Q :: pi
   
  assumes "P ≈ Q"

  shows "Q ≈ P"
using assms
by(auto dest: unfoldE intro: unfoldI)

lemma transitive:
  fixes P :: pi
  and   Q :: pi
  and   R :: pi

  assumes PBiSimQ: "P ≈ Q"
  and     QBiSimR: "Q ≈ R"

  shows "P ≈ R"
proof -
  let ?X = "weakBisim O weakBisim"
  from assms have "(P, R) ∈ ?X" by blast
  moreover have "⋀P Q R. ⟦Q ↝^<weakBisim> R; P ≈ Q⟧ ⟹
                          P ↝^<(?X ∪ weakBisim)> R"
  proof -
    fix P Q R
    assume PBiSimQ: "P ≈ Q"
    assume "Q ↝^<weakBisim> R"
    moreover have "eqvt weakBisim" by(rule eqvt)
    moreover from eqvt have "eqvt (?X ∪ weakBisim)" by(auto simp add: eqvtTrans)
    moreover have "weakBisim O weakBisim ⊆ ?X ∪ weakBisim" by auto
    moreover have "⋀P Q. P ≈ Q ⟹ P ↝^<weakBisim> Q" by(rule unfoldE)

    ultimately show "P ↝^<(?X ∪ weakBisim)> R" using PBiSimQ
      by(rule Weak_Late_Sim.transitive)
  qed

  ultimately show ?thesis
    apply(coinduct rule: weakBisimCoinduct, auto)
    by(blast dest: unfoldE symmetric)+
qed


lemma transitive_coinduct_weak[case_names WeakBisimEarly, case_conclusion WeakBisimEarly step, consumes 2]:
  assumes p: "(P, Q) ∈ X"
  and Eqvt: "eqvt X"
  and step: "⋀P Q. (P, Q) ∈ X ⟹ P ↝^<(bisim O X O bisim)> Q ∧ (Q, P) ∈ X"

  shows "P ≈ Q"
proof -
  let ?X = "bisim O X O bisim"

  have Sim: "⋀P P' Q' Q. ⟦P ∼ P'; P'↝^<?X> Q'; Q' ↝[bisim] Q⟧ ⟹
                          P ↝^<?X> Q"
  proof -
    fix P P' Q' Q
    assume PBisimP': "P ∼ P'"
    assume P'SimQ': "P' ↝^<?X> Q'"
    assume Q'SimQ: "Q' ↝[bisim] Q"

    show "P ↝^<?X> Q"
    proof -
      have "P' ↝^<?X> Q"
      proof -
        have "?X O bisim ⊆ ?X" by(blast intro: Strong_Late_Bisim.transitive)
        moreover from Strong_Late_Bisim.bisimEqvt Eqvt have "eqvt ?X" by blast
        ultimately show ?thesis using P'SimQ' Q'SimQ by(blast intro: strongAppend)
      qed
      moreover have "eqvt bisim" by(rule Strong_Late_Bisim.bisimEqvt)
      moreover from Strong_Late_Bisim.bisimEqvt Eqvt have "eqvt ?X" by blast
      moreover have "bisim O ?X ⊆ ?X" by(blast intro: Strong_Late_Bisim.transitive)
      moreover have "⋀P Q. P ∼ Q ⟹ P ↝^<bisim> Q" by(blast dest: Strong_Late_Bisim.bisimE strongSimWeakSim)
      ultimately show ?thesis using PBisimP' by(rule Weak_Late_Sim.transitive)
    qed
  qed

  from p have "(P, Q) ∈ ?X" by(blast intro: Strong_Late_Bisim.reflexive)
  moreover from step Sim have "⋀P Q. (P, Q) ∈ ?X ⟹ P ↝^<?X> Q ∧ (Q, P) ∈ ?X"
    by(blast dest: Strong_Late_Bisim.bisimE Strong_Late_Bisim.symmetric)

  ultimately show ?thesis by(rule weak_coinduct)
qed

lemma weakBisimTransitiveCoinduct[case_names cSim cSym, consumes 2]:
  assumes p: "(P, Q) ∈ X"
  and Eqvt: "eqvt X"
  and rSim: "⋀P Q. (P, Q) ∈ X ⟹ P ↝^<(bisim O X O bisim)> Q"
  and rSym: "⋀P Q. (P, Q) ∈ X ⟹ (Q, P) ∈ X"

  shows "P ≈ Q"
using assms
by(coinduct rule: transitive_coinduct_weak) auto

end