Theory Tau_Chain

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

context env begin

abbreviation tauChain :: "'b ⇒ ('a, 'b, 'c) psi ⇒ ('a, 'b, 'c) psi ⇒ bool" (‹_ ⊳ _ ⟹^τ _› [80, 80, 80] 80)
where "Ψ ⊳ P ⟹^τ P' ≡ (P, P') ∈ {(P, P'). Ψ ⊳ P ⟼τ ≺ P'}^*"

abbreviation tauStepChain :: "'b ⇒ ('a, 'b, 'c) psi ⇒ ('a, 'b, 'c) psi ⇒ bool" (‹_ ⊳ _ ⟹τ _› [80, 80, 80] 80)
where "Ψ ⊳ P ⟹τ P' ≡ (P, P') ∈ {(P, P'). Ψ ⊳ P ⟼τ ≺ P'}^+"

abbreviation tauContextChain :: "('a, 'b, 'c) psi ⇒ ('a, 'b, 'c) psi ⇒ bool" (‹_ ⟹^τ _› [80, 80] 80)
where "P ⟹^τ P' ≡ 𝟭 ⊳ P ⟹^τ P'"
abbreviation tauContextStepChain :: "('a, 'b, 'c) psi ⇒ ('a, 'b, 'c) psi ⇒ bool" (‹_ ⟹τ _› [80, 80] 80)
where "P ⟹τ P' ≡ 𝟭 ⊳ P ⟹τ P'"

lemmas tauChainInduct[consumes 1, case_names TauBase TauStep] = rtrancl.induct[of _ _ "{(P, P'). Ψ ⊳ P ⟼τ ≺ P'}", simplified] for Ψ
lemmas tauStepChainInduct[consumes 1, case_names TauBase TauStep] = trancl.induct[of _ _ "{(P, P'). Ψ ⊳ P ⟼τ ≺ P'}", simplified] for Ψ


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

  assumes "Ψ ⊳ P ⟼τ ≺ P'"

  shows "Ψ ⊳ P ⟹τ P'"
using assms by auto

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

  assumes "Ψ ⊳ P ⟼τ ≺ P'"

  shows "Ψ ⊳ P ⟹^τ P'"
using assms by(auto simp add: rtrancl_eq_or_trancl)

lemma tauStepChainEqvt[eqvt]:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  and   p  :: "name prm"

  assumes "Ψ ⊳ P ⟹τ P'"

  shows "(p ∙ Ψ) ⊳ (p ∙ P) ⟹τ (p ∙ P')"
using assms
proof(induct rule: tauStepChainInduct)  
  case(TauBase P P')
  hence "Ψ ⊳ P ⟼τ ≺ P'" by simp
  thus ?case by(force dest: semantics.eqvt simp add: eqvts)
next
  case(TauStep P P' P'')
  hence "Ψ ⊳ P' ⟼τ ≺ P''" by simp  
  hence "(p ∙ Ψ) ⊳ (p ∙ P') ⟼τ ≺ (p ∙ P'')" by(force dest: semantics.eqvt simp add: eqvts)
  with ‹(p ∙ Ψ) ⊳ (p ∙ P) ⟹τ (p ∙ P')› show ?case
    by(subst trancl.trancl_into_trancl) auto
qed

lemma tauChainEqvt[eqvt]:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  and   p  :: "name prm"

  assumes "Ψ ⊳ P ⟹^τ P'"

  shows "(p ∙ Ψ) ⊳ (p ∙ P) ⟹^τ (p ∙ P')"
using assms
by(auto simp add: rtrancl_eq_or_trancl eqvts)

lemma tauStepChainEqvt'[eqvt]:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  and   p  :: "name prm"

  shows "(p ∙ (Ψ ⊳ P ⟹τ P')) = (p ∙ Ψ) ⊳ (p ∙ P) ⟹τ (p ∙ P')"
apply(auto simp add: eqvts perm_set_def pt_bij[OF pt_name_inst, OF at_name_inst])
by(drule_tac p="rev p" in tauStepChainEqvt) auto

lemma tauChainEqvt'[eqvt]:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  and   p  :: "name prm"

  shows "(p ∙ (Ψ ⊳ P ⟹^τ P')) = (p ∙ Ψ) ⊳ (p ∙ P) ⟹^τ (p ∙ P')"
apply(auto simp add: eqvts perm_set_def pt_bij[OF pt_name_inst, OF at_name_inst] rtrancl_eq_or_trancl)
by(drule_tac p="rev p" in tauStepChainEqvt) auto

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

  assumes "Ψ ⊳ P ⟹τ P'"
  and     "x ♯ P"

  shows "x ♯ P'"
using assms
by(induct rule: trancl.induct) (auto dest: tauFreshDerivative)

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

  assumes "Ψ ⊳ P ⟹^τ P'"
  and     "x ♯ P"

  shows "x ♯ P'"
using assms
by(auto simp add: rtrancl_eq_or_trancl intro: tauStepChainFresh)

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

  assumes "Ψ ⊳ P ⟹τ P'"
  and     "xvec ♯* P"

  shows "xvec ♯* P'"
using assms
by(induct xvec) (auto intro: tauStepChainFresh)

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

  assumes "Ψ ⊳ P ⟹^τ P'"
  and     "xvec ♯* P"

  shows "xvec ♯* P'"
using assms
by(induct xvec) (auto intro: tauChainFresh)

lemma tauStepChainCase:
  fixes Ψ  :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  and   φ  :: 'c
  and   Cs :: "('c × ('a, 'b, 'c) psi) list"

  assumes "Ψ ⊳ P ⟹τ P'"
  and     "(φ, P) mem Cs"
  and     "Ψ ⊢ φ"
  and     "guarded P"

  shows "Ψ ⊳ (Cases Cs) ⟹τ P'"
using assms
by(induct rule: trancl.induct) (auto intro: Case trancl_into_trancl)

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

  assumes "Ψ ⊳ P ⟹τ P'"
  and     "x ♯ Ψ"

  shows "Ψ ⊳ ⦇νx⦈P ⟹τ ⦇νx⦈P'"
using assms
by(induct rule: trancl.induct) (auto dest: Scope trancl_into_trancl)

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

  assumes "Ψ ⊳ P ⟹^τ P'"
  and     "x ♯ Ψ"

  shows "Ψ ⊳ ⦇νx⦈P ⟹^τ ⦇νx⦈P'"
using assms
by(auto simp add: rtrancl_eq_or_trancl intro: tauStepChainResPres)

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

  assumes "Ψ ⊳ P ⟹τ P'"
  and     "xvec ♯* Ψ"

  shows "Ψ ⊳ ⦇ν*xvec⦈P ⟹τ ⦇ν*xvec⦈P'"
using assms
by(induct xvec) (auto intro: tauStepChainResPres)

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

  assumes "Ψ ⊳ P ⟹^τ P'"
  and     "xvec ♯* Ψ"

  shows "Ψ ⊳ ⦇ν*xvec⦈P ⟹^τ ⦇ν*xvec⦈P'"
using assms
by(induct xvec) (auto intro: tauChainResPres)

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

  assumes "Ψ ⊗ ΨQ ⊳ P ⟹τ P'"
  and     "extractFrame Q = ⟨AQ, ΨQ⟩"
  and     "AQ ♯* Ψ"
  and     "AQ ♯* P"

  shows "Ψ ⊳ P ∥ Q ⟹τ P' ∥ Q"
using assms
by(induct rule: trancl.induct)  (auto dest: Par1 tauStepChainFreshChain trancl_into_trancl)

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

  assumes "Ψ ⊗ ΨQ ⊳ P ⟹^τ P'"
  and     "extractFrame Q = ⟨AQ, ΨQ⟩"
  and     "AQ ♯* Ψ"
  and     "AQ ♯* P"

  shows "Ψ ⊳ P ∥ Q ⟹^τ P' ∥ Q"
using assms
by(auto simp add: rtrancl_eq_or_trancl intro: tauStepChainPar1)

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

  assumes "Ψ ⊗ ΨP ⊳ Q ⟹τ Q'"
  and     "extractFrame P = ⟨AP, ΨP⟩"
  and     "AP ♯* Ψ"
  and     "AP ♯* Q"

  shows "Ψ ⊳ P ∥ Q ⟹τ P ∥ Q'"
using assms
by(induct rule: trancl.induct) (auto dest: Par2 trancl_into_trancl tauStepChainFreshChain)

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

  assumes "Ψ ⊗ ΨP ⊳ Q ⟹^τ Q'"
  and     "extractFrame P = ⟨AP, ΨP⟩"
  and     "AP ♯* Ψ"
  and     "AP ♯* Q"

  shows "Ψ ⊳ P ∥ Q ⟹^τ P ∥ Q'"
using assms
by(auto simp add: rtrancl_eq_or_trancl intro: tauStepChainPar2)

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

  assumes "Ψ ⊳ P ∥ !P ⟹τ P'"
  and     "guarded P"

  shows "Ψ ⊳ !P ⟹τ P'"
using assms
by(induct x1=="P ∥ !P" P' rule: trancl.induct) (auto intro: Bang dest: Bang trancl_into_trancl)

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

  assumes "Ψ ⊳ P ⟹τ P'"
  and     "Ψ ≃ Ψ'"

  shows "Ψ' ⊳ P ⟹τ P'"
using assms
by(induct rule: trancl.induct) (auto dest: statEqTransition trancl_into_trancl)

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

  assumes "Ψ ⊳ P ⟹^τ P'"
  and     "Ψ ≃ Ψ'"

  shows "Ψ' ⊳ P ⟹^τ P'"
using assms
by(auto simp add: rtrancl_eq_or_trancl intro: tauStepChainStatEq)

definition weakTransition :: "'b ⇒ ('a, 'b, 'c) psi ⇒  ('a, 'b, 'c) psi ⇒ 'a action ⇒ ('a, 'b, 'c) psi ⇒ bool" (‹_ : _ ⊳ _ ⟹_ ≺ _› [80, 80, 80, 80, 80] 80)
where
  "Ψ : Q ⊳ P ⟹α ≺ P' ≡ ∃P''. Ψ ⊳ P ⟹^τ P'' ∧ (insertAssertion (extractFrame Q) Ψ) ↪F (insertAssertion (extractFrame P'') Ψ) ∧
                                          Ψ ⊳ P'' ⟼α ≺ P'"

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

  assumes "Ψ ⊳ P ⟹^τ P''"
  and     "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
  and     "Ψ ⊳ P'' ⟼α ≺ P'"

  shows "Ψ : Q ⊳ P ⟹α ≺ P'"
using assms
by(auto simp add: weakTransition_def)

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

  assumes "Ψ : Q ⊳ P ⟹α ≺ P'"

  obtains P'' where "Ψ ⊳ P ⟹^τ P''" and "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                 and "Ψ ⊳ P'' ⟼α ≺ P'"
using assms
by(auto simp add: weakTransition_def)

lemma weakTransitionClosed[eqvt]:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   p    :: "name prm"

  assumes "Ψ : Q ⊳ P ⟹α ≺ P'"

  shows "(p ∙ Ψ) : (p ∙ Q) ⊳ (p ∙ P) ⟹(p ∙ α)≺ (p ∙ P')"
proof -
  from assms obtain P'' where "Ψ ⊳ P ⟹^τ P''" and "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                           and "Ψ ⊳ P'' ⟼α ≺ P'"
    by(rule weakTransitionE)

  from ‹Ψ ⊳ P ⟹^τ P''› have "(p ∙ Ψ) ⊳ (p ∙ P) ⟹^τ (p ∙ P'')"
    by(rule tauChainEqvt)
  moreover from ‹insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ› 
  have "(p ∙ (insertAssertion (extractFrame Q) Ψ)) ↪F (p ∙ (insertAssertion (extractFrame P'') Ψ))"
    by(rule FrameStatImpClosed)
  hence "insertAssertion (extractFrame(p ∙ Q)) (p ∙ Ψ) ↪F insertAssertion (extractFrame(p ∙ P'')) (p ∙ Ψ)" by(simp add: eqvts)
  moreover from ‹Ψ ⊳ P'' ⟼α ≺ P'› have "(p ∙ Ψ) ⊳ (p ∙ P'') ⟼(p ∙ (α ≺ P'))"
    by(rule semantics.eqvt)
  hence "(p ∙ Ψ) ⊳ (p ∙ P'') ⟼(p ∙ α) ≺ (p ∙ P')" by(simp add: eqvts)
  ultimately show ?thesis by(rule weakTransitionI)
qed
(*
lemma weakTransitionAlpha:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   xvec :: "name list"
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   p    :: "name prm"
  and   yvec :: "name list"

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and     S: "set p ⊆ set xvec × set(p ∙ xvec)"
  and     "xvec ♯* (p ∙ xvec)"
  and     "(p ∙ xvec) ♯* P"
  and     "(p ∙ xvec) ♯* N"

  shows "Ψ : Q ⊳ P ⟹M⦇ν*(p ∙ xvec)⦈⟨(p ∙ N)⟩ ≺ (p ∙ P')"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                           and P''Trans: "Ψ ⊳ P'' ⟼M⦇ν*xvec⦈⟨N⟩ ≺ P'"
    by(rule weakTransitionE)

  note PChain QeqP''
  moreover from PChain `(p ∙ xvec) ♯* P` have "(p ∙ xvec) ♯* P''" by(rule tauChainFreshChain)
  with P''Trans `xvec ♯* (p ∙ xvec)` `(p ∙ xvec) ♯* N` have "(p ∙ xvec) ♯* P'"
    by(force intro: outputFreshChainDerivative)
  with P''Trans S `(p ∙ xvec) ♯* N` have "Ψ ⊳ P'' ⟼M⦇ν*(p ∙ xvec)⦈⟨(p ∙ N)⟩ ≺ (p ∙ P')"
    by(simp add: boundOutputChainAlpha'')
  ultimately show ?thesis by(rule weakTransitionI)
qed
*)
lemma weakOutputAlpha:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   xvec :: "name list"
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   p    :: "name prm"
  and   yvec :: "name list"

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇ν*(p ∙ xvec)⦈⟨(p ∙ N)⟩ ≺ P'"
  and     S: "set p ⊆ set xvec × set(p ∙ xvec)"
  and     "distinctPerm p"
  and     "xvec ♯* P"
  and     "xvec ♯* (p ∙ xvec)"
  and     "(p ∙ xvec) ♯* M"
  and     "distinct xvec"

  shows "Ψ : Q ⊳ P ⟹M⦇ν*xvec⦈⟨N⟩ ≺ (p ∙ P')"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                           and P''Trans: "Ψ ⊳ P'' ⟼M⦇ν*(p ∙ xvec)⦈⟨(p ∙ N)⟩ ≺ P'"
    by(rule weakTransitionE)


  note PChain QeqP''
  moreover from PChain ‹xvec ♯* P› have "xvec ♯* P''" by(rule tauChainFreshChain)
  with P''Trans ‹xvec ♯* (p ∙ xvec)› ‹distinct xvec› ‹(p ∙ xvec) ♯* M› have "xvec ♯* (p ∙ N)" and "xvec ♯* P'"
    by(force intro: outputFreshChainDerivative)+
  hence "(p ∙ xvec) ♯* (p ∙ p ∙ N)" and "(p ∙ xvec) ♯* (p ∙ P')"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])+
  with ‹distinctPerm p› have "(p ∙ xvec) ♯* N" and "(p ∙ xvec) ♯* (p ∙ P')" by simp+
  with P''Trans S ‹distinctPerm p› have "Ψ ⊳ P'' ⟼M⦇ν*xvec⦈⟨N⟩ ≺ (p ∙ P')"
    apply(simp add: residualInject)
    by(subst boundOutputChainAlpha) auto
    
  ultimately show ?thesis by(rule weakTransitionI)
qed

lemma weakFreshDerivative:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   x    :: name

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and     "x ♯ P"
  and     "x ♯ α"
  and     "bn α ♯* subject α"
  and     "distinct(bn α)"

  shows "x ♯ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and P''Trans: "Ψ ⊳ P'' ⟼α ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹x ♯ P› have "x ♯ P''" by(rule tauChainFresh)
  with P''Trans show "x ♯ P'" using ‹x ♯ α› ‹bn α ♯* subject α› ‹distinct(bn α)›
    by(force intro: freeFreshDerivative)
qed

lemma weakFreshChainDerivative:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   yvec :: "name list"

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and     "yvec ♯* P"
  and     "yvec ♯* α"
  and     "bn α ♯* subject α"
  and     "distinct(bn α)"

  shows "yvec ♯* P'"
using assms
by(induct yvec) (auto intro: weakFreshDerivative)

lemma weakInputFreshDerivative:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   x    :: name

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇N⦈ ≺ P'"
  and     "x ♯ P"
  and     "x ♯ N"

  shows "x ♯ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and P''Trans: "Ψ ⊳ P'' ⟼M⦇N⦈ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹x ♯ P› have "x ♯ P''" by(rule tauChainFresh)
  with P''Trans show "x ♯ P'" using ‹x ♯ N› 
    by(force intro: inputFreshDerivative)
qed

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇N⦈ ≺ P'"
  and     "xvec ♯* P"
  and     "xvec ♯* N"

  shows "xvec ♯* P'"
using assms
by(induct xvec) (auto intro: weakInputFreshDerivative)

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇ν*xvec⦈⟨N⟩ ≺ P'"
  and     "x ♯ P"
  and     "x ♯ xvec"
  and     "xvec ♯* M"
  and     "distinct xvec"

  shows "x ♯ N"
  and   "x ♯ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and P''Trans: "Ψ ⊳ P'' ⟼M⦇ν*xvec⦈⟨N⟩ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹x ♯ P› have "x ♯ P''" by(rule tauChainFresh)
  with P''Trans show "x ♯ N" and "x ♯ P'" using ‹x ♯ xvec› ‹xvec ♯* M› ‹distinct xvec›
    by(force intro: outputFreshDerivative)+
qed

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇ν*xvec⦈⟨N⟩ ≺ P'"
  and     "yvec ♯* P"
  and     "xvec ♯* yvec"
  and     "xvec ♯* M"
  and     "distinct xvec"

  shows "yvec ♯* N"
  and   "yvec ♯* P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and P''Trans: "Ψ ⊳ P'' ⟼M⦇ν*xvec⦈⟨N⟩ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹yvec ♯* P› have "yvec ♯* P''" by(rule tauChainFreshChain)
  with P''Trans show "yvec ♯* N" and "yvec ♯* P'" using ‹xvec ♯* yvec› ‹xvec ♯* M› ‹distinct xvec›
    by(force intro: outputFreshChainDerivative)+
qed

lemma weakOutputPermSubject:
  fixes Ψ   :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   xvec :: "name list"
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   p    :: "name prm"
  and   yvec :: "name list"
  and   zvec :: "name list"

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇ν*xvec⦈⟨N⟩ ≺ P'"
  and     S: "set p ⊆ set yvec × set zvec"
  and     "yvec ♯* Ψ"
  and     "zvec ♯* Ψ"
  and     "yvec ♯* P"
  and     "zvec ♯* P"

  shows "Ψ : Q ⊳ P ⟹(p ∙ M)⦇ν*xvec⦈⟨N⟩ ≺ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ" 
                            and P''Trans: "Ψ ⊳ P'' ⟼M⦇ν*xvec⦈⟨N⟩ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹yvec ♯* P› ‹zvec ♯* P› have "yvec ♯* P''" and "zvec ♯* P''"
    by(force intro: tauChainFreshChain)+

  note PChain QeqP''
  moreover from P''Trans S ‹yvec ♯* Ψ› ‹zvec ♯* Ψ› ‹yvec ♯* P''› ‹zvec ♯* P''› have "Ψ ⊳ P'' ⟼(p ∙ M)⦇ν*xvec⦈⟨N⟩ ≺ P'"
    by(rule_tac outputPermSubject) (assumption | auto)
  ultimately show ?thesis by(rule weakTransitionI)
qed

lemma weakInputPermSubject:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   p    :: "name prm"
  and   yvec :: "name list"
  and   zvec :: "name list"

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇N⦈ ≺ P'"
  and     S: "set p ⊆ set yvec × set zvec"
  and     "yvec ♯* Ψ"
  and     "zvec ♯* Ψ"
  and     "yvec ♯* P"
  and     "zvec ♯* P"

  shows "Ψ : Q ⊳ P ⟹(p ∙ M)⦇N⦈ ≺ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ" 
                            and P''Trans: "Ψ ⊳ P'' ⟼M⦇N⦈ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹yvec ♯* P› ‹zvec ♯* P› have "yvec ♯* P''" and "zvec ♯* P''"
    by(force intro: tauChainFreshChain)+

  note PChain QeqP''
  moreover from P''Trans S ‹yvec ♯* Ψ› ‹zvec ♯* Ψ› ‹yvec ♯* P''› ‹zvec ♯* P''› have "Ψ ⊳ P'' ⟼(p ∙ M)⦇N⦈ ≺ P'"
    by(rule_tac inputPermSubject) auto
  ultimately show ?thesis by(rule weakTransitionI)
qed

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

  assumes "Ψ ⊢ M ↔ K"
  and     "distinct xvec" 
  and     "set xvec ⊆ supp N"
  and     "length xvec = length Tvec"
  and     QeqΨ: "insertAssertion (extractFrame Q) Ψ ↪F ⟨ε, Ψ ⊗ 𝟭⟩"

  shows "Ψ : Q ⊳ M⦇λ*xvec N⦈.P ⟹K⦇(N[xvec::=Tvec])⦈ ≺ P[xvec::=Tvec]"
proof -
  have "Ψ ⊳  M⦇λ*xvec N⦈.P ⟹^τ M⦇λ*xvec N⦈.P" by simp
  moreover from QeqΨ have "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame(M⦇λ*xvec N⦈.P)) Ψ"
    by auto
  moreover from assms have "Ψ ⊳ M⦇λ*xvec N⦈.P ⟼K⦇(N[xvec::=Tvec])⦈ ≺ P[xvec::=Tvec]"
    by(rule_tac Input)
  ultimately show ?thesis by(rule weakTransitionI)
qed

lemma weakOutput:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   K    :: 'a
  and   N    :: 'a
  and   P    :: "('a, 'b, 'c) psi"
  
  assumes "Ψ ⊢ M ↔ K"
  and     QeqΨ: "insertAssertion (extractFrame Q) Ψ ↪F ⟨ε, Ψ ⊗ 𝟭⟩"

  shows "Ψ : Q ⊳ M⟨N⟩.P ⟹K⟨N⟩ ≺ P"
proof -
  have "Ψ ⊳  M⟨N⟩.P ⟹^τ M⟨N⟩.P" by simp
  moreover from QeqΨ have "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame(M⟨N⟩.P)) Ψ"
    by auto
  moreover have "insertAssertion (extractFrame(M⟨N⟩.P)) Ψ ↪F insertAssertion (extractFrame(M⟨N⟩.P)) Ψ" by simp
  moreover from ‹Ψ ⊢ M ↔ K› have "Ψ ⊳ M⟨N⟩.P ⟼K⟨N⟩ ≺ P"
    by(rule Output)
  ultimately show ?thesis by(rule_tac weakTransitionI) auto
qed

lemma insertGuardedAssertion:
  fixes P :: "('a, 'b, 'c) psi"

  assumes "guarded P"

  shows "insertAssertion(extractFrame P) Ψ ≃F ⟨ε, Ψ ⊗ 𝟭⟩"
proof -
  obtain AP ΨP where FrP: "extractFrame P = ⟨AP, ΨP⟩" and "AP ♯* Ψ" by(rule freshFrame)
  from ‹guarded P› FrP have "ΨP ≃ 𝟭" and "supp ΨP = ({}::name set)"
    by(blast dest: guardedStatEq)+
  
  from FrP ‹AP ♯* Ψ› ‹ΨP ≃ 𝟭› have "insertAssertion(extractFrame P) Ψ ≃F ⟨AP, Ψ ⊗ 𝟭⟩"
    by simp (metis frameIntCompositionSym)
  moreover from ‹AP ♯* Ψ› have "⟨AP, Ψ ⊗ 𝟭⟩ ≃F ⟨ε, Ψ ⊗ 𝟭⟩"
    by(rule_tac frameResFreshChain) auto
  ultimately show ?thesis by(rule FrameStatEqTrans)
qed
  
lemma weakCase:
  fixes Ψ   :: 'b 
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   R    :: "('a, 'b, 'c) psi"

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and     "(φ, P) mem CsP"
  and     "Ψ ⊢ φ"
  and     "guarded P"
  and     RImpQ: "insertAssertion (extractFrame R) Ψ ↪F insertAssertion (extractFrame Q) Ψ"
  and     ImpR: "insertAssertion (extractFrame R) Ψ ↪F ⟨ε, Ψ⟩"

  shows "Ψ : R ⊳ Cases CsP ⟹α ≺ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''"
                           and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                           and P''Trans: "Ψ ⊳ P'' ⟼α ≺ P'"
    by(rule weakTransitionE)
  show ?thesis
  proof(case_tac "P = P''")
    assume "P = P''"
    have "Ψ ⊳ Cases CsP ⟹^τ Cases CsP" by simp
    moreover from ImpR AssertionStatEq_def have "insertAssertion(extractFrame R) Ψ ↪F insertAssertion(extractFrame(Cases CsP)) Ψ"
      by(rule_tac FrameStatImpTrans) (auto intro: Identity)+

    moreover from P''Trans ‹(φ, P) mem CsP› ‹Ψ ⊢ φ› ‹guarded P› ‹P = P''› have "Ψ ⊳ Cases CsP ⟼α ≺ P'"
      by(blast intro: Case)
    ultimately show ?thesis
      by(rule weakTransitionI)
  next
    assume "P ≠ P''"
    with PChain have "Ψ ⊳ P ⟹τ P''" by(simp add: rtrancl_eq_or_trancl)
    hence "Ψ ⊳ Cases CsP ⟹τ P''" using ‹(φ, P) mem CsP› ‹Ψ ⊢ φ› ‹guarded P› 
      by(rule tauStepChainCase)
    hence "Ψ ⊳ Cases CsP ⟹^τ P''" by simp
    moreover from RImpQ QeqP'' have "insertAssertion(extractFrame R) Ψ ↪F insertAssertion(extractFrame P'') Ψ"
      by(rule FrameStatImpTrans)
    ultimately show ?thesis using P''Trans by(rule weakTransitionI)
  qed
qed

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹M⦇ν*(xvec@yvec)⦈⟨N⟩ ≺ P'"
  and     "x ∈ supp N"
  and     "x ♯ Ψ"
  and     "x ♯ M"
  and     "x ♯ xvec"
  and     "x ♯ yvec"

  shows "Ψ : ⦇νx⦈Q ⊳ ⦇νx⦈P ⟹M⦇ν*(xvec@x#yvec)⦈⟨N⟩ ≺ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                           and P''Trans: "Ψ ⊳ P'' ⟼M⦇ν*(xvec@yvec)⦈⟨N⟩ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹x ♯ Ψ› have "Ψ ⊳ ⦇νx⦈P ⟹^τ ⦇νx⦈P''" by(rule tauChainResPres)
  moreover from QeqP'' ‹x ♯ Ψ› have "insertAssertion (extractFrame(⦇νx⦈Q)) Ψ ↪F insertAssertion (extractFrame(⦇νx⦈P'')) Ψ" by(force intro: frameImpResPres)
  moreover from P''Trans ‹x ∈ supp N› ‹x ♯ Ψ› ‹x ♯ M› ‹x ♯ xvec› ‹x ♯ yvec› have "Ψ ⊳ ⦇νx⦈P'' ⟼M⦇ν*(xvec@x#yvec)⦈⟨N⟩ ≺ P'"
    by(rule Open)
  ultimately show ?thesis by(rule weakTransitionI)
qed

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and     "x ♯ Ψ"
  and     "x ♯ α"

  shows "Ψ : ⦇νx⦈Q ⊳ ⦇νx⦈P ⟹α ≺ ⦇νx⦈P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''" and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                           and P''Trans: "Ψ ⊳ P'' ⟼α ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹x ♯ Ψ› have "Ψ ⊳ ⦇νx⦈P ⟹^τ ⦇νx⦈P''" by(rule tauChainResPres)
  moreover from QeqP'' ‹x ♯ Ψ› have "insertAssertion (extractFrame(⦇νx⦈Q)) Ψ ↪F insertAssertion (extractFrame(⦇νx⦈P'')) Ψ" by(force intro: frameImpResPres)
  moreover from P''Trans ‹x ♯ Ψ› ‹x ♯ α› have "Ψ ⊳ ⦇νx⦈P'' ⟼α ≺ ⦇νx⦈P'"
    by(rule Scope)
  ultimately show ?thesis by(rule weakTransitionI)
qed

lemma weakPar1:
  fixes Ψ   :: 'b
  and   R    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   Q    :: "('a, 'b, 'c) psi"
  and   AQ   :: "name list"
  and   ΨQ   :: 'b

  assumes PTrans: "Ψ ⊗ ΨQ : R ⊳ P ⟹α ≺ P'"
  and     FrQ: "extractFrame Q = ⟨AQ, ΨQ⟩"
  and     "bn α ♯* Q"
  and     "AQ ♯* Ψ"
  and     "AQ ♯* P"
  and     "AQ ♯* α"
  and     "AQ ♯* R"

  shows "Ψ : R ∥ Q ⊳ P ∥ Q ⟹α ≺ P' ∥ Q"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊗ ΨQ ⊳ P ⟹^τ P''"
                           and ReqP'': "insertAssertion (extractFrame R) (Ψ ⊗ ΨQ) ↪F insertAssertion (extractFrame P'') (Ψ ⊗ ΨQ)"
                           and P''Trans: "Ψ ⊗ ΨQ ⊳ P'' ⟼α ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹AQ ♯* P› have "AQ ♯* P''" by(rule tauChainFreshChain)
  from PChain FrQ ‹AQ ♯* Ψ› ‹AQ ♯* P› have "Ψ ⊳ P ∥ Q ⟹^τ P'' ∥ Q" by(rule tauChainPar1)
  moreover have "insertAssertion (extractFrame(R ∥ Q)) Ψ ↪F insertAssertion (extractFrame(P'' ∥ Q)) Ψ"
  proof -
    obtain AR ΨR where FrR: "extractFrame R = ⟨AR, ΨR⟩" and "AR ♯* AQ" and "AR ♯* ΨQ" and "AR ♯* Ψ"
      by(rule_tac C="(AQ, ΨQ, Ψ)" in freshFrame) auto
    obtain AP'' ΨP'' where FrP'': "extractFrame P'' = ⟨AP'', ΨP''⟩" and "AP'' ♯* AQ" and "AP'' ♯* ΨQ" and "AP'' ♯* Ψ"
      by(rule_tac C="(AQ, ΨQ, Ψ)" in freshFrame) auto

    from FrR FrP'' ‹AQ ♯* R› ‹AQ ♯* P''› ‹AR ♯* AQ› ‹AP'' ♯* AQ› have "AQ ♯* ΨR" and "AQ ♯* ΨP''"
      by(force dest: extractFrameFreshChain)+
    have "⟨AR, Ψ ⊗ ΨR ⊗ ΨQ⟩ ≃F ⟨AR, (Ψ ⊗ ΨQ) ⊗ ΨR⟩"
      by(metis frameNilStatEq frameResChainPres Associativity Commutativity Composition AssertionStatEqTrans)
    moreover from ReqP'' FrR FrP'' ‹AR ♯* Ψ› ‹AR ♯* ΨQ› ‹AP'' ♯* Ψ› ‹AP'' ♯* ΨQ›
    have "⟨AR, (Ψ ⊗ ΨQ) ⊗ ΨR⟩ ↪F ⟨AP'', (Ψ ⊗ ΨQ) ⊗ ΨP''⟩" using freshCompChain by auto
    moreover have "⟨AP'', (Ψ ⊗ ΨQ) ⊗ ΨP''⟩ ≃F ⟨AP'', Ψ ⊗ ΨP'' ⊗ ΨQ⟩"
      by(metis frameNilStatEq frameResChainPres Associativity Commutativity Composition AssertionStatEqTrans)
    ultimately have "⟨AR, Ψ ⊗ ΨR ⊗ ΨQ⟩ ↪F ⟨AP'', Ψ ⊗ ΨP'' ⊗ ΨQ⟩"
      by(force dest: FrameStatImpTrans simp add: FrameStatEq_def)

    hence "⟨(AR@AQ), Ψ ⊗ ΨR ⊗ ΨQ⟩ ↪F ⟨(AP''@AQ), Ψ ⊗ ΨP'' ⊗ ΨQ⟩"
      apply(simp add: frameChainAppend)
      apply(drule_tac xvec=AQ in frameImpResChainPres)
      by(metis frameImpChainComm FrameStatImpTrans)
    with FrR FrQ FrP'' ‹AR ♯* AQ› ‹AR ♯* ΨQ› ‹AQ ♯* ΨR› ‹AP'' ♯* AQ› ‹AP'' ♯* ΨQ› ‹AQ ♯* ΨP''› ‹AR ♯* Ψ› ‹AP'' ♯* Ψ› ‹AQ ♯* Ψ› ReqP''
    show ?thesis by simp
  qed
  moreover from P''Trans FrQ ‹bn α ♯* Q› ‹AQ ♯* Ψ› ‹AQ ♯* P''› ‹AQ ♯* α› have "Ψ ⊳ P'' ∥ Q ⟼α ≺ (P' ∥ Q)"
    by(rule Par1)  
  ultimately show ?thesis by(rule weakTransitionI)
qed

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

  assumes QTrans: "Ψ ⊗ ΨP : R ⊳ Q ⟹α ≺ Q'"
  and     FrP: "extractFrame P = ⟨AP, ΨP⟩"
  and     "bn α ♯* P"
  and     "AP ♯* Ψ"
  and     "AP ♯* Q"
  and     "AP ♯* α"
  and     "AP ♯* R"

  shows "Ψ : P ∥ R ⊳ P ∥ Q ⟹α ≺ P ∥ Q'"
proof -
  from QTrans obtain Q'' where QChain: "Ψ ⊗ ΨP ⊳ Q ⟹^τ Q''"
                           and ReqQ'': "insertAssertion (extractFrame R) (Ψ ⊗ ΨP) ↪F insertAssertion (extractFrame Q'') (Ψ ⊗ ΨP)"
                           and Q''Trans: "Ψ ⊗ ΨP ⊳ Q'' ⟼α ≺ Q'"
    by(rule weakTransitionE)

  from QChain ‹AP ♯* Q› have "AP ♯* Q''" by(rule tauChainFreshChain)

  from QChain FrP ‹AP ♯* Ψ› ‹AP ♯* Q› have "Ψ ⊳ P ∥ Q ⟹^τ P ∥ Q''" by(rule tauChainPar2)
  moreover have "insertAssertion (extractFrame(P ∥ R)) Ψ ↪F insertAssertion (extractFrame(P ∥ Q'')) Ψ"
  proof -
    obtain AR ΨR where FrR: "extractFrame R = ⟨AR, ΨR⟩" and "AR ♯* AP" and "AR ♯* ΨP" and "AR ♯* Ψ"
      by(rule_tac C="(AP, ΨP, Ψ)" in freshFrame) auto
    obtain AQ'' ΨQ'' where FrQ'': "extractFrame Q'' = ⟨AQ'', ΨQ''⟩" and "AQ'' ♯* AP" and "AQ'' ♯* ΨP" and "AQ'' ♯* Ψ"
      by(rule_tac C="(AP, ΨP, Ψ)" in freshFrame) auto

    from FrR FrQ'' ‹AP ♯* R› ‹AP ♯* Q''› ‹AR ♯* AP› ‹AQ'' ♯* AP› have "AP ♯* ΨR" and "AP ♯* ΨQ''"
      by(force dest: extractFrameFreshChain)+
    have "⟨AR, Ψ ⊗ ΨP ⊗ ΨR⟩ ≃F ⟨AR, (Ψ ⊗ ΨP) ⊗ ΨR⟩"
      by(metis frameNilStatEq frameResChainPres Associativity Commutativity Composition AssertionStatEqTrans)

    moreover from ReqQ'' FrR FrQ'' ‹AR ♯* Ψ› ‹AR ♯* ΨP› ‹AQ'' ♯* Ψ› ‹AQ'' ♯* ΨP›
    have "⟨AR, (Ψ ⊗ ΨP) ⊗ ΨR⟩ ↪F ⟨AQ'', (Ψ ⊗ ΨP) ⊗ ΨQ''⟩" using freshCompChain by simp
    moreover have "⟨AQ'', (Ψ ⊗ ΨP) ⊗ ΨQ''⟩ ≃F ⟨AQ'', Ψ ⊗ ΨP ⊗ ΨQ''⟩"
      by(metis frameNilStatEq frameResChainPres Associativity Commutativity Composition AssertionStatEqTrans)
    ultimately have "⟨AR, Ψ ⊗ ΨP ⊗ ΨR⟩ ↪F ⟨AQ'', Ψ ⊗ ΨP ⊗ ΨQ''⟩"
      by(force dest: FrameStatImpTrans simp add: FrameStatEq_def)
    hence "⟨(AP@AR), Ψ ⊗ ΨP ⊗ ΨR⟩ ↪F ⟨(AP@AQ''), Ψ ⊗ ΨP ⊗ ΨQ''⟩"
      apply(simp add: frameChainAppend)
      apply(drule_tac xvec=AP in frameImpResChainPres)
      by(metis frameImpChainComm FrameStatImpTrans)
    with FrR FrP FrQ'' ‹AR ♯* AP› ‹AR ♯* ΨP› ‹AP ♯* ΨR› ‹AQ'' ♯* AP› ‹AQ'' ♯* ΨP› ‹AP ♯* ΨQ''› ‹AR ♯* Ψ› ‹AQ'' ♯* Ψ› ‹AP ♯* Ψ› ReqQ''
    show ?thesis by simp
  qed
  moreover from Q''Trans FrP ‹bn α ♯* P› ‹AP ♯* Ψ› ‹AP ♯* Q''› ‹AP ♯* α› have "Ψ ⊳ P ∥ Q'' ⟼α ≺ (P ∥ Q')"
    by(rule_tac Par2) auto
  ultimately show ?thesis by(rule weakTransitionI)
qed

lemma weakComm1:
  fixes Ψ   :: 'b
  and   R    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   Q    :: "('a, 'b, 'c) psi"
  and   AQ   :: "name list"
  and   ΨQ   :: 'b

  assumes PTrans: "Ψ ⊗ ΨQ : R ⊳ P ⟹M⦇N⦈ ≺ P'"
  and     FrR: "extractFrame R = ⟨AR, ΨR⟩"
  and     QTrans: "Ψ ⊗ ΨR ⊳ Q ⟼K⦇ν*xvec⦈⟨N⟩ ≺ Q'"
  and     FrQ: "extractFrame Q = ⟨AQ, ΨQ⟩"
  and     MeqK: "Ψ ⊗ ΨR ⊗ ΨQ ⊢ M ↔ K"
  and     "AR ♯* Ψ"
  and     "AR ♯* P"
  and     "AR ♯* Q"
  and     "AR ♯* R"
  and     "AR ♯* M"
  and     "AR ♯* AQ"
  and     "AQ ♯* Ψ"
  and     "AQ ♯* P"
  and     "AQ ♯* Q"
  and     "AQ ♯* R"
  and     "AQ ♯* K"
  and     "xvec ♯* P"

  shows "Ψ ⊳ P ∥ Q ⟹τ (⦇ν*xvec⦈(P' ∥ Q'))"
proof -
  from ‹extractFrame Q = ⟨AQ, ΨQ⟩› ‹AQ ♯* Ψ› ‹AQ ♯* P› ‹AQ ♯* Q› ‹AQ ♯* R› ‹AQ ♯* K› ‹AR ♯* AQ›
  obtain AQ' where FrQ': "extractFrame Q = ⟨AQ', ΨQ⟩" and "distinct AQ'" and "AQ' ♯* Ψ" and "AQ' ♯* P" 
               and "AQ' ♯* Q" and "AQ' ♯* R" and "AQ' ♯* K" and "AR ♯* AQ'"
    by(rule_tac C="(Ψ, P, Q, R, K, AR)" in distinctFrame) auto

  from PTrans obtain P'' where PChain: "Ψ ⊗ ΨQ ⊳ P ⟹^τ P''"
                           and RimpP'': "insertAssertion (extractFrame R) (Ψ ⊗ ΨQ) ↪F insertAssertion (extractFrame P'') (Ψ ⊗ ΨQ)"
                           and P''Trans: "Ψ ⊗ ΨQ ⊳ P'' ⟼M⦇N⦈ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹AQ' ♯* P› have "AQ' ♯* P''" by(rule tauChainFreshChain)
  obtain AP'' ΨP'' where FrP'': "extractFrame P'' = ⟨AP'', ΨP''⟩" and "AP'' ♯* (Ψ, AQ', ΨQ, AR, ΨR, M, N, K, R, Q, P'', xvec)" and "distinct AP''"
    by(rule freshFrame)
  hence "AP'' ♯* Ψ" and "AP'' ♯* AQ'" and "AP'' ♯* ΨQ" and "AP'' ♯* M" and "AP'' ♯* R" and "AP'' ♯* Q"
    and "AP'' ♯* N" and "AP'' ♯* K" and "AP'' ♯* AR" and "AP'' ♯* P''" and "AP'' ♯* xvec" and "AP'' ♯* ΨR"
    by simp+
  from FrR ‹AR ♯* AQ'› ‹AQ' ♯* R› have "AQ' ♯* ΨR" by(drule_tac extractFrameFreshChain) auto
  from FrQ' ‹AR ♯* AQ'› ‹AR ♯* Q› have "AR ♯* ΨQ" by(drule_tac extractFrameFreshChain) auto
  from PChain ‹xvec ♯* P› have "xvec ♯* P''" by(force intro: tauChainFreshChain)+

  have "⟨AR, (Ψ ⊗ ΨR) ⊗ ΨQ⟩ ≃F ⟨AR, (Ψ ⊗ ΨQ) ⊗ ΨR⟩" 
    by(metis frameResChainPres frameNilStatEq Commutativity AssertionStatEqTrans Composition Associativity)
  moreover with RimpP'' FrP'' FrR ‹AP'' ♯* Ψ› ‹AR ♯* Ψ› ‹AP'' ♯* ΨQ› ‹AR ♯* ΨQ›
  have "⟨AR, (Ψ ⊗ ΨQ) ⊗ ΨR⟩ ↪F ⟨AP'', (Ψ ⊗ ΨQ) ⊗ ΨP''⟩" using freshCompChain
    by(simp add: freshChainSimps)
  moreover have "⟨AP'', (Ψ ⊗ ΨQ) ⊗ ΨP''⟩ ≃F ⟨AP'', (Ψ ⊗ ΨP'') ⊗ ΨQ⟩"
    by(metis frameResChainPres frameNilStatEq Commutativity AssertionStatEqTrans Composition Associativity)
  ultimately have RImpP'': "⟨AR, (Ψ ⊗ ΨR) ⊗ ΨQ⟩ ↪F ⟨AP'', (Ψ ⊗ ΨP'') ⊗ ΨQ⟩"
    by(rule FrameStatEqImpCompose)
      
  from PChain FrQ' ‹AQ' ♯* Ψ› ‹AQ' ♯* P› have "Ψ ⊳ P ∥ Q ⟹^τ P'' ∥ Q" by(rule tauChainPar1)
  moreover from QTrans FrR P''Trans MeqK RImpP'' FrP'' FrQ' ‹distinct AP''› ‹distinct AQ'› ‹AP'' ♯* AQ'› ‹AR ♯* AQ'›
        ‹AQ' ♯* Ψ› ‹AQ' ♯* P''› ‹AQ' ♯* Q› ‹AQ' ♯* R› ‹AQ' ♯* K› ‹AP'' ♯* Ψ› ‹AP'' ♯* R› ‹AP'' ♯* Q›
        ‹AP'' ♯* P''› ‹AP'' ♯* M› ‹AQ ♯* R› ‹AR ♯* Q› ‹AR ♯* M›
  obtain K' where "Ψ ⊗ ΨP'' ⊳ Q ⟼K'⦇ν*xvec⦈⟨N⟩ ≺ Q'" and "Ψ ⊗ ΨP'' ⊗ ΨQ ⊢ M ↔ K'" and "AQ' ♯* K'"
    by(rule_tac comm1Aux) (assumption | simp)+
  with P''Trans FrP'' have "Ψ ⊳ P'' ∥ Q ⟼τ ≺ ⦇ν*xvec⦈(P' ∥ Q')" using FrQ' ‹AQ' ♯* Ψ› ‹AQ' ♯* P''› ‹AQ' ♯* Q›
    ‹xvec ♯* P''› ‹AP'' ♯* Ψ› ‹AP'' ♯* P''› ‹AP'' ♯* Q› ‹AP'' ♯* M›  ‹AP'' ♯* AQ'›
    by(rule_tac Comm1)
  ultimately show ?thesis
    by(drule_tac tauActTauStepChain) auto
qed

lemma weakComm2:
  fixes Ψ   :: 'b
  and   R    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   Q    :: "('a, 'b, 'c) psi"
  and   AQ   :: "name list"
  and   ΨQ   :: 'b

  assumes PTrans: "Ψ ⊗ ΨQ : R ⊳ P ⟹M⦇ν*xvec⦈⟨N⟩ ≺ P'"
  and     FrR: "extractFrame R = ⟨AR, ΨR⟩"
  and     QTrans: "Ψ ⊗ ΨR ⊳ Q ⟼K⦇N⦈ ≺ Q'"
  and     FrQ: "extractFrame Q = ⟨AQ, ΨQ⟩"
  and     MeqK: "Ψ ⊗ ΨR ⊗ ΨQ ⊢ M ↔ K"
  and     "AR ♯* Ψ"
  and     "AR ♯* P"
  and     "AR ♯* Q"
  and     "AR ♯* R"
  and     "AR ♯* M"
  and     "AR ♯* AQ"
  and     "AQ ♯* Ψ"
  and     "AQ ♯* P"
  and     "AQ ♯* Q"
  and     "AQ ♯* R"
  and     "AQ ♯* K"
  and     "xvec ♯* Q"
  and     "xvec ♯* M"
  and     "xvec ♯* AQ"
  and     "xvec ♯* AR"

  shows "Ψ ⊳ P ∥ Q ⟹τ (⦇ν*xvec⦈(P' ∥ Q'))"
proof -
  from ‹extractFrame Q = ⟨AQ, ΨQ⟩› ‹AQ ♯* Ψ› ‹AQ ♯* P› ‹AQ ♯* Q› ‹AQ ♯* R› ‹AQ ♯* K› ‹AR ♯* AQ› ‹xvec ♯* AQ›
  obtain AQ' where FrQ': "extractFrame Q = ⟨AQ', ΨQ⟩" and "distinct AQ'" and "AQ' ♯* Ψ" and "AQ' ♯* P" 
               and "AQ' ♯* Q" and "AQ' ♯* R" and "AQ' ♯* K" and "AR ♯* AQ'" and "AQ' ♯* xvec"
    by(rule_tac C="(Ψ, P, Q, R, K, AR, xvec)" in distinctFrame) auto

  from PTrans obtain P'' where PChain: "Ψ ⊗ ΨQ ⊳ P ⟹^τ P''"
                           and RimpP'': "insertAssertion (extractFrame R) (Ψ ⊗ ΨQ) ↪F insertAssertion (extractFrame P'') (Ψ ⊗ ΨQ)"
                           and P''Trans: "Ψ ⊗ ΨQ ⊳ P'' ⟼M⦇ν*xvec⦈⟨N⟩ ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹AQ' ♯* P› have "AQ' ♯* P''" by(rule tauChainFreshChain)
  obtain AP'' ΨP'' where FrP'': "extractFrame P'' = ⟨AP'', ΨP''⟩" and "AP'' ♯* (Ψ, AQ', ΨQ, AR, ΨR, M, N, K, R, Q, P'', xvec)" and "distinct AP''"
    by(rule freshFrame)
  hence "AP'' ♯* Ψ" and "AP'' ♯* AQ'" and "AP'' ♯* ΨQ" and "AP'' ♯* M" and "AP'' ♯* R" and "AP'' ♯* Q"
    and "AP'' ♯* N" and "AP'' ♯* K" and "AP'' ♯* AR" and "AP'' ♯* P''" and "AP'' ♯* xvec" and "AP'' ♯* ΨR"
    by simp+
  from FrR ‹AR ♯* AQ'› ‹AQ' ♯* R› have "AQ' ♯* ΨR" by(drule_tac extractFrameFreshChain) auto
  from FrQ' ‹AR ♯* AQ'› ‹AR ♯* Q› have "AR ♯* ΨQ" by(drule_tac extractFrameFreshChain) auto

  have "⟨AR, (Ψ ⊗ ΨR) ⊗ ΨQ⟩ ≃F ⟨AR, (Ψ ⊗ ΨQ) ⊗ ΨR⟩" 
    by(metis frameResChainPres frameNilStatEq Commutativity AssertionStatEqTrans Composition Associativity)
  moreover with RimpP'' FrP'' FrR ‹AP'' ♯* Ψ› ‹AR ♯* Ψ› ‹AP'' ♯* ΨQ› ‹AR ♯* ΨQ›
  have "⟨AR, (Ψ ⊗ ΨQ) ⊗ ΨR⟩ ↪F ⟨AP'', (Ψ ⊗ ΨQ) ⊗ ΨP''⟩" using freshCompChain
    by(simp add: freshChainSimps)
  moreover have "⟨AP'', (Ψ ⊗ ΨQ) ⊗ ΨP''⟩ ≃F ⟨AP'', (Ψ ⊗ ΨP'') ⊗ ΨQ⟩"
    by(metis frameResChainPres frameNilStatEq Commutativity AssertionStatEqTrans Composition Associativity)
  ultimately have RImpP'': "⟨AR, (Ψ ⊗ ΨR) ⊗ ΨQ⟩ ↪F ⟨AP'', (Ψ ⊗ ΨP'') ⊗ ΨQ⟩"
    by(rule FrameStatEqImpCompose)
      
  from PChain FrQ' ‹AQ' ♯* Ψ› ‹AQ' ♯* P› have "Ψ ⊳ P ∥ Q ⟹^τ P'' ∥ Q" by(rule tauChainPar1)
  moreover from QTrans FrR P''Trans MeqK RImpP'' FrP'' FrQ' ‹distinct AP''› ‹distinct AQ'› ‹AP'' ♯* AQ'› ‹AR ♯* AQ'›
        ‹AQ' ♯* Ψ› ‹AQ' ♯* P''› ‹AQ' ♯* Q› ‹AQ' ♯* R› ‹AQ' ♯* K› ‹AP'' ♯* Ψ› ‹AP'' ♯* R› ‹AP'' ♯* Q›
        ‹AP'' ♯* P''› ‹AP'' ♯* M› ‹AQ ♯* R› ‹AR ♯* Q› ‹AR ♯* M› ‹xvec ♯* AR› ‹xvec ♯* M› ‹AQ' ♯* xvec›
  obtain K' where "Ψ ⊗ ΨP'' ⊳ Q ⟼K'⦇N⦈ ≺ Q'" and "Ψ ⊗ ΨP'' ⊗ ΨQ ⊢ M ↔ K'" and "AQ' ♯* K'"
    by(rule_tac comm2Aux) (assumption | simp)+
  with P''Trans FrP'' have "Ψ ⊳ P'' ∥ Q ⟼τ ≺ ⦇ν*xvec⦈(P' ∥ Q')" using FrQ' ‹AQ' ♯* Ψ› ‹AQ' ♯* P''› ‹AQ' ♯* Q›
    ‹xvec ♯* Q› ‹AP'' ♯* Ψ› ‹AP'' ♯* P''› ‹AP'' ♯* Q› ‹AP'' ♯* M›  ‹AP'' ♯* AQ'›
    by(rule_tac Comm2)
  ultimately show ?thesis
    by(drule_tac tauActTauStepChain) auto
qed

lemma frameImpIntComposition:
  fixes Ψ  :: 'b
  and   Ψ' :: 'b
  and   AF :: "name list"
  and   ΨF :: 'b

  assumes "Ψ ≃ Ψ'"

  shows "⟨AF, Ψ ⊗ ΨF⟩ ↪F ⟨AF, Ψ' ⊗ ΨF⟩"
proof -
  from assms have "⟨AF, Ψ ⊗ ΨF⟩ ≃F ⟨AF, Ψ' ⊗ ΨF⟩" by(rule frameIntComposition)
  thus ?thesis by(simp add: FrameStatEq_def)
qed

lemma insertAssertionStatImp:
  fixes F  :: "'b frame"
  and   Ψ  :: 'b
  and   G  :: "'b frame"
  and   Ψ' :: 'b

  assumes FeqG: "insertAssertion F Ψ ↪F insertAssertion G Ψ"
  and     "Ψ ≃ Ψ'"

  shows "insertAssertion F Ψ' ↪F insertAssertion G Ψ'"
proof -
  obtain AF ΨF where FrF: "F = ⟨AF, ΨF⟩" and "AF ♯* Ψ" and "AF ♯* Ψ'"
    by(rule_tac C="(Ψ, Ψ')" in freshFrame) auto
  obtain AG ΨG where FrG: "G = ⟨AG, ΨG⟩" and "AG ♯* Ψ" and "AG ♯* Ψ'"
    by(rule_tac C="(Ψ, Ψ')" in freshFrame) auto

  from ‹Ψ ≃ Ψ'› have "⟨AF, Ψ' ⊗ ΨF⟩ ≃F ⟨AF, Ψ ⊗ ΨF⟩" by (metis frameIntComposition FrameStatEqSym)
  moreover from ‹Ψ ≃ Ψ'› have "⟨AG, Ψ ⊗ ΨG⟩ ≃F ⟨AG, Ψ' ⊗ ΨG⟩" by(rule frameIntComposition)
  ultimately have "⟨AF, Ψ' ⊗ ΨF⟩ ↪F ⟨AG, Ψ' ⊗ ΨG⟩" using FeqG FrF FrG ‹AF ♯* Ψ› ‹AG ♯* Ψ› ‹Ψ ≃ Ψ'›
    by(force simp add: FrameStatEq_def dest: FrameStatImpTrans)
  with FrF FrG ‹AF ♯* Ψ'› ‹AG ♯* Ψ'› show ?thesis by simp
qed

lemma insertAssertionStatEq:
  fixes F  :: "'b frame"
  and   Ψ  :: 'b
  and   G  :: "'b frame"
  and   Ψ' :: 'b

  assumes FeqG: "insertAssertion F Ψ ≃F insertAssertion G Ψ"
  and     "Ψ ≃ Ψ'"

  shows "insertAssertion F Ψ' ≃F insertAssertion G Ψ'"
proof -
  obtain AF ΨF where FrF: "F = ⟨AF, ΨF⟩" and "AF ♯* Ψ" and "AF ♯* Ψ'"
    by(rule_tac C="(Ψ, Ψ')" in freshFrame) auto
  obtain AG ΨG where FrG: "G = ⟨AG, ΨG⟩" and "AG ♯* Ψ" and "AG ♯* Ψ'"
    by(rule_tac C="(Ψ, Ψ')" in freshFrame) auto

  from FeqG FrF FrG ‹AF ♯* Ψ› ‹AG ♯* Ψ› ‹Ψ ≃ Ψ'›
  have "⟨AF, Ψ' ⊗ ΨF⟩ ≃F ⟨AG, Ψ' ⊗ ΨG⟩"
    by simp (metis frameIntComposition FrameStatEqTrans FrameStatEqSym)
  with FrF FrG ‹AF ♯* Ψ'› ‹AG ♯* Ψ'› show ?thesis by simp
qed

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and     "Ψ ≃ Ψ'"

  shows "Ψ' : Q ⊳ P ⟹α ≺ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ⟹^τ P''"
                           and QeqP'': "insertAssertion (extractFrame Q) Ψ ↪F insertAssertion (extractFrame P'') Ψ"
                           and P''Trans: "Ψ ⊳ P'' ⟼α ≺ P'"
    by(rule weakTransitionE)

  from PChain ‹Ψ ≃ Ψ'› have "Ψ' ⊳ P ⟹^τ P''" by(rule tauChainStatEq)
  moreover from QeqP'' ‹Ψ ≃ Ψ'› have "insertAssertion (extractFrame Q) Ψ' ↪F insertAssertion (extractFrame P'') Ψ'"
    by(rule insertAssertionStatImp)
  moreover from P''Trans ‹Ψ ≃ Ψ'› have "Ψ' ⊳ P'' ⟼α ≺ P'"
    by(rule statEqTransition)
  ultimately show ?thesis by(rule weakTransitionI)
qed

lemma transitionWeakTransition:
  fixes Ψ   :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  
  assumes "Ψ ⊳ P ⟼α ≺ P'"
  and     "insertAssertion(extractFrame Q) Ψ ↪F insertAssertion(extractFrame P) Ψ"

  shows "Ψ : Q ⊳ P ⟹α ≺ P'"
using assms
by(fastforce intro: weakTransitionI)

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

  assumes PTrans: "Ψ : R ⊳ P ⟹α ≺ P'"
  and     "bn α ♯* Q"
  and     "guarded Q"

  shows "Ψ : (R ∥ Q) ⊳ P ∥ Q ⟹α ≺ P' ∥ Q"
proof -
  obtain AQ ΨQ where FrQ: "extractFrame Q = ⟨AQ, ΨQ⟩" and "AQ ♯* Ψ" and "AQ ♯* P" and "AQ ♯* α" and "AQ ♯* R"
    by(rule_tac C="(Ψ, P, α, R)" in freshFrame) auto
  from ‹guarded Q› FrQ have "ΨQ ≃ 𝟭" by(blast dest: guardedStatEq)
  with PTrans have "Ψ ⊗ ΨQ : R ⊳ P ⟹α ≺ P'" by(metis weakTransitionStatEq Identity AssertionStatEqSym compositionSym)
  thus ?thesis using FrQ ‹bn α ♯* Q› ‹AQ ♯* Ψ› ‹AQ ♯* P› ‹AQ ♯* α› ‹AQ ♯* R› 
    by(rule weakPar1)
qed

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

  assumes PTrans: "Ψ : R ⊳ P ∥ !P ⟹α ≺ P'"
  and     "guarded P"

  shows "Ψ : R ⊳ !P ⟹α ≺ P'"
proof -
  from PTrans obtain P'' where PChain: "Ψ ⊳ P ∥ !P ⟹^τ P''"
                           and RImpP'': "insertAssertion(extractFrame R) Ψ ↪F insertAssertion(extractFrame P'') Ψ"
                           and P''Trans: "Ψ ⊳ P'' ⟼α ≺ P'"
    by(rule weakTransitionE)
  moreover obtain AP ΨP where FrP: "extractFrame P = ⟨AP, ΨP⟩" and "AP ♯* Ψ" by(rule freshFrame)
  moreover from ‹guarded P› FrP have "ΨP ≃ 𝟭" by(blast dest: guardedStatEq)
  ultimately show ?thesis
  proof(auto simp add: rtrancl_eq_or_trancl)
    have "Ψ ⊳ !P ⟹^τ !P" by simp
    moreover assume RimpP: "insertAssertion(extractFrame R) Ψ ↪F ⟨AP, Ψ ⊗ ΨP ⊗ 𝟭⟩"
    have "insertAssertion(extractFrame R) Ψ ↪F insertAssertion(extractFrame(!P)) Ψ"
    proof -
      from ‹ΨP ≃ 𝟭› have "⟨AP, Ψ ⊗ ΨP ⊗ 𝟭⟩ ≃F ⟨AP, Ψ ⊗ 𝟭⟩"
        by(metis frameIntCompositionSym frameIntAssociativity frameIntCommutativity frameIntIdentity FrameStatEqTrans FrameStatEqSym)
      moreover from ‹AP ♯* Ψ› have "⟨AP, Ψ ⊗ 𝟭⟩ ≃F ⟨ε, Ψ ⊗ 𝟭⟩"
        by(force intro: frameResFreshChain)
      ultimately show ?thesis using RimpP by(auto simp add: FrameStatEq_def dest: FrameStatImpTrans)
    qed
    moreover assume "Ψ ⊳ P ∥ !P ⟼α ≺ P'"
    hence "Ψ ⊳ !P ⟼α ≺ P'" using ‹guarded P› by(rule Bang)
   ultimately show ?thesis by(rule weakTransitionI)
  next
    fix P'''
    assume "Ψ ⊳ P ∥ !P ⟹τ  P''"
    hence "Ψ ⊳ !P ⟹τ P''" using ‹guarded P› by(rule tauStepChainBang)
    hence "Ψ ⊳ !P ⟹^τ P''" by simp
    moreover assume "insertAssertion(extractFrame R) Ψ ↪F insertAssertion(extractFrame P'') Ψ"
                and "Ψ ⊳ P'' ⟼α ≺ P'"
    ultimately show ?thesis by(rule weakTransitionI)
  qed
qed

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and             "insertAssertion(extractFrame R) Ψ ↪F insertAssertion(extractFrame Q) Ψ"

  shows "Ψ : R ⊳ P ⟹α ≺ P'"
using assms
by(auto simp add: weakTransition_def intro: FrameStatImpTrans)

lemma guardedFrameStatEq:
  fixes P :: "('a, 'b, 'c) psi"

  assumes "guarded P"

  shows "extractFrame P ≃F ⟨ε, 𝟭⟩"
proof -
  obtain AP ΨP where FrP: "extractFrame P = ⟨AP, ΨP⟩" by(rule freshFrame)
  from ‹guarded P› FrP have "ΨP ≃ 𝟭" by(blast dest: guardedStatEq)
  hence "⟨AP, ΨP⟩ ≃F ⟨AP, 𝟭⟩" by(rule_tac frameResChainPres) auto
  moreover have "⟨AP, 𝟭⟩ ≃F ⟨ε, 𝟭⟩" by(rule_tac frameResFreshChain) auto
  ultimately show ?thesis using FrP by(force intro: FrameStatEqTrans)
qed

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

  assumes PTrans: "Ψ : Q ⊳ P ⟹α ≺ P'"
  and    "guarded Q"

  shows "Ψ : 𝟬 ⊳ P ⟹α ≺ P'"
proof -
  obtain AQ ΨQ where FrQ: "extractFrame Q = ⟨AQ, ΨQ⟩" and "AQ ♯* Ψ" by(rule freshFrame)
  moreover from ‹guarded Q› FrQ have "ΨQ ≃ 𝟭" by(blast dest: guardedStatEq)
  hence "⟨AQ, Ψ ⊗ ΨQ⟩ ≃F ⟨AQ, Ψ ⊗ 𝟭⟩" by(metis frameIntCompositionSym)
  moreover from ‹AQ ♯* Ψ› have "⟨AQ, Ψ ⊗ 𝟭⟩ ≃F ⟨ε, Ψ ⊗ 𝟭⟩" by(rule_tac frameResFreshChain) auto
  ultimately have "insertAssertion(extractFrame Q) Ψ ≃F insertAssertion (extractFrame (𝟬)) Ψ"
    using FrQ ‹AQ ♯* Ψ› by simp (blast intro: FrameStatEqTrans)
  with PTrans show ?thesis by(rule_tac weakTransitionFrameImp) (auto simp add: FrameStatEq_def) 
qed

lemma expandTauChainFrame:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  and   AP :: "name list"
  and   ΨP :: 'b
  and   C   :: "'d::fs_name"

  assumes PChain: "Ψ ⊳ P ⟹^τ P'"
  and     FrP: "extractFrame P = ⟨AP, ΨP⟩"
  and     "distinct AP"
  and     "AP ♯* P"
  and     "AP ♯* C"

  obtains Ψ' AP' ΨP' where "extractFrame P' = ⟨AP', ΨP'⟩" and "ΨP ⊗ Ψ' ≃ ΨP'" and "AP' ♯* P'" and "AP' ♯* C" and "distinct AP'"
using PChain FrP ‹AP ♯* P›
proof(induct arbitrary: thesis rule: tauChainInduct)
  case(TauBase P)
  have "ΨP ⊗ SBottom' ≃ ΨP" by(rule Identity)
  with ‹extractFrame P = ⟨AP, ΨP⟩› show ?case using ‹AP ♯* P› ‹AP ♯* C› ‹distinct AP› by(rule TauBase)
next
  case(TauStep P P' P'')
  from ‹extractFrame P = ⟨AP, ΨP⟩› ‹AP ♯* P›
  obtain Ψ' AP' ΨP' where FrP': "extractFrame P' = ⟨AP', ΨP'⟩" and "ΨP ⊗ Ψ' ≃ ΨP'"
                       and "AP' ♯* P'" and "AP' ♯* C" and "distinct AP'"
    by(rule_tac TauStep)
  from ‹Ψ ⊳ P' ⟼τ ≺ P''› FrP' ‹distinct AP'› ‹AP' ♯* P'› ‹AP' ♯* C›
  obtain Ψ'' AP'' ΨP'' where FrP'': "extractFrame P'' = ⟨AP'', ΨP''⟩" and "ΨP' ⊗ Ψ'' ≃ ΨP''"
                          and "AP'' ♯* P''" and "AP'' ♯* C" and "distinct AP''"
    by(rule expandTauFrame)
  from ‹ΨP ⊗ Ψ' ≃ ΨP'› have "(ΨP ⊗ Ψ') ⊗ Ψ'' ≃ ΨP' ⊗ Ψ''" by(rule Composition)
  with ‹ΨP' ⊗ Ψ'' ≃ ΨP''› have "ΨP ⊗ Ψ' ⊗ Ψ'' ≃ ΨP''"
    by(metis AssertionStatEqTrans Associativity Commutativity)
  with FrP'' show ?case using ‹AP'' ♯* P''› ‹AP'' ♯* C› ‹distinct AP''›
    by(rule TauStep)
qed

lemma frameIntImpComposition:
  fixes Ψ  :: 'b
  and   Ψ' :: 'b
  and   AF :: "name list"
  and   ΨF :: 'b

  assumes "Ψ ≃ Ψ'"

  shows "⟨AF, Ψ ⊗ ΨF⟩ ↪F ⟨AF, Ψ' ⊗ ΨF⟩"
using assms frameIntComposition
by(simp add: FrameStatEq_def)

lemma tauChainInduct2[consumes 1, case_names TauBase TauStep]:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"

  assumes PChain: "Ψ ⊳ P ⟹^τ P'"
  and     cBase: "⋀P. Prop P P"
  and     cStep: "⋀P P' P''. ⟦Ψ ⊳ P' ⟼τ ≺ P''; Ψ ⊳ P ⟹^τ P'; Prop P P'⟧ ⟹ Prop P P''"

  shows "Prop P P'"
using assms
by(rule tauChainInduct)

lemma tauStepChainInduct2[consumes 1, case_names TauBase TauStep]:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"

  assumes PChain: "Ψ ⊳ P ⟹τ P'"
  and     cBase: "⋀P P'. Ψ ⊳ P ⟼τ ≺ P' ⟹ Prop P P'"
  and     cStep: "⋀P P' P''. ⟦Ψ ⊳ P' ⟼τ ≺ P''; Ψ ⊳ P ⟹τ P'; Prop P P'⟧ ⟹ Prop P P''"

  shows "Prop P P'"
using assms
by(rule tauStepChainInduct)

lemma weakTransferTauChainFrame:
  fixes ΨF :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  and   AP :: "name list"
  and   ΨP :: 'b
  and   AF :: "name list"
  and   AG :: "name list"
  and   ΨG :: 'b

  assumes PChain: "ΨF ⊳ P ⟹^τ P'"
  and     FrP: "extractFrame P = ⟨AP, ΨP⟩"
  and     "distinct AP"
  and     FeqG: "⋀Ψ. insertAssertion (⟨AF, ΨF ⊗ ΨP⟩) Ψ ↪F insertAssertion (⟨AG, ΨG ⊗ ΨP⟩) Ψ"
  and     "AF ♯* ΨG"
  and     "AG ♯* Ψ"
  and     "AG ♯* ΨF"
  and     "AF ♯* AG"
  and     "AF ♯* P"
  and     "AG ♯* P"
  and     "AP ♯* AF"
  and     "AP ♯* AG"
  and     "AP ♯* ΨF"
  and     "AP ♯* ΨG"
  and     "AP ♯* P"

  shows "ΨG ⊳ P ⟹^τ P'"
using PChain FrP ‹AF ♯* P› ‹AG ♯* P› ‹AP ♯* P› 
proof(induct rule: tauChainInduct2)
  case TauBase
  thus ?case by simp
next
  case(TauStep P P' P'')
  have FrP: "extractFrame P = ⟨AP, ΨP⟩" by fact
  then have PChain: "ΨG ⊳ P ⟹^τ P'" using ‹AF ♯* P› ‹AG ♯* P› ‹AP ♯* P› by(rule TauStep)
  then obtain AP' ΨP' Ψ' where FrP': "extractFrame P' = ⟨AP', ΨP'⟩" and "ΨP ⊗ Ψ' ≃ ΨP'"
                            and "AP' ♯* AF" and "AP' ♯* AG" and "AP' ♯* ΨF" and "AP' ♯* ΨG"
                            and "distinct AP'"
                
    using FrP ‹distinct AP› ‹AP ♯* P› ‹AP ♯* AF› ‹AP ♯* AG› ‹AP ♯* ΨF› ‹AP ♯* ΨG›
    by(rule_tac C="(AF, AG, ΨF, ΨG)" in expandTauChainFrame) auto

  from PChain ‹AF ♯* P› ‹AG ♯* P› have "AF ♯* P'" and "AG ♯* P'" by(blast dest: tauChainFreshChain)+

  with ‹AF ♯* P› ‹AG ♯* P› ‹AP ♯* AF› ‹AP ♯* AG›‹AP' ♯* AF› ‹AP' ♯* AG› FrP FrP'
  have "AF ♯* ΨP" and "AG ♯* ΨP" and "AF ♯* ΨP'" and "AG ♯* ΨP'"
    by(auto dest: extractFrameFreshChain)

  from FeqG have FeqG: "insertAssertion (⟨AF, ΨF ⊗ ΨP⟩) Ψ' ↪F insertAssertion (⟨AG, ΨG ⊗ ΨP⟩) Ψ'"
    by blast
  obtain p::"name prm" where "(p ∙ AF) ♯* ΨF" and  "(p ∙ AF) ♯* ΨP" and "(p ∙ AF) ♯* ΨP'" and "(p ∙ AF) ♯* Ψ'"
                         and Sp: "(set p) ⊆ set AF × set(p ∙ AF)" and "distinctPerm p"
      by(rule_tac xvec=AF and c="(ΨF, ΨP, Ψ', ΨP')" in name_list_avoiding) auto
  obtain q::"name prm" where "(q ∙ AG) ♯* ΨG" and  "(q ∙ AG) ♯* ΨP" and "(q ∙ AG) ♯* ΨP'" and "(q ∙ AG) ♯* Ψ'"
                         and Sq: "(set q) ⊆ set AG × set(q ∙ AG)" and "distinctPerm q"
    by(rule_tac xvec=AG and c="(ΨG, ΨP, Ψ', ΨP')" in name_list_avoiding) auto
  from ‹ΨP ⊗ Ψ' ≃ ΨP'› have "⟨(p ∙ AF), ((p ∙ ΨF) ⊗ ΨP')⟩ ≃F ⟨(p ∙ AF), (p ∙ ΨF) ⊗ (ΨP ⊗ Ψ')⟩"
    by(rule frameIntCompositionSym[OF AssertionStatEqSym])
  hence "⟨(p ∙ AF), (p ∙ ΨF) ⊗ ΨP'⟩ ≃F ⟨(p ∙ AF), Ψ' ⊗ ((p ∙ ΨF) ⊗ ΨP)⟩"
    by(metis frameIntAssociativity FrameStatEqTrans frameIntCommutativity FrameStatEqSym)
  moreover from FeqG ‹AF ♯* ΨP› ‹(p ∙ AF) ♯* ΨP› ‹(p ∙ AF) ♯* ΨF› ‹(p ∙ AF) ♯* Ψ'› Sp
  have "⟨(p ∙ AF), Ψ' ⊗ ((p ∙ ΨF) ⊗ ΨP)⟩ ↪F insertAssertion (⟨AG, ΨG ⊗ ΨP⟩) Ψ'"
    apply(erule_tac rev_mp) by(subst frameChainAlpha) (auto simp add: eqvts)
  hence "⟨(p ∙ AF), Ψ' ⊗ ((p ∙ ΨF) ⊗ ΨP)⟩ ↪F  (⟨(q ∙ AG), Ψ' ⊗ (q ∙ ΨG) ⊗ ΨP⟩)"
    using ‹AG ♯* ΨP› ‹(q ∙ AG) ♯* ΨP› ‹(q ∙ AG) ♯* ΨG› ‹(q ∙ AG) ♯* Ψ'› Sq
    apply(erule_tac rev_mp) by(subst frameChainAlpha) (auto simp add: eqvts)
  moreover have "⟨(q ∙ AG), Ψ' ⊗ ((q ∙ ΨG) ⊗ ΨP)⟩ ≃F ⟨(q ∙ AG), (q ∙ ΨG) ⊗ (ΨP ⊗ Ψ')⟩"
    by(metis frameIntAssociativity FrameStatEqTrans frameIntCommutativity FrameStatEqSym)
  hence "⟨(q ∙ AG), Ψ' ⊗ ((q ∙ ΨG) ⊗ ΨP)⟩ ≃F ⟨(q ∙ AG), (q ∙ ΨG) ⊗ ΨP'⟩" using ‹ΨP ⊗ Ψ' ≃ ΨP'›
    by(blast intro: FrameStatEqTrans frameIntCompositionSym)
  ultimately have "⟨(p ∙ AF), (p ∙ ΨF) ⊗ ΨP'⟩ ↪F ⟨(q ∙ AG), (q ∙ ΨG) ⊗ ΨP'⟩"
    by(rule FrameStatEqImpCompose)
  with ‹AF ♯* ΨP'› ‹(p ∙ AF) ♯* ΨP'› ‹(p ∙ AF) ♯* ΨF› Sp have "⟨AF, ΨF ⊗ ΨP'⟩ ↪F ⟨(q ∙ AG), (q ∙ ΨG) ⊗ ΨP'⟩"
    by(subst frameChainAlpha) (auto simp add: eqvts)
  with ‹AG ♯* ΨP'› ‹(q ∙ AG) ♯* ΨP'› ‹(q ∙ AG) ♯* ΨG› Sq have "⟨AF, ΨF ⊗ ΨP'⟩ ↪F ⟨AG, ΨG ⊗ ΨP'⟩"
    by(subst frameChainAlpha) (auto simp add: eqvts)
  
  with ‹ΨF ⊳ P' ⟼τ ≺ P''› FrP' ‹distinct AP'›
       ‹AF ♯* P'› ‹AG ♯* P'› ‹AF ♯* ΨG› ‹AG ♯* ΨF› ‹AP' ♯* AF› ‹AP' ♯* AG› ‹AP' ♯* ΨF› ‹AP' ♯* ΨG›
  have "ΨG ⊳ P' ⟼τ ≺ P''" by(rule_tac transferTauFrame)
  with PChain show ?case by(simp add: r_into_rtrancl rtrancl_into_rtrancl)
qed

coinductive quiet :: "('a, 'b, 'c) psi ⇒ bool"
  where "⟦∀Ψ. (insertAssertion (extractFrame P) Ψ ≃F ⟨ε, Ψ⟩ ∧ 
              (∀Rs. Ψ ⊳ P ⟼ Rs ⟶ (∃P'. Rs = τ ≺ P' ∧ quiet P')))⟧ ⟹ quiet P"

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

  assumes "quiet P"

  shows "insertAssertion (extractFrame P) Ψ ≃F ⟨ε, Ψ⟩"
using assms
by(erule_tac quiet.cases) force
  
lemma quietTransition:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   Rs :: "('a, 'b, 'c) residual"

  assumes "quiet P"
  and     "Ψ ⊳ P ⟼ Rs"

  obtains P' where "Rs = τ ≺ P'" and "quiet P'"
using assms
by(erule_tac quiet.cases) force
  
lemma quietEqvt:
  fixes P :: "('a, 'b, 'c) psi"
  and   p :: "name prm"

  assumes "quiet P"

  shows "quiet(p ∙ P)"
proof -
  let ?X = "λP. ∃p::name prm. quiet(p ∙ P)"
  from assms have "?X (p ∙ P)" by(rule_tac x="rev p" in exI) auto
  thus ?thesis
    apply coinduct
    apply(clarify)
    apply(rule_tac x=x in exI)
    apply auto
    apply(drule_tac Ψ="p ∙ Ψ" in quietFrame)
    apply(drule_tac p="rev p" in FrameStatEqClosed)
    apply(simp add: eqvts)
    apply(drule_tac pi=p in semantics.eqvt)
    apply(erule_tac quietTransition)
    apply assumption
    apply(rule_tac x="rev p ∙ P'" in exI)
    apply auto
    apply(drule_tac pi="rev p" in pt_bij3)
    apply(simp add: eqvts)
    apply(rule_tac x=p in exI)
    by simp
qed
  

lemma quietOutput:
  fixes Ψ   :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   xvec :: "name list"
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  
  assumes "Ψ ⊳ P ⟼M⦇ν*xvec⦈⟨N⟩ ≺ P'"
  and     "quiet P"

  shows False
using assms
apply(erule_tac quiet.cases)
by(force simp add: residualInject)

lemma quietInput:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   M  :: 'a
  and   N  :: 'a
  and   P' :: "('a, 'b, 'c) psi"
  
  assumes "Ψ ⊳ P ⟼M⦇N⦈ ≺ P'"
  and     "quiet P"

  shows False
using assms
by(erule_tac quiet.cases) (force simp add: residualInject)

lemma quietTau:
  fixes Ψ :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"
  
  assumes "Ψ ⊳ P ⟼τ ≺ P'"
  and     "insertAssertion (extractFrame P) Ψ ≃F ⟨ε, Ψ⟩"
  and     "quiet P"

  shows "quiet P'"
using assms
by(erule_tac quiet.cases) (force simp add: residualInject)

lemma tauChainCases[consumes 1, case_names TauBase TauStep]:
  fixes Ψ  :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   P' :: "('a, 'b, 'c) psi"

  assumes "Ψ ⊳ P ⟹^τ P'"
  and     "P = P' ⟹ Prop"
  and     "Ψ ⊳ P ⟹τ P' ⟹ Prop"

  shows Prop
using assms
by(blast elim: rtranclE dest: rtrancl_into_trancl1)

end

end