Theory Weak_Bisimulation

(* 
   Title: Psi-calculi   
   Author/Maintainer: Jesper Bengtson (jebe@itu.dk), 2012
*)
theory Weak_Bisimulation
  imports Weak_Simulation Weak_Stat_Imp Bisim_Struct_Cong
begin

context env begin

lemma monoCoinduct: "⋀x y xa xb xc P Q Ψ.
                      x ≤ y ⟹
                      (Ψ ⊳ Q ↝<{(xc, xb, xa). x xc xb xa}> P) ⟶
                     (Ψ ⊳ Q ↝<{(xb, xa, xc). y xb xa xc}> P)"
apply auto
apply(rule weakSimMonotonic)
by(auto dest: le_funE)

lemma monoCoinduct2: "⋀x y xa xb xc P Q Ψ.
                      x ≤ y ⟹
                      (Ψ ⊳ Q ⪅<{(xc, xb, xa). x xc xb xa}> P) ⟶
                     (Ψ ⊳ Q ⪅<{(xb, xa, xc). y xb xa xc}> P)"
apply auto
apply(rule weakStatImpMonotonic)
by(auto dest: le_funE)

coinductive_set weakBisim :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set" 
where
  step: "⟦Ψ ⊳ P ⪅<weakBisim> Q; Ψ ⊳ P ↝<weakBisim> Q;
          ∀Ψ'. (Ψ ⊗ Ψ',  P, Q) ∈ weakBisim; (Ψ, Q, P) ∈ weakBisim⟧ ⟹ (Ψ, P, Q) ∈ weakBisim"
monos monoCoinduct monoCoinduct2

abbreviation
  weakBisimJudge (‹_ ⊳ _ ≈ _› [70, 70, 70] 65) where "Ψ ⊳ P ≈ Q ≡ (Ψ, P, Q) ∈ weakBisim"
abbreviation
  weakBisimNilJudge (‹_ ≈ _› [70, 70] 65) where "P ≈ Q ≡ 𝟭 ⊳ P ≈ Q"

lemma weakBisimCoinductAux[consumes 1]:
  fixes F :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   X :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set"

  assumes "(Ψ, P, Q) ∈ X"
  and     "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ (Ψ ⊳ P ⪅<(X ∪ weakBisim)> Q) ∧
                                      (Ψ ⊳ P ↝<(X ∪ weakBisim)> Q) ∧
                                      (∀Ψ'. (Ψ ⊗ Ψ', P, Q) ∈ X ∨ (Ψ ⊗ Ψ', P, Q) ∈ weakBisim) ∧
                                      ((Ψ, Q, P) ∈ X ∨ (Ψ, Q, P) ∈ weakBisim)"

  shows "(Ψ, P, Q) ∈ weakBisim"
proof -
  have "X ∪ weakBisim = {(Ψ, P, Q). (Ψ, P, Q) ∈ X ∨ (Ψ, P, Q) ∈ weakBisim}" by auto
  with assms show ?thesis
    by coinduct (simp add: rtrancl_def)
qed

lemma weakBisimCoinduct[consumes 1, case_names cStatImp cSim cExt cSym]:
  fixes F :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   X :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set"

  assumes "(Ψ, P, Q) ∈ X"
  and     "⋀Ψ' R S. (Ψ', R, S) ∈ X ⟹ Ψ' ⊳ R ⪅<(X ∪ weakBisim)> S"
  and     "⋀Ψ' R S. (Ψ', R, S) ∈ X ⟹ Ψ' ⊳ R ↝<(X ∪ weakBisim)> S"
  and     "⋀Ψ' R S Ψ''. (Ψ', R, S) ∈ X ⟹ (Ψ' ⊗ Ψ'', R, S) ∈ X ∨ Ψ' ⊗ Ψ'' ⊳ R ≈ S"
  and     "⋀Ψ' R S. (Ψ', R, S) ∈ X ⟹ (Ψ', S, R) ∈ X ∨ Ψ' ⊳ S ≈ R"

  shows "Ψ ⊳ P ≈ Q"
proof -
  have "X ∪ weakBisim = {(Ψ, P, Q). (Ψ, P, Q) ∈ X ∨ (Ψ, P, Q) ∈ weakBisim}" by auto
  with assms show ?thesis
    by coinduct (simp add: rtrancl_def)
qed

lemma weakBisimWeakCoinductAux[consumes 1]:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   X :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set"

  assumes "(Ψ, P, Q) ∈ X"
  and     "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ⪅<X> Q ∧ Ψ ⊳ P ↝<X> Q ∧
                                      (∀Ψ'. (Ψ ⊗ Ψ', P, Q) ∈ X) ∧ (Ψ, Q, P) ∈ X" 

  shows "Ψ ⊳ P ≈ Q"
using assms
by(coinduct rule: weakBisimCoinductAux) (blast intro: weakSimMonotonic weakStatImpMonotonic)

lemma weakBisimWeakCoinduct[consumes 1, case_names cStatImp cSim cExt cSym]:
  fixes F :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   X :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set"

  assumes "(Ψ, P, Q) ∈ X"
  and     "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ⪅<X> Q"
  and     "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ↝<X> Q"
  and     "⋀Ψ P Q Ψ'. (Ψ, P, Q) ∈ X ⟹ (Ψ ⊗ Ψ', P, Q) ∈ X"
  and     "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ (Ψ, Q, P) ∈ X"

  shows "(Ψ, P, Q) ∈ weakBisim"
proof -
  have "X ∪ weakBisim = {(Ψ, P, Q). (Ψ, P, Q) ∈ X ∨ (Ψ, P, Q) ∈ weakBisim}" by auto
  with assms show ?thesis
    by(coinduct rule: weakBisimWeakCoinductAux) blast
qed

lemma weakBisimE:
  fixes P  :: "('a, 'b, 'c) psi"
  and   Q  :: "('a, 'b, 'c) psi"
  and   Ψ  :: 'b
  and   Ψ' :: 'b

  assumes "Ψ ⊳ P ≈ Q"

  shows "Ψ ⊳ P ⪅<weakBisim> Q"
  and   "Ψ ⊳ P ↝<weakBisim> Q"
  and   "Ψ ⊗ Ψ' ⊳  P ≈ Q"
  and   "Ψ ⊳ Q ≈ P"
using assms
by(auto intro: weakBisim.cases simp add: rtrancl_def)

lemma weakBisimI:
  fixes P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   Ψ :: 'b

  assumes "Ψ ⊳ P ⪅<weakBisim> Q"
  and     "Ψ ⊳ P ↝<weakBisim> Q"
  and     "∀Ψ'. Ψ ⊗ Ψ' ⊳ P ≈ Q"
  and     "Ψ ⊳ Q ≈ P"

  shows "Ψ ⊳ P ≈ Q"
using assms
by(rule_tac weakBisim.step) (auto simp add: rtrancl_def)

lemma weakBisimReflexive:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"


  shows "Ψ ⊳ P ≈ P"
proof -
  let ?X = "{(Ψ, P, P) | Ψ P. True}"
  have "(Ψ, P, P) ∈ ?X" by simp
  thus ?thesis
    by(coinduct rule: weakBisimWeakCoinduct, auto intro: weakSimReflexive weakStatImpReflexive)
qed

lemma weakBisimClosed:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   p :: "name prm"
  
  assumes "Ψ ⊳ P ≈ Q"

  shows "(p ∙ Ψ) ⊳  (p ∙ P) ≈ (p ∙ Q)"
proof -
  let ?X = "{(p ∙ Ψ, p ∙ P, p ∙ Q) | (p::name prm) Ψ  P Q. Ψ ⊳ P ≈ Q}"
  have "eqvt ?X"
    apply(auto simp add: eqvt_def)
    apply(rule_tac x="pa@p" in exI)
    by(auto simp add: pt2[OF pt_name_inst])
  from ‹Ψ ⊳ P ≈ Q› have "(p ∙ Ψ, p ∙ P, p ∙ Q) ∈ ?X" by blast
  thus ?thesis
  proof(coinduct rule: weakBisimWeakCoinduct)
    case(cStatImp Ψ P Q)
    {
      fix Ψ P Q p
      assume "Ψ ⊳ P ≈ (Q::('a, 'b, 'c) psi)"
      hence "Ψ ⊳ P ⪅<weakBisim> Q" by(rule weakBisimE)
      hence "Ψ ⊳ P ⪅<?X> Q"
        apply(rule_tac A=weakBisim in weakStatImpMonotonic, auto)
        by(rule_tac x="[]::name prm" in exI) auto
      with ‹eqvt ?X› have "((p::name prm) ∙ Ψ) ⊳ (p ∙ P) ⪅<?X> (p ∙ Q)"
        by(rule weakStatImpClosed)
    }
    with ‹(Ψ, P, Q) ∈ ?X› show ?case by blast
  next
    case(cSim Ψ P Q)
    {
      fix p :: "name prm"
      fix Ψ P Q
      assume "Ψ ⊳ P ↝<weakBisim> Q"
      hence "Ψ ⊳ P ↝<?X> Q"
        apply(rule_tac A=weakBisim in weakSimMonotonic, auto)
        by(rule_tac x="[]::name prm" in exI) auto
      with ‹eqvt ?X› have "((p::name prm) ∙ Ψ) ⊳ (p ∙ P) ↝<?X> (p ∙ Q)"
        by(rule_tac weakSimClosed)
    }
    with ‹(Ψ, P, Q) ∈ ?X› show ?case
      by(blast dest: weakBisimE)
  next
    case(cExt Ψ P Q Ψ')
    {
      fix p :: "name prm"
      fix Ψ P Q Ψ'
      assume "∀Ψ'. (Ψ ⊗ Ψ', P, Q) ∈ weakBisim"
      hence "((p ∙ Ψ) ⊗ Ψ', p ∙ P, p ∙ Q) ∈ ?X"
        apply(auto, rule_tac x=p in exI)
        apply(rule_tac x="Ψ ⊗ (rev p ∙ Ψ')" in exI)
        by(auto simp add: eqvts)
    }
    with ‹(Ψ, P, Q) ∈ ?X› show ?case
      by(blast dest: weakBisimE)
  next
    case(cSym Ψ P Q)
    thus ?case
      by(blast dest: weakBisimE)
  qed
qed

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

lemma statEqWeakBisim:
  fixes Ψ  :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   Q  :: "('a, 'b, 'c) psi"
  and   Ψ' :: 'b
  
  assumes "Ψ ⊳ P ≈ Q"
  and     "Ψ ≃ Ψ'"

  shows "Ψ' ⊳ P ≈ Q"
proof -
  let ?X = "{(Ψ', P, Q) | Ψ P Q Ψ'. Ψ ⊳ P ≈ Q ∧ Ψ ≃ Ψ'}"
  from ‹Ψ ⊳ P ≈ Q› ‹Ψ ≃ Ψ'› have "(Ψ', P, Q) ∈ ?X" by auto
  thus ?thesis
  proof(coinduct rule: weakBisimCoinduct)
    case(cStatImp Ψ' P Q)
    from ‹(Ψ', P, Q) ∈ ?X› obtain Ψ where "Ψ ⊳ P ≈ Q" and "Ψ ≃ Ψ'"
      by auto
    from ‹Ψ ⊳ P ≈ Q› have "Ψ ⊳ P ⪅<weakBisim> Q" by(rule weakBisimE)
    moreover note ‹Ψ ≃ Ψ'›
    moreover have "⋀Ψ P Q Ψ'. ⟦Ψ ⊳ P ≈ Q; Ψ ≃ Ψ'⟧ ⟹ (Ψ', P, Q) ∈ ?X ∪ weakBisim"
      by auto
    ultimately show ?case by(rule weakStatImpStatEq)
  next
    case(cSim Ψ' P Q)
    from ‹(Ψ', P, Q) ∈ ?X› obtain Ψ where "Ψ ⊳ P ≈ Q" and "Ψ ≃ Ψ'"
      by auto
    from ‹Ψ ⊳ P ≈ Q› have "Ψ ⊳ P ↝<weakBisim> Q" by(blast dest: weakBisimE)
    moreover have "eqvt ?X"
      by(auto simp add: eqvt_def) (metis weakBisimClosed AssertionStatEqClosed)
    hence "eqvt(?X ∪ weakBisim)" by auto
    moreover note ‹Ψ ≃ Ψ'›
    moreover have "⋀Ψ P Q Ψ'. ⟦Ψ ⊳ P ≈ Q; Ψ ≃ Ψ'⟧ ⟹ (Ψ', P, Q) ∈ ?X ∪ weakBisim"
      by auto
    ultimately show ?case by(rule weakSimStatEq)
  next
    case(cExt Ψ' P Q Ψ'')
    from ‹(Ψ', P, Q) ∈ ?X› obtain Ψ where "Ψ ⊳ P ≈ Q" and "Ψ ≃ Ψ'"
      by auto
    from ‹Ψ ⊳ P ≈ Q› have "Ψ ⊗ Ψ'' ⊳ P ≈ Q" by(rule weakBisimE)
    moreover from ‹Ψ ≃ Ψ'› have "Ψ ⊗ Ψ'' ≃ Ψ' ⊗ Ψ''" by(rule Composition)
    ultimately show ?case by blast
  next
    case(cSym Ψ' P Q)
    from ‹(Ψ', P, Q) ∈ ?X› obtain Ψ where "Ψ ⊳ P ≈ Q" and "Ψ ≃ Ψ'"
      by auto
    from ‹Ψ ⊳ P ≈ Q› have "Ψ ⊳ Q ≈ P" by(rule weakBisimE)
    thus ?case using ‹Ψ ≃ Ψ'› by auto
  qed
qed

lemma weakBisimTransitive:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   R :: "('a, 'b, 'c) psi"

  assumes PQ: "Ψ ⊳ P ≈ Q"
  and     QR: "Ψ ⊳ Q ≈ R"

  shows "Ψ ⊳ P ≈ R"
proof -
  let ?X = "{(Ψ, P, R) | Ψ P R. ∃Q. Ψ ⊳ P ≈ Q ∧ Ψ ⊳ Q ≈ R}" 
  from PQ QR have "(Ψ, P, R) ∈ ?X" by auto
  thus ?thesis
  proof(coinduct rule: weakBisimCoinduct)
    case(cStatImp Ψ P R)
    from ‹(Ψ, P, R) ∈ ?X› obtain Q where "Ψ ⊳ P ≈ Q" and  "Ψ ⊳ Q ≈ R" by blast
    from ‹Ψ ⊳ P ≈ Q› have "Ψ ⊳ P ⪅<weakBisim> Q" by(rule weakBisimE)
    moreover note ‹Ψ ⊳ Q ≈ R›
    moreover have "?X ⊆ ?X ∪ weakBisim" by auto
    moreover note weakBisimE(1)
    moreover from weakBisimE(2) have "⋀Ψ P Q P'. ⟦Ψ ⊳ P ≈ Q; Ψ ⊳ P ⟹^τ P'⟧ ⟹ ∃Q'. Ψ ⊳ Q ⟹^τ Q' ∧ Ψ ⊳ P' ≈ Q'"
      by(metis weakBisimE(4) weakSimTauChain)
    ultimately show ?case by(rule weakStatImpTransitive)
  next
    case(cSim Ψ P R)
    {
      fix Ψ P Q R
      assume "Ψ ⊳ P ≈ Q" and "Ψ ⊳ Q ↝<weakBisim> R"
      moreover have "eqvt ?X"
        by(force simp add: eqvt_def dest: weakBisimClosed)
      with weakBisimEqvt have "eqvt (?X ∪ weakBisim)" by blast
      moreover have "?X ⊆ ?X ∪ weakBisim" by auto
      moreover note weakBisimE(2)
      ultimately have "Ψ ⊳ P ↝<(?X ∪ weakBisim)> R"
        by(rule_tac weakSimTransitive) auto
    }
    with ‹(Ψ, P, R) ∈ ?X› show ?case
      by(blast dest: weakBisimE)
  next
    case(cExt Ψ P R Ψ')
    thus ?case by(blast dest: weakBisimE)
  next
    case(cSym Ψ P R)
    thus ?case by(blast dest: weakBisimE)
  qed
qed

lemma strongBisimWeakBisim:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"

  assumes "Ψ ⊳ P ∼ Q"

  shows "Ψ ⊳ P ≈ Q"
proof -
  from ‹Ψ ⊳ P ∼ Q›
  show ?thesis
  proof(coinduct rule: weakBisimWeakCoinduct)
    case(cStatImp Ψ P Q)
    from ‹Ψ ⊳ P ∼ Q› have "insertAssertion(extractFrame P) Ψ ↪F insertAssertion(extractFrame Q) Ψ"
      by(metis bisimE FrameStatEq_def)
    moreover from ‹Ψ ⊳ P ∼ Q› have "⋀Ψ'. Ψ ⊗ Ψ' ⊳ P ∼ Q" by(rule bisimE)
    ultimately show ?case by(rule statImpWeakStatImp)
  next
    case(cSim Ψ P Q)
    note ‹Ψ ⊳ P ∼ Q›
    moreover have "⋀Ψ P Q. Ψ ⊳ P ∼ Q ⟹ insertAssertion(extractFrame Q) Ψ ↪F insertAssertion(extractFrame P) Ψ"
      by(drule_tac bisimE) (simp add: FrameStatEq_def)
    ultimately show ?case using bisimE(2) bisimE(3)
      by(rule strongSimWeakSim)
  next
    case(cExt Ψ P Q Ψ')
    from ‹Ψ ⊳ P ∼ Q› show ?case
      by(rule bisimE)
  next
    case(cSym Ψ P Q)
    from ‹Ψ ⊳ P ∼ Q› show ?case
      by(rule bisimE)
  qed
qed

lemma structCongWeakBisim:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"

  assumes "P ≡s Q"

  shows "P ≈ Q"
using assms
by(metis structCongBisim strongBisimWeakBisim)

lemma simTauChain:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   Q  :: "('a, 'b, 'c) psi"
  and   Q' :: "('a, 'b, 'c) psi"

  assumes "(Ψ, P, Q) ∈ Rel"
  and     "Ψ ⊳ Q ⟹^τ Q'"
  and     Sim: "⋀Ψ P Q. (Ψ, P, Q) ∈ Rel ⟹ Ψ ⊳ P ↝[Rel] Q"
  
  obtains P' where "Ψ ⊳ P ⟹^τ P'" and "(Ψ, P', Q') ∈ Rel"
proof -
  assume A: "⋀P'. ⟦Ψ ⊳ P ⟹^τ P'; (Ψ, P', Q') ∈ Rel⟧ ⟹ thesis"
  from ‹Ψ ⊳ Q ⟹^τ Q'› ‹(Ψ, P, Q) ∈ Rel› A show ?thesis
  proof(induct arbitrary: P thesis rule: tauChainInduct)
    case(TauBase Q P)
    moreover have "Ψ ⊳ P ⟹^τ P" by simp
    ultimately show ?case by blast
  next
    case(TauStep Q Q' Q'' P)
    from ‹(Ψ, P, Q) ∈ Rel› obtain P' where PChain: "Ψ ⊳ P ⟹^τ P'" and "(Ψ, P', Q') ∈ Rel"
      by(rule TauStep)
    from ‹(Ψ, P', Q') ∈ Rel› have "Ψ ⊳ P' ↝[Rel] Q'" by(rule Sim)
    then obtain P'' where P'Chain: "Ψ ⊳ P' ⟼τ ≺ P''" and "(Ψ, P'', Q'') ∈ Rel"
      using ‹Ψ ⊳ Q' ⟼τ ≺ Q''› by(drule_tac simE) auto
    from PChain P'Chain have "Ψ ⊳ P ⟹^τ P''" by(auto dest: tauActTauChain)
    thus ?case using ‹(Ψ, P'', Q'') ∈ Rel› by(rule TauStep)
  qed
qed

lemma quietBisimNil:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"

  assumes "quiet P"

  shows "Ψ ⊳ P ≈ 𝟬"
proof -
  let ?X = "{(Ψ, 𝟬, P) | Ψ P. quiet P} ∪ {(Ψ, P, 𝟬) | Ψ P. quiet P}"

  from ‹quiet P› have "(Ψ, P, 𝟬) ∈ ?X" by auto
  thus ?thesis
  proof(coinduct rule: weakBisimWeakCoinduct)
    case(cStatImp Ψ P Q)
    thus ?case
      apply(simp add: weakStatImp_def)
      apply(rule allI)
      apply(rule_tac x=Q in exI)
      apply auto
      apply(drule_tac Ψ=Ψ in quietFrame)
      apply(rule_tac G="⟨ε, Ψ⟩" in FrameStatImpTrans)
      using Identity
      apply(simp add: AssertionStatEq_def)
      apply(simp add: FrameStatEq_def)
      apply(drule_tac Ψ=Ψ in quietFrame)
      apply(rule_tac G="⟨ε, Ψ⟩" in FrameStatImpTrans)
      apply auto
      defer
      using Identity
      apply(simp add: AssertionStatEq_def)
      apply(simp add: FrameStatEq_def)
      done
  next
    case(cSim Ψ P Q)
    moreover have "eqvt ?X" by(auto simp add: eqvt_def intro: quietEqvt)
    ultimately show ?case
      apply auto
      apply(rule quietSim)
      apply auto
      apply(auto simp add: weakSimulation_def)
      done
  next
    case(cExt Ψ P Q Ψ')
    thus ?case by blast
  next
    case(cSym Ψ P Q)
    thus ?case by blast
  qed
qed

lemma weakTransitiveWeakCoinduct[case_names cStatImp cSim cExt cSym, case_conclusion bisim step, consumes 2]:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   X :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set"

  assumes p: "(Ψ, P, Q) ∈ X"
  and Eqvt: "eqvt X"
  and rStatImp: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ⪅<X> Q"
  and rSim: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ↝<({(Ψ, P, Q) | Ψ P Q. ∃P' Q'. Ψ ⊳ P ∼ P' ∧
                                                                        (Ψ, P', Q') ∈ X ∧
                                                                        Ψ ⊳ Q' ∼ Q})> Q"
  and rExt: "⋀Ψ P Q Ψ'. (Ψ, P, Q) ∈ X ⟹ (Ψ ⊗ Ψ', P, Q) ∈ X"
  and rSym: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ (Ψ, Q, P) ∈ X"

  shows "Ψ ⊳ P ≈ Q"
proof -
  let ?X = "{(Ψ, P, Q) | Ψ P Q. ∃P' Q'. Ψ ⊳ P ∼ P' ∧ (Ψ, P', Q') ∈ X ∧ Ψ ⊳ Q' ∼ Q}"
  from p have "(Ψ, P, Q) ∈ ?X"
    by(blast intro: bisimReflexive)
  thus ?thesis
  proof(coinduct rule: weakBisimWeakCoinduct)
    case(cStatImp Ψ P Q)
    {
      fix Ψ'
      from ‹(Ψ , P, Q) ∈ ?X› obtain P' Q' where "Ψ ⊳ P ∼ P'" and "(Ψ, P', Q') ∈ X" and "Ψ ⊳ Q' ∼ Q" by auto
      from ‹(Ψ, P', Q') ∈ X› obtain Q'' Q''' where Q'Chain: "Ψ ⊳ Q' ⟹^τ Q''"
                                               and PImpQ: "insertAssertion (extractFrame P') Ψ ↪F insertAssertion (extractFrame Q'') Ψ"
                                               and Q''Chain: "Ψ ⊗ Ψ' ⊳ Q'' ⟹^τ Q'''" and "(Ψ ⊗ Ψ', P', Q''') ∈ X"
        apply(drule_tac rStatImp) by(auto simp add: weakStatImp_def) blast
      from ‹Ψ ⊳ Q' ∼ Q› have "Ψ ⊳ Q ∼ Q'" by(rule bisimE)
      then obtain Q'''' where "Ψ ⊳ Q ⟹^τ Q''''" and "Ψ ⊳ Q'''' ∼ Q''" using  ‹Ψ ⊳ Q' ⟹^τ Q''› bisimE(2)
        by(rule simTauChain)
      note ‹Ψ ⊳ Q ⟹^τ Q''''›
      moreover have "insertAssertion (extractFrame P) Ψ ↪F insertAssertion (extractFrame Q'''') Ψ"
      proof -
        from ‹Ψ ⊳ P ∼ P'› have "insertAssertion (extractFrame P) Ψ ↪F insertAssertion (extractFrame P') Ψ"
          by(drule_tac bisimE) (simp add: FrameStatEq_def)
        moreover from ‹Ψ ⊳ Q'''' ∼ Q''› have "insertAssertion (extractFrame Q'') Ψ ↪F insertAssertion (extractFrame Q'''') Ψ"
          by(drule_tac bisimE) (simp add: FrameStatEq_def)
        ultimately show ?thesis using PImpQ by(blast intro: FrameStatImpTrans)
      qed
      moreover from ‹Ψ ⊳ Q'''' ∼ Q''› have "Ψ ⊗ Ψ' ⊳ Q'''' ∼ Q''" by(metis bisimE)
      then obtain Q''''' where Q''''Chain: "Ψ ⊗ Ψ' ⊳ Q'''' ⟹^τ Q'''''" and "Ψ ⊗ Ψ' ⊳ Q''''' ∼ Q'''" using Q''Chain bisimE(2)
        by(rule simTauChain)
      moreover from ‹Ψ ⊳ P ∼ P'› ‹(Ψ ⊗ Ψ' , P', Q''') ∈ X› ‹Ψ ⊗ Ψ' ⊳ Q''''' ∼ Q'''› have "(Ψ ⊗ Ψ', P, Q''''') ∈ ?X" by(auto dest: bisimE)
      ultimately have "∃Q' Q''. Ψ ⊳ Q ⟹^τ Q'' ∧ insertAssertion (extractFrame P) Ψ ↪F insertAssertion (extractFrame Q'') Ψ ∧ Ψ ⊗ Ψ' ⊳ Q'' ⟹^τ Q' ∧ (Ψ ⊗ Ψ', P, Q') ∈ ?X" by blast
    }
    with ‹(Ψ, P, Q) ∈ ?X› show ?case by(simp add: weakStatImp_def) blast
  next
    case(cSim Ψ P Q)
    from ‹(Ψ, P, Q) ∈ ?X› obtain P' Q' where "Ψ ⊳ P ∼ P'" and "(Ψ, P', Q') ∈ X" and "Ψ ⊳ Q' ∼ Q" by auto
    from ‹(Ψ, P', Q') ∈ X› have "Ψ ⊳ P' ↝<?X> Q'" 
      by(rule rSim)
    moreover from ‹Ψ ⊳ Q' ∼ Q› have "Ψ ⊳ Q' ↝[bisim] Q" by(rule bisimE)
    moreover from ‹eqvt X› have "eqvt ?X"
      apply(auto simp add: eqvt_def)
      apply(drule_tac p=p in bisimClosed)
      apply(drule_tac p=p in bisimClosed)
      apply(rule_tac x="p ∙ P'" in exI, simp)
      by(rule_tac x="p ∙ Q'" in exI, auto)
    moreover from ‹Ψ ⊳ Q' ∼ Q› have "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame Q') Ψ"
      by(drule_tac bisimE) (simp add: FrameStatEq_def)
    moreover have "{(Ψ, P, R) | Ψ P R. ∃Q. (Ψ, P, Q) ∈ ?X ∧ Ψ ⊳ Q ∼ R} ⊆ ?X"
      by(blast intro: bisimTransitive)
    moreover note bisimE(3)
    ultimately have "Ψ ⊳ P' ↝<?X> Q" by(rule strongAppend) 
    moreover have "{(Ψ, P, R) | Ψ P R. ∃Q. Ψ ⊳ P ∼ Q ∧ (Ψ, Q, R) ∈ ?X} ⊆ ?X"
      by(blast intro: bisimTransitive)
    moreover {
      fix Ψ P Q

      assume "Ψ ⊳ P ∼ Q"
      moreover have "⋀Ψ P Q. Ψ ⊳ P ∼ Q ⟹ insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P) Ψ"
        by(drule_tac bisimE) (simp add: FrameStatEq_def)
      ultimately have "Ψ ⊳ P ↝<bisim> Q" using bisimE(2) bisimE(3)
        by(rule strongSimWeakSim)
    }
    ultimately show ?case using ‹Ψ ⊳ P ∼ P'› ‹eqvt ?X›
      by(rule_tac weakSimTransitive)
  next
    case(cExt Ψ P Q Ψ')
    thus ?case by(blast dest: bisimE intro: rExt)
  next
    case(cSym Ψ P Q)
    thus ?case by(blast dest: bisimE intro: rSym)
  qed
qed

lemma weakTransitiveCoinduct[case_names cStatImp cSim cExt cSym, case_conclusion bisim step, consumes 2]:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   X :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set"

  assumes p: "(Ψ, P, Q) ∈ X"
  and Eqvt: "eqvt X"
  and rStatImp: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ⪅<(X ∪ weakBisim)> Q"
  and rSim: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ↝<({(Ψ, P, Q) | Ψ P Q. ∃P' Q'. Ψ ⊳ P ∼ P' ∧
                                                                        (Ψ, P', Q') ∈ (X ∪ weakBisim) ∧
                                                                        Ψ ⊳ Q' ∼ Q})> Q"
  and rExt: "⋀Ψ P Q Ψ'. (Ψ, P, Q) ∈ X ⟹ (Ψ ⊗ Ψ', P, Q) ∈ X ∪ weakBisim"
  and rSym: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ (Ψ, Q, P) ∈ X ∪ weakBisim"

  shows "Ψ ⊳ P ≈ Q"
proof -
  from p have "(Ψ, P, Q) ∈ X ∪ weakBisim" by auto
  moreover from ‹eqvt X› have "eqvt(X ∪ weakBisim)" by auto
  ultimately show ?thesis
  proof(coinduct rule: weakTransitiveWeakCoinduct)
    case(cStatImp Ψ P Q)
    thus ?case by(blast dest: rStatImp weakBisimE(1) weakStatImpMonotonic)
  next
    case(cSim Ψ P Q)
    thus ?case by(fastforce intro: rSim weakBisimE(2) weakSimMonotonic bisimReflexive)
  next
    case(cExt Ψ P Q Ψ')
    thus ?case by(blast dest: weakBisimE rExt) 
  next
    case(cSym Ψ P Q)
    thus ?case by(blast dest: weakBisimE rSym)
  qed
qed

lemma weakTransitiveCoinduct2[case_names cStatImp cSim cExt cSym, case_conclusion bisim step, consumes 2]:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   X :: "('b × ('a, 'b, 'c) psi × ('a, 'b, 'c) psi) set"

  assumes p: "(Ψ, P, Q) ∈ X"
  and Eqvt: "eqvt X"
  and rStatImp: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ⪅<X> Q"
  and rSim: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ Ψ ⊳ P ↝<({(Ψ, P, Q) | Ψ P Q. ∃P' Q'. Ψ ⊳ P ≈ P' ∧ (Ψ, P', Q') ∈ X ∧ Ψ ⊳ Q' ∼ Q})> Q"
  and rExt: "⋀Ψ P Q Ψ'. (Ψ, P, Q) ∈ X ⟹ (Ψ ⊗ Ψ', P, Q) ∈ X"
  and rSym: "⋀Ψ P Q. (Ψ, P, Q) ∈ X ⟹ (Ψ, Q, P) ∈ X"

  shows "Ψ ⊳ P ≈ Q"
proof -
  let ?X = "{(Ψ, P, Q) | Ψ P Q. ∃P' Q'. Ψ ⊳ P ≈ P' ∧ (Ψ, P', Q') ∈ X ∧ Ψ ⊳ Q' ∼ Q}"
  let ?Y = "{(Ψ, P, Q) | Ψ P Q. ∃P' Q'. Ψ ⊳ P ≈ P' ∧ (Ψ, P', Q') ∈ X ∧ Ψ ⊳ Q' ≈ Q}"

  from ‹eqvt X› have "eqvt ?X"
    apply(auto simp add: eqvt_def)
    apply(drule_tac p=p in bisimClosed)
    apply(drule_tac p=p in weakBisimClosed)
    apply(rule_tac x="p ∙ P'" in exI, simp)
    by(rule_tac x="p ∙ Q'" in exI, auto)
  from ‹eqvt X› have "eqvt ?Y"
    apply(auto simp add: eqvt_def)
    apply(drule_tac p=p in weakBisimClosed)
    apply(drule_tac p=p in weakBisimClosed)
    apply(rule_tac x="p ∙ P'" in exI, simp)
    by(rule_tac x="p ∙ Q'" in exI, auto)

  {
    fix Ψ P Q
    assume "(Ψ, P, Q) ∈ ?X"
    then obtain P' Q' where "Ψ ⊳ P ≈ P'" and "(Ψ, P', Q') ∈ X" and "Ψ ⊳ Q' ∼ Q"
      by auto
    note ‹Ψ ⊳ P ≈ P'›
    moreover from ‹(Ψ, P', Q') ∈ X› have "Ψ ⊳ P' ↝<?X> Q'" by(rule rSim)
    moreover note ‹eqvt ?X›
    moreover have "{(Ψ, P, R) | Ψ P R. ∃Q. Ψ ⊳ P ≈ Q ∧ (Ψ, Q, R) ∈ ?X} ⊆ ?X"
      by(blast intro: weakBisimTransitive)
    ultimately have "Ψ ⊳ P ↝<?X> Q'" using weakBisimE(2) by(rule weakSimTransitive)
    moreover from ‹Ψ ⊳ Q' ∼ Q› have "Ψ ⊳ Q' ↝[bisim] Q" by(rule bisimE)
    moreover note ‹eqvt ?X›
    moreover from ‹Ψ ⊳ Q' ∼ Q› have "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame Q') Ψ"
      by(drule_tac bisimE) (simp add: FrameStatEq_def)
    moreover have "{(Ψ, P, R) | Ψ P R. ∃Q. (Ψ, P, Q) ∈ ?X ∧ Ψ ⊳ Q ∼ R} ⊆ ?X"
      by(blast dest: bisimTransitive)
    moreover note bisimE(3)
    ultimately have "Ψ ⊳ P ↝<?X> Q" by(rule_tac strongAppend) 
  }
  note Goal = this

  from p have "(Ψ, P, Q) ∈ ?Y" by(blast intro: weakBisimReflexive bisimReflexive rSym)
  thus ?thesis
  proof(coinduct rule: weakBisimWeakCoinduct)
  next
    case(cStatImp Ψ P Q)
    {
      fix Ψ'

      from ‹(Ψ, P, Q) ∈ ?Y› obtain R S where "Ψ ⊳ P ≈ R" and "(Ψ, R, S) ∈ X" and "Ψ ⊳ S ≈ Q" by auto
      from ‹Ψ ⊳ P ≈ R› obtain R'' R' 
        where RChain: "Ψ ⊳ R ⟹^τ R''" 
          and PImpR'': "insertAssertion (extractFrame P) Ψ ↪F insertAssertion (extractFrame R'') Ψ"
          and R''Chain: "Ψ ⊗ Ψ' ⊳ R'' ⟹^τ R'" 
          and "Ψ ⊗ Ψ' ⊳ P ≈ R'"
        apply(drule_tac weakBisimE) by(simp add: weakStatImp_def) blast

      from ‹(Ψ, R, S) ∈ X› have "(Ψ, S, R) ∈ ?X" by(blast intro: weakBisimReflexive bisimReflexive rSym)
      with RChain obtain S'' where SChain: "Ψ ⊳ S ⟹^τ S''" and "(Ψ, S'', R'') ∈ ?X" using Goal
        by(rule weakSimTauChain)

      from ‹(Ψ, S'', R'') ∈ ?X› obtain T U where "Ψ ⊳ S'' ≈ T" and "(Ψ, T, U) ∈ X" and "Ψ ⊳ U ∼ R''"
        by auto
      from ‹Ψ ⊳ U ∼ R''› have R''ImpU: "insertAssertion (extractFrame R'') Ψ ↪F insertAssertion (extractFrame U) Ψ"
        by(drule_tac bisimE) (simp add: FrameStatEq_def)
      
      from ‹(Ψ, T, U) ∈ X› weakStatImp_def
      obtain T'' T' where TChain: "Ψ ⊳ T ⟹^τ T''"
                      and UImpT'': "insertAssertion (extractFrame U) Ψ ↪F insertAssertion (extractFrame T'') Ψ"
                      and T''Chain: "Ψ ⊗ Ψ' ⊳ T'' ⟹^τ T'" 
                      and "(Ψ ⊗ Ψ', U, T') ∈ X"
        by(blast dest: rStatImp rSym)

      from TChain ‹Ψ ⊳ S'' ≈ T› weakBisimE(2) obtain S''' where S''Chain: "Ψ ⊳ S'' ⟹^τ S'''" and "Ψ ⊳ S''' ≈ T''"
        by(rule weakSimTauChain)

      from ‹Ψ ⊳ S''' ≈ T''› weakStatImp_def
      obtain S''''' S'''' where S'''Chain: "Ψ ⊳ S''' ⟹^τ S'''''"
                            and T''ImpS''''': "insertAssertion (extractFrame T'') Ψ ↪F insertAssertion (extractFrame S''''') Ψ"
                            and S'''''Chain: "Ψ ⊗ Ψ' ⊳ S''''' ⟹^τ S''''" 
                            and "Ψ ⊗ Ψ' ⊳ T'' ≈ S''''"
        by(metis weakBisimE)
      
      from SChain S''Chain S'''Chain have "Ψ ⊳ S ⟹^τ S'''''" by auto
      moreover from ‹Ψ ⊳ S ≈ Q› have "Ψ ⊳ Q ≈ S" by(rule weakBisimE)
      ultimately obtain Q''' where QChain: "Ψ ⊳ Q ⟹^τ Q'''" and "Ψ ⊳ Q''' ≈ S'''''" using weakBisimE(2)
        by(rule weakSimTauChain)
      from ‹Ψ ⊳ Q''' ≈ S'''''› have "Ψ ⊳ S''''' ≈ Q'''" by(rule weakBisimE)
      then obtain Q'' Q' where Q'''Chain: "Ψ ⊳ Q''' ⟹^τ Q''"
                           and S'''''ImpQ'': "insertAssertion (extractFrame S''''') Ψ ↪F insertAssertion (extractFrame Q'') Ψ"
                           and Q''Chain: "Ψ ⊗ Ψ' ⊳ Q'' ⟹^τ Q'" 
                           and "Ψ ⊗ Ψ' ⊳ S''''' ≈ Q'" using weakStatImp_def
        by(metis weakBisimE)

      from QChain Q'''Chain have "Ψ ⊳ Q ⟹^τ Q''" by auto
      moreover from PImpR'' R''ImpU UImpT'' T''ImpS''''' S'''''ImpQ''
      have "insertAssertion (extractFrame P) Ψ ↪F insertAssertion (extractFrame Q'') Ψ"
        by(blast dest: FrameStatImpTrans)

      moreover from ‹Ψ ⊳ U ∼ R''› have "Ψ ⊗ Ψ' ⊳ U ≈ R''" by(metis weakBisimE strongBisimWeakBisim)
      with R''Chain obtain U' where UChain: "Ψ ⊗ Ψ' ⊳ U ⟹^τ U'" and "Ψ ⊗ Ψ' ⊳ U' ≈ R'" using weakBisimE(2)
        by(rule weakSimTauChain)
      from ‹Ψ ⊗ Ψ' ⊳ U' ≈ R'› have "Ψ ⊗ Ψ' ⊳ R' ≈ U'" by(rule weakBisimE)
      from ‹(Ψ ⊗ Ψ', U, T') ∈ X› have "(Ψ ⊗ Ψ', T', U) ∈ ?X" by(blast intro: rSym weakBisimReflexive bisimReflexive)
      with UChain obtain T''' where T'Chain: "Ψ ⊗ Ψ' ⊳ T' ⟹^τ T'''" and "(Ψ ⊗ Ψ', T''', U') ∈ ?X" using Goal
        by(rule weakSimTauChain)
      from ‹(Ψ ⊗ Ψ', T''', U') ∈ ?X› have "(Ψ ⊗ Ψ', U', T''') ∈ ?Y" 
        by(blast dest: weakBisimE rSym strongBisimWeakBisim)
      from T''Chain T'Chain have "Ψ ⊗ Ψ' ⊳ T'' ⟹^τ T'''" by auto
      then obtain S'''''' where S''''Chain: "Ψ ⊗ Ψ' ⊳ S'''' ⟹^τ S''''''" and "Ψ ⊗ Ψ' ⊳ T''' ≈ S''''''" 
        using  ‹Ψ ⊗ Ψ' ⊳ T'' ≈ S''''› weakBisimE(2)
        apply(drule_tac weakBisimE(4))
        by(rule weakSimTauChain) (auto dest: weakBisimE(4))
      from S'''''Chain S''''Chain have "Ψ ⊗ Ψ' ⊳ S''''' ⟹^τ S''''''" by auto

      with ‹Ψ ⊗ Ψ' ⊳ S''''' ≈ Q'›
      obtain Q'''' where Q'Chain: "Ψ ⊗ Ψ' ⊳ Q' ⟹^τ Q''''" and "Ψ ⊗ Ψ' ⊳ S'''''' ≈ Q''''" using weakBisimE(2)
        apply(drule_tac weakBisimE(4))
        by(rule weakSimTauChain) (auto dest: weakBisimE(4))

      from Q''Chain Q'Chain have "Ψ ⊗ Ψ' ⊳ Q'' ⟹^τ Q''''" by auto
      moreover from ‹Ψ ⊗ Ψ' ⊳ P ≈ R'› ‹Ψ ⊗ Ψ' ⊳ R' ≈ U'› ‹(Ψ ⊗ Ψ', U', T''') ∈ ?Y› ‹Ψ ⊗ Ψ' ⊳ T''' ≈ S''''''›
                    ‹Ψ ⊗ Ψ' ⊳ S'''''' ≈ Q''''›
      have "(Ψ ⊗ Ψ', P, Q'''') ∈ ?Y"
        by auto (blast dest: weakBisimTransitive)
      ultimately have "∃Q'' Q'. Ψ ⊳ Q ⟹^τ Q'' ∧ insertAssertion (extractFrame P) Ψ ↪F insertAssertion (extractFrame Q'') Ψ ∧ Ψ ⊗ Ψ' ⊳ Q'' ⟹^τ Q' ∧ (Ψ ⊗ Ψ', P, Q') ∈ ?Y"
        by blast
    }
    thus ?case by(simp add: weakStatImp_def)
  next
    case(cSim Ψ P Q)
    moreover {
      fix Ψ P P' Q' Q
      assume "Ψ ⊳ P ≈ P'" and "(Ψ, P', Q') ∈ X" and "Ψ ⊳ Q' ≈ Q"
      from ‹(Ψ, P', Q') ∈ X› have "(Ψ, P', Q') ∈ ?X"
        by(blast intro: weakBisimReflexive bisimReflexive)
      moreover from ‹Ψ ⊳ Q' ≈ Q› have "Ψ ⊳ Q' ↝<weakBisim> Q" by(rule weakBisimE)
      moreover note ‹eqvt ?Y›
      moreover have "{(Ψ, P, R) | Ψ P R. ∃Q. (Ψ, P, Q) ∈ ?X ∧ Ψ ⊳ Q ≈ R} ⊆ ?Y"
        by(blast dest: weakBisimTransitive strongBisimWeakBisim)
      ultimately have "Ψ ⊳ P' ↝<?Y> Q" using Goal
        by(rule weakSimTransitive)
      note ‹Ψ ⊳ P ≈ P'› this ‹eqvt ?Y›
      moreover have "{(Ψ, P, R) | Ψ P R. ∃Q. Ψ ⊳ P ≈ Q ∧ (Ψ, Q, R) ∈ ?Y} ⊆ ?Y"
        by(blast dest: weakBisimTransitive)
      ultimately have "Ψ ⊳ P ↝<?Y> Q" using weakBisimE(2)
        by(rule weakSimTransitive)
    }      
    ultimately show ?case by auto
  next
    case(cExt Ψ P Q Ψ')
    thus ?case by(blast dest: bisimE weakBisimE intro: rExt)
  next
    case(cSym Ψ P Q) 
    thus ?case by(blast dest: bisimE(4) weakBisimE(4) rSym)
  qed
qed

end

end