Theory Bisim_Pres

(* 
   Title: Psi-calculi   
   Author/Maintainer: Jesper Bengtson (jebe@itu.dk), 2012
*)
theory Bisim_Pres
  imports Bisimulation Sim_Pres
begin

context env begin

lemma bisimInputPres:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   Q    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   xvec :: "name list"
  and   N    :: 'a

  assumes "Tvec. length xvec = length Tvec  Ψ  P[xvec::=Tvec]  Q[xvec::=Tvec]"

  shows "Ψ  M⦇λ*xvec N⦈.P  M⦇λ*xvec N⦈.Q"
proof -
  let ?X = "{(Ψ, M⦇λ*xvec N⦈.P, M⦇λ*xvec N⦈.Q) | Ψ M xvec N P Q. Tvec. length xvec = length Tvec  Ψ  P[xvec::=Tvec]  Q[xvec::=Tvec]}"

  from assms have "(Ψ, M⦇λ*xvec N⦈.P, M⦇λ*xvec N⦈.Q)  ?X" by blast
  thus ?thesis
  proof(coinduct rule: bisimCoinduct)
    case(cStatEq Ψ P Q)
    thus ?case by auto
  next
    case(cSim Ψ P Q)
    thus ?case by(blast intro: inputPres)
  next
    case(cExt Ψ P Q Ψ')
    thus ?case by(blast dest: bisimE)
  next
    case(cSym Ψ P Q)
    thus ?case by(blast dest: bisimE)
  qed
qed
  
lemma bisimOutputPres:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   M :: 'a
  and   N :: 'a

  assumes "Ψ  P  Q"

  shows "Ψ  MN⟩.P  MN⟩.Q"
proof -
  let ?X = "{(Ψ, MN⟩.P, MN⟩.Q) | Ψ M N P Q. Ψ  P  Q}"
  from Ψ  P  Q have "(Ψ, MN⟩.P, MN⟩.Q)  ?X" by auto
  thus ?thesis
    by(coinduct rule: bisimCoinduct, auto) (blast intro: outputPres dest: bisimE)+
qed

lemma bisimCasePres:
  fixes Ψ   :: 'b
  and   CsP :: "('c × ('a, 'b, 'c) psi) list"
  and   CsQ :: "('c × ('a, 'b, 'c) psi) list"

  assumes "φ P. (φ, P) mem CsP  Q. (φ, Q) mem CsQ  guarded Q  Ψ  P  Q"
  and     "φ Q. (φ, Q) mem CsQ  P. (φ, P) mem CsP  guarded P  Ψ  P  Q"

  shows "Ψ  Cases CsP  Cases CsQ"
proof -
  let ?X = "{(Ψ, Cases CsP, Cases CsQ) | Ψ CsP CsQ. (φ P. (φ, P) mem CsP  (Q. (φ, Q) mem CsQ  guarded Q  Ψ  P  Q)) 
                                                     (φ Q. (φ, Q) mem CsQ  (P. (φ, P) mem CsP  guarded P  Ψ  P  Q))}"
  from assms have "(Ψ, Cases CsP, Cases CsQ)  ?X" by auto
  thus ?thesis
  proof(coinduct rule: bisimCoinduct)
    case(cStatEq Ψ P Q)
    thus ?case by auto
  next
    case(cSim Ψ CasesP CasesQ)
    then obtain CsP CsQ where C1: "φ Q. (φ, Q) mem CsQ  P. (φ, P) mem CsP  guarded P  Ψ  P  Q"
                          and A: "CasesP = Cases CsP" and B: "CasesQ = Cases CsQ"
      by auto
    note C1
    moreover have "Ψ P Q. Ψ  P  Q  Ψ  P ↝[bisim] Q" by(rule bisimE)
    moreover have "bisim  ?X  bisim" by blast
    ultimately have "Ψ  Cases CsP ↝[(?X  bisim)] Cases CsQ"
      by(rule casePres)
    thus ?case using A B by blast
  next
    case(cExt Ψ P Q)
    thus ?case by(blast dest: bisimE)
  next
    case(cSym Ψ P Q)
    thus ?case by(blast dest: bisimE)
  qed
qed

lemma bisimResPres:
  fixes Ψ :: 'b
  and   P :: "('a, 'b, 'c) psi"
  and   Q :: "('a, 'b, 'c) psi"
  and   x :: name
  
  assumes "Ψ  P  Q"
  and     "x  Ψ"

  shows "Ψ  ⦇νxP  ⦇νxQ"
proof -
  let ?X = "{(Ψ, ⦇νxP, ⦇νxQ) | Ψ x P Q. Ψ  P  Q  x  Ψ}"
  
  from assms have "(Ψ, ⦇νxP, ⦇νxQ)  ?X" by auto
  thus ?thesis
  proof(coinduct rule: bisimCoinduct)
    case(cStatEq Ψ xP xQ)
    from (Ψ, xP, xQ)  ?X obtain x P Q where "Ψ  P  Q" and "x  Ψ" and "xP = ⦇νxP" and "xQ = ⦇νxQ"
      by auto
    moreover from Ψ  P  Q have PeqQ: "insertAssertion(extractFrame P) Ψ F insertAssertion(extractFrame Q) Ψ"
      by(rule bisimE)
    ultimately show ?case by(auto intro: frameResPres)
  next
    case(cSim Ψ xP xQ)
    from (Ψ, xP, xQ)  ?X obtain x P Q where "Ψ  P  Q" and "x  Ψ" and "xP = ⦇νxP" and "xQ = ⦇νxQ"
      by auto
    from Ψ  P  Q have "Ψ  P ↝[bisim] Q" by(rule bisimE)
    moreover have "eqvt ?X"
      by(force simp add: eqvt_def bisimClosed pt_fresh_bij[OF pt_name_inst, OF at_name_inst])
    hence "eqvt(?X  bisim)" by auto
    moreover note x  Ψ
    moreover have "bisim  ?X  bisim" by auto
    moreover have "Ψ P Q x. (Ψ, P, Q)  bisim; x  Ψ  (Ψ, ⦇νxP, ⦇νxQ)  ?X  bisim"
      by auto
    ultimately have "Ψ  ⦇νxP ↝[(?X  bisim)] ⦇νxQ"
      by(rule resPres)
    with xP = ⦇νxP xQ = ⦇νxQ show ?case
      by simp
  next
    case(cExt Ψ xP xQ Ψ')
    from (Ψ, xP, xQ)  ?X obtain x P Q where "Ψ  P  Q" and "x  Ψ" and "xP = ⦇νxP" and "xQ = ⦇νxQ"
      by auto
    obtain y::name where "y  P" and "y  Q" and "y  Ψ" and "y  Ψ'"
     by(generate_fresh "name", auto simp add: fresh_prod)
   from Ψ  P  Q have "Ψ  ([(x, y)]  Ψ')  P  Q"
     by(rule bisimE)
   hence "([(x, y)]  (Ψ  ([(x, y)]  Ψ')))  ([(x, y)]  P)  ([(x, y)]  Q)"
     by(rule bisimClosed)
   with x  Ψ y  Ψ have "Ψ  Ψ'  ([(x, y)]  P)  ([(x, y)]  Q)"
     by(simp add: eqvts)
   with y  Ψ y  Ψ' have "(Ψ  Ψ', ⦇νy([(x, y)]  P), ⦇νy([(x, y)]  Q))  ?X"
     by auto
   moreover from y  P y  Q have "⦇νxP = ⦇νy([(x, y)]  P)" and "⦇νxQ = ⦇νy([(x, y)]  Q)"
     by(simp add: alphaRes)+
   ultimately show ?case using xP = ⦇νxP xQ = ⦇νxQ by simp
 next
    case(cSym Ψ P Q)
    thus ?case
      by(blast dest: bisimE)
  qed
qed

lemma bisimResChainPres:
  fixes Ψ   :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   Q    :: "('a, 'b, 'c) psi"
  and   xvec :: "name list"

  assumes "Ψ  P  Q"
  and     "xvec ♯* Ψ"

  shows "Ψ  ⦇ν*xvecP  ⦇ν*xvecQ"
using assms
by(induct xvec) (auto intro: bisimResPres)

lemma bisimParPresAux:
  fixes Ψ  :: 'b
  and   ΨR :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   Q  :: "('a, 'b, 'c) psi"
  and   R  :: "('a, 'b, 'c) psi"
  and   AR :: "name list"
  
  assumes "Ψ  ΨR  P  Q"
  and     FrR: "extractFrame R = AR, ΨR"
  and     "AR ♯* Ψ"
  and     "AR ♯* P"
  and     "AR ♯* Q"

  shows "Ψ  P  R  Q  R"
proof -
  let ?X = "{(Ψ, ⦇ν*xvec(P  R), ⦇ν*xvec(Q  R)) | xvec Ψ P Q R. xvec ♯* Ψ  (AR ΨR. (extractFrame R = AR, ΨR  AR ♯* Ψ  AR ♯* P  AR ♯* Q) 
                                                                                          Ψ  ΨR  P  Q)}"
  {
    fix xvec :: "name list"
    and Ψ    :: 'b 
    and P    :: "('a, 'b, 'c) psi"
    and Q    :: "('a, 'b, 'c) psi"
    and R    :: "('a, 'b, 'c) psi"

    assume "xvec ♯* Ψ"
    and    "AR ΨR. extractFrame R = AR, ΨR; AR ♯* Ψ; AR ♯* P; AR ♯* Q  Ψ  ΨR  P  Q"

    hence "(Ψ, ⦇ν*xvec(P  R), ⦇ν*xvec(Q  R))  ?X"
      apply auto
      by blast
  }

  note XI = this
  {
    fix xvec :: "name list"
    and Ψ    :: 'b 
    and P    :: "('a, 'b, 'c) psi"
    and Q    :: "('a, 'b, 'c) psi"
    and R    :: "('a, 'b, 'c) psi"
    and C    :: "'d::fs_name"

    assume "xvec ♯* Ψ"
    and    A: "AR ΨR. extractFrame R = AR, ΨR; AR ♯* Ψ; AR ♯* P; AR ♯* Q; AR ♯* C  Ψ  ΨR  P  Q"

    from xvec ♯* Ψ have "(Ψ, ⦇ν*xvec(P  R), ⦇ν*xvec(Q  R))  ?X"
    proof(rule XI)
      fix AR ΨR
      assume FrR: "extractFrame R = AR, ΨR"
      obtain p::"name prm" where "(p  AR) ♯* Ψ" and "(p  AR) ♯* P" and "(p  AR) ♯* Q" and "(p  AR) ♯* R" and "(p  AR) ♯* C"
                             and "(p  AR) ♯* ΨR" and S: "(set p)  (set AR) × (set(p  AR))" and "distinctPerm p"
        by(rule_tac c="(Ψ, P, Q, R, ΨR, C)" in name_list_avoiding) auto
      from FrR (p  AR) ♯* ΨR S have "extractFrame R = (p  AR), p  ΨR" by(simp add: frameChainAlpha')

      moreover assume "AR ♯* Ψ"
      hence "(p  AR) ♯* (p  Ψ)" by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with AR ♯* Ψ (p  AR) ♯* Ψ S have "(p  AR) ♯* Ψ" by simp
      moreover assume "AR ♯* P"
      hence "(p  AR) ♯* (p  P)" by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with AR ♯* P (p  AR) ♯* P S have "(p  AR) ♯* P" by simp
      moreover assume "AR ♯* Q"
      hence "(p  AR) ♯* (p  Q)" by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with AR ♯* Q (p  AR) ♯* Q S have "(p  AR) ♯* Q" by simp
      ultimately have "Ψ  (p  ΨR)  P  Q" using (p  AR) ♯* C A by blast
      hence "(p  (Ψ  (p  ΨR)))  (p  P)  (p  Q)" by(rule bisimClosed)
      with AR ♯* Ψ (p  AR) ♯* Ψ AR ♯* P (p  AR) ♯* P AR ♯* Q (p  AR) ♯* Q S distinctPerm p
      show "Ψ  ΨR  P  Q" by(simp add: eqvts)
    qed
  }
  note XI' = this

  have "eqvt ?X"
    apply(auto simp add: eqvt_def)
    apply(rule_tac x="p  xvec" in exI)
    apply(rule_tac x="p  P" in exI)
    apply(rule_tac x="p  Q" in exI)
    apply(rule_tac x="p  R" in exI)
    apply(simp add: eqvts)
    apply(simp add: fresh_star_bij)
    apply(clarify)
    apply(erule_tac x="(rev p)  AR" in allE)
    apply(erule_tac x="(rev p)  ΨR" in allE)
    apply(drule mp)
    apply(rule conjI)
    apply(rule_tac pi=p in pt_bij4[OF pt_name_inst, OF at_name_inst])
    apply(simp add: eqvts)
    defer
    apply(drule_tac p=p in bisimClosed)
    apply(simp add: eqvts)
    apply(subst pt_fresh_star_bij[OF pt_name_inst,OF at_name_inst, of p, THEN sym])
    apply simp
    apply(subst pt_fresh_star_bij[OF pt_name_inst,OF at_name_inst, of p, THEN sym])
    apply simp
    apply(subst pt_fresh_star_bij[OF pt_name_inst,OF at_name_inst, of p, THEN sym])
    by simp

  moreover have Res: "Ψ P Q x. (Ψ, P, Q)  ?X  bisim; x  Ψ  (Ψ, ⦇νxP, ⦇νxQ)  ?X  bisim"
  proof -
    fix Ψ P Q x
    assume "(Ψ, P, Q)  ?X  bisim" and "(x::name)  Ψ"
    show "(Ψ, ⦇νxP, ⦇νxQ)  ?X  bisim"
    proof(case_tac "(Ψ, P, Q)  ?X")
      assume "(Ψ, P, Q)  ?X"
      with x  Ψ have "(Ψ, ⦇νxP, ⦇νxQ)  ?X"
        apply auto
        by(rule_tac x="x#xvec" in exI) auto
      thus ?thesis by simp
    next
      assume "¬(Ψ, P, Q)  ?X"
      with (Ψ, P, Q)  ?X  bisim have "Ψ  P  Q"
        by blast
      hence "Ψ  ⦇νxP  ⦇νxQ" using x  Ψ
        by(rule bisimResPres)
      thus ?thesis
        by simp
    qed
  qed

  have "(Ψ, P  R, Q  R)  ?X" 
  proof -
    {
      fix AR' :: "name list"
      and ΨR' :: 'b

      assume FrR': "extractFrame R = AR', ΨR'"
      and    "AR' ♯* Ψ"
      and    "AR' ♯* P"
      and    "AR' ♯* Q"

      obtain p where "(p  AR') ♯* AR" and "(p  AR') ♯* ΨR'" and "(p  AR') ♯* Ψ" and "(p  AR') ♯* P" and "(p  AR') ♯* Q"
                 and Sp: "(set p)  (set AR') × (set(p  AR'))" and "distinctPerm p"
        by(rule_tac c="(AR, Ψ, ΨR', P, Q)" in name_list_avoiding) auto
            
      from FrR' (p  AR') ♯*  ΨR' Sp have "extractFrame R = (p  AR'), p  ΨR'"
        by(simp add: frameChainAlpha eqvts)
      with FrR (p  AR') ♯* AR obtain q::"name prm" 
        where Sq: "set q  set(p  AR') × set AR" and "distinctPerm q" and "ΨR = q  p  ΨR'"
        by(force elim: frameChainEq)

      from Ψ  ΨR  P  Q ΨR = q  p  ΨR' have "Ψ  (q  p  ΨR')  P  Q" by simp
      hence "(q  (Ψ  (q  p  ΨR')))  (q  P)  (q  Q)" by(rule bisimClosed)
      with Sq AR ♯* Ψ (p  AR') ♯* Ψ AR ♯* P (p  AR') ♯* P AR ♯* Q (p  AR') ♯* Q distinctPerm q
      have "Ψ  (p  ΨR')  P  Q" by(simp add: eqvts)
      hence "(p  (Ψ  (p  ΨR')))  (p  P)  (p  Q)" by(rule bisimClosed)
      with Sp AR' ♯* Ψ (p  AR') ♯* Ψ AR' ♯* P (p  AR') ♯* P AR' ♯* Q (p  AR') ♯* Q distinctPerm p
      have "Ψ  ΨR'  P  Q" by(simp add: eqvts)
    }
    thus ?thesis
      apply auto
      apply(rule_tac x="[]" in exI)
      by auto blast
  qed
  thus ?thesis
  proof(coinduct rule: bisimCoinduct)
    case(cStatEq Ψ PR QR)
    from (Ψ, PR, QR)  ?X
    obtain xvec P Q R AR ΨR where PFrR: "PR = ⦇ν*xvec(P  R)" and QFrR: "QR = ⦇ν*xvec(Q  R)"
                              and "xvec ♯* Ψ" and FrR: "extractFrame R = AR, ΨR" and PSimQ: "Ψ  ΨR  P  Q"
                              and "AR ♯* xvec" and "AR ♯* Ψ" and "AR ♯* P" and "AR ♯* Q" and "AR ♯* R"
      apply auto
      apply(subgoal_tac "AR ΨR. extractFrame R = AR, ΨR  AR ♯* (xvec, Ψ, P, Q, R)")
      apply auto
      apply(rule_tac F="extractFrame R" and C="(xvec, Ψ, P, Q, R)" in freshFrame)
      by auto

    obtain AP ΨP where FrP: "extractFrame P = AP, ΨP" and "AP ♯* Ψ" and "AP ♯* AR" and "AP ♯* ΨR"
      by(rule_tac C="(Ψ, AR, ΨR)" in freshFrame) auto
    obtain AQ ΨQ where FrQ: "extractFrame Q = AQ, ΨQ" and "AQ ♯* Ψ" and "AQ ♯* AR" and "AQ ♯* ΨR"
      by(rule_tac C="(Ψ, AR, ΨR)" in freshFrame) auto
    from AR ♯* P AR ♯* Q AP ♯* AR AQ ♯* AR FrP FrQ have "AR ♯* ΨP" and  "AR ♯* ΨQ"
      by(force dest: extractFrameFreshChain)+
    
    have "(AP@AR), Ψ  ΨP  ΨR F (AQ@AR), Ψ  ΨQ  ΨR"
    proof -
      have "AP, Ψ  ΨP  ΨR F AP, (Ψ  ΨR)  ΨP"
        by(metis frameResChainPres frameNilStatEq Associativity Commutativity AssertionStatEqTrans Composition)
      moreover from PSimQ have "insertAssertion(extractFrame P) (Ψ  ΨR) F insertAssertion(extractFrame Q) (Ψ  ΨR)"
        by(rule bisimE)
      with FrP FrQ freshCompChain AP ♯* Ψ AP ♯* ΨR AQ ♯* Ψ AQ ♯* ΨR have "AP, (Ψ  ΨR)  ΨP F AQ, (Ψ  ΨR)  ΨQ"
        by auto
      moreover have "AQ, (Ψ  ΨR)  ΨQ F AQ, Ψ  ΨQ  ΨR"
        by(metis frameResChainPres frameNilStatEq Associativity Commutativity AssertionStatEqTrans Composition)
      ultimately have "AP, Ψ  ΨP  ΨR F AQ, Ψ  ΨQ  ΨR"
        by(blast intro: FrameStatEqTrans)
      hence "(AR@AP), Ψ  ΨP  ΨR F (AR@AQ), Ψ  ΨQ  ΨR"
        by(drule_tac frameResChainPres) (simp add: frameChainAppend)
      thus ?thesis
        apply(simp add: frameChainAppend)
        by(metis frameResChainComm FrameStatEqTrans)
    qed
    moreover from AP ♯* Ψ AR ♯* Ψ have "(AP@AR) ♯* Ψ" by simp
    moreover from AQ ♯* Ψ AR ♯* Ψ have "(AQ@AR) ♯* Ψ" by simp
    ultimately have PFrRQR: "insertAssertion(extractFrame(P  R)) Ψ F insertAssertion(extractFrame(Q  R)) Ψ"
      using FrP FrQ FrR AP ♯* AR AP ♯* ΨR AQ ♯* AR AQ ♯* ΨR AR ♯* ΨP AR ♯* ΨQ
      by simp
      
    from xvec ♯* Ψ have "insertAssertion (extractFrame(⦇ν*xvecP  R)) Ψ F ⦇ν*xvec(insertAssertion (extractFrame(P  R)) Ψ)"
      by(rule insertAssertionExtractFrameFresh)
    moreover from PFrRQR have "⦇ν*xvec(insertAssertion (extractFrame(P  R)) Ψ) F ⦇ν*xvec(insertAssertion (extractFrame(Q  R)) Ψ)"
      by(induct xvec) (auto intro: frameResPres)
    moreover from xvec ♯* Ψ have "⦇ν*xvec(insertAssertion (extractFrame(Q  R)) Ψ) F insertAssertion (extractFrame(⦇ν*xvecQ  R)) Ψ"
      by(rule FrameStatEqSym[OF insertAssertionExtractFrameFresh])
    ultimately show ?case using PFrR QFrR
      by(blast intro: FrameStatEqTrans)
  next
    case(cSim Ψ PR QR)
    {
      fix Ψ P Q R xvec
      assume "AR ΨR. extractFrame R = AR, ΨR; AR ♯* Ψ; AR ♯* P; AR ♯* Q  Ψ  ΨR  P  Q"
      moreover have "eqvt bisim" by simp
      moreover from eqvt ?X have "eqvt(?X  bisim)" by auto
      moreover from bisimE(1) have "Ψ P Q. Ψ  P  Q  insertAssertion (extractFrame Q) Ψ F insertAssertion (extractFrame P) Ψ" by(simp add: FrameStatEq_def)
      moreover note bisimE(2) bisimE(3)
      moreover 
      {
        fix Ψ P Q AR ΨR R
        assume PSimQ: "Ψ  ΨR  P  Q"
           and FrR: "extractFrame R = AR, ΨR"
           and "AR ♯* Ψ"
           and "AR ♯* P"
           and "AR ♯* Q"
        hence "(Ψ, P  R, Q  R)  ?X"
        proof -
          have "P  R = ⦇ν*[](P  R)" by simp
          moreover have "Q  R = ⦇ν*[](Q  R)" by simp
          moreover have "([]::name list) ♯* Ψ" by simp
          moreover 
          {
            fix AR' ΨR'

            assume FrR': "extractFrame R = AR', ΨR'"
               and "AR' ♯* Ψ"
               and "AR' ♯* P"
               and "AR' ♯* Q"
            obtain p where "(p  AR') ♯* AR"
                       and "(p  AR') ♯* ΨR'"
                       and "(p  AR') ♯* Ψ"
                       and "(p  AR') ♯* P"
                       and "(p  AR') ♯* Q"
                       and S: "(set p)  (set AR') × (set(p  AR'))" and "distinctPerm p"
              by(rule_tac c="(AR, Ψ, ΨR', P, Q)" in name_list_avoiding) auto


            from (p  AR') ♯* ΨR' S have "AR', ΨR' = p  AR', p  ΨR'"
              by(simp add: frameChainAlpha)

            with FrR' have FrR'': "extractFrame R = p  AR', p  ΨR'" by simp
            with FrR (p  AR') ♯* AR
            obtain q where "p  ΨR' = (q::name prm)  ΨR" and S': "set q  (set AR) × set(p  AR')" and "distinctPerm q"
              apply auto
              apply(drule_tac sym) apply simp
              by(drule_tac frameChainEq) auto
            from PSimQ have "(q  (Ψ  ΨR))  (q  P)  (q  Q)"
              by(rule bisimClosed)
            with AR ♯* Ψ AR ♯* P AR ♯* Q (p  AR') ♯* Ψ (p  AR') ♯* P (p  AR') ♯* Q S'
            have "Ψ  (q  ΨR)  P  Q" by(simp add: eqvts)
            hence "(p  (Ψ  (q  ΨR)))  (p  P)  (p  Q)" by(rule bisimClosed)
            with AR' ♯* Ψ AR' ♯* P AR' ♯* Q (p  AR') ♯* Ψ (p  AR') ♯* P (p  AR') ♯* Q S distinctPerm p (p  ΨR') = q  ΨR 
            have "Ψ  ΨR'  P  Q"
              by(drule_tac sym) (simp add: eqvts)
          }
          ultimately show ?thesis
            by blast
        qed
        hence "(Ψ, P  R, Q  R)  ?X  bisim"
          by simp
      }
      moreover have "Ψ P Q xvec. (Ψ, P, Q)  ?X  bisim; (xvec::name list) ♯* Ψ  (Ψ, ⦇ν*xvecP, ⦇ν*xvecQ)  ?X  bisim"
      proof -
        fix Ψ P Q xvec
        assume "(Ψ, P, Q)  ?X  bisim"
        assume "(xvec::name list) ♯* Ψ"
        thus "(Ψ, ⦇ν*xvecP, ⦇ν*xvecQ)  ?X  bisim"
        proof(induct xvec)
          case Nil
          thus ?case using (Ψ, P, Q)  ?X  bisim by simp
        next
          case(Cons x xvec)
          thus ?case by(simp only: resChain.simps) (rule_tac Res, auto)
        qed
      qed
      ultimately have "Ψ  P  R ↝[(?X  bisim)] Q  R" using statEqBisim
        by(rule parPres)
      moreover assume "(xvec::name list) ♯* Ψ"
      moreover from eqvt ?X have "eqvt(?X  bisim)" by auto
      ultimately have "Ψ  ⦇ν*xvec(P  R) ↝[(?X  bisim)] ⦇ν*xvec(Q  R)" using Res
        by(rule_tac resChainPres)
    }
    with (Ψ, PR, QR)  ?X show ?case by blast
  next
    case(cExt Ψ PR QR Ψ')

    from (Ψ, PR, QR)  ?X
    obtain xvec P Q R AR ΨR where PFrR: "PR = ⦇ν*xvec(P  R)" and QFrR: "QR = ⦇ν*xvec(Q  R)"
                               and "xvec ♯* Ψ" and A: "AR ΨR. (extractFrame R = AR, ΨR  AR ♯* Ψ  AR ♯* P  AR ♯* Q)  Ψ  ΨR  P  Q"
      by auto
    
    obtain p where "(p  xvec) ♯* Ψ"
               and "(p  xvec) ♯* P"
               and "(p  xvec) ♯* Q"
               and "(p  xvec) ♯* R"
               and "(p  xvec) ♯* Ψ'"
               and S: "(set p)  (set xvec) × (set(p  xvec))" and "distinctPerm p"
      by(rule_tac c="(Ψ, P, Q, R, Ψ')" in name_list_avoiding) auto

    from (p  xvec) ♯* P (p  xvec) ♯* R S have "⦇ν*xvec(P  R) = ⦇ν*(p  xvec)(p  (P  R))"
      by(subst resChainAlpha) auto
    hence PRAlpha: "⦇ν*xvec(P  R) = ⦇ν*(p  xvec)((p  P)  (p  R))"
      by(simp add: eqvts)

    from (p  xvec) ♯* Q (p  xvec) ♯* R S have "⦇ν*xvec(Q  R) = ⦇ν*(p  xvec)(p  (Q  R))"
      by(subst resChainAlpha) auto
    hence QRAlpha: "⦇ν*xvec(Q  R) = ⦇ν*(p  xvec)((p  Q)  (p  R))"
      by(simp add: eqvts)

    from (p  xvec) ♯* Ψ (p  xvec) ♯* Ψ' have "(Ψ  Ψ', ⦇ν*(p  xvec)((p  P)  (p  R)), ⦇ν*(p  xvec)((p  Q)  (p  R)))  ?X"
    proof(rule_tac C2="(Ψ, (p  P), (p  Q), R, Ψ', xvec, p  xvec)" in XI', auto)
      fix AR ΨR
      assume FrR: "extractFrame (p  R) = AR, ΨR" and "AR ♯* Ψ" and "AR ♯* Ψ'" and "AR ♯* (p  P)" and "AR ♯* (p  Q)"
      from FrR have "(p  (extractFrame (p  R))) = (p  AR, ΨR)" by simp
      with distinctPerm p have "extractFrame R = p  AR, p  ΨR" by(simp add: eqvts)
      moreover from AR ♯* Ψ have "(p  AR) ♯* (p  Ψ)" by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with xvec ♯* Ψ (p  xvec) ♯* Ψ S have "(p  AR) ♯* Ψ" by simp
      moreover from AR ♯* (p  P) have "(p  AR) ♯* (p  p  P)" by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with distinctPerm p have "(p  AR) ♯* P" by simp
      moreover from AR ♯* (p  Q) have "(p  AR) ♯* (p  p  Q)" by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with distinctPerm p have "(p  AR) ♯* Q" by simp
      ultimately have "Ψ  (p  ΨR)  P  Q" using A by blast
      hence "(Ψ  (p  ΨR))  (p  Ψ')  P  Q" by(rule bisimE)
      moreover have "(Ψ  (p  ΨR))  (p  Ψ')  (Ψ  (p  Ψ'))  (p  ΨR)"
        by(metis Associativity Commutativity Composition AssertionStatEqTrans AssertionStatEqSym)
      ultimately have "(Ψ  (p  Ψ'))  (p  ΨR)  P  Q" 
        by(rule statEqBisim)
      hence "(p  ((Ψ  (p  Ψ'))  (p  ΨR)))  (p  P)  (p  Q)"
        by(rule bisimClosed)
      with distinctPerm p xvec ♯* Ψ (p  xvec) ♯* Ψ S show "(Ψ  Ψ')  ΨR  (p  P)  (p  Q)"
        by(simp add: eqvts)
    qed
    with PFrR QFrR PRAlpha QRAlpha show ?case by simp
  next
    case(cSym Ψ PR QR)
    thus ?case by(blast dest: bisimE)
  qed
qed

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

  shows "Ψ  P  R  Q  R"
proof -
  obtain AR ΨR where "extractFrame R = AR, ΨR" and "AR ♯* Ψ" and "AR ♯* P" and "AR ♯* Q"
    by(rule_tac C="(Ψ, P, Q)" in freshFrame) auto
  moreover from Ψ  P  Q have "Ψ  ΨR  P  Q" by(rule bisimE)
  ultimately show ?thesis by(rule_tac bisimParPresAux)
qed

end

end