Theory Semantics

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

nominal_datatype ('a, 'b, 'c) boundOutput = 
  BOut "'a::fs_name" "('a, 'b::fs_name, 'c::fs_name) psi" (‹_ ≺'' _› [110, 110] 110)
| BStep "«name» ('a, 'b, 'c) boundOutput"                (⦇ν__› [110, 110] 110)

primrec BOresChain :: "name list  ('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput  
                      ('a, 'b, 'c) boundOutput" where
  Base: "BOresChain [] B = B"
| Step: "BOresChain (x#xs) B = ⦇νx(BOresChain xs B)"

abbreviation
  BOresChainJudge (⦇ν*__› [80, 80] 80) where "⦇ν*xvecB  BOresChain xvec B"

lemma BOresChainEqvt[eqvt]:
  fixes perm :: "name prm"
  and   lst  :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  
  shows "perm  (⦇ν*xvecB) = ⦇ν*(perm  xvec)(perm  B)"
by(induct_tac xvec, auto)

lemma BOresChainSimps[simp]:
  fixes xvec :: "name list"
  and   N    :: "'a::fs_name"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   N'   :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   B    :: "('a, 'b, 'c) boundOutput"
  and   B'    :: "('a, 'b, 'c) boundOutput"

  shows "(⦇ν*xvecN ≺' P = N' ≺' P') = (xvec = []  N = N'  P = P')"
  and   "(N' ≺' P' = ⦇ν*xvecN ≺' P) = (xvec = []  N = N'  P = P')"
  and   "(N' ≺' P' = N ≺' P) = (N = N'  P = P')"
  and   "(⦇ν*xvecB = ⦇ν*xvecB') = (B = B')"
by(induct xvec) (auto simp add: boundOutput.inject alpha)

lemma outputFresh[simp]:
  fixes Xs   :: "name set"
  and   xvec :: "name list"
  and   N    :: "'a::fs_name"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"

  shows "(Xs ♯* (N ≺' P)) = ((Xs ♯* N)  (Xs ♯* P))"
  and   "(xvec ♯* (N ≺' P)) = ((xvec ♯* N)  (xvec ♯* P))"
by(auto simp add: fresh_star_def)

lemma boundOutputFresh: 
  fixes x    :: name
  and   xvec :: "name list"
  and   B   :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"

  shows "(x  (⦇ν*xvecB)) = (x  set xvec  x  B)"
by (induct xvec) (simp_all add: abs_fresh)

lemma boundOutputFreshSet: 
  fixes Xs   :: "name set"
  and   xvec :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   yvec :: "name list"
  and   x    :: name

  shows "Xs ♯* (⦇ν*xvecB) = (xXs. x  set xvec  x  B)"
  and   "yvec ♯* (⦇ν*xvecB) = (x(set yvec). x  set xvec  x  B)"
  and   "Xs ♯* (⦇νxB) = Xs ♯* [x].B"
  and   "xvec ♯* (⦇νxB) = xvec ♯* [x].B"
by(simp add: fresh_star_def boundOutputFresh)+

lemma BOresChainSupp:
  fixes xvec :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"

  shows "(supp(⦇ν*xvecB)::name set) = (supp B) - (supp xvec)" 
by(induct xvec)
  (auto simp add: boundOutput.supp supp_list_nil supp_list_cons abs_supp supp_atm)

lemma boundOutputFreshSimps[simp]:
  fixes Xs   :: "name set"
  and   xvec :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   yvec :: "name list"
  and   x    :: name

  shows "Xs ♯* xvec  (Xs ♯* (⦇ν*xvecB)) = (Xs ♯* B)"
  and   "yvec ♯* xvec  yvec ♯* (⦇ν*xvecB) = yvec ♯* B"
  and   "xvec ♯* (⦇ν*xvecB)"
  and   "x  xvec  x  ⦇ν*xvecB = x  B"
apply(simp add: boundOutputFreshSet) apply(force simp add: fresh_star_def name_list_supp fresh_def)
apply(simp add: boundOutputFreshSet) apply(force simp add: fresh_star_def name_list_supp fresh_def)
apply(simp add: boundOutputFreshSet)  
by(simp add: BOresChainSupp fresh_def)

lemma boundOutputChainAlpha:
  fixes p    :: "name prm"
  and   xvec :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   yvec :: "name list"

  assumes xvecFreshB: "(p  xvec) ♯* B"
  and     S: "set p  set xvec × set (p  xvec)"
  and     "(set xvec)  (set yvec)"

  shows "(⦇ν*yvecB) = (⦇ν*(p  yvec)(p  B))"
proof -
  note pt_name_inst at_name_inst S
  moreover from (set xvec)  (set yvec) have "set xvec ♯* (⦇ν*yvecB)"
    by(force simp add: boundOutputFreshSet)
  moreover from xvecFreshB (set xvec)  (set yvec) have "set (p  xvec) ♯* (⦇ν*yvecB)"
    by (simp add: boundOutputFreshSet) (simp add: fresh_star_def)
  ultimately have "(⦇ν*yvecB) = p  (⦇ν*yvecB)"
    by (rule_tac pt_freshs_freshs [symmetric])
  then show ?thesis by(simp add: eqvts)
qed

lemma boundOutputChainAlpha':
  fixes p    :: "name prm"
  and   xvec :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   yvec :: "name list"
  and   zvec :: "name list"

  assumes xvecFreshB: "xvec ♯* B"
  and     S: "set p  set xvec × set yvec"
  and     "yvec ♯* (⦇ν*zvecB)"

  shows "(⦇ν*zvecB) = (⦇ν*(p  zvec)(p  B))"
proof -
  note pt_name_inst at_name_inst S yvec ♯* (⦇ν*zvecB)
  moreover from xvecFreshB have "set (xvec) ♯* (⦇ν*zvecB)"
    by (simp add: boundOutputFreshSet) (simp add: fresh_star_def)
  ultimately have "(⦇ν*zvecB) = p  (⦇ν*zvecB)"
    by (rule_tac pt_freshs_freshs [symmetric]) auto
  then show ?thesis by(simp add: eqvts)
qed

lemma boundOutputChainAlpha'':
  fixes p    :: "name prm"
  and   xvec :: "name list"
  and   M    :: "'a::fs_name"
  and   P    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) psi"
  and   yvec :: "name list"

  assumes "(p  xvec) ♯* M"
  and     "(p  xvec) ♯* P"
  and      "set p  set xvec × set (p  xvec)"
  and     "(set xvec)  (set yvec)"

  shows "(⦇ν*yvecM ≺' P) = (⦇ν*(p  yvec)(p  M) ≺' (p  P))"
using assms
by(subst boundOutputChainAlpha) auto

lemma boundOutputChainSwap:
  fixes x    :: name
  and   y    :: name
  and   N    :: "'a::fs_name"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   xvec :: "name list"

  assumes "y  N"
  and     "y  P"
  and     "x  (set xvec)"

  shows "⦇ν*xvecN ≺' P = ⦇ν*([(x, y)]  xvec)([(x ,y)]  N) ≺' ([(x, y)]  P)"
proof(case_tac "x=y")
  assume "x=y"
  thus ?thesis by simp
next
  assume "x  y"
  with assms show ?thesis
    by(rule_tac xvec="[x]" in boundOutputChainAlpha'') (auto simp add: calc_atm)
qed

lemma alphaBoundOutput:
  fixes x  :: name
  and   y  :: name
  and   B  :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"

  assumes "y  B"

  shows "⦇νxB = ⦇νy([(x, y)]  B)"
using assms
by(auto simp add: boundOutput.inject alpha fresh_left calc_atm)

lemma boundOutputEqFresh:
  fixes B :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   C :: "('a, 'b, 'c) boundOutput"
  and   x :: name
  and   y :: name

  assumes "⦇νxB = ⦇νyC"
  and     "x  B"
  
  shows "y  C"
using assms
by(auto simp add: boundOutput.inject alpha fresh_left calc_atm)  

lemma boundOutputEqSupp:
  fixes B :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   C :: "('a, 'b, 'c) boundOutput"
  and   x :: name
  and   y :: name

  assumes "⦇νxB = ⦇νyC"
  and     "x  supp B"
  
  shows "y  supp C"
using assms
apply(auto simp add: boundOutput.inject alpha fresh_left calc_atm)
apply(drule_tac pi="[(x, y)]" in pt_set_bij2[OF pt_name_inst, OF at_name_inst])
by(simp add: eqvts calc_atm)

lemma boundOutputChainEq:
  fixes xvec :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   yvec :: "name list"
  and   B'   :: "('a, 'b, 'c) boundOutput"

  assumes "⦇ν*xvecB = ⦇ν*yvecB'"
  and     "xvec ♯* yvec"
  and     "length xvec = length yvec"

  shows "p. (set p)  (set xvec) × set (yvec)  distinctPerm p   B = p  B'  (set (map fst p))  (supp B)  xvec ♯* B'  yvec ♯* B"
proof -
  obtain n where "n = length xvec" by auto
  with assms show ?thesis
  proof(induct n arbitrary: xvec yvec B B')
    case(0 xvec yvec B B')
    have Eq: "⦇ν*xvecB = ⦇ν*yvecB'" by fact
    from 0 = length xvec have "xvec = []" by auto
    moreover with length xvec = length yvec have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case using Eq
      by(simp add: boundOutput.inject)
  next
    case(Suc n xvec yvec B B')
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecB = ⦇ν*yvecB' xvec = x # xvec' length xvec = length yvec
    obtain y yvec' where "⦇ν*(x#xvec')B = ⦇ν*(y#yvec')B'"
      and "yvec = y#yvec'" and "length xvec' = length yvec'"
      by(case_tac yvec) auto
    hence EQ: "⦇νx(⦇ν*xvec'B) = ⦇νy(⦇ν*yvec'B')"
      by simp
    from xvec = x#xvec' yvec=y#yvec' xvec ♯* yvec
    have "x  y" and "xvec' ♯* yvec'" and "x  yvec'" and "y  xvec'"
      by auto
    have IH: "xvec yvec B B'. ⦇ν*xvec(B::('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput) = ⦇ν*yvecB'; xvec ♯* yvec; length xvec = length yvec; n = length xvec  p. (set p)  (set xvec) × (set yvec)  distinctPerm p   B = p  B'  set(map fst p)  supp B  xvec ♯* B'  yvec ♯* B"
      by fact
    from EQ x  y have EQ': "⦇ν*xvec'B = ([(x, y)]  (⦇ν*yvec'B'))" 
                     and xFreshB': "x  (⦇ν*yvec'B')"
                     and yFreshB: "y  (⦇ν*xvec'B)"
      by(metis boundOutput.inject alpha)+
    from xFreshB' x  yvec' have "x  B'"
      by(auto simp add: boundOutputFresh) (simp add: fresh_def name_list_supp)+
    from yFreshB y  xvec' have "y  B"
      by(auto simp add: boundOutputFresh) (simp add: fresh_def name_list_supp)+
    show ?case
    proof(case_tac "x  ⦇ν*xvec'B")
      assume xFreshB: "x  ⦇ν*xvec'B"
      with EQ have yFreshB': "y  ⦇ν*yvec'B'"
        by(rule boundOutputEqFresh)
      with xFreshB' EQ' have "⦇ν*xvec'B = ⦇ν*yvec'B'" 
        by(simp)
      with xvec' ♯* yvec' length xvec' = length yvec' length xvec' = n IH
      obtain p where S: "(set p)  (set xvec') × (set yvec')" and "distinctPerm p" and "B = p  B'"
                 and "set(map fst p)  supp B" and "xvec' ♯* B'"  and "yvec' ♯* B"
        by blast
      from S have "(set p)  set(x#xvec') × set(y#yvec')" by auto
      moreover note xvec = x#xvec' yvec=y#yvec' distinctPerm p B = p  B'
                    xvec' ♯* B' x  B' x  B' yvec' ♯* B y  B set(map fst p)  supp B

      ultimately show ?case by auto
    next
      assume "¬(x  ⦇ν*xvec'B)"
      hence xSuppB: "x  supp(⦇ν*xvec'B)"
        by(simp add: fresh_def)
      with EQ have ySuppB': "y  supp (⦇ν*yvec'B')"
        by(rule boundOutputEqSupp)
      hence "y  yvec'"
        by(induct yvec') (auto simp add: boundOutput.supp abs_supp)      
      with x  yvec' EQ' have "⦇ν*xvec'B = ⦇ν*yvec'([(x, y)]  B')"
        by(simp add: eqvts)
      with  xvec' ♯* yvec' length xvec' = length yvec' length xvec' = n IH
      obtain p where S: "(set p)  (set xvec') × (set yvec')" and "distinctPerm p" and "B = p  [(x, y)]  B'"
                 and "set(map fst p)  supp B" and "xvec' ♯* ([(x, y)]  B')" and "yvec' ♯* B" 
        by blast

      from xSuppB have "x  xvec'"
        by(induct xvec') (auto simp add: boundOutput.supp abs_supp)      
      with x  yvec' y  xvec' y  yvec' S have "x  p" and "y  p"
        apply(induct p)
        by(auto simp add: name_list_supp) (auto simp add: fresh_def) 
      from S have "(set ((x, y)#p))  (set(x#xvec')) × (set(y#yvec'))"
        by force
      moreover from x  y x  p y  p S distinctPerm p
      have "distinctPerm((x,y)#p)" by simp
      moreover from B = p  [(x, y)]  B' x  p y  p have "B = [(x, y)]  p  B'"
        by(subst perm_compose) simp
      hence "B = ((x, y)#p)  B'" by simp
      moreover from xvec' ♯* ([(x, y)]  B') have "([(x, y)]  xvec') ♯* ([(x, y)]  [(x, y)]  B')"
        by(simp only: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with x  xvec' y  xvec' x  B' have "(x#xvec') ♯* B'" by simp
      moreover from y  B yvec' ♯* B have "(y#yvec') ♯* B" by simp
      moreover from set(map fst p)  supp B xSuppB x  xvec'
      have "set(map fst ((x, y)#p))  supp B"
        by(simp add: BOresChainSupp)
      ultimately show ?case using xvec=x#xvec' yvec=y#yvec'
        by metis
    qed
  qed
qed

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' Q"

  shows "length xvec = length yvec"
proof -
  obtain n where "n = length xvec" by auto
  with assms show ?thesis
  proof(induct n arbitrary: xvec yvec M P N Q)
    case(0 xvec yvec M P N Q)
    from 0 = length xvec have "xvec = []" by auto
    moreover with ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' Q have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case by simp
  next
    case(Suc n xvec yvec M P N Q)
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' Q xvec = x # xvec'
    obtain y yvec' where "⦇ν*(x#xvec')M ≺' P = ⦇ν*(y#yvec')N ≺' Q"
      and "yvec = y#yvec'"
      by(case_tac yvec) auto
    hence EQ: "⦇νx(⦇ν*xvec'M ≺' P) = ⦇νy(⦇ν*yvec'N ≺' Q)"
      by simp
    have IH: "xvec yvec M P N Q. ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q::('a, 'b, 'c) psi); n = length xvec  length xvec = length yvec"
      by fact
    show ?case
    proof(case_tac "x = y")
      assume "x = y"
      with EQ have "⦇ν*xvec'M ≺' P  = ⦇ν*yvec'N ≺' Q"
        by(simp add: alpha boundOutput.inject)
      with IH length xvec' = n have "length xvec' = length yvec'"
        by blast
      with xvec = x#xvec' yvec=y#yvec'
      show ?case by simp
    next
      assume "x  y"
      with EQ have "⦇ν*xvec'M ≺' P = [(x, y)]  ⦇ν*yvec'N ≺' Q"
        by(simp add: alpha boundOutput.inject)
      hence "⦇ν*xvec'M ≺' P = ⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ([(x, y)]  Q)"
        by(simp add: eqvts)
      with IH length xvec' = n have "length xvec' = length ([(x, y)]  yvec')"
        by blast
      hence "length xvec' = length yvec'"
        by simp
      with xvec = x#xvec' yvec=y#yvec'
      show ?case by simp
    qed
  qed
qed

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' Q"
  and     "xvec ♯* yvec"

  shows "p. (set p)  (set xvec) × set (yvec)  distinctPerm p   M = p  N   P = p  Q  xvec ♯* N  xvec ♯* Q  yvec ♯* M  yvec ♯* P"
using assms
apply(frule_tac boundOutputChainEqLength)
apply(drule_tac boundOutputChainEq)
by(auto simp add: boundOutput.inject)

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' Q"
  and     "xvec ♯* yvec"
  and     "distinct xvec"
  and     "distinct yvec"

  obtains p where "(set p)  (set xvec) × set (p  xvec)" and "distinctPerm p" and "yvec = p  xvec" and "N = p  M" and "Q = p  P" and "xvec ♯* N" and "xvec ♯* Q" and "(p  xvec) ♯* M" and "(p  xvec) ♯* P"
proof -

  assume "p. set p  set xvec × set (p  xvec); distinctPerm p; yvec = p  xvec; N = p  M; Q = p  P; xvec ♯* N; xvec ♯* Q; (p  xvec) ♯* M; (p  xvec) ♯* P  thesis"

  moreover obtain n where "n = length xvec" by auto
  with assms have "p. (set p)  (set xvec) × set (yvec)  distinctPerm p   yvec = p  xvec  N = p  M  Q = p  P  xvec ♯* N  xvec ♯* Q  (p  xvec) ♯* M  (p  xvec) ♯* P"
  proof(induct n arbitrary: xvec yvec M P N Q)
    case(0 xvec yvec M P N Q)
    have Eq: "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' Q" by fact
    from 0 = length xvec have "xvec = []" by auto
    moreover with Eq have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case using Eq
      by(simp add: boundOutput.inject)
  next
    case(Suc n xvec yvec M P N Q)
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' Q xvec = x # xvec'
    obtain y yvec' where "⦇ν*(x#xvec')M ≺' P = ⦇ν*(y#yvec')N ≺' Q"
      and "yvec = y#yvec'"
      by(case_tac yvec) auto
    hence EQ: "⦇νx(⦇ν*xvec'M ≺' P) = ⦇νy(⦇ν*yvec'N ≺' Q)"
      by simp
    from xvec = x#xvec' yvec=y#yvec' xvec ♯* yvec
    have "x  y" and "xvec' ♯* yvec'" and "x  yvec'" and "y  xvec'"
      by auto
    from distinct xvec distinct yvec xvec=x#xvec' yvec=y#yvec' have "x  xvec'" and "y  yvec'" and "distinct xvec'" and "distinct yvec'"
      by simp+
    have IH: "xvec yvec M P N Q. ⦇ν*xvec(M::'a) ≺' (P::('a, 'b, 'c) psi) = ⦇ν*yvecN ≺' Q; xvec ♯* yvec; distinct xvec; distinct yvec; n = length xvec  p. (set p)  (set xvec) × (set yvec)  distinctPerm p   yvec = p  xvec  N = p  M  Q = p  P  xvec ♯* N  xvec ♯* Q  (p  xvec) ♯* M  (p  xvec) ♯* P"
      by fact 
    from EQ x  y  x  yvec' y  yvec' y  xvec' x  xvec' have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'([(x, y)]  N) ≺' ([(x, y)]  Q)" and "x  N" and "x  Q" and "y  M" and "y  P"
      apply -
      apply(simp add: boundOutput.inject alpha eqvts)
      apply(simp add: boundOutput.inject alpha eqvts)
      apply(simp add: boundOutput.inject alpha eqvts)
      by(simp add: boundOutput.inject alpha' eqvts)+
    with xvec' ♯* yvec' distinct xvec' distinct yvec' length xvec' = n IH
    obtain p where S: "(set p)  (set xvec') × (set yvec')" and "distinctPerm p" and "yvec' = p  xvec'" and "([(x, y)]  N) = p  M" and "([(x, y)]  Q) = p  P" and "xvec' ♯* ([(x, y)]  N)" and "xvec' ♯* ([(x, y)]  Q)" and "yvec' ♯* M" and "yvec' ♯* P"
      by metis
    from S have "set((x, y)#p)  set(x#xvec') × set(y#yvec')" by auto
    moreover from x  xvec' x  yvec' y  xvec' y  yvec' S have "x  p" and "y  p"
      apply(induct p)
      by(auto simp add: fresh_prod name_list_supp) (auto simp add: fresh_def) 

    with S distinctPerm p x  y have "distinctPerm((x, y)#p)" by auto
    moreover from yvec' = p  xvec' x  p y  p x  xvec' y  xvec' have "(y#yvec') = ((x, y)#p)  (x#xvec')"
      by(simp add: eqvts calc_atm perm_compose freshChainSimps)
    moreover from ([(x, y)]  N) = p  M
    have "([(x, y)]  [(x, y)]  N) = [(x, y)]  p  M"
      by(simp add: pt_bij)
    hence "N = ((x, y)#p)  M" by simp
    moreover from ([(x, y)]  Q) = p  P
    have "([(x, y)]  [(x, y)]  Q) = [(x, y)]  p  P"
      by(simp add: pt_bij)
    hence "Q = ((x, y)#p)  P" by simp
    moreover from xvec' ♯* ([(x, y)]  N) have "([(x, y)]  xvec') ♯* ([(x, y)]  [(x, y)]  N)"
      by(subst fresh_star_bij)
    with x  xvec' y  xvec' have "xvec' ♯* N" by simp
    with x  N have "(x#xvec') ♯* N" by simp
    moreover from xvec' ♯* ([(x, y)]  Q) have "([(x, y)]  xvec') ♯* ([(x, y)]  [(x, y)]  Q)"
      by(subst fresh_star_bij)
    with x  xvec' y  xvec' have "xvec' ♯* Q" by simp
    with x  Q have "(x#xvec') ♯* Q" by simp
    moreover from y  M yvec' ♯* M have "(y#yvec') ♯* M" by simp
    moreover from y  P yvec' ♯* P have "(y#yvec') ♯* P" by simp
    ultimately show ?case using xvec=x#xvec' yvec=y#yvec'
      by metis
  qed
  ultimately show ?thesis by blast
qed

lemma boundOutputEqSupp':
  fixes x    :: name
  and   xvec :: "name list"
  and   M    :: "'a::fs_name"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   y    :: name
  and   yvec :: "name list"
  and   N    :: 'a
  and   Q    :: "('a, 'b, 'c) psi"

  assumes Eq: "⦇νx(⦇ν*xvecM ≺' P) = ⦇νy(⦇ν*yvecN ≺' Q)"
  and     "x  y"
  and     "x  yvec"
  and     "x  xvec"
  and     "y  xvec"
  and     "y  yvec"
  and     "xvec ♯* yvec"
  and     "x  supp M"
  
  shows "y  supp N"
proof -
  from Eq x  y x  yvec y  yvec have "⦇ν*xvecM ≺' P = ⦇ν*yvec([(x, y)]  N) ≺' ([(x, y)]  Q)"
    by(simp add: boundOutput.inject alpha eqvts)
  then obtain p where S: "set p  set xvec × set yvec" and "M = p  [(x, y)]  N" and "distinctPerm p" using xvec ♯* yvec
    by(blast dest: boundOutputChainEq')
  with x  supp M have "x  supp(p  [(x, y)]  N)" by simp
  hence "(p  x)  p  supp(p  [(x, y)]  N)"
    by(simp add: pt_set_bij[OF pt_name_inst, OF at_name_inst])
  with x  xvec x  yvec S distinctPerm p have "x  supp([(x, y)]  N)"
    by(simp add: eqvts)
  hence "([(x, y)]  x)  ([(x, y)]  (supp([(x, y)]  N)))"
    by(simp add: pt_set_bij[OF pt_name_inst, OF at_name_inst])
  with x  y show ?thesis by(simp add: calc_atm eqvts)
qed

lemma boundOutputChainOpenIH:
  fixes xvec :: "name list"
  and   x    :: name
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"
  and   yvec :: "name list"
  and   y    :: name
  and   B'   :: "('a, 'b, 'c) boundOutput"

  assumes Eq: "⦇ν*xvec(⦇νxB) = ⦇ν*yvec(⦇νyB')"
  and     L: "length xvec = length yvec"
  and     xFreshB': "x  B'"
  and     xFreshxvec: "x  xvec"
  and     xFreshyvec: "x  yvec"

  shows "⦇ν*xvecB = ⦇ν*yvec([(x, y)]  B')"
using assms
proof(induct n=="length xvec" arbitrary: xvec yvec y B' rule: nat.induct)
  case(zero xvec yvec y B')
  have "0 = length xvec" and "length xvec = length yvec" by fact+
  moreover have "⦇ν*xvec⦇νxB = ⦇ν*yvec⦇νyB'" by fact
  ultimately show ?case by(auto simp add: boundOutput.inject alpha)
next
  case(Suc n xvec yvec y B')
  have L: "length xvec = length yvec" and "Suc n = length xvec" by fact+
  then obtain x' xvec' y' yvec' where xEq: "xvec = x'#xvec'" and yEq: "yvec = y'#yvec'"
                                  and L': "length xvec' = length yvec'"
    by(cases xvec, auto, cases yvec, auto)
  have xFreshB': "x  B'" by fact
  have "x  xvec" and "x  yvec" by fact+
  with xEq yEq have xineqx': "x  x'" and xFreshxvec': "x  xvec'"
                and xineqy': "x  y'" and xFreshyvec': "x  yvec'"
    by simp+
  have "⦇ν*xvec⦇νxB = ⦇ν*yvec⦇νyB'" by fact
  with xEq yEq have Eq: "⦇νx'(⦇ν*xvec'⦇νxB) = ⦇νy'(⦇ν*yvec'⦇νyB')" by simp
  have "Suc n = length xvec" by fact
  with xEq have L'': "n = length xvec'" by simp
  have "⦇νx'(⦇ν*xvec'B) = ⦇νy'(⦇ν*yvec'([(x, y)]  B'))"
  proof(case_tac "x'=y'")
    assume x'eqy': "x' = y'"
    with Eq have "⦇ν*xvec'⦇νxB = ⦇ν*yvec'⦇νyB'" by(simp add: boundOutput.inject alpha)
    hence "⦇ν*xvec'B = ⦇ν*yvec'([(x, y)]  B')" using L' xFreshB' xFreshxvec' xFreshyvec' L'' 
      by(rule_tac Suc)
    with x'eqy' show ?thesis by(simp add: boundOutput.inject alpha)
  next
    assume x'ineqy': "x'  y'"
    with Eq have Eq': "⦇ν*xvec'⦇νxB = ⦇ν*([(x', y')]  yvec')⦇ν([(x', y')]  y)([(x', y')]  B')"
             and x'FreshB': "x'  ⦇ν*yvec'⦇νyB'"
      by(simp add: boundOutput.inject alpha eqvts)+
    from L' have "length xvec' = length ([(x', y')]  yvec')" by simp
    moreover from xineqx' xineqy' xFreshB' have "x  [(x', y')]  B'" by(simp add: fresh_left calc_atm)
    moreover from xineqx' xineqy' xFreshyvec' have "x  [(x', y')]  yvec'" by(simp add: fresh_left calc_atm)
    ultimately have "⦇ν*xvec'B = ⦇ν*([(x', y')]  yvec')([(x, ([(x', y')]  y))]  [(x', y')]  B')" using Eq' xFreshxvec' L''
      by(rule_tac Suc)
    moreover from x'FreshB' have "x'  ⦇ν*yvec'([(x, y)]  B')"
    proof(case_tac "x'  yvec'")
      assume "x'  yvec'"
      with x'FreshB' have x'FreshB': "x'  ⦇νyB'"
        by(simp add: fresh_def BOresChainSupp)
      show ?thesis
      proof(case_tac "x'=y")
        assume x'eqy: "x' = y"
        show ?thesis
        proof(case_tac "x=y")
          assume "x=y"
          with xFreshB' x'eqy show ?thesis by(simp add: BOresChainSupp fresh_def)
        next
          assume "x  y"
          with x  B' have "y  [(x, y)]  B'" by(simp add: fresh_left calc_atm)
          with x'eqy show ?thesis by(simp add: BOresChainSupp fresh_def)
        qed
      next
        assume x'ineqy: "x'  y"
        with x'FreshB' have "x'  B'" by(simp add: abs_fresh)
        with xineqx' x'ineqy have "x'  ([(x, y)]  B')" by(simp add: fresh_left calc_atm)
        thus ?thesis by(simp add: BOresChainSupp fresh_def)
      qed
    next
      assume "¬x'  yvec'"
      thus ?thesis by(simp add: BOresChainSupp fresh_def)
    qed
    ultimately show ?thesis using x'ineqy' xineqx' xineqy'
      apply(simp add: boundOutput.inject alpha eqvts)
      apply(subst perm_compose[of "[(x', y')]"])
      by(simp add: calc_atm)
  qed
  with xEq yEq show ?case by simp
qed

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)"
  and     "xvec ♯* R"
  and     "yvec ♯* R"

  obtains T where "P = T  R" and "⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' Q"
proof -
  assume "T. P = T  R; ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' Q  thesis"
  moreover obtain n where "n = length xvec" by auto
  with assms have "T. P = T  R  ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' Q"
  proof(induct n arbitrary: xvec yvec M N P Q R)
    case(0 xvec yvec M N P Q R)
    have Eq: "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)" by fact
    from 0 = length xvec have "xvec = []" by auto
    moreover with Eq have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case using Eq
      by(simp add: boundOutput.inject)
  next
    case(Suc n xvec yvec M N P Q R)
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R) xvec = x # xvec'
    obtain y yvec' where "⦇ν*(x#xvec')M ≺' P = ⦇ν*(y#yvec')N ≺' (Q  R)"
      and "yvec = y#yvec'"
      by(case_tac yvec) auto
    hence EQ: "⦇νx(⦇ν*xvec'M ≺' P) = ⦇νy(⦇ν*yvec'N ≺' (Q  R))"
      by simp
    from xvec ♯* R yvec ♯* R xvec = x#xvec' yvec = y#yvec'
    have "x  R" and "xvec' ♯* R" and "y  R" and "yvec' ♯* R" by auto
    show ?case
    proof(case_tac "x = y")
      assume "x = y"
      with EQ have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'N ≺' (Q  R)"
        by(simp add: boundOutput.inject alpha)
      with xvec' ♯* R yvec' ♯* R length xvec' = n
      obtain T where "P = T  R" and "⦇ν*xvec'M ≺' T = ⦇ν*yvec'N ≺' Q"
        by(drule_tac Suc) auto
      with xvec=x#xvec' yvec=y#yvec' x=y show ?case
        by(force simp add: boundOutput.inject alpha)
    next
      assume "x  y"
      with EQ x  R y  R
      have "⦇ν*xvec'M ≺' P = ⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' (([(x, y)]  Q)  R)"
       and xFreshQR: "x  ⦇ν*yvec'N ≺' (Q  R)"
        by(simp add: boundOutput.inject alpha eqvts)+
      moreover from yvec' ♯* R have "([(x, y)]  yvec') ♯* ([(x, y)]  R)"
        by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with x  R y  R have "([(x, y)]  yvec') ♯* R" by simp
      moreover note xvec' ♯* R length xvec' = n
      ultimately obtain T where "P = T  R" and A: "⦇ν*xvec'M ≺' T = ⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ([(x, y)]  Q)"
        by(drule_tac Suc) auto

      from A have "⦇νx(⦇ν*xvec'M ≺' T) = ⦇νx(⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ([(x, y)]  Q))"
        by(simp add: boundOutput.inject alpha)
      moreover from xFreshQR have "x  ⦇ν*yvec'N ≺' Q"
        by(force simp add: boundOutputFresh)
      ultimately show ?thesis using P = T  R xvec=x#xvec' yvec=y#yvec' xFreshQR
        by(force simp add: alphaBoundOutput name_swap eqvts)
    qed
  qed
  ultimately show ?thesis
    by blast
qed

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)"
  and     "xvec ♯* yvec"

  obtains T p where "set p  set xvec × set yvec" and "P = T  (p  R)" and "⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' Q"
proof -
  assume "p T. set p  set xvec × set yvec; P = T  (p  R); ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' Q  thesis"
  moreover obtain n where "n = length xvec" by auto
  with assms have "p T. set p  set xvec × set yvec  P = T  (p  R)  ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' Q"
  proof(induct n arbitrary: xvec yvec M N P Q R)
    case(0 xvec yvec M N P Q R)
    have Eq: "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)" by fact
    from 0 = length xvec have "xvec = []" by auto
    moreover with Eq have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case using Eq
      by(simp add: boundOutput.inject)
  next
    case(Suc n xvec yvec M N P Q R)
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R) xvec = x # xvec'
    obtain y yvec' where "⦇ν*(x#xvec')M ≺' P = ⦇ν*(y#yvec')N ≺' (Q  R)"
      and "yvec = y#yvec'"
      by(case_tac yvec) auto
    hence Eq: "⦇νx(⦇ν*xvec'M ≺' P) = ⦇νy(⦇ν*yvec'N ≺' (Q  R))"
      by simp
    from xvec = x#xvec' yvec=y#yvec' xvec ♯* yvec have "x  y" and "x  yvec'" and "y  xvec'" and "xvec' ♯* yvec'"
      by auto
    from Eq x  y have Eq': "⦇ν*xvec'M ≺' P = [(x, y)]  ⦇ν*yvec'N ≺' (Q  R)"
                     and xFreshQR: "x  ⦇ν*yvec'N ≺' (Q  R)"
      by(simp add: boundOutput.inject alpha)+
    have IH: "xvec yvec M N P Q R. ⦇ν*xvecM ≺' (P::('a, 'b, 'c) psi) = ⦇ν*yvecN ≺' (Q  R);  xvec ♯* yvec; n = length xvec  p T. set p  set xvec × set yvec  P = T  (p  R)  ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' Q"
      by fact
    show ?case
    proof(case_tac "x  ⦇ν*xvec'M ≺' P")
      assume "x  ⦇ν*xvec'M ≺' P"
      with Eq have yFreshQR: "y  ⦇ν*yvec'N ≺' (Q  R)"
        by(rule boundOutputEqFresh)
      with Eq' xFreshQR have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'N ≺' (Q  R)"
        by simp
      with xvec' ♯* yvec' length xvec' = n
      obtain p T where S: "set p  set xvec' × set yvec'" and "P = T  (p  R)" and A: "⦇ν*xvec'M ≺' T = ⦇ν*yvec'N ≺' Q"
        by(drule_tac IH) auto
      from yFreshQR xFreshQR have yFreshQ: "y  ⦇ν*yvec'N ≺' Q" and xFreshQ: "x  ⦇ν*yvec'N ≺' Q" 
        by(force simp add: BOresChainSupp fresh_def boundOutput.supp psi.supp)+
      hence "⦇νx(⦇ν*yvec'N ≺' Q) = ⦇νy(⦇ν*yvec'N ≺' Q)" by (subst alphaBoundOutput) simp+
      with A have "⦇νx(⦇ν*xvec'M ≺' T) = ⦇νy(⦇ν*yvec'N ≺' Q)" by simp
      with xvec=x#xvec' yvec=y#yvec' S P = T  (p  R) show ?case
        by auto
    next
      assume "¬(x  ⦇ν*xvec'M ≺' P)"
      hence "x  supp(⦇ν*xvec'M ≺' P)" by(simp add: fresh_def)
      with Eq have "y  supp(⦇ν*yvec'N ≺' (Q  R))"
        by(rule boundOutputEqSupp)
      hence "y  yvec'" by(simp add: BOresChainSupp fresh_def)
      with Eq' x  yvec' have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'([(x, y)]  N) ≺' (([(x, y)]  Q)  ([(x, y)]  R))"
        by(simp add: eqvts)
      moreover note xvec' ♯* yvec' length xvec' = n
      ultimately obtain p T where S: "set p  set xvec' × set yvec'" and "P = T  (p  [(x, y)]  R)" and A: "⦇ν*xvec'M ≺' T = ⦇ν*yvec'([(x, y)]  N) ≺' ([(x, y)]  Q)"
        by(drule_tac IH) auto

      from S have "set(p@[(x, y)])  set(x#xvec') × set(y#yvec')" by auto
      moreover from P = T  (p  [(x, y)]  R)  have "P = T  ((p @ [(x, y)])  R)"
        by(simp add: pt2[OF pt_name_inst])
      moreover from xFreshQR have xFreshQ: "x  ⦇ν*yvec'N ≺' Q" 
        by(force simp add: BOresChainSupp fresh_def boundOutput.supp psi.supp)+
      with x  yvec' y  yvec' x  y have "y  ⦇ν*yvec'([(x, y)]  N) ≺' ([(x, y)]  Q)"
        by(simp add: fresh_left calc_atm)
      with x  yvec' y  yvec' have "⦇νx(⦇ν*yvec'([(x, y)]  N) ≺' ([(x, y)]  Q)) = ⦇νy(⦇ν*yvec'N ≺' Q)"
        by(subst alphaBoundOutput) (assumption | simp add: eqvts)+
      with  A have "⦇νx(⦇ν*xvec'M ≺' T) = ⦇νy(⦇ν*yvec'N ≺' Q)" by simp
      ultimately show ?thesis using xvec=x#xvec' yvec=y#yvec'
        by(rule_tac x="p@[(x, y)]" in exI) force
    qed
  qed
  ultimately show ?thesis
    by blast
qed

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)"
  and     "xvec ♯* Q"
  and     "yvec ♯* Q"

  obtains T where "P = Q  T" and "⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R"
proof -
  assume "T. P = Q  T; ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R  thesis"
  moreover obtain n where "n = length xvec" by auto
  with assms have "T. P = Q  T  ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R"
  proof(induct n arbitrary: xvec yvec M N P Q R)
    case(0 xvec yvec M N P Q R)
    have Eq: "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)" by fact
    from 0 = length xvec have "xvec = []" by auto
    moreover with Eq have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case using Eq
      by(simp add: boundOutput.inject)
  next
    case(Suc n xvec yvec M N P Q R)
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R) xvec = x # xvec'
    obtain y yvec' where "⦇ν*(x#xvec')M ≺' P = ⦇ν*(y#yvec')N ≺' (Q  R)"
      and "yvec = y#yvec'"
      by(case_tac yvec) auto
    hence EQ: "⦇νx(⦇ν*xvec'M ≺' P) = ⦇νy(⦇ν*yvec'N ≺' (Q  R))"
      by simp
    from xvec ♯* Q yvec ♯* Q xvec = x#xvec' yvec = y#yvec'
    have "x  Q" and "xvec' ♯* Q" and "y  Q" and "yvec' ♯* Q" by auto
    have IH: "xvec yvec M N P Q R. ⦇ν*xvecM ≺' (P::('a, 'b, 'c) psi) = ⦇ν*yvecN ≺' (Q  R); xvec ♯* Q; yvec ♯* Q; n = length xvec  T. P = Q  T  ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R"
      by fact
    show ?case
    proof(case_tac "x = y")
      assume "x = y"
      with EQ have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'N ≺' (Q  R)"
        by(simp add: boundOutput.inject alpha)
      with xvec' ♯* Q yvec' ♯* Q length xvec' = n
      obtain T where "P = Q  T" and "⦇ν*xvec'M ≺' T = ⦇ν*yvec'N ≺' R"
        by(drule_tac IH) auto
      with xvec=x#xvec' yvec=y#yvec' x=y show ?case
        by(force simp add: boundOutput.inject alpha)
    next
      assume "x  y"
      with EQ x  Q y  Q
      have "⦇ν*xvec'M ≺' P = ⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' (Q  ([(x, y)]  R))"
       and xFreshQR: "x  ⦇ν*yvec'N ≺' (Q  R)"
        by(simp add: boundOutput.inject alpha eqvts)+
      moreover from yvec' ♯* Q have "([(x, y)]  yvec') ♯* ([(x, y)]  Q)"
        by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
      with x  Q y  Q have "([(x, y)]  yvec') ♯* Q" by simp
      moreover note xvec' ♯* Q length xvec' = n
      ultimately obtain T where "P = Q  T" and A: "⦇ν*xvec'M ≺' T = ⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ([(x, y)]  R)"
        by(drule_tac IH) auto

      from A have "⦇νx(⦇ν*xvec'M ≺' T) = ⦇νx(⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ([(x, y)]  R))"
        by(simp add: boundOutput.inject alpha)
      moreover from xFreshQR have "x  ⦇ν*yvec'N ≺' R"
        by(force simp add: boundOutputFresh)
      ultimately show ?thesis using P = Q  T xvec=x#xvec' yvec=y#yvec' xFreshQR
        by(force simp add: alphaBoundOutput name_swap eqvts)
    qed
  qed
  ultimately show ?thesis
    by blast
qed

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)"
  and     "xvec ♯* yvec"

  obtains T p where "set p  set xvec × set yvec" and "P = (p  Q)  T" and "⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R"
proof -
  assume "p T. set p  set xvec × set yvec; P = (p  Q)  T; ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R  thesis"
  moreover obtain n where "n = length xvec" by auto
  with assms have "p T. set p  set xvec × set yvec  P = (p  Q)  T  ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R"
  proof(induct n arbitrary: xvec yvec M N P Q R)
    case(0 xvec yvec M N P Q R)
    have Eq: "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R)" by fact
    from 0 = length xvec have "xvec = []" by auto
    moreover with Eq have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case using Eq
      by(simp add: boundOutput.inject)
  next
    case(Suc n xvec yvec M N P Q R)
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (Q  R) xvec = x # xvec'
    obtain y yvec' where "⦇ν*(x#xvec')M ≺' P = ⦇ν*(y#yvec')N ≺' (Q  R)"
      and "yvec = y#yvec'"
      by(case_tac yvec) auto
    hence Eq: "⦇νx(⦇ν*xvec'M ≺' P) = ⦇νy(⦇ν*yvec'N ≺' (Q  R))"
      by simp
    from xvec = x#xvec' yvec=y#yvec' xvec ♯* yvec have "x  y" and "x  yvec'" and "y  xvec'" and "xvec' ♯* yvec'"
      by auto
    from Eq x  y have Eq': "⦇ν*xvec'M ≺' P = [(x, y)]  ⦇ν*yvec'N ≺' (Q  R)"
                     and xFreshQR: "x  ⦇ν*yvec'N ≺' (Q  R)"
      by(simp add: boundOutput.inject alpha)+
    have IH: "xvec yvec M N P Q R. ⦇ν*xvecM ≺' (P::('a, 'b, 'c) psi) = ⦇ν*yvecN ≺' (Q  R);  xvec ♯* yvec; n = length xvec  p T. set p  set xvec × set yvec  P = (p  Q)  T  ⦇ν*xvecM ≺' T = ⦇ν*yvecN ≺' R"
      by fact
    show ?case
    proof(case_tac "x  ⦇ν*xvec'M ≺' P")
      assume "x  ⦇ν*xvec'M ≺' P"
      with Eq have yFreshQR: "y  ⦇ν*yvec'N ≺' (Q  R)"
        by(rule boundOutputEqFresh)
      with Eq' xFreshQR have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'N ≺' (Q  R)"
        by simp
      with xvec' ♯* yvec' length xvec' = n
      obtain p T where S: "set p  set xvec' × set yvec'" and "P = (p  Q)  T" and A: "⦇ν*xvec'M ≺' T = ⦇ν*yvec'N ≺' R"
        by(drule_tac IH) auto
      from yFreshQR xFreshQR have yFreshR: "y  ⦇ν*yvec'N ≺' R" and xFreshQ: "x  ⦇ν*yvec'N ≺' R" 
        by(force simp add: BOresChainSupp fresh_def boundOutput.supp psi.supp)+
      hence "⦇νx(⦇ν*yvec'N ≺' R) = ⦇νy(⦇ν*yvec'N ≺' R)" by (subst alphaBoundOutput) simp+
      with A have "⦇νx(⦇ν*xvec'M ≺' T) = ⦇νy(⦇ν*yvec'N ≺' R)" by simp
      with xvec=x#xvec' yvec=y#yvec' S P = (p  Q)  T show ?case
        by auto
    next
      assume "¬(x  ⦇ν*xvec'M ≺' P)"
      hence "x  supp(⦇ν*xvec'M ≺' P)" by(simp add: fresh_def)
      with Eq have "y  supp(⦇ν*yvec'N ≺' (Q  R))"
        by(rule boundOutputEqSupp)
      hence "y  yvec'" by(simp add: BOresChainSupp fresh_def)
      with Eq' x  yvec' have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'([(x, y)]  N) ≺' (([(x, y)]  Q)  ([(x, y)]  R))"
        by(simp add: eqvts)
      moreover note xvec' ♯* yvec' length xvec' = n
      ultimately obtain p T where S: "set p  set xvec' × set yvec'" and "P = (p  [(x, y)]  Q)  T" and A: "⦇ν*xvec'M ≺' T = ⦇ν*yvec'([(x, y)]  N) ≺' ([(x, y)]  R)"
        by(drule_tac IH) auto

      from S have "set(p@[(x, y)])  set(x#xvec') × set(y#yvec')" by auto
      moreover from P = (p  [(x, y)]  Q)  T  have "P = ((p @ [(x, y)])  Q)  T"
        by(simp add: pt2[OF pt_name_inst])
      moreover from xFreshQR have xFreshR: "x  ⦇ν*yvec'N ≺' R" 
        by(force simp add: BOresChainSupp fresh_def boundOutput.supp psi.supp)+
      with x  yvec' y  yvec' x  y have "y  ⦇ν*yvec'([(x, y)]  N) ≺' ([(x, y)]  R)"
        by(simp add: fresh_left calc_atm)
      with x  yvec' y  yvec' have "⦇νx(⦇ν*yvec'([(x, y)]  N) ≺' ([(x, y)]  R)) = ⦇νy(⦇ν*yvec'N ≺' R)"
        by(subst alphaBoundOutput) (assumption | simp add: eqvts)+
      with  A have "⦇νx(⦇ν*xvec'M ≺' T) = ⦇νy(⦇ν*yvec'N ≺' R)" by simp
      ultimately show ?thesis using xvec=x#xvec' yvec=y#yvec'
        by(rule_tac x="p@[(x, y)]" in exI) force
    qed
  qed
  ultimately show ?thesis
    by blast
qed

lemma boundOutputApp:
  fixes xvec :: "name list"
  and   yvec :: "name list"
  and   B    :: "('a::fs_name, 'b::fs_name, 'c::fs_name) boundOutput"

  shows "⦇ν*(xvec@yvec)B = ⦇ν*xvec(⦇ν*yvecB)"
by(induct xvec) auto
  
lemma openInjectAuxAuxAux:
  fixes x    :: name
  and   xvec :: "name list"

  shows "y yvec. x # xvec = yvec @ [y]  length xvec = length yvec"
apply(induct xvec arbitrary: x)
apply auto
apply(subgoal_tac "y yvec. a # xvec = yvec @ [y]  length xvec = length yvec")
apply(clarify)
apply(rule_tac x=y in exI)
by auto

lemma openInjectAuxAux:
  fixes xvec1 :: "name list"
  and   xvec2 :: "name list"
  and   yvec  :: "name list"

  assumes "length(xvec1@xvec2) = length yvec"

  shows "yvec1 yvec2. yvec = yvec1@yvec2  length xvec1 = length yvec1  length xvec2 = length yvec2"
using assms
apply(induct yvec arbitrary: xvec1)
apply simp
apply simp
apply(case_tac xvec1)
apply simp
apply simp
apply(subgoal_tac "yvec1 yvec2.
                   yvec = yvec1 @ yvec2  length list = length yvec1  length xvec2 = length yvec2")
apply(clarify)
apply(rule_tac x="a#yvec1" in exI)
apply(rule_tac x=yvec2 in exI)
by auto

lemma openInjectAux:
  fixes xvec1 :: "name list"
  and   x     :: name
  and   xvec2 :: "name list"
  and   yvec  :: "name list"

  assumes "length(xvec1@x#xvec2) = length yvec"

  shows "yvec1 y yvec2. yvec = yvec1@y#yvec2  length xvec1 = length yvec1  length xvec2 = length yvec2"
using assms
apply(case_tac yvec)
apply simp
apply simp
apply(subgoal_tac "(yvec1::name list) (yvec2::name list). yvec1@yvec2 = list  length xvec1 = length yvec1  length xvec2 = length yvec2")
apply(clarify)
apply hypsubst_thin
apply simp
apply(subgoal_tac "y (yvec::name list). a # yvec1 = yvec @ [y]  length yvec1 = length yvec")
apply(clarify)
apply(rule_tac x=yvec in exI)
apply(rule_tac x=y in exI)
apply simp
apply(rule_tac x=yvec2 in exI)
apply simp
apply(rule openInjectAuxAuxAux)
apply(insert openInjectAuxAux)
apply simp
by blast

lemma boundOutputOpenDest:
  fixes yvec  :: "name list"
  and   M     :: "'a::fs_name"
  and   P     :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   xvec1 :: "name list"
  and   x     :: name
  and   xvec2 :: "name list"
  and   N     :: 'a
  and   Q     :: "('a, 'b, 'c) psi"

  assumes Eq: "⦇ν*(xvec1@x#xvec2)M ≺' P = ⦇ν*yvecN ≺' Q"
  and     "x  xvec1"
  and     "x  yvec"
  and     "x  N"
  and     "x  Q"
  and     "distinct yvec"
  

  obtains yvec1 y yvec2 where "yvec=yvec1@y#yvec2" and "length xvec1 = length yvec1" and "length xvec2 = length yvec2" 
                          and "⦇ν*(xvec1@xvec2)M ≺' P = ⦇ν*(yvec1@yvec2)([(x, y)]  N) ≺' ([(x, y)]  Q)"
proof -
  assume Ass: "yvec1 y yvec2.
        yvec = yvec1 @ y # yvec2; length xvec1 = length yvec1; length xvec2 = length yvec2;
         ⦇ν*(xvec1 @ xvec2)M ≺' P = ⦇ν*(yvec1 @ yvec2)([(x, y)]  N) ≺' ([(x, y)]  Q)
         thesis"
  from Eq have "length(xvec1@x#xvec2) = length yvec" by(rule boundOutputChainEqLength)
  then obtain yvec1 y yvec2 where A: "yvec = yvec1@y#yvec2" and "length xvec1 = length yvec1"
          and "length xvec2 = length yvec2"
    by(metis openInjectAux sym)

  from distinct yvec A have "y  yvec2" by simp
  from A x  yvec have "x  yvec2" and "x  yvec1"  by simp+
  with Eq length xvec1 = length yvec1 x  N x  Q y  yvec2 x  xvec1 A
  have "⦇ν*(xvec1@xvec2)M ≺' P = ⦇ν*(yvec1@yvec2)([(x, y)]  N) ≺' ([(x, y)]  Q)"
    by(force dest: boundOutputChainOpenIH simp add: boundOutputApp BOresChainSupp fresh_def boundOutput.supp eqvts)
  with length xvec1 = length yvec1 length xvec2 = length yvec2 A Ass show ?thesis
    by blast
qed

lemma boundOutputOpenDest':
  fixes yvec  :: "name list"
  and   M     :: "'a::fs_name"
  and   P     :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   xvec1 :: "name list"
  and   x     :: name
  and   xvec2 :: "name list"
  and   N     :: 'a
  and   Q     :: "('a, 'b, 'c) psi"

  assumes Eq: "⦇ν*(xvec1@x#xvec2)M ≺' P = ⦇ν*yvecN ≺' Q"
  and     "x  xvec1"
  and     "x  yvec"
  and     "x  N"
  and     "x  Q"
  

  obtains yvec1 y yvec2 where "yvec=yvec1@y#yvec2" and "length xvec1 = length yvec1" and "length xvec2 = length yvec2" 
                          and "⦇ν*(xvec1@xvec2)M ≺' P = ⦇ν*(yvec1@[(x, y)]  yvec2)([(x, y)]  N) ≺' ([(x, y)]  Q)"
proof -
  assume Ass: "yvec1 y yvec2.
        yvec = yvec1 @ y # yvec2; length xvec1 = length yvec1; length xvec2 = length yvec2;
         ⦇ν*(xvec1 @ xvec2)M ≺' P = ⦇ν*(yvec1 @ ([(x, y)]  yvec2))([(x, y)]  N) ≺' ([(x, y)]  Q)
         thesis"
  from Eq have "length(xvec1@x#xvec2) = length yvec" by(rule boundOutputChainEqLength)
  then obtain yvec1 y yvec2 where A: "yvec = yvec1@y#yvec2" and "length xvec1 = length yvec1"
          and "length xvec2 = length yvec2"
    by(metis openInjectAux sym)

  from A x  yvec have "x  yvec2" and "x  yvec1"  by simp+
  with Eq length xvec1 = length yvec1 x  N x  Q x  xvec1 A
  have "⦇ν*(xvec1@xvec2)M ≺' P = ⦇ν*(yvec1@([(x, y)]  yvec2))([(x, y)]  N) ≺' ([(x, y)]  Q)"
    by(force dest: boundOutputChainOpenIH simp add: boundOutputApp BOresChainSupp fresh_def boundOutput.supp eqvts)
  with length xvec1 = length yvec1 length xvec2 = length yvec2 A Ass show ?thesis
    by blast
qed

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

  assumes "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' ⦇νzQ"
  and     "z  xvec"
  and     "z  yvec"

  obtains R where "P = ⦇νzR" and "⦇ν*xvecM ≺' R = ⦇ν*yvecN ≺' Q"
proof -
  assume "R. P = ⦇νzR; ⦇ν*xvecM ≺' R = ⦇ν*yvecN ≺' Q  thesis"
  moreover obtain n where "n = length xvec" by auto
  with assms have "R. P = ⦇νzR  ⦇ν*xvecM ≺' R = ⦇ν*yvecN ≺' Q"
  proof(induct n arbitrary: xvec yvec M N P Q z)
    case(0 xvec yvec M N P Q z)
    have Eq: "⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' ⦇νzQ" by fact
    from 0 = length xvec have "xvec = []" by auto
    moreover with Eq have "yvec = []"
      by(case_tac yvec) auto
    ultimately show ?case using Eq
      by(simp add: boundOutput.inject)
  next
    case(Suc n xvec yvec M N P Q z)
    from Suc n = length xvec
    obtain x xvec' where "xvec = x#xvec'" and "length xvec' = n"
      by(case_tac xvec) auto
    from ⦇ν*xvecM ≺' P = ⦇ν*yvecN ≺' (⦇νzQ) xvec = x # xvec'
    obtain y yvec' where "⦇ν*(x#xvec')M ≺' P = ⦇ν*(y#yvec')N ≺' ⦇νzQ"
      and "yvec = y#yvec'"
      by(case_tac yvec) auto
    hence EQ: "⦇νx(⦇ν*xvec'M ≺' P) = ⦇νy(⦇ν*yvec'N ≺' ⦇νzQ)"
      by simp
    from z  xvec z  yvec xvec = x#xvec' yvec = y#yvec'
    have "z  x" and "z  y" and "z  xvec'" and "z  yvec'"
      by simp+
    have IH: "xvec yvec M N P Q z. ⦇ν*xvecM ≺' (P::('a, 'b, 'c) psi) = ⦇ν*yvecN ≺' ⦇νzQ; z  xvec; z  yvec; n = length xvec  R. P = ⦇νzR  ⦇ν*xvecM ≺' R = ⦇ν*yvecN ≺' Q"
      by fact
    show ?case
    proof(case_tac "x = y")
      assume "x = y"
      with EQ have "⦇ν*xvec'M ≺' P = ⦇ν*yvec'N ≺' ⦇νzQ"
        by(simp add: boundOutput.inject alpha)
      with z  xvec' z  yvec' length xvec' = n
      obtain R where "P = ⦇νzR" and "⦇ν*xvec'M ≺' R = ⦇ν*yvec'N ≺' Q"
        by(drule_tac IH) auto
      with xvec=x#xvec' yvec=y#yvec' x=y show ?case
        by(force simp add: boundOutput.inject alpha)
    next
      assume "x  y"
      with EQ z  x z  y
      have "⦇ν*xvec'M ≺' P = ⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ⦇νz([(x, y)]  Q)"
       and xFreshzQ: "x  ⦇ν*yvec'N ≺' ⦇νzQ"
        by(simp add: boundOutput.inject alpha eqvts)+
      moreover from z  x z  y z  yvec' x  y have "z  ([(x, y)]  yvec')"
        by(simp add: fresh_left calc_atm)
      moreover note z  xvec' length xvec' = n
      ultimately obtain R where "P = ⦇νzR" and A: "⦇ν*xvec'M ≺' R = ⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ([(x, y)]  Q)"
        by(drule_tac IH) auto

      from A have "⦇νx(⦇ν*xvec'M ≺' R) = ⦇νx(⦇ν*([(x, y)]  yvec')([(x, y)]  N) ≺' ([(x, y)]  Q))"
        by(simp add: boundOutput.inject alpha)
      moreover from xFreshzQ z  x have "x  ⦇ν*yvec'N ≺' Q"
        by(simp add: boundOutputFresh abs_fresh)
      ultimately show ?thesis using P = ⦇νzR xvec=x#xvec' yvec=y#yvec' xFreshzQ
        by(force simp add: alphaBoundOutput name_swap eqvts)
    qed
  qed
  ultimately show ?thesis
    by blast
qed

nominal_datatype ('a, 'b, 'c) residual = 
  RIn "'a::fs_name" 'a "('a, 'b::fs_name, 'c::fs_name) psi" 
| ROut 'a "('a, 'b, 'c) boundOutput"
| RTau "('a, 'b, 'c) psi"

nominal_datatype 'a action = In "'a::fs_name" 'a      (‹__ [90, 90] 90)
                   | Out "'a::fs_name" "name list" 'a (‹_⦇ν*_⦈⟨_ [90, 90, 90] 90)
                   | Tau                              (τ 90)

nominal_primrec bn :: "('a::fs_name) action  name list"
  where
  "bn (MN) = []"
| "bn (M⦇ν*xvec⦈⟨N) = xvec"
| "bn (τ) = []"
by(rule TrueI)+

lemma bnEqvt[eqvt]:
  fixes p :: "name prm"
  and   α :: "('a::fs_name) action"

  shows "(p  bn α) = bn(p  α)"
by(nominal_induct α rule: action.strong_induct) auto

nominal_primrec create_residual :: "('a::fs_name) action  ('a, 'b::fs_name, 'c::fs_name) psi  ('a, 'b, 'c) residual" (‹_  _› [80, 80] 80)
where 
  "(MN)  P = RIn M N P"
| "M⦇ν*xvec⦈⟨N  P = ROut M (⦇ν*xvec(N ≺' P))"
| "τ  P = (RTau P)"
by(rule TrueI)+

nominal_primrec subject :: "('a::fs_name) action  'a option" 
  where 
  "subject (MN) = Some M"
| "subject (M⦇ν*xvec⦈⟨N) = Some M"
| "subject (τ) = None"
by(rule TrueI)+

nominal_primrec object :: "('a::fs_name) action  'a option" 
  where 
  "object (MN) = Some N"
| "object (M⦇ν*xvec⦈⟨N) = Some N"
| "object (τ) = None"
by(rule TrueI)+

lemma optionFreshChain[simp]:
  fixes xvec :: "name list"
  and   X    :: "name set"

  shows "xvec ♯* (Some x) = xvec ♯* x"
  and   "X ♯* (Some x) = X ♯* x"
  and   "xvec ♯* None"
  and   "X ♯* None"
by(auto simp add: fresh_star_def fresh_some fresh_none)

lemmas [simp] = fresh_some fresh_none
  
lemma actionFresh[simp]:
  fixes x :: name
  and   α :: "('a::fs_name) action"

  shows "(x  α)  = (x  (subject α)  x  (bn α)  x  (object α))"
by(nominal_induct α rule: action.strong_induct) auto
  
lemma actionFreshChain[simp]:
  fixes X    :: "name set"
  and   α    :: "('a::fs_name) action"
  and   xvec :: "name list"

  shows "(X ♯* α) = (X ♯* (subject α)  X ♯* (bn α)  X ♯* (object α))"
  and   "(xvec ♯* α) = (xvec ♯* (subject α)  xvec ♯* (bn α)  xvec ♯* (object α))"
by(auto simp add: fresh_star_def)

lemma subjectEqvt[eqvt]:
  fixes p :: "name prm"
  and   α :: "('a::fs_name) action"

  shows "(p  subject α) = subject(p  α)"
by(nominal_induct α rule: action.strong_induct) auto

lemma okjectEqvt[eqvt]:
  fixes p :: "name prm"
  and   α :: "('a::fs_name) action"

  shows "(p  object α) = object(p  α)"
by(nominal_induct α rule: action.strong_induct) auto

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

  shows "(p  (α  P)) = (p  α)  (p  P)"
by(nominal_induct α rule: action.strong_induct)
  (auto simp add: eqvts)

lemma residualFresh:
  fixes x :: name
  and   α :: "'a::fs_name action"
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"

  shows "(x  (α  P)) = (x  (subject α)  (x  (set(bn(α)))  (x  object(α)  x  P)))"
by(nominal_induct α rule: action.strong_induct)
  (auto simp add: fresh_some fresh_none boundOutputFresh)

lemma residualFresh2[simp]:
  fixes x :: name
  and   α :: "('a::fs_name) action"
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"

  assumes "x  α"
  and     "x  P"

  shows "x  α  P"
using assms
by(nominal_induct α rule: action.strong_induct) auto

lemma residualFreshChain2[simp]:
  fixes xvec :: "name list"
  and   X    :: "name set"
  and   α    :: "('a::fs_name) action"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"

  shows "xvec ♯* α; xvec ♯* P  xvec ♯* (α  P)"
  and   "X ♯* α; X ♯* P  X ♯* (α  P)"
by(auto simp add: fresh_star_def)

lemma residualFreshSimp[simp]:
  fixes x :: name
  and   M :: "'a::fs_name"
  and   N :: 'a
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"
  

  shows "x  (MN  P) = (x  M  x  N  x  P)"
  and   "x  (M⦇ν*xvec⦈⟨N  P) = (x  M  x  (⦇ν*xvec(N ≺' P)))"
  and   "x  (τ  P) = (x  P)"
by(auto simp add: residualFresh)

lemma residualInject':

  shows "(α  P = RIn M N Q) = (P = Q  α = MN)"
  and   "(α  P = ROut M B) = (xvec N. α = M⦇ν*xvec⦈⟨N  B = ⦇ν*xvec(N ≺' P))"
  and   "(α  P = RTau Q) = (α = τ  P = Q)"
  and   "(RIn M N Q = α  P) = (P = Q  α = MN)"
  and   "(ROut M B = α  P) = (xvec N. α = M⦇ν*xvec⦈⟨N  B = ⦇ν*xvec(N ≺' P))"
  and   "(RTau Q = α  P) = (α = τ  P = Q)"
proof -
  show "(α  P = RIn M N Q) = (P = Q  α = MN)"
    by(nominal_induct α rule: action.strong_induct)
      (auto simp add: residual.inject action.inject)
next
  show "(α  P = ROut M B) = (xvec N. α = M⦇ν*xvec⦈⟨N  B = ⦇ν*xvec(N ≺' P))"
    by(nominal_induct α rule: action.strong_induct)
      (auto simp add: residual.inject action.inject)
next
  show  "(α  P = RTau Q) = (α = τ  P = Q)"
    by(nominal_induct α rule: action.strong_induct)
      (auto simp add: residual.inject action.inject)
next
  show "(RIn M N Q = α  P) = (P = Q  α = MN)"
    by(nominal_induct α rule: action.strong_induct)
      (auto simp add: residual.inject action.inject)
next
  show "(ROut M B = α  P) = (xvec N. α = M⦇ν*xvec⦈⟨N  B = ⦇ν*xvec(N ≺' P))"
    by(nominal_induct α rule: action.strong_induct)
      (auto simp add: residual.inject action.inject)
next
  show  "(RTau Q = α  P) = (α = τ  P = Q)"
    by(nominal_induct α rule: action.strong_induct)
      (auto simp add: residual.inject action.inject)
qed

lemma residualFreshChainSimp[simp]:
  fixes xvec :: "name list"
  and   X    :: "name set"
  and   M    :: "'a::fs_name"
  and   N    :: 'a
  and   yvec :: "name list"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"

  shows "xvec ♯* (MN  P) = (xvec ♯* M  xvec ♯* N  xvec ♯* P)"
  and   "xvec ♯* (M⦇ν*yvec⦈⟨N  P) = (xvec ♯* M  xvec ♯* (⦇ν*yvec(N ≺' P)))"
  and   "xvec ♯* (τ  P) = (xvec ♯* P)"
  and   "X ♯* (MN  P) = (X ♯* M  X ♯* N  X ♯* P)"
  and   "X ♯* (M⦇ν*yvec⦈⟨N  P) = (X ♯* M  X ♯* (⦇ν*yvec(N ≺' P)))"
  and   "X ♯* (τ  P) = (X ♯* P)"
by(auto simp add: fresh_star_def)

lemma residualFreshChainSimp2[simp]:
  fixes xvec :: "name list"
  and   X    :: "name set"
  and   M    :: "'a::fs_name"
  and   N    :: 'a
  and   yvec :: "name list"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"

  shows "xvec ♯* (RIn M N P) = (xvec ♯* M  xvec ♯* N  xvec ♯* P)"
  and   "xvec ♯* (ROut M B) = (xvec ♯* M  xvec ♯* B)"
  and   "xvec ♯* (RTau P) = (xvec ♯* P)"
  and   "X ♯* (RIn M N P) = (X ♯* M  X ♯* N  X ♯* P)"
  and   "X ♯* (ROut M B) = (X ♯* M  X ♯* B)"
  and   "X ♯* (RTau P) = (X ♯* P)"
by(auto simp add: fresh_star_def)

lemma freshResidual3[dest]:
  fixes x :: name
  and   α :: "('a::fs_name) action"
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"
  
  assumes "x  bn α"
  and     "x  α  P"

  shows "x  α" and "x  P"
using assms
by(nominal_induct rule: action.strong_induct) auto

lemma freshResidualChain3[dest]:
  fixes xvec :: "name list"
  and   α    :: "('a::fs_name) action"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"
  
  assumes "xvec ♯* (α  P)"
  and     "xvec ♯* bn α"

  shows "xvec ♯* α" and "xvec ♯* P"
using assms
by(nominal_induct rule: action.strong_induct) auto

lemma freshResidual4[dest]:
  fixes x :: name
  and   α :: "('a::fs_name) action"
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"
  
  assumes "x  α  P"

  shows "x  subject α"
using assms
by(nominal_induct rule: action.strong_induct) auto

lemma freshResidualChain4[dest]:
  fixes xvec :: "name list"
  and   α    :: "('a::fs_name) action"
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"
  
  assumes "xvec ♯* (α  P)"

  shows "xvec ♯* subject α"
using assms
by(nominal_induct rule: action.strong_induct) auto

lemma alphaOutputResidual:
  fixes M    :: "'a::fs_name"
  and   xvec :: "name list"
  and   N    :: 'a
  and   P    :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   p    :: "name prm"

  assumes "(p  xvec) ♯* N"
  and     "(p  xvec) ♯* P"
  and     "set p  set xvec × set(p  xvec)"
  and     "set xvec  set yvec"

  shows "M⦇ν*yvec⦈⟨N  P = M⦇ν*(p  yvec)⦈⟨(p  N)  (p  P)"
using assms
by(simp add: boundOutputChainAlpha'')

lemmas[simp del] =  create_residual.simps

lemma residualInject'':

  assumes "bn α = bn β"

  shows "(α  P = β  Q) = (α = β  P = Q)"
using assms
apply(nominal_induct α rule: action.strong_induct)
apply(auto simp add: residual.inject create_residual.simps residualInject' action.inject boundOutput.inject)
by(rule_tac x="bn β" in exI) auto

lemmas residualInject = residual.inject create_residual.simps residualInject' residualInject''

lemma bnFreshResidual[simp]:
  fixes α :: "('a::fs_name) action"

  shows "(bn α) ♯* (α  P) = bn α ♯* (subject α)"
by(nominal_induct α rule: action.strong_induct)
  (auto simp add: residualFresh fresh_some fresh_star_def)

lemma actionCases[case_names cInput cOutput cTau]:
  fixes α :: "('a::fs_name) action"

  assumes "M N. α = MN  Prop"
  and     "M xvec N. α = M⦇ν*xvec⦈⟨N  Prop"
  and     "α = τ  Prop"

  shows Prop
using assms
by(nominal_induct α rule: action.strong_induct) auto

lemma actionPar1Dest:
  fixes α :: "('a::fs_name) action"
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   β :: "('a::fs_name) action"
  and   Q :: "('a, 'b, 'c) psi"
  and   R :: "('a, 'b, 'c) psi"

  assumes "α  P = β  (Q  R)"
  and     "bn α ♯* bn β"

  obtains T p where "set p  set(bn α) × set(bn β)" and "P = T  (p  R)" and "α  T = β  Q"
using assms
apply(cases rule: actionCases[where α=α])
apply(auto simp add: residualInject)
by(drule_tac boundOutputPar1Dest') auto

lemma actionPar2Dest:
  fixes α :: "('a::fs_name) action"
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"
  and   β :: "('a::fs_name) action"
  and   Q :: "('a, 'b, 'c) psi"
  and   R :: "('a, 'b, 'c) psi"

  assumes "α  P = β  (Q  R)"
  and     "bn α ♯* bn β"

  obtains T p where "set p  set(bn α) × set(bn β)" and "P = (p  Q)  T" and "α  T = β  R"
using assms
apply(cases rule: actionCases[where α=α])
apply(auto simp add: residualInject)
by(drule_tac boundOutputPar2Dest') auto

lemma actionScopeDest:
  fixes α :: "('a::fs_name) action"
  and   P :: "('a, 'b::fs_name, 'c::fs_name) psi"
  fixes β :: "('a::fs_name) action"
  and   x :: name
  and   Q :: "('a, 'b, 'c) psi"

  assumes "α  P = β  ⦇νxQ"
  and     "x  bn α"
  and     "x  bn β"

  obtains R where "P = ⦇νxR" and "α  R = β  Q"
using assms
apply(cases rule: actionCases[where α=α])
apply(auto simp add: residualInject)
by(drule_tac boundOutputScopeDest) auto

abbreviation
  outputJudge (‹__ [110, 110] 110) where "MN  M⦇ν*([])⦈⟨N"

declare [[unify_trace_bound=100]]

locale env = substPsi substTerm substAssert substCond + 
             assertion SCompose' SImp' SBottom' SChanEq'
  for substTerm :: "('a::fs_name)  name list  'a::fs_name list  'a"
  and substAssert :: "('b::fs_name)  name list  'a::fs_name list  'b"
  and substCond :: "('c::fs_name)  name list  'a::fs_name list  'c"
  and SCompose'  :: "'b  'b  'b"
  and SImp'      :: "'b  'c  bool"
  and SBottom'   :: 'b
  and SChanEq'   :: "'a  'a  'c"
begin
notation SCompose' (infixr  90)
notation SImp' (‹_  _› [85, 85] 85)
notation FrameImp (‹_ F _› [85, 85] 85) 
abbreviation
  FBottomJudge (F 90) where "F  (FAssert SBottom')"
notation SChanEq' (‹_  _› [90, 90] 90)
notation substTerm (‹_[_::=_] [100, 100, 100] 100)
notation subs (‹_[_::=_] [100, 100, 100] 100)
notation AssertionStatEq (‹_  _› [80, 80] 80)
notation FrameStatEq (‹_ F _› [80, 80] 80)
notation SBottom' (𝟭 190)
abbreviation insertAssertion' (insertAssertion) where "insertAssertion'  assertionAux.insertAssertion (⊗)"

inductive semantics :: "'b  ('a, 'b, 'c) psi  ('a, 'b, 'c) residual  bool"
                       (‹_  _  _› [50, 50, 50] 50)
where
  cInput:  "Ψ  M  K; distinct xvec; set xvec  supp N; xvec ♯* Tvec;
            length xvec = length Tvec;
            xvec ♯* Ψ; xvec ♯* M; xvec ♯* K  Ψ  M⦇λ*xvec N⦈.P  K(N[xvec::=Tvec])  P[xvec::=Tvec]"
| Output: "Ψ  M  K  Ψ  MN⟩.P  KN  P"
| Case:   "Ψ  P  Rs; (φ, P) mem Cs; Ψ  φ; guarded P  Ψ  Cases Cs  Rs"

| cPar1:   "(Ψ  ΨQ)  P α  P'; extractFrame Q = AQ, ΨQ; distinct AQ;
             AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* α; AQ ♯* P'; distinct(bn α); 
             bn α ♯* Ψ; bn α ♯* ΨQ; bn α ♯* Q; bn α ♯* P; bn α ♯* (subject α) 
             Ψ  P  Q α  (P'  Q)"
| cPar2:   "(Ψ  ΨP)  Q α  Q'; extractFrame P = AP, ΨP; distinct AP;
             AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* α; AP ♯* Q'; distinct(bn α); 
             bn α ♯* Ψ; bn α ♯* ΨP; bn α ♯* P; bn α ♯* Q; bn α ♯* (subject α) 
             Ψ  P  Q α  (P  Q')"
| cComm1:   "Ψ  ΨQ  P  MN  P'; extractFrame P = AP, ΨP; distinct AP;
             Ψ  ΨP  Q  K⦇ν*xvec⦈⟨N  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
             Ψ  ΨP  ΨQ  M  K; 
             AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P';
             AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; 
             AQ ♯* Ψ; AQ ♯* ΨP; AQ ♯* P; AQ ♯* N; AQ ♯* P';
             AQ ♯* Q; AQ ♯* K; AQ ♯* Q'; AQ ♯* xvec; distinct xvec;
             xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M;
             xvec ♯* Q; xvec ♯* K 
             Ψ  P  Q  τ  ⦇ν*xvec(P'  Q')"
| cComm2:   "Ψ  ΨQ  P  M⦇ν*xvec⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
             Ψ  ΨP  Q  KN  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
             Ψ  ΨP  ΨQ  M  K; 
             AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P';
             AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; 
             AQ ♯* Ψ; AQ ♯* ΨP; AQ ♯* P; AQ ♯* N; AQ ♯* P';
             AQ ♯* Q; AQ ♯* K; AQ ♯* Q'; AQ ♯* xvec; distinct xvec;
             xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M;
             xvec ♯* Q; xvec ♯* K 
             Ψ  P  Q  τ  ⦇ν*xvec(P'  Q')"
| cOpen:    "Ψ  P  M⦇ν*(xvec@yvec)⦈⟨N  P'; x  supp N; x  xvec; x  yvec; x  M; x  Ψ;
              distinct xvec; distinct yvec;
              xvec ♯* Ψ; xvec ♯* P; xvec ♯* M; xvec ♯* yvec; yvec ♯* Ψ; yvec ♯* P; yvec ♯* M 
              Ψ  ⦇νxP  M⦇ν*(xvec@x#yvec)⦈⟨N  P'"
| cScope:  "Ψ  P α  P'; x  Ψ; x  α; bn α ♯* Ψ; bn α ♯* P; bn α ♯* (subject α); distinct(bn α)  Ψ  ⦇νxP α  (⦇νxP')"
| Bang:    "Ψ  P  !P  Rs; guarded P  Ψ  !P  Rs"

abbreviation
  semanticsBottomJudge (‹_  _› [50, 50] 50) where "P  Rs  𝟭  P  Rs"

equivariance env.semantics

nominal_inductive2 env.semantics
  avoids cInput: "set xvec"
       | cPar1: "set AQ  set(bn α)"
       | cPar2: "set AP  set(bn α)"
       | cComm1: "set AP  set AQ  set xvec"
       | cComm2: "set AP  set AQ  set xvec"
       | cOpen:  "{x}  set xvec  set yvec"
       | cScope: "{x}  set(bn α)"
apply(auto intro: substTerm.subst4Chain subst4Chain simp add: abs_fresh residualFresh)
apply(force simp add: fresh_star_def abs_fresh)
apply(simp add: boundOutputFresh)
apply(simp add: boundOutputFreshSet)
apply(simp add: boundOutputFreshSet)
by(simp add: fresh_star_def abs_fresh)

lemma nilTrans[dest]:
  fixes Ψ   :: 'b
  and   Rs   :: "('a, 'b, 'c) residual"
  and   M    :: 'a
  and   xvec :: "name list"
  and   N    :: 'a
  and   P    :: "('a, 'b, 'c) psi"
  and   K    :: 'a
  and   yvec :: "name list"
  and   N'   :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   CsP  :: "('c ×  ('a, 'b, 'c) psi) list"
  and   Ψ'   :: 'b

  shows "Ψ  𝟬  Rs  False"
  and   "Ψ  M⦇λ*xvec N⦈.P K⦇ν*yvec⦈⟨N'  P'  False"
  and   "Ψ  M⦇λ*xvec N⦈.P τ  P'  False"
  and   "Ψ  MN⟩.P KN'  P'  False"
  and   "Ψ  MN⟩.P τ  P'  False"
  and   "Ψ  Ψ'  Rs  False"
apply(cases rule: semantics.cases) apply auto
apply(cases rule: semantics.cases) apply(auto simp add: residualInject)
apply(cases rule: semantics.cases) apply(auto simp add: residualInject)
apply(cases rule: semantics.cases) apply(auto simp add: residualInject)
apply(cases rule: semantics.cases) apply(auto simp add: residualInject)
by(cases rule: semantics.cases) (auto simp add: residualInject)
  
lemma residualEq:
  fixes α :: "'a action"
  and   P :: "('a, 'b, 'c) psi"
  and   β :: "'a action"
  and   Q :: "('a, 'b, 'c) psi"

  assumes "α  P = β  Q"
  and     "bn α ♯* (bn β)"
  and     "distinct(bn α)"
  and     "distinct(bn β)"
  and     "bn α ♯* (α  P)"
  and     "bn β ♯* (β  Q)"

  obtains p where "set p  set(bn α) × set(bn(p  α))" and "distinctPerm p" and "β = p  α" and "Q = p  P" and "bn α ♯* β" and "bn α ♯* Q" and "bn(p  α) ♯* α" and "bn(p  α) ♯* P"
using assms
proof(nominal_induct α rule: action.strong_induct)
  case(In M N)
  thus ?case by(simp add: residualInject)
next
  case(Out M xvec N)
  thus ?case 
    by(auto simp add: residualInject)
      (drule_tac boundOutputChainEq'', auto) 
next
  case Tau
  thus ?case by(simp add: residualInject)
qed

lemma semanticsInduct[consumes 3, case_names cAlpha cInput cOutput cCase cPar1 cPar2 cComm1 cComm2 cOpen cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   α    :: "'a action"
  and   P'   :: "('a, 'b, 'c) psi"
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                'a action  ('a, 'b, 'c) psi  bool"
  and   C    :: "'d::fs_name"

  assumes "Ψ  P α  P'"
  and     "bn α ♯* (subject α)"
  and     "distinct(bn α)"
  and     rAlpha: "Ψ P α P' p C. bn α ♯* Ψ; bn α ♯* P; bn α ♯* (subject α); 
                                    bn α ♯* C; bn α ♯* (bn(p  α)); 
                                    set p  set(bn α) × set(bn(p  α)); distinctPerm p;
                                    (bn(p  α)) ♯* α; (bn(p  α)) ♯* P'; Prop C Ψ P α P' 
                                     Prop C Ψ P (p  α) (p  P')"
  and     rInput: "Ψ M K xvec N Tvec P C.
                   Ψ  M  K; distinct xvec; set xvec  supp N;
                    length xvec = length Tvec; xvec ♯* Ψ;
                    xvec ♯* M; xvec ♯* K; xvec ♯* C 
                    Prop C Ψ (M⦇λ*xvec N⦈.P)
                              (K(N[xvec::=Tvec])) (P[xvec::=Tvec])"
  and     rOutput: "Ψ M K N P C. Ψ  M  K  Prop C Ψ (MN⟩.P) (KN) P"
  and     rCase: "Ψ P α P' φ Cs C. Ψ  P α  P'; C. Prop C Ψ P α P'; (φ, P) mem Cs; Ψ  φ; guarded P 
                                      Prop C Ψ (Cases Cs) α P'"
  and     rPar1: "Ψ ΨQ P α P' AQ Q C.
                   Ψ  ΨQ  P α  P'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    C. Prop C (Ψ  ΨQ) P α P';
                    AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* α; AQ ♯* P'; AQ ♯* C; distinct(bn α); bn α ♯* Q;
                    bn α ♯* Ψ; bn α ♯* ΨQ; bn α ♯* P; bn α ♯* subject α; bn α ♯* C 
                    Prop C Ψ (P  Q) α (P'  Q)"
  and     rPar2: "Ψ ΨP Q α Q' AP P C.
                   Ψ  ΨP  Q α  Q'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C (Ψ  ΨP) Q α Q';
                    AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* α; AP ♯* Q'; AP ♯* C; distinct(bn α); bn α ♯* Q;
                    bn α ♯* Ψ; bn α ♯* ΨP; bn α ♯* P; bn α ♯* subject α; bn α ♯* C 
                    Prop C Ψ (P  Q) α (P  Q')"
  and     rComm1: "Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ C.
                   Ψ  ΨQ  P MN  P'; C. Prop C (Ψ  ΨQ) P (MN) P'; 
                    extractFrame P = AP, ΨP; distinct AP;
                    Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q'; C. Prop C (Ψ  ΨP) Q (K⦇ν*xvec⦈⟨N) Q'; 
                    extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q'; distinct xvec;
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (τ) (⦇ν*xvec(P'  Q'))"
  and     rComm2: "Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P'; C. Prop C (Ψ  ΨQ) P (M⦇ν*xvec⦈⟨N) P'; 
                    extractFrame P = AP, ΨP; distinct AP; 
                    Ψ  ΨP  Q KN  Q'; C. Prop C (Ψ  ΨP) Q (KN) Q'; 
                    extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q'; distinct xvec;
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (τ) (⦇ν*xvec(P'  Q'))"
  and     rOpen:  "Ψ P M xvec yvec N P' x C.
                   Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'; x  supp N; C. Prop C Ψ P (M⦇ν*(xvec@yvec)⦈⟨N) P';
                    x  Ψ; x  M; x  xvec; x  yvec; xvec ♯* Ψ; xvec ♯* P; xvec ♯* M;  distinct xvec; distinct yvec;
                    yvec ♯* Ψ; yvec ♯* P; yvec ♯* M; yvec ♯* C; x  C; xvec ♯* C  
                    Prop C Ψ (⦇νxP) (M⦇ν*(xvec@x#yvec)⦈⟨N) P'"
  and     rScope: "Ψ P α P' x C.
                    Ψ  P α  P'; C. Prop C Ψ P α P';
                    x  Ψ; x  α; bn α ♯* Ψ;
                    bn α ♯* P; bn α ♯* (subject α); x  C; bn α ♯* C; distinct(bn α) 
                    Prop C Ψ (⦇νxP) α (⦇νxP')"
  and     rBang:    "Ψ P α P' C.
                     Ψ  P  !P α  P'; guarded P; C. Prop C Ψ (P  !P) α P' 
                      Prop C Ψ (!P) α P'"

  shows "Prop C Ψ P α P'"
using Ψ  P α  P' bn α ♯* (subject α) distinct(bn α)
proof(nominal_induct x3=="α  P'" avoiding: α C arbitrary: P' rule: semantics.strong_induct)
  case(cInput Ψ M K xvec N Tvec P α C P')
  thus ?case by(force intro: rInput simp add: residualInject)
next
  case(Output Ψ M K N P α C P')
  thus ?case by(force intro: rOutput simp add: residualInject)
next
  case(Case Ψ P Rs φ Cs α C)
  thus ?case by(auto intro: rCase)
next
  case(cPar1 Ψ ΨQ P α P' Q AQ α' C P'')
  note α  (P'  Q) = α'  P''
  moreover from bn α ♯* α' have "bn α ♯* (bn α')" by auto
  moreover note distinct (bn α) distinct(bn α')
  moreover from bn α ♯* subject α bn α' ♯* subject α'
  have "bn α ♯* (α  P'  Q)" and "bn α' ♯* (α'  P'')" by simp+
  ultimately obtain p where S: "(set p)  (set(bn α)) × (set(bn(p  α)))" and "distinctPerm p"
                        and αEq: "α' = p  α" and P'eq: "P'' = p  (P'  Q)" and "(bn(p  α)) ♯* α"
                        and "(bn(p  α)) ♯* (P'  Q)"
    by(rule residualEq)
    
  note Ψ  ΨQ  P α  P' extractFrame Q = AQ, ΨQ distinct AQ
  moreover from bn α ♯* subject α distinct(bn α)
  have "C. Prop C (Ψ  ΨQ) P α P'" by(rule_tac cPar1) auto
  moreover note AQ ♯* P AQ ♯* Q AQ ♯* Ψ AQ ♯* α AQ ♯* P' AQ ♯* C
                bn α ♯* Q distinct(bn α) bn α ♯* Ψ bn α ♯* ΨQ bn α ♯* P bn α ♯* subject α bn α ♯* C
  ultimately have "Prop C Ψ (P  Q) α (P'  Q)"
    by(rule_tac rPar1)

  with bn α ♯* Ψ bn α ♯* P bn α ♯* Q bn α ♯* subject α bn α ♯* C bn α ♯* bn α' S distinctPerm p bn(p  α) ♯* α bn(p  α) ♯* (P'  Q) AQ ♯* C
  have "Prop C Ψ (P  Q) (p  α) (p  (P'  Q))"
    by(rule_tac rAlpha) auto
  with αEq P'eq distinctPerm p show ?case by simp
next
  case(cPar2 Ψ ΨP Q α Q' P AP α' C Q'')
  note α  (P  Q') = α'  Q''
  moreover from bn α ♯* α' have "bn α ♯* (bn α')" by auto
  moreover note distinct (bn α) distinct(bn α')
  moreover from bn α ♯* subject α bn α' ♯* subject α'
  have "bn α ♯* (α  P  Q')" and "bn α' ♯* (α'  Q'')" by simp+
  ultimately obtain p where S: "(set p)  (set(bn α)) × (set(bn(p  α)))" and "distinctPerm p"
                        and αEq: "α' = p  α" and Q'eq: "Q'' = p  (P  Q')" and "(bn(p  α)) ♯* α"
                        and "(bn(p  α)) ♯* (P  Q')"
    by(rule residualEq)
    
  note Ψ  ΨP  Q α  Q' extractFrame P = AP, ΨP distinct AP
  moreover from bn α ♯* subject α distinct(bn α)
  have "C. Prop C (Ψ  ΨP) Q α Q'" by(rule_tac cPar2) auto

  moreover note AP ♯* P AP ♯* Q AP ♯* Ψ AP ♯* α AP ♯* Q' AP ♯* C
                bn α ♯* Q distinct(bn α) bn α ♯* Ψ bn α ♯* ΨP bn α ♯* P bn α ♯* subject α bn α ♯* C
  ultimately have "Prop C Ψ (P  Q) α (P  Q')"
    by(rule_tac rPar2)
  with bn α ♯* Ψ bn α ♯* P bn α ♯* Q bn α ♯* subject α bn α ♯* C bn α ♯* (bn α') S distinctPerm p bn(p  α) ♯* α bn(p  α) ♯* (P  Q')
  have "Prop C Ψ (P  Q) (p  α) (p  (P  Q'))"
    by(rule_tac rAlpha) auto
  with αEq Q'eq distinctPerm p show ?case by simp
next
  case(cComm1 Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ α C P'')
  hence "Prop C Ψ (P  Q) (τ) (⦇ν*xvec(P'  Q'))"
    by(rule_tac rComm1) (assumption | simp)+
  thus ?case using τ  ⦇ν*xvec(P'  Q') = α  P''
    by(simp add: residualInject)
next
  case(cComm2 Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ α C P'')
  hence "Prop C Ψ (P  Q) (τ) (⦇ν*xvec(P'  Q'))"
    by(rule_tac rComm2) (assumption | simp)+
  thus ?case using τ  ⦇ν*xvec(P'  Q') = α  P''
    by(simp add: residualInject)
next
  case(cOpen Ψ P M xvec yvec N P' x α C P'')
  note M⦇ν*(xvec@x#yvec)⦈⟨N  P' = α  P''
  moreover from xvec ♯* α x  α yvec ♯* α have "(xvec@x#yvec) ♯* (bn α)"
    by auto
  moreover from xvec ♯* yvec x  xvec x  yvec distinct xvec distinct yvec
  have "distinct(xvec@x#yvec)"
    by(auto simp add: fresh_star_def) (simp add: fresh_def name_list_supp)
  moreover note distinct(bn α)
  moreover from xvec ♯* M x  M yvec ♯* M have "(xvec@x#yvec) ♯* M" by auto
  hence "(xvec@x#yvec) ♯* (M⦇ν*(xvec@x#yvec)⦈⟨N  P')" by auto
  moreover from bn α ♯* subject α have "bn α ♯* (α  P'')" by simp
  ultimately obtain p where S: "(set p)  (set(xvec@x#yvec)) × (set(p  (xvec@x#yvec)))" and "distinctPerm p"
             and αeq: "α = (p  M)⦇ν*(p  (xvec@x#yvec))⦈⟨(p  N)" and P'eq: "P'' = (p  P')"
             and A: "(xvec@x#yvec) ♯* ((p  M)⦇ν*(p  (xvec@x#yvec))⦈⟨(p  N))"
             and B: "(p  (xvec@x#yvec)) ♯* (M⦇ν*(xvec@x#yvec)⦈⟨N)"
             and C: "(p  (xvec@x#yvec)) ♯* P'"
    by(rule_tac residualEq) (assumption | simp)+
    
  note Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P' x  (supp N)

  moreover {
    fix C
    from xvec ♯* M yvec ♯* M have "(xvec@yvec) ♯* M" by simp
    moreover from distinct xvec distinct yvec xvec ♯* yvec have "distinct(xvec@yvec)"
      by auto (simp add: fresh_star_def name_list_supp fresh_def)
    ultimately have "Prop C Ψ P (M⦇ν*(xvec@yvec)⦈⟨N) P'" by(rule_tac cOpen) auto
  }

  moreover note x  Ψ x  M x  xvec x  yvec xvec ♯* Ψ xvec ♯* P xvec ♯* M
                 yvec ♯* Ψ yvec ♯* P yvec ♯* M yvec ♯* C x  C xvec ♯* C distinct xvec distinct yvec
  ultimately have "Prop C Ψ (⦇νxP) (M⦇ν*(xvec@x#yvec)⦈⟨N) P'"
    by(rule_tac rOpen) 

  with xvec ♯* Ψ yvec ♯* Ψ xvec ♯* P yvec ♯* P xvec ♯* M yvec ♯* M 
       yvec ♯* C  S distinctPerm p x  C xvec ♯* C
       x  Ψ x  M x  xvec x  yvec A B C
  have "Prop C Ψ (⦇νxP) (p  (M⦇ν*(xvec@x#yvec)⦈⟨N)) (p  P')"
    apply(rule_tac α="M⦇ν*(xvec@x#yvec)⦈⟨N" in rAlpha)
    apply(assumption | simp)+
    apply(fastforce simp add: fresh_star_def abs_fresh)
    by(assumption | simp)+
  with αeq P'eq show ?case by simp
next
  case(cScope Ψ P α P' x α' C P'')
  note α  (⦇νxP') = α'  P''
  moreover from bn α ♯* α' have "bn α ♯* (bn α')" by auto
  moreover note distinct (bn α) distinct(bn α')
  moreover from bn α ♯* subject α bn α' ♯* subject α'
  have "bn α ♯* (α  ⦇νxP')" and "bn α' ♯* (α'  P'')" by simp+
  ultimately obtain p where S: "(set p)  (set(bn α)) × (set(bn(p  α)))" and "distinctPerm p"
                        and αEq: "α' = p  α" and P'eq: "P'' = p  (⦇νxP')" and "(bn(p  α)) ♯* α"
                        and "(bn(p  α)) ♯* (⦇νxP')"
    by(rule residualEq)
    
  note Ψ  P α  P'
  moreover from bn α ♯* subject α distinct(bn α)
  have "C. Prop C Ψ P α P'" by(rule_tac cScope) auto

  moreover note x  Ψ x  α bn α ♯* Ψ bn α ♯* P bn α ♯* subject α
                x  C bn α ♯* C distinct(bn α)
  ultimately have "Prop C Ψ (⦇νxP) α (⦇νxP')"
    by(rule rScope) 
  with bn α ♯* Ψ bn α ♯* P x  α bn α ♯* subject α bn α ♯* C bn α ♯* (bn α') S distinctPerm p bn(p  α) ♯* α bn(p  α) ♯* (⦇νxP')
  have "Prop C Ψ (⦇νxP) (p  α) (p  (⦇νxP'))"
    by(rule_tac rAlpha) simp+
  with αEq P'eq distinctPerm p show ?case by simp
next
  case(Bang Ψ P Rs α C)
  thus ?case by(rule_tac rBang) auto
qed

lemma outputInduct[consumes 1, case_names cOutput cCase cPar1 cPar2 cOpen cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   B    :: "('a, 'b, 'c) boundOutput"
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 'a  ('a, 'b, 'c) boundOutput  bool"
  and   C    :: "'d::fs_name"

  assumes "Ψ  P ROut M B"
  and     rOutput: "Ψ M K N P C. Ψ  M  K  Prop C Ψ (MN⟩.P) K (N ≺' P)"
  and     rCase: "Ψ P M B φ Cs C.  
                  Ψ  P (ROut M B); C. Prop C Ψ P M B; (φ, P) mem Cs; Ψ  φ; guarded P  
                   Prop C Ψ (Cases Cs) M B"
  and     rPar1: "Ψ ΨQ P M xvec N  P' AQ Q C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    C. Prop C (Ψ  ΨQ) P M (⦇ν*xvecN ≺' P');
                    AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* M; 
                    AQ ♯* xvec; AQ ♯* N; AQ ♯* P'; AQ ♯* C; xvec ♯* Q;
                    xvec ♯* Ψ; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; xvec ♯* C 
                    Prop C Ψ (P  Q) M (⦇ν*xvecN ≺' (P'  Q))"
  and     rPar2: "Ψ ΨP Q M xvec N  Q' AP P C.
                   Ψ  ΨP  Q M⦇ν*xvec⦈⟨N  Q'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C (Ψ  ΨP) Q M (⦇ν*xvecN ≺' Q');
                    AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* M; 
                    AP ♯* xvec; AP ♯* N; AP ♯* Q'; AP ♯* C; xvec ♯* P;
                    xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* Q; xvec ♯* M; xvec ♯* C 
                    Prop C Ψ (P  Q) M (⦇ν*xvecN ≺' (P  Q'))"
  and     rOpen:  "Ψ P M xvec yvec N P' x C.
                   Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'; x  supp N; C. Prop C Ψ P M (⦇ν*(xvec@yvec)N ≺' P');
                    x  Ψ; x  M; x  xvec; x  yvec; xvec ♯* Ψ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* yvec; yvec ♯* Ψ; yvec ♯* P; yvec ♯* M; yvec ♯* C; x  C; xvec ♯* C 
                    Prop C Ψ (⦇νxP) M (⦇ν*(xvec@x#yvec)N ≺' P')"
  and     rScope: "Ψ P M xvec N P' x C.
                    Ψ  P M⦇ν*xvec⦈⟨N  P'; C. Prop C Ψ P M (⦇ν*xvecN ≺' P');
                    x  Ψ; x  M; x  xvec; x  N; xvec ♯* Ψ; xvec ♯* P; xvec ♯* M;
                    x  C; xvec ♯* C 
                    Prop C Ψ (⦇νxP) M (⦇ν*xvecN ≺' ⦇νxP')"
  and     rBang:    "Ψ P M B C.
                     Ψ  P  !P (ROut M B); guarded P; C. Prop C Ψ (P  !P) M B 
                      Prop C Ψ (!P) M B"
  shows "Prop C Ψ P M B"
using Ψ  P (ROut M B)
proof(nominal_induct Ψ P Rs=="(ROut M B)" avoiding: C arbitrary: B rule: semantics.strong_induct)
  case(cInput Ψ M K xvec N Tvec P C)
  thus ?case by(simp add: residualInject)
next
  case(Output Ψ M K N P C)
  thus ?case by(force simp add: residualInject intro: rOutput)
next
  case(Case Ψ P Rs φ Cs C)
  thus ?case by(force intro: rCase) 
next
  case(cPar1 Ψ ΨQ P α P' Q AQ C)
  thus ?case by(force intro: rPar1 simp add: residualInject)
next
  case(cPar2 Ψ ΨP Q α Q' P AP C)
  thus ?case by(force intro: rPar2 simp add: residualInject)
next
  case cComm1
  thus ?case by(simp add: residualInject)
next
  case cComm2
  thus ?case by(simp add: residualInject)
next
  case(cOpen Ψ P M xvec yvec N P' x C B)
  thus ?case by(force intro: rOpen simp add: residualInject)
next
  case(cScope Ψ P M α P' x C)
  thus ?case by(force intro: rScope simp add: residualInject)
next
  case(Bang  Ψ P Rs C)
  thus ?case by(force intro: rBang)
qed

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

  assumes "Ψ  P α  P'"
  and     "bn α ♯* subject α"
  and     "distinct(bn α)"
  and     "y  set(bn α)"

  shows "y  supp(object α)"
using assms
proof(nominal_induct avoiding: P' arbitrary: y rule: semanticsInduct)
  case(cAlpha Ψ P α P' p P'' y)
  from y  set(bn(p  α)) have "(p  y)  (p  set(bn(p  α)))"
    by(rule pt_set_bij2[OF pt_name_inst, OF at_name_inst])
  hence "(p  y)  set(bn α)" using distinctPerm p
    by(simp add: eqvts)
  hence "(p  y)  supp(object α)" by(rule cAlpha)
  hence "(p  p  y)  (p  supp(object α))"
    by(rule pt_set_bij2[OF pt_name_inst, OF at_name_inst])
  thus ?case using distinctPerm p
    by(simp add: eqvts)
next
  case cInput 
  thus ?case by(simp add: supp_list_nil)
next
  case cOutput
  thus ?case by(simp add: supp_list_nil)
next
  case cCase
  thus ?case by simp
next
  case cPar1
  thus ?case by simp
next
  case cPar2
  thus ?case by simp
next
  case cComm1
  thus ?case by(simp add: supp_list_nil)
next
  case cComm2
  thus ?case by(simp add: supp_list_nil)
next
  case cOpen
  thus ?case by(auto simp add: supp_list_cons supp_list_append supp_atm supp_some)
next
  case cScope
  thus ?case by simp
next
  case cBang
  thus ?case by simp
qed

lemma alphaBoundOutputChain':
  fixes yvec :: "name list"
  and   xvec :: "name list"
  and   B    :: "('a, 'b, 'c) boundOutput"

  assumes "length xvec = length yvec"
  and     "yvec ♯* B"
  and     "yvec ♯* xvec"
  and     "distinct yvec"

  shows "⦇ν*xvecB = ⦇ν*yvec([xvec yvec] v B)"
using assms
proof(induct rule: composePermInduct)
  case cBase
  show ?case by simp
next
  case(cStep x xvec y yvec)
  thus ?case
    apply auto
    by(subst alphaBoundOutput[of y]) (auto simp add: eqvts)
qed

lemma alphaBoundOutputChain'':
  fixes yvec :: "name list"
  and   xvec :: "name list"
  and   N    :: 'a
  and   P    :: "('a, 'b, 'c) psi"

  assumes "length xvec = length yvec"
  and     "yvec ♯* N"
  and     "yvec ♯* P"
  and     "yvec ♯* xvec"
  and     "distinct yvec"

  shows "⦇ν*xvec(N ≺' P) = ⦇ν*yvec(([xvec yvec] v N) ≺' ([xvec yvec] v P))"
proof -
  from assms have "⦇ν*xvec(N ≺' P) = ⦇ν*yvec([xvec yvec] v (N ≺' P))"
    by(simp add: alphaBoundOutputChain')
  thus ?thesis by simp
qed

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

  assumes "α  P = β  Q"
  and     "distinct(bn α)"
  and     "x. x  set(bn α)  x  supp(object α)"
  and     "bn α ♯* bn β"
  and     "bn α ♯* (object β)"
  and     "bn α ♯* Q"

  shows "distinct(bn β)"
using assms
proof(rule_tac actionCases[where α=α], auto simp add: residualInject supp_some)
  fix xvec M yvec N
  assume Eq: "⦇ν*xvecN ≺' P = ⦇ν*yvecM ≺' Q" 
  assume "distinct xvec" and "xvec ♯* M" and "xvec ♯* yvec" and "xvec ♯* Q" 
  assume Mem: "x. x  set xvec  x  (supp N)"
  show "distinct yvec"
proof -
  from Eq have "length xvec = length yvec"
    by(rule boundOutputChainEqLength)
  with Eq distinct xvec xvec ♯* yvec xvec ♯* M xvec ♯* Q Mem show ?thesis
  proof(induct n=="length xvec" arbitrary: xvec yvec M Q rule: nat.induct)
    case(zero xvec yvec M Q)
    thus ?case by simp
  next
    case(Suc n xvec yvec M Q)
    have L: "length xvec = length yvec" and "Suc n = length xvec" by fact+
    then obtain x xvec' y yvec' where xEq: "xvec = x#xvec'" and yEq: "yvec = y#yvec'"
                                  and L': "length xvec' = length yvec'"
      by(cases xvec, auto, cases yvec, auto)
    have xvecFreshyvec: "xvec ♯* yvec" and xvecDist: "distinct xvec" by fact+
    with xEq yEq have xineqy: "x  y" and xvec'Freshyvec': "xvec' ♯* yvec'"
                  and xvec'Dist: "distinct xvec'" and xFreshxvec': "x  xvec'"
                  and xFreshyvec': "x  yvec'" and yFreshxvec': "y  xvec'"
      by auto
    have Eq: "⦇ν*xvecN ≺' P = ⦇ν*yvecM ≺' Q" by fact
    with xEq yEq xineqy have Eq': "⦇ν*xvec'N ≺' P = ⦇ν*([(x, y)]  yvec')([(x, y)]  M) ≺' ([(x, y)]  Q)"
      by(simp add: boundOutput.inject alpha eqvts) 
    moreover have Mem:"x. x  set xvec  x  supp N" by fact
    with xEq have "x. x  set xvec'  x  supp N" by simp
    moreover have "xvec ♯* M" by fact
    with xEq xFreshxvec' yFreshxvec' have "xvec' ♯* ([(x, y)]  M)" by simp
    moreover have xvecFreshQ: "xvec ♯* Q" by fact
    with xEq xFreshxvec' yFreshxvec' have "xvec' ♯* ([(x, y)]  Q)" by simp
    moreover have "Suc n = length xvec" by fact
    with xEq have "n = length xvec'" by simp
    moreover from xvec'Freshyvec' xFreshxvec' yFreshxvec' have "xvec' ♯* ([(x, y)]  yvec')"
      by simp
    moreover from L' have "length xvec' = length([(x, y)]  yvec')" by simp
    ultimately have "distinct([(x, y)]  yvec')" using xvec'Dist
      by(rule_tac Suc) (assumption | simp)+
    hence "distinct yvec'" by simp
    from Mem xEq have xSuppN: "x  supp N" by simp
    from L distinct xvec xvec ♯* yvec xvec ♯* M xvec ♯* Q 
    have "⦇ν*yvecM ≺' Q = ⦇ν*xvec([yvec xvec] v M) ≺' ([yvec xvec] v Q)"
      by(simp add: alphaBoundOutputChain'')
    with Eq have "N = [yvec xvec] v M" by simp
    with xEq yEq have "N = [(y, x)]  [yvec' xvec'] v M"
      by simp
    with xSuppN have ySuppM: "y  supp([yvec' xvec'] v M)"
      by(drule_tac pi="[(x, y)]" in pt_set_bij2[OF pt_name_inst, OF at_name_inst])
        (simp add: calc_atm eqvts name_swap)
    have "y  yvec'"
    proof(simp add: fresh_def, rule notI)
      assume "y  supp yvec'"
      hence "y mem yvec'"
        by(induct yvec') (auto simp add: supp_list_nil supp_list_cons supp_atm)
      moreover from xvec ♯* M xEq xFreshxvec' have "xvec' ♯* M" by simp
      ultimately have "y  [yvec' xvec'] v  M" using L' xvec'Freshyvec' xvec'Dist
        by(force intro: freshChainPerm)
      with ySuppM show "False" by(simp add: fresh_def)
    qed
    with distinct yvec'  yEq show ?case by simp
  qed
qed
qed

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

  assumes "Ψ  P α  P'"

  shows "distinct(bn α)"
using assms
proof(nominal_induct Ψ P x3=="α  P'" avoiding: α P' rule: semantics.strong_induct)
  case cInput
  thus ?case by(simp add: residualInject)
next
  case Output
  thus ?case by(simp add: residualInject)
next
  case Case
  thus ?case by(simp add: residualInject)
next
  case cPar1
  thus ?case by(force intro: alphaDistinct boundOutputBindObject)
next
  case cPar2
  thus ?case by(force intro: alphaDistinct boundOutputBindObject)
next 
  case cComm1
  thus ?case by(simp add: residualInject)
next
  case cComm2
  thus ?case by(simp add: residualInject)
next
  case(cOpen Ψ P M xvec yvec N P' x α P'')
  note M⦇ν*(xvec@x#yvec)⦈⟨N  P' = α  P''
  moreover from xvec ♯* yvec x  xvec x  yvec distinct xvec distinct yvec
  have "distinct(bn(M⦇ν*(xvec@x#yvec)⦈⟨N))"
    by auto (simp add: fresh_star_def fresh_def name_list_supp)
  moreover {
    fix y
    from Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P' x  supp N x  xvec x  yvec x  M x  Ψ distinct xvec distinct yvec xvec ♯* Ψ xvec ♯* P xvec ♯* M xvec ♯* yvec yvec ♯* Ψ yvec ♯* P yvec ♯* M
    have "Ψ  ⦇νxP M⦇ν*(xvec@x#yvec)⦈⟨N  P'" by(rule semantics.cOpen)
    moreover moreover from xvec ♯* M x  M yvec ♯* M 
    have "bn(M⦇ν*(xvec@x#yvec)⦈⟨N) ♯* (subject(M⦇ν*(xvec@x#yvec)⦈⟨N))"
      by simp
    moreover note distinct(bn(M⦇ν*(xvec@x#yvec)⦈⟨N))
    moreover assume "y  set(bn(M⦇ν*(xvec@x#yvec)⦈⟨N))"

    ultimately have "y  supp(object(M⦇ν*(xvec@x#yvec)⦈⟨N))"
      by(rule_tac boundOutputBindObject)
  }
  moreover from xvec ♯* α x  α yvec ♯* α
  have "bn(M⦇ν*(xvec@x#yvec)⦈⟨N) ♯* bn α" and "bn(M⦇ν*(xvec@x#yvec)⦈⟨N) ♯* object α" by simp+
  moreover from xvec ♯* P'' x  P'' yvec ♯* P''
  have "bn(M⦇ν*(xvec@x#yvec)⦈⟨N) ♯* P''" by simp
  ultimately show ?case by(rule alphaDistinct)
next
  case cScope
  thus ?case
    by(rule_tac alphaDistinct, auto) (rule_tac boundOutputBindObject, auto)
next
  case Bang
  thus ?case by simp
qed

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

  assumes "Ψ  M⦇λ*xvec N⦈.P  Rs"

  shows "distinct xvec"
using assms
by(nominal_induct Ψ P=="M⦇λ*xvec N⦈.P" Rs avoiding: xvec N P rule: semantics.strong_induct)
  (auto simp add: psi.inject intro: alphaInputDistinct)

lemma outputInduct'[consumes 2, case_names cAlpha cOutput cCase cPar1 cPar2 cOpen cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   yvec :: "name list"
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 'a  name list  'a  ('a, 'b, 'c) psi  bool"
  and   C    :: "'d::fs_name"

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     "xvec ♯* M"
  and     rAlpha: "Ψ P M xvec N P' p C. xvec ♯* Ψ; xvec ♯* P; xvec ♯* M;  xvec ♯* C; xvec ♯* (p  xvec); 
                                           set p  set xvec × set(p  xvec); distinctPerm p;
                                           (p  xvec) ♯* N; (p  xvec) ♯* P'; Prop C Ψ P M xvec N P' 
                                           Prop C Ψ P M (p  xvec) (p  N) (p  P')"
  and     rOutput: "Ψ M K N P C. Ψ  M  K  Prop C Ψ (MN⟩.P) K ([]) N P"
  and     rCase: "Ψ P M xvec N P' φ Cs C. Ψ  P M⦇ν*xvec⦈⟨N  P'; C. Prop C Ψ P M xvec N P'; (φ, P) mem Cs; Ψ  φ; guarded P 
                                             Prop C Ψ (Cases Cs) M xvec N P'"
  and     rPar1: "Ψ ΨQ P M xvec N  P' AQ Q C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    C. Prop C (Ψ  ΨQ) P M xvec N P';
                    AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* M; 
                    AQ ♯* xvec; AQ ♯* N; AQ ♯* P'; AQ ♯* C; xvec ♯* Q;
                    xvec ♯* Ψ; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; xvec ♯* C 
                    Prop C Ψ (P  Q) M xvec N (P'  Q)"
  and     rPar2: "Ψ ΨP Q M xvec N  Q' AP P C.
                   Ψ  ΨP  Q M⦇ν*xvec⦈⟨N  Q'; extractFrame P = AP, ΨP;  distinct AP;
                    C. Prop C (Ψ  ΨP) Q M xvec N Q';
                    AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* M; 
                    AP ♯* xvec; AP ♯* N; AP ♯* Q'; AP ♯* C; xvec ♯* Q;
                    xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* P; xvec ♯* M; xvec ♯* C 
                    Prop C Ψ (P  Q) M xvec N (P  Q')"
  and     rOpen:  "Ψ P M xvec yvec N P' x C.
                   Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'; x  supp N; C. Prop C Ψ P M (xvec@yvec) N P';
                    x  Ψ; x  M; x  xvec; x  yvec; xvec ♯* Ψ; xvec ♯* P; xvec ♯* M; 
                    yvec ♯* Ψ; yvec ♯* P; yvec ♯* M; yvec ♯* C; x  C; xvec ♯* C  
                    Prop C Ψ (⦇νxP) M (xvec@x#yvec) N P'"
  and     rScope: "Ψ P M xvec N P' x C.
                    Ψ  P M⦇ν*xvec⦈⟨N  P'; C. Prop C Ψ P M xvec N P';
                    x  Ψ; x  M; x  xvec; x  N; xvec ♯* Ψ;
                    xvec ♯* P; xvec ♯* M; x  C; xvec ♯* C 
                    Prop C Ψ (⦇νxP) M xvec N (⦇νxP')"
  and     rBang:    "Ψ P M xvec N P' C.
                     Ψ  P  !P M⦇ν*xvec⦈⟨N  P'; guarded P; C. Prop C Ψ (P  !P) M xvec N P' 
                      Prop C Ψ (!P) M xvec N P'"
  shows "Prop C Ψ P M xvec N P'"
proof -
  note Ψ  P M⦇ν*xvec⦈⟨N  P'
  moreover from xvec ♯* M have "bn(M⦇ν*xvec⦈⟨N) ♯* subject(M⦇ν*xvec⦈⟨N)" by simp
  moreover from Ψ  P M⦇ν*xvec⦈⟨N  P' have "distinct(bn(M⦇ν*xvec⦈⟨N))"
    by(rule boundOutputDistinct)
  ultimately show ?thesis
  proof(nominal_induct Ψ P α=="M⦇ν*xvec⦈⟨N" P' avoiding: C arbitrary: M xvec N rule: semanticsInduct)
    case(cAlpha Ψ P α P' p C M xvec N)
    from (p  α) = M⦇ν*xvec⦈⟨N have "(p  p  α) = p  (M⦇ν*xvec⦈⟨N)"
      by(simp add: fresh_bij)
    with distinctPerm p have A: "α = (p  M)⦇ν*(p  xvec)⦈⟨(p  N)"
      by(simp add: eqvts)
    with bn α ♯* Ψ bn α ♯* P bn α ♯* subject α bn α ♯* C bn α ♯* bn(p  α) distinctPerm p
    have "(p  xvec) ♯* Ψ" and  "(p  xvec) ♯* P" and  "(p  xvec) ♯* (p  M)" and  "(p  xvec) ♯* C" and  "(p  xvec) ♯* (p  p  xvec)"
      by auto
    moreover from A set p  set(bn α) × set(bn(p  α)) distinctPerm p
    have S: "set p  set(p  xvec) × set(p  p  xvec)" by simp
    moreover note distinctPerm p
    moreover from A bn(p  α) ♯* α bn(p  α) ♯* P'
    have "(p  p  xvec) ♯* (p  N)" and "(p  p  xvec) ♯* P'" by simp+
    moreover from A have "Prop C Ψ P (p  M) (p  xvec) (p  N) P'"
      by(rule cAlpha)
    ultimately have "Prop C Ψ P (p  M) (p  p  xvec) (p  p  N) (p  P')"
      by(rule rAlpha)
    moreover from A bn α ♯* subject α have "(p  xvec) ♯* (p  M)" by simp
    hence "xvec ♯* M" by(simp add: fresh_star_bij)
    from A bn(p  α) ♯* α distinctPerm p have "xvec ♯* (p  M)" by simp
    hence "(p  xvec) ♯* (p  p  M)" by(simp add: fresh_star_bij)
    with distinctPerm p have "(p  xvec) ♯* M" by simp
    with xvec ♯* M S distinctPerm p have  "(p  M) = M" by simp
    ultimately show ?case using S distinctPerm p by simp 
  next
    case cInput
    thus ?case by(simp add: residualInject)
  next
    case cOutput
    thus ?case by(force dest: rOutput simp add: action.inject)
  next
    case cCase
    thus ?case by(force intro: rCase)
  next
    case cPar1
    thus ?case by(force intro: rPar1)
  next
    case cPar2
    thus ?case by(force intro: rPar2)
  next
    case cComm1
    thus ?case by(simp add: action.inject)
  next
    case cComm2
    thus ?case by(simp add: action.inject)
  next
    case cOpen
    thus ?case by(fastforce intro: rOpen simp add: action.inject)
  next
    case cScope
    thus ?case by(fastforce intro: rScope)
  next
    case cBang
    thus ?case by(fastforce intro: rBang)
  qed
qed

lemma inputInduct[consumes 1, case_names cInput cCase cPar1 cPar2 cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 'a  'a  ('a, 'b, 'c) psi  bool"
  and   C    :: "'d::fs_name"

  assumes Trans: "Ψ  P MN  P'"
  and     rInput: "Ψ M K xvec N Tvec P C.
                   Ψ  M  K; distinct xvec; set xvec  supp N;
                    length xvec = length Tvec; xvec ♯* Ψ;
                    xvec ♯* M; xvec ♯* K; xvec ♯* C 
                    Prop C Ψ (M⦇λ*xvec N⦈.P)
                              K (N[xvec::=Tvec]) (P[xvec::=Tvec])"
  and     rCase: "Ψ P M N P' φ Cs C. Ψ  P MN  P'; C. Prop C Ψ P M N P'; (φ, P) mem Cs; Ψ  φ; guarded P 
                                        Prop C Ψ (Cases Cs) M N P'" 
  and     rPar1: "Ψ ΨQ P M N P' AQ Q C.
                   Ψ  ΨQ  P MN  P'; extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨQ) P M N P'; distinct AQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* M; AQ ♯* N;
                   AQ ♯* P'; AQ ♯* C 
                   Prop C Ψ (P  Q) M N (P'  Q)"
  and     rPar2: "Ψ ΨP Q M N Q' AP P C.
                   Ψ  ΨP  Q MN  Q'; extractFrame P = AP, ΨP; distinct AP;
                   C. Prop C (Ψ  ΨP) Q M N Q'; distinct AP;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* M; AP ♯* N;
                   AP ♯* Q'; AP ♯* C 
                   Prop C Ψ (P  Q) M N (P  Q')"
  and     rScope: "Ψ P M N P' x C.
                    Ψ  P MN  P'; C. Prop C Ψ P M N P'; x  Ψ; x  M; x  N; x  C 
                     Prop C Ψ (⦇νxP) M N (⦇νxP')"
  and     rBang:    "Ψ P M N P' C.
                     Ψ  P  !P MN  P'; guarded P; C. Prop C Ψ (P  !P) M N P'  Prop C Ψ (!P) M N P'"
  shows "Prop C Ψ P M N P'"
using Trans
proof(nominal_induct Ψ P Rs=="MN  P'" avoiding: C arbitrary: P' rule: semantics.strong_induct)
  case(cInput Ψ M K xvec N Tvec P C)
  thus ?case
    by(force intro: rInput simp add: residualInject action.inject)
next
  case(Output Ψ M K N P C)
  thus ?case by(simp add: residualInject)
next
  case(Case Ψ P Rs φ CS C)
  thus ?case by(force intro: rCase)
next
  case(cPar1 Ψ ΨQ P α P' Q AQ C P'')
  thus ?case by(force intro: rPar1 simp add: residualInject)
next 
  case(cPar2 Ψ ΨP Q α Q' xvec P C Q'')
  thus ?case by(force intro: rPar2 simp add: residualInject)
next
  case(cComm1 Ψ ΨQ P M N P' xvec ΨP Q K zvec Q' yvec C PQ)
  thus ?case by(simp add: residualInject)
next
  case(cComm2 Ψ ΨQ P M zvec N P' xvec ΨP Q K yvec Q' C PQ)
  thus ?case by(simp add: residualInject)
next
  case(cOpen Ψ P M xvec N P' x yvec C P'') 
  thus ?case by(simp add: residualInject)
next
  case(cScope Ψ P α P' x C P'')
  thus ?case by(force intro: rScope simp add: residualInject)
next
  case(Bang Ψ P Rs C)
  thus ?case by(force intro: rBang)
qed

lemma tauInduct[consumes 1, case_names cCase cPar1 cPar2 cComm1 cComm2 cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   Rs   :: "('a, 'b, 'c) residual"
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 ('a, 'b, 'c) psi  bool"
  and   C    :: "'d::fs_name"

  assumes Trans: "Ψ  P τ  P'"
  and     rCase: "Ψ P P' φ Cs C. Ψ  P τ  P'; C. Prop C Ψ P P'; (φ, P) mem Cs; Ψ  φ; guarded P  
                                    Prop C Ψ (Cases Cs) P'"
  and     rPar1: "Ψ ΨQ P P' AQ Q C.
                   Ψ  ΨQ  P τ  P'; extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨQ) P P';
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ;
                   AQ ♯* P'; AQ ♯* C 
                   Prop C Ψ (P  Q) (P'  Q)"
  and     rPar2: "Ψ ΨP Q Q' AP P C.
                   Ψ  ΨP  Q τ  Q'; extractFrame P = AP, ΨP; distinct AP;
                   C. Prop C (Ψ  ΨP) Q Q';
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ;
                   AP ♯* Q'; AP ♯* C 
                   Prop C Ψ (P  Q) (P  Q')"
  and     rComm1: "Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ C.
                   Ψ  ΨQ  P MN  P'; extractFrame P = AP, ΨP; distinct AP;
                    Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (⦇ν*xvec(P'  Q'))"
  and     rComm2: "Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P';  extractFrame P = AP, ΨP; distinct AP; 
                    Ψ  ΨP  Q KN  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (⦇ν*xvec(P'  Q'))"
  and     rScope: "Ψ P P' x C.
                    Ψ  P τ  P'; C. Prop C Ψ P P'; x  Ψ; x  C 
                     Prop C Ψ (⦇νxP) (⦇νxP')"
  and     rBang:    "Ψ P P' C.
                     Ψ  P  !P τ  P'; guarded P; C. Prop C Ψ (P  !P) P'  Prop C Ψ (!P) P'"
  shows "Prop C Ψ P P'"
using Trans
proof(nominal_induct Ψ P Rs=="τ  P'" avoiding: C arbitrary: P' rule: semantics.strong_induct)
  case(cInput M K xvec N Tvec P C)
  thus ?case by(simp add: residualInject)
next
  case(Output Ψ M K N P C)
  thus ?case by(simp add: residualInject)
next
  case(Case Ψ P Rs φ Cs C)
  thus ?case by(force intro: rCase simp add: residualInject)
next
  case(cPar1 Ψ ΨQ P α P' AQ Q C P'')
  thus ?case by(force intro: rPar1 simp add: residualInject)
next
  case(cPar2 Ψ ΨP Q α Q' AP P C Q'')
  thus ?case by(force intro: rPar2 simp add: residualInject)
next
  case(cComm1 Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ C PQ)
  thus ?case by(force intro: rComm1 simp add: residualInject)
next
  case(cComm2 Ψ ΨQ P M xvec N P' AP ΨP Q' AQ C PQ)
  thus ?case by(force intro: rComm2 simp add: residualInject)
next
  case(cOpen Ψ P M xvec N P' x yvec C P'')
  thus ?case by(simp add: residualInject)
next
  case(cScope Ψ P α P' x C P'')
  thus ?case by(force intro: rScope simp add: residualInject)
next
  case(Bang Ψ P Rs C )
  thus ?case by(force intro: rBang simp add: residualInject)
qed

lemma semanticsFrameInduct[consumes 3, case_names cAlpha cInput cOutput cCase cPar1 cPar2 cComm1 cComm2 cOpen cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   Rs   :: "('a, 'b, 'c) residual"
  and   AP   :: "name list"
  and   ΨP   :: 'b
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 ('a, 'b, 'c) residual  name list  'b  bool"
  and   C    :: "'d::fs_name"

  assumes Trans: "Ψ  P  Rs"
  and     FrP: "extractFrame P = AP, ΨP"
  and     "distinct AP"
  and     rAlpha: "Ψ P AP ΨP p Rs C. AP ♯* Ψ; AP ♯* P; AP ♯* (p  AP); AP ♯* Rs; AP ♯* C;
                                         set p  set AP × set(p  AP); distinctPerm p;
                                          Prop C Ψ P Rs AP ΨP  Prop C Ψ P Rs (p  AP) (p  ΨP)"
  and     rInput: "Ψ M K xvec N Tvec P C.
                   Ψ  M  K; distinct xvec; set xvec  supp N;
                    length xvec = length Tvec; xvec ♯* Ψ;
                    xvec ♯* M; xvec ♯* K; xvec ♯* C 
                    Prop C Ψ (M⦇λ*xvec N⦈.P)
                              (K(N[xvec::=Tvec])  (P[xvec::=Tvec])) ([]) (𝟭)"
  and     rOutput: "Ψ M K N P C. Ψ  M  K  Prop C Ψ (MN⟩.P) (KN  P) ([]) (𝟭)"
  and     rCase: "Ψ P Rs φ Cs AP ΨP C. Ψ  P  Rs; extractFrame P = AP, ΨP; distinct AP; C. Prop C Ψ P Rs AP ΨP;
                                            (φ, P) mem Cs; Ψ  φ; guarded P;  ΨP  𝟭; (supp ΨP) = ({}::name set);
                                            AP ♯* Ψ; AP ♯* P; AP ♯* Rs; AP ♯* C  Prop C Ψ (Cases Cs) Rs ([]) (𝟭)"
  and     rPar1: "Ψ ΨQ P α P' AQ Q AP ΨP C.
                   Ψ  ΨQ  P α  P';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨQ) P (α  P') AP ΨP; distinct(bn α);
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* α; AP ♯* P'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* α; AQ ♯* P'; AQ ♯* ΨP;
                   bn α ♯* Ψ; bn α ♯* P; bn α ♯* Q; bn α ♯* subject α; bn α ♯* ΨP; bn α ♯* ΨQ;
                   AP ♯* C; AQ ♯* C; bn α ♯* C 
                   Prop C Ψ (P  Q) (α  (P'  Q)) (AP@AQ) (ΨP  ΨQ)"
  and     rPar2: "Ψ ΨP Q α Q' AP P AQ ΨQ C.
                   Ψ  ΨP  Q α  Q';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨP) Q (α  Q') AQ ΨQ; distinct(bn α);
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* α; AP ♯* Q'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* α; AQ ♯* Q'; AQ ♯* ΨP;
                   bn α ♯* Ψ; bn α ♯* P; bn α ♯* Q; bn α ♯* subject α; bn α ♯* ΨP; bn α ♯* ΨQ;
                   AP ♯* C; AQ ♯* C; bn α ♯* C 
                   Prop C Ψ (P  Q) (α  (P  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rComm1: "Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ C.
                   Ψ  ΨQ  P MN  P'; extractFrame P = AP, ΨP; distinct AP;
                   C. Prop C (Ψ  ΨQ) P ((MN)  P') AP ΨP;
                    Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K;
                   C. Prop C (Ψ  ΨP) Q (K⦇ν*xvec⦈⟨N  Q') AQ ΨQ; distinct xvec;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (τ  ⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rComm2: "Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
                   C. Prop C (Ψ  ΨQ) P (M⦇ν*xvec⦈⟨N  P') AP ΨP;
                    Ψ  ΨP  Q KN  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨP) Q (KN  Q') AQ ΨQ;
                    Ψ  ΨP  ΨQ  M  K; distinct xvec;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (τ  ⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rOpen: "Ψ P M xvec yvec N P' x AP ΨP C.
                    Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P (M⦇ν*(xvec@yvec)⦈⟨N  P') AP ΨP; x  supp N; x  Ψ; x  M;
                     x  AP; x  xvec; x  yvec; AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P';
                     AP ♯* xvec; AP ♯* yvec; xvec ♯* yvec; distinct xvec; distinct yvec;
                     xvec ♯* Ψ; xvec ♯* P; xvec ♯* M; xvec ♯* ΨP; yvec ♯* ΨP;
                     yvec ♯* Ψ; yvec ♯* P; yvec ♯* M; AP ♯* C; x  C; xvec ♯* C; yvec ♯* C 
                     Prop C Ψ (⦇νxP) (M⦇ν*(xvec@x#yvec)⦈⟨N  P') (x#AP) ΨP"
  and     rScope: "Ψ P α P' x AP ΨP C.
                    Ψ  P α  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P (α  P') AP ΨP;
                     x  Ψ; x  α; x  AP; AP ♯* Ψ; AP ♯* P;
                     AP ♯* α; AP ♯* P'; distinct(bn α);
                     bn α ♯* Ψ; bn α ♯* P; bn α ♯* subject α; bn α ♯* ΨP;
                     AP ♯* C; x  C; bn α ♯* C 
                     Prop C Ψ (⦇νxP) (α  (⦇νxP')) (x#AP) ΨP"
  and     rBang:    "Ψ P Rs AP ΨP C.
                     Ψ  P  !P  Rs; guarded P; extractFrame P = AP, ΨP; distinct AP;
                      C. Prop C Ψ (P  !P) Rs AP (ΨP  𝟭); ΨP  𝟭; supp ΨP = ({}::name set);
                      AP ♯* Ψ; AP ♯* P; AP ♯* Rs; AP ♯* C  Prop C Ψ (!P) Rs ([]) (𝟭)"
  shows "Prop C Ψ P Rs AP ΨP"
using Trans FrP distinct AP
proof(nominal_induct  avoiding: AP ΨP C rule: semantics.strong_induct)
  case(cInput Ψ M K xvec N Tvec P AP ΨP C)
  from extractFrame (M⦇λ*xvec N⦈.P) = AP, ΨP
  have "AP = []" and "ΨP = 𝟭"
    by auto
  with Ψ  M  K distinct xvec set xvec  supp N length xvec = length Tvec
       xvec ♯* Ψ xvec ♯* M xvec ♯* K xvec ♯* C
  show ?case by(blast intro: rInput)
next
  case(Output Ψ M K N P AP ΨP)
  from extractFrame (MN⟩.P) = AP, ΨP
  have "AP = []" and "ΨP = 𝟭"
    by auto
  with Ψ  M  K show ?case
    by(blast intro: rOutput)
next
  case(Case Ψ P Rs φ Cs AcP ΨcP C)
  obtain AP ΨP where FrP: "extractFrame P = AP, ΨP" and "distinct AP"
                  and "AP ♯* (Ψ, P, Rs, C)"
    by(rule freshFrame)
  hence "AP ♯* Ψ" and "AP ♯* P" and "AP ♯* Rs" and "AP ♯* C"
    by simp+
  note Ψ  P  Rs FrP distinct AP
  moreover from FrP distinct AP AP ΨP C. extractFrame P = AP, ΨP; distinct AP  Prop C Ψ P Rs AP ΨP 
  have "C. Prop C Ψ P Rs AP ΨP" by simp
  moreover note (φ, P) mem Cs Ψ  φ guarded P
  moreover from guarded P FrP have "ΨP  𝟭" and "supp ΨP = ({}::name set)" by(metis guardedStatEq)+
  moreover note AP ♯* Ψ AP ♯* P AP ♯* Rs AP ♯* C
  ultimately have "Prop C Ψ (Cases Cs) Rs ([]) (𝟭)"
    by(rule rCase)
  thus ?case using extractFrame(Cases Cs) = AcP, ΨcP by simp
next
  case(cPar1 Ψ ΨQ P α P' Q AQ APQ ΨPQ C)
  obtain AP ΨP where FrP: "extractFrame P = AP, ΨP" and "distinct AP"
                           "AP ♯* (P, Q, Ψ, α, P', AQ, APQ, C, ΨQ)"
    by(rule freshFrame)
  hence "AP ♯* P" and "AP ♯* Q" and "AP ♯* Ψ" and "AP ♯* α" and "AP ♯* P'"
    and "AP ♯* AQ" and "AP ♯* APQ" and "AP ♯* C" and "AP ♯* ΨQ"
    by simp+

  have FrQ: "extractFrame Q = AQ, ΨQ" by fact

  from AQ ♯* P AP ♯* AQ FrP have "AQ ♯* ΨP"
    by(force dest: extractFrameFreshChain)

  from bn α ♯* P AP ♯* α FrP have "bn α ♯* ΨP"
    by(force dest: extractFrameFreshChain)

  from extractFrame(P  Q) = APQ, ΨPQ FrP FrQ AP ♯* AQ AP ♯* ΨQ AQ ♯* ΨP
  have "(AP@AQ), ΨP  ΨQ = APQ, ΨPQ"
    by simp
  moreover from distinct AP distinct AQ AP ♯* AQ have "distinct(AP@AQ)"
    by(auto simp add: fresh_star_def fresh_def name_list_supp)
  ultimately obtain p where S: "set p  set(AP@AQ) × set((p  AP)@(p  AQ))"  and "distinctPerm p"
                        and Ψeq: "ΨPQ = p  (ΨP  ΨQ)" and Aeq: "APQ = (p  AP)@(p  AQ)"
    using AP ♯* APQ AQ ♯* APQ distinct APQ
    by(rule_tac frameChainEq') (assumption | simp add: eqvts)+
  
  note Ψ  ΨQ  P α  P' FrP distinct AP FrQ distinct AQ

  moreover from FrP distinct AP AP ΨP C. extractFrame P = AP, ΨP; distinct AP  Prop C (Ψ  ΨQ) P (α  P') AP ΨP
  have "C. Prop C (Ψ  ΨQ) P (α  P') AP ΨP" by simp

  moreover note AP ♯* P AP ♯* Q AP ♯* Ψ AP ♯* α AP ♯* P' AP ♯* AQ AP ♯* ΨQ
                AQ ♯* P AQ ♯* Q AQ ♯* Ψ AQ ♯* α AQ ♯* P' AQ ♯* ΨP distinct(bn α)
                bn α ♯* Ψ bn α ♯* P  bn α ♯* Q  bn α ♯* subject α  bn α ♯* ΨP  bn α ♯* ΨQ 
                AP ♯* C AQ ♯* C bn α ♯* C
  ultimately have "Prop C Ψ (P  Q) (α  (P'  Q)) (AP@AQ) (ΨP  ΨQ)"
    by(rule_tac rPar1)
  with AP ♯* Ψ AP ♯* P AP ♯* Q AP ♯* α AP ♯* P' AP ♯* APQ AP ♯* C
       AQ ♯* Ψ AQ ♯* P AQ ♯* Q AQ ♯* α AQ ♯* P' AQ ♯* APQ AQ ♯* C
       S distinctPerm p Aeq
  have "Prop C Ψ (P  Q) (α  (P'  Q)) (p  (AP@AQ)) (p  (ΨP  ΨQ))"
    by(rule_tac rAlpha) (assumption | simp add: eqvts)+
  with Ψeq Aeq show ?case by(simp add: eqvts)
next
  case(cPar2 Ψ ΨP Q α Q' P AP APQ ΨPQ C)
  obtain AQ ΨQ where FrQ: "extractFrame Q = AQ, ΨQ" and "distinct AQ"
                           "AQ ♯* (P, Q, Ψ, α, Q', AP, APQ, C, ΨP)"
    by(rule freshFrame)
  hence "AQ ♯* P" and "AQ ♯* Q" and "AQ ♯* Ψ" and "AQ ♯* α" and "AQ ♯* Q'"
    and "AQ ♯* AP" and "AQ ♯* APQ" and "AQ ♯* C" and "AQ ♯* ΨP"
    by simp+

  from AQ ♯* AP have "AP ♯* AQ" by simp
  have FrP: "extractFrame P = AP, ΨP" by fact

  from AP ♯* Q AQ ♯* AP FrQ have "AP ♯* ΨQ"
    by(force dest: extractFrameFreshChain)
  from bn α ♯* Q AQ ♯* α FrQ have "bn α ♯* ΨQ"
    by(force dest: extractFrameFreshChain)

  from extractFrame(P  Q) = APQ, ΨPQ FrP FrQ AP ♯* AQ AP ♯* ΨQ AQ ♯* ΨP
  have "(AP@AQ), ΨP  ΨQ = APQ, ΨPQ"
    by simp
  moreover from distinct AP distinct AQ AP ♯* AQ have "distinct(AP@AQ)"
    by(auto simp add: fresh_star_def fresh_def name_list_supp)
  ultimately obtain p where S: "(set p  (set(AP@AQ)) × (set APQ))"  and "distinctPerm p"
                        and Ψeq: "ΨPQ = p  (ΨP  ΨQ)" and Aeq: "APQ = ((p  AP)@(p  AQ))"
    using AP ♯* APQ AQ ♯* APQ distinct APQ
    by(rule_tac frameChainEq') (assumption | simp add: eqvts)+

  note Ψ  ΨP  Q α  Q' FrP distinct AP FrQ distinct AQ

  moreover from FrQ distinct AQ AQ ΨQ C. extractFrame Q = AQ, ΨQ; distinct AQ  Prop C (Ψ  ΨP) Q (α  Q') AQ ΨQ
  have "C. Prop C (Ψ  ΨP) Q (α  Q') AQ ΨQ" by simp

  moreover note AP ♯* P AP ♯* Q AP ♯* Ψ AP ♯* α AP ♯* Q' AP ♯* AQ AP ♯* ΨQ
                AQ ♯* P AQ ♯* Q AQ ♯* Ψ AQ ♯* α AQ ♯* Q' AQ ♯* ΨP distinct(bn α)
                bn α ♯* Ψ bn α ♯* P  bn α ♯* Q  bn α ♯* subject α  bn α ♯* ΨP  bn α ♯* ΨQ 
                AP ♯* C AQ ♯* C bn α ♯* C
  ultimately have "Prop C Ψ (P  Q) (α  (P  Q')) (AP@AQ) (ΨP  ΨQ)"
    by(rule_tac rPar2)

  with AP ♯* Ψ AP ♯* P AP ♯* Q AP ♯* α AP ♯* Q' AP ♯* APQ AP ♯* C
       AQ ♯* Ψ AQ ♯* P AQ ♯* Q AQ ♯* α AQ ♯* Q' AQ ♯* APQ AQ ♯* C
       S distinctPerm p Aeq
  have "Prop C Ψ (P  Q) (α  (P  Q')) (p  (AP@AQ)) (p  (ΨP  ΨQ))"
    by(rule_tac rAlpha) (assumption | simp add: eqvts)+
  with Ψeq Aeq show ?case by(simp add: eqvts)
next
  case(cComm1 Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ APQ ΨPQ C)
  from distinct AP distinct AQ AP ♯* AQ have "distinct(AP@AQ)"
    by(auto simp add: fresh_star_def fresh_def name_list_supp)
  from cComm1 have  "Prop C Ψ (P  Q) (τ  ⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
    by(rule_tac rComm1)
  moreover from extractFrame(P  Q) = APQ, ΨPQ extractFrame P = AP, ΨP extractFrame Q = AQ, ΨQ
                AP ♯* AQ AP ♯* ΨQ AQ ♯* ΨP
  have "(AP@AQ), (ΨP  ΨQ) = APQ, ΨPQ"
    by simp
  with AP ♯* APQ AQ ♯* APQ distinct(AP@AQ) distinct APQ
  obtain p where S: "(set p  (set(AP@AQ)) × (set APQ))"  and "distinctPerm p"
             and Ψeq: "ΨPQ = p  (ΨP  ΨQ)" and Aeq: "APQ = p  (AP@AQ)"
    by(rule_tac frameChainEq') (assumption | simp)+
  moreover note AP ♯* Ψ AQ ♯* Ψ AP ♯* P AQ ♯* P AP ♯* Q AQ ♯* Q AP ♯* xvec
                AQ ♯* xvec AP ♯* P' AQ ♯* P' AP ♯* Q' AQ ♯* Q' AP ♯* APQ AQ ♯* APQ
                AP ♯* C AQ ♯* C
  ultimately have "Prop C Ψ (P  Q) (τ  ⦇ν*xvec(P'  Q')) (p  (AP@AQ)) (p  (ΨP  ΨQ))"
    by(rule_tac rAlpha) auto
  with Ψeq Aeq show ?case by simp
next
  case(cComm2 Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ APQ ΨPQ C)
  from distinct AP distinct AQ AP ♯* AQ have "distinct(AP@AQ)"
    by(auto simp add: fresh_star_def fresh_def name_list_supp)
  from cComm2 have  "Prop C Ψ (P  Q) (τ  ⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
    by(rule_tac rComm2)
  moreover from extractFrame(P  Q) = APQ, ΨPQ extractFrame P = AP, ΨP extractFrame Q = AQ, ΨQ
                AP ♯* AQ AP ♯* ΨQ AQ ♯* ΨP
  have "(AP@AQ), (ΨP  ΨQ) = APQ, ΨPQ"
    by simp
  with AP ♯* APQ AQ ♯* APQ distinct(AP@AQ) distinct APQ
  obtain p where S: "(set p  (set(AP@AQ)) × (set APQ))"  and "distinctPerm p"
             and Ψeq: "ΨPQ = p  (ΨP  ΨQ)" and Aeq: "APQ = p  (AP@AQ)"
    by(rule_tac frameChainEq') (assumption | simp)+
  moreover note AP ♯* Ψ AQ ♯* Ψ AP ♯* P AQ ♯* P AP ♯* Q AQ ♯* Q AP ♯* xvec
                AQ ♯* xvec AP ♯* P' AQ ♯* P' AP ♯* Q' AQ ♯* Q' AP ♯* APQ AQ ♯* APQ
                AP ♯* C AQ ♯* C
  ultimately have "Prop C Ψ (P  Q) (τ  ⦇ν*xvec(P'  Q')) (p  (AP@AQ)) (p  (ΨP  ΨQ))"
    by(rule_tac rAlpha) auto
  with Ψeq Aeq show ?case by simp
next
  case(cOpen Ψ P M xvec yvec N P' x AxP ΨxP C)
  obtain AP ΨP where FrP: "extractFrame P = AP, ΨP" and "distinct AP"
                  and "AP ♯* (Ψ, P, M, xvec, yvec, N, P', AxP, ΨxP, C, x)"
    by(rule freshFrame)
  hence "AP ♯* Ψ" and "AP ♯* P" and "AP ♯* M" and "AP ♯* xvec"and "AP ♯* yvec" and "AP ♯* N" and "AP ♯* P'"
    and "AP ♯* AxP" and "AP ♯* ΨxP" and "AP ♯* C" and "x  AP"
    by simp+

  from xvec ♯* P AP ♯* xvec FrP have "xvec ♯* ΨP"
    by(force dest: extractFrameFreshChain)
  from yvec ♯* P AP ♯* yvec FrP have "yvec ♯* ΨP"
    by(force dest: extractFrameFreshChain)

  from extractFrame(⦇νxP) = AxP, ΨxP FrP
  have "(x#AP), ΨP = AxP, ΨxP"
    by simp
  moreover from x  AP distinct AP have "distinct(x#AP)" by simp
  ultimately obtain p where S: "set p  set (x#AP) × set (p  (x#AP))" and "distinctPerm p"
                        and Ψeq: "ΨxP = p  ΨP" and Aeq: "AxP = (p  x)#(p  AP)"
    using AP ♯* AxPx  AxP distinct AxP
    by(rule_tac frameChainEq') (assumption | simp add: eqvts)+

  note Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P' FrP distinct AP
  moreover from FrP distinct AP AP ΨP C. extractFrame P = AP, ΨP; distinct AP  Prop C Ψ P (M⦇ν*(xvec@yvec)⦈⟨N  P') AP ΨP
  have "C. Prop C Ψ P (M⦇ν*(xvec@yvec)⦈⟨N  P') AP ΨP" by simp
  moreover note x  Ψ x  M x  xvec x  yvec x  supp N x  AP AP ♯* Ψ AP ♯* Ψ AP ♯* P AP ♯* M AP ♯* xvec AP ♯* yvec AP ♯* N AP ♯* P'
                xvec ♯* Ψ xvec ♯* P  xvec ♯* M  xvec ♯* ΨP yvec ♯* Ψ yvec ♯* P  yvec ♯* M  yvec ♯* ΨP 
                AP ♯* C x  C xvec ♯* C yvec ♯* C xvec ♯* yvec distinct xvec distinct yvec
  ultimately have "Prop C Ψ (⦇νxP) (M⦇ν*(xvec@x#yvec)⦈⟨N  P') (x#AP) ΨP"
    by(rule_tac rOpen)
  
  with AP ♯* Ψ AP ♯* P AP ♯* M AP ♯* xvec AP ♯* yvec AP ♯* N AP ♯* P' AP ♯* AxP AP ♯* C x  AxP AP ♯* AxP x  AP
       x  Ψ x  M x  C x  xvec x  yvec Aeq
       S distinctPerm p
  have "Prop C Ψ (⦇νxP) (M⦇ν*(xvec@x#yvec)⦈⟨N  P') (p  (x#AP)) (p  ΨP)"
    by(rule_tac AP="x#AP" in rAlpha) (assumption | simp add: abs_fresh fresh_star_def boundOutputFresh)+
  with Ψeq Aeq show ?case by(simp add: eqvts)
next
  case(cScope Ψ P α P' x AxP ΨxP C)
  obtain AP ΨP where FrP: "extractFrame P = AP, ΨP" and "distinct AP"
                  and "AP ♯* (Ψ, P, α, P', AxP, ΨxP, C, x)"
    by(rule freshFrame)
  hence "AP ♯* Ψ" and "AP ♯* P" and "AP ♯* α" and "AP ♯* P'"
    and "AP ♯* AxP" and "AP ♯* ΨxP" and "AP ♯* C" and "x  AP"
    by simp+

  from bn α ♯* P AP ♯* α FrP have "bn α ♯* ΨP"
    by(force dest: extractFrameFreshChain)

  from extractFrame(⦇νxP) = AxP, ΨxP FrP
  have "(x#AP), ΨP = AxP, ΨxP"
    by simp
  moreover from x  AP distinct AP have "distinct(x#AP)" by simp
  ultimately obtain p where S: "set p  set (x#AP) × set (p  (x#AP))" and "distinctPerm p"
                        and Ψeq: "ΨxP = p  ΨP" and Aeq: "AxP = (p  x)#(p  AP)"
    using AP ♯* AxPx  AxP distinct AxP
    by(rule_tac frameChainEq') (assumption | simp add: eqvts)+

  note Ψ  P α  P' FrP distinct AP
  moreover from FrP distinct AP AP ΨP C. extractFrame P = AP, ΨP; distinct AP  Prop C Ψ P (α  P') AP ΨP
  have "C. Prop C Ψ P (α  P') AP ΨP" by simp
  moreover note x  Ψ x  α x  AP AP ♯* Ψ AP ♯* Ψ AP ♯* P AP ♯* α AP ♯* P' distinct(bn α)
                bn α ♯* Ψ bn α ♯* P  bn α ♯* subject α  bn α ♯* ΨP AP ♯* C x  C bn α ♯* C 
  ultimately have "Prop C Ψ (⦇νxP) (α  (⦇νxP')) (x#AP) ΨP"
    by(rule_tac rScope)
  
  with AP ♯* Ψ AP ♯* P AP ♯* α AP ♯* P' AP ♯* AxP AP ♯* C x  AxP AP ♯* AxP x  AP
       x  Ψ x  α x  C Aeq
       S distinctPerm p
  have "Prop C Ψ (⦇νxP) (α  (⦇νxP')) (p  (x#AP)) (p  ΨP)"
    by(rule_tac AP="x#AP" in rAlpha) (assumption | simp add: abs_fresh fresh_star_def)+
  with Ψeq Aeq show ?case by(simp add: eqvts)
next
  case(Bang Ψ P Rs AbP ΨbP C)

  obtain AP ΨP where FrP: "extractFrame P = AP, ΨP" and "distinct AP"
                  and "AP ♯* (Ψ, P, Rs, C)"
    by(rule freshFrame)
  hence "AP ♯* Ψ" and "AP ♯* P" and "AP ♯* Rs" and "AP ♯* C" 
    by simp+

  note Ψ  P  !P  Rs guarded P FrP distinct AP
  moreover from FrP have "extractFrame (P  !P) = AP, ΨP  𝟭"
    by simp
  with distinct AP AP ΨP C. extractFrame (P  !P) = AP, ΨP; distinct AP  Prop C Ψ (P  !P) Rs AP ΨP
  have "C. Prop C Ψ (P  !P) Rs AP (ΨP  𝟭)" by simp
  moreover from guarded P FrP have "ΨP  𝟭" and "supp ΨP = ({}::name set)" by(metis guardedStatEq)+
  moreover note AP ♯* Ψ AP ♯* P AP ♯* Rs AP ♯* C
  ultimately have "Prop C Ψ (!P) Rs ([]) (𝟭)"
    by(rule rBang) 
  thus ?case using extractFrame(!P) = AbP, ΨbP by simp
qed

lemma semanticsFrameInduct'[consumes 5, case_names cAlpha cFrameAlpha cInput cOutput cCase cPar1 cPar2 cComm1 cComm2 cOpen cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   Rs   :: "('a, 'b, 'c) residual"
  and   AP   :: "name list"
  and   ΨP   :: 'b
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi  'a action 
                 ('a, 'b, 'c) psi  name list  'b  bool"
  and   C    :: "'d::fs_name"

  assumes Trans: "Ψ  P α  P'"
  and     FrP: "extractFrame P = AP, ΨP"
  and     "distinct AP"
  and     "bn α ♯* subject α"
  and     "distinct(bn α)"
  and     rAlpha: "Ψ P α P' p AP ΨP C. bn α ♯* Ψ; bn α ♯* P; bn α ♯* subject α; bn α ♯* ΨP;
                                           bn α ♯* C; bn α ♯* (p  α); AP ♯* Ψ; AP ♯* P; AP ♯* α; AP ♯* P'; AP ♯* C;
                                           set p  set(bn α) × set(bn(p  α)); distinctPerm p;
                                           bn(p  α) ♯* α; (bn(p  α)) ♯* P'; Prop C Ψ P α P' AP ΨP 
                                           Prop C Ψ P (p  α) (p  P') AP ΨP"
  and     rFrameAlpha: "Ψ P AP ΨP p α P' C. AP ♯* Ψ; AP ♯* P; AP ♯* (p  AP); AP ♯* α; AP ♯* P'; AP ♯* C;
                                                set p  set AP × set(p  AP); distinctPerm p; AP ♯* subject α;
                                                Prop C Ψ P α P' AP ΨP  Prop C Ψ P α P' (p  AP) (p  ΨP)"
  and     rInput: "Ψ M K xvec N Tvec P C.
                   Ψ  M  K; distinct xvec; set xvec  supp N;
                    length xvec = length Tvec; xvec ♯* Ψ;
                    xvec ♯* M; xvec ♯* K; xvec ♯* C 
                    Prop C Ψ (M⦇λ*xvec N⦈.P)
                              (K(N[xvec::=Tvec])) (P[xvec::=Tvec]) ([]) (𝟭)"
  and     rOutput: "Ψ M K N P C. Ψ  M  K  Prop C Ψ (MN⟩.P) (KN) P ([]) (𝟭)"
  and     rCase: "Ψ P α P' φ Cs AP ΨP C. Ψ  P α  P'; extractFrame P = AP, ΨP; distinct AP; C. Prop C Ψ P α P' AP ΨP;
                                            (φ, P) mem Cs; Ψ  φ; guarded P;  ΨP  𝟭; (supp ΨP) = ({}::name set);
                                            AP ♯* Ψ; AP ♯* P; AP ♯* α; AP ♯* P'; AP ♯* C  Prop C Ψ (Cases Cs) α P' ([]) (𝟭)"
  and     rPar1: "Ψ ΨQ P α P' AQ Q AP ΨP C.
                   Ψ  ΨQ  P α  P';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨQ) P α P' AP ΨP;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* α; AP ♯* P'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* α; AQ ♯* P'; AQ ♯* ΨP;
                   bn α ♯* Ψ; bn α ♯* P; bn α ♯* Q; bn α ♯* subject α; bn α ♯* ΨP; bn α ♯* ΨQ;
                   AP ♯* C; AQ ♯* C; bn α ♯* C 
                   Prop C Ψ (P  Q) α (P'  Q) (AP@AQ) (ΨP  ΨQ)"
  and     rPar2: "Ψ ΨP Q α Q' AP P AQ ΨQ C.
                   Ψ  ΨP  Q α  Q';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨP) Q α Q' AQ ΨQ;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* α; AP ♯* Q'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* α; AQ ♯* Q'; AQ ♯* ΨP;
                   bn α ♯* Ψ; bn α ♯* P; bn α ♯* Q; bn α ♯* subject α; bn α ♯* ΨP; bn α ♯* ΨQ;
                   AP ♯* C; AQ ♯* C; bn α ♯* C 
                   Prop C Ψ (P  Q) α (P  Q') (AP@AQ) (ΨP  ΨQ)"
  and     rComm1: "Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ C.
                   Ψ  ΨQ  P MN  P'; extractFrame P = AP, ΨP; distinct AP;
                   C. Prop C (Ψ  ΨQ) P (MN) P' AP ΨP;
                    Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K; distinct xvec;
                   C. Prop C (Ψ  ΨP) Q (K⦇ν*xvec⦈⟨N) Q' AQ ΨQ;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (τ) (⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rComm2: "Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
                   C. Prop C (Ψ  ΨQ) P (M⦇ν*xvec⦈⟨N) P' AP ΨP;
                    Ψ  ΨP  Q KN  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨP) Q (KN) Q' AQ ΨQ;
                    Ψ  ΨP  ΨQ  M  K; distinct xvec;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (τ) (⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rOpen: "Ψ P M xvec yvec N P' x AP ΨP y C.
                    Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P (M⦇ν*(xvec@yvec)⦈⟨N) P' AP ΨP; x  supp N; x  Ψ; x  M;
                     x  AP; x  xvec; x  yvec; AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P';
                     AP ♯* xvec; AP ♯* yvec; xvec ♯* yvec; distinct xvec; distinct yvec;
                     xvec ♯* Ψ; xvec ♯* P; xvec ♯* M; xvec ♯* ΨP; 
                     yvec ♯* Ψ; yvec ♯* P; yvec ♯* M; AP ♯* C; x  C; xvec ♯* C; yvec ♯* C;
                     y  x; y  Ψ; y  P; y  M; y  xvec; y  yvec; y  N; y  P'; y  AP; y  ΨP; y  C 
                     Prop C Ψ (⦇νxP) (M⦇ν*(xvec@y#yvec)⦈⟨([(x, y)]  N)) ([(x, y)]  P') (x#AP) ΨP"
  and     rScope: "Ψ P α P' x AP ΨP C.
                    Ψ  P α  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P α P' AP ΨP;
                     x  Ψ; x  α; x  AP; AP ♯* Ψ; AP ♯* P;
                     AP ♯* α; AP ♯* P';
                     bn α ♯* Ψ; bn α ♯* P; bn α ♯* subject α; bn α ♯* ΨP;
                     AP ♯* C; x  C; bn α ♯* C 
                     Prop C Ψ (⦇νxP) α (⦇νxP') (x#AP) ΨP"
  and     rBang:    "Ψ P α P' AP ΨP C.
                     Ψ  P  !P α  P'; guarded P; extractFrame P = AP, ΨP; distinct AP;
                      C. Prop C Ψ (P  !P) α P' AP (ΨP  𝟭); ΨP  𝟭; supp ΨP = ({}::name set);
                      AP ♯* Ψ; AP ♯* P; AP ♯* α; AP ♯* P'; AP ♯* C  Prop C Ψ (!P) α P' ([]) (𝟭)"
  shows "Prop C Ψ P α P' AP ΨP"
using Trans FrP distinct AP bn α ♯* subject α distinct(bn α)
proof(nominal_induct Ψ P Rs=="α  P'" AP ΨP avoiding: C α P' rule: semanticsFrameInduct)
  case cAlpha 
  thus ?case using rFrameAlpha
    by auto
next
  case cInput
  thus ?case using rInput
    by(auto simp add: residualInject)
next
  case cOutput
  thus ?case using rOutput
    by(auto simp add: residualInject)
next
  case cCase
  thus ?case using rCase
    by(auto simp add: residualInject)
next
  case(cPar1 Ψ ΨQ P α P' AQ Q AP ΨP C α' P'')
  note α  (P'  Q) = α'  P''
  moreover from bn α ♯* α' have "bn α ♯* (bn α')" by auto
  moreover note distinct (bn α) distinct(bn α')
  moreover from bn α ♯* subject α bn α' ♯* subject α'
  have "bn α ♯* (α  P'  Q)" and "bn α' ♯* (α'  P'')" by simp+
  ultimately obtain p where S: "(set p)  (set(bn α)) × (set(bn(p  α)))" and "distinctPerm p"
                        and αEq: "α' = p  α" and P'eq: "P'' = p  (P'  Q)" and "(bn(p  α)) ♯* α"
                        and "(bn(p  α)) ♯* (P'  Q)"
    by(rule residualEq)
    
  note Ψ  ΨQ  P α  P' extractFrame Q = AQ, ΨQ distinct AQ
  moreover from bn α ♯* subject α distinct(bn α) AP ♯* α
  have "C. Prop C (Ψ  ΨQ) P α P' AP ΨP" by(rule_tac cPar1) auto

  moreover note AQ ♯* P AQ ♯* Q AQ ♯* Ψ AQ ♯* α AQ ♯* P' AQ ♯* C AP ♯* P AP ♯* Q AP ♯* Ψ AP ♯* α AP ♯* P' AP ♯* C
                bn α ♯* Q distinct(bn α) bn α ♯* Ψ bn α ♯* ΨQ bn α ♯* P bn α ♯* subject α bn α ♯* C
                extractFrame P = AP, ΨP distinct AP AP ♯* AQ AP ♯* ΨQ AQ ♯* ΨP bn α ♯* ΨP
  ultimately have "Prop C Ψ (P  Q) α (P'  Q) (AP@AQ) (ΨP  ΨQ)"
    by(rule_tac rPar1)
  with bn α ♯* Ψ bn α ♯* P bn α ♯* Q bn α ♯* subject α bn α ♯* C bn α ♯* (bn α') S distinctPerm p bn(p  α) ♯* α bn(p  α) ♯* (P'  Q) bn α ♯* ΨP bn α ♯* ΨQ AP ♯* α AQ ♯* α AP ♯* α' AQ ♯* α' αEq bn α ♯* ΨP bn α ♯* α' AP ♯* Ψ AQ ♯* Ψ AP ♯* P AQ ♯* P AP ♯* Q AQ ♯* Q AP ♯* P' AQ ♯* P' AP ♯* C AQ ♯* C
  have "Prop C Ψ (P  Q) (p  α) (p  (P'  Q)) (AP@AQ) (ΨP  ΨQ)"
    by(rule_tac rAlpha) auto
  with αEq P'eq distinctPerm p show ?case by simp
next
  case(cPar2 Ψ ΨP Q α Q' AP P AQ ΨQ C α' Q'')
  note α  (P  Q') = α'  Q''
  moreover from bn α ♯* α' have "bn α ♯* (bn α')" by auto
  moreover note distinct (bn α) distinct(bn α')
  moreover from bn α ♯* subject α bn α' ♯* subject α'
  have "bn α ♯* (α  P  Q')" and "bn α' ♯* (α'  Q'')" by simp+
  ultimately obtain p where S: "(set p)  (set(bn α)) × (set(bn(p  α)))" and "distinctPerm p"
                        and αEq: "α' = p  α" and Q'eq: "Q'' = p  (P  Q')" and "(bn(p  α)) ♯* α"
                        and "(bn(p  α)) ♯* (P  Q')"
    by(rule residualEq)
    
  note Ψ  ΨP  Q α  Q' extractFrame P = AP, ΨP distinct AP
  moreover from bn α ♯* subject α distinct(bn α) AQ ♯* α
  have "C. Prop C (Ψ  ΨP) Q α Q' AQ ΨQ" by(rule_tac cPar2) auto

  moreover note AQ ♯* P AQ ♯* Q AQ ♯* Ψ AQ ♯* α AQ ♯* Q' AQ ♯* C AP ♯* P AP ♯* Q AP ♯* Ψ AP ♯* α AP ♯* Q' AP ♯* C
                bn α ♯* Q distinct(bn α) bn α ♯* Ψ bn α ♯* ΨQ bn α ♯* P bn α ♯* subject α bn α ♯* C
                extractFrame Q = AQ, ΨQ distinct AQ AP ♯* AQ AP ♯* ΨQ AQ ♯* ΨP bn α ♯* ΨP
  ultimately have "Prop C Ψ (P  Q) α (P  Q') (AP@AQ) (ΨP  ΨQ)"
    by(rule_tac rPar2) auto
  with bn α ♯* Ψ bn α ♯* P bn α ♯* Q bn α ♯* subject α bn α ♯* C bn α ♯* (bn α') S distinctPerm p bn(p  α) ♯* α bn(p  α) ♯* (P  Q') bn α ♯* ΨP bn α ♯* ΨQ AP ♯* α AQ ♯* α AP ♯* α' AQ ♯* α' αEq bn α ♯* α' AP ♯* Ψ AQ ♯* Ψ AP ♯* P AQ ♯* P AP ♯* Q AQ ♯* Q AP ♯* Q' AQ ♯* Q' AP ♯* C AQ ♯* C
  have "Prop C Ψ (P  Q) (p  α) (p  (P  Q')) (AP@AQ) (ΨP  ΨQ)"
   by(rule_tac rAlpha) auto
  with αEq Q'eq distinctPerm p show ?case by simp
next
  case(cComm1 Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ C α P'')
  thus ?case using rComm1
    apply(auto)
    apply(drule_tac x="MN" in meta_spec)
    apply(drule_tac x="K⦇ν*xvec⦈⟨N" in meta_spec)
    apply(drule_tac x=P' in meta_spec)
    apply(drule_tac x=Q' in meta_spec)
    apply auto
    apply(drule_tac x=Ψ in meta_spec)
    apply(drule_tac x=ΨQ in meta_spec)
    apply(drule_tac x=P in meta_spec)
    apply(drule_tac x=M in meta_spec)
    apply(drule_tac x=N in meta_spec)
    apply(drule_tac x=P' in meta_spec)
    apply(drule_tac x=AP in meta_spec)
    apply(drule_tac x=ΨP in meta_spec)
    apply(drule_tac x=Q in meta_spec)
    apply(drule_tac x=K in meta_spec)
    apply(drule_tac x=xvec in meta_spec)
    apply(drule_tac x=Q' in meta_spec)
    apply(drule_tac x=AQ in meta_spec)
    apply auto
    apply(subgoal_tac "C. Prop C (Ψ  ΨP) Q (K⦇ν*xvec⦈⟨N) Q' AQ ΨQ")
    apply(subgoal_tac "C. Prop C (Ψ  ΨQ) P (MN) P' AP ΨP")
    by(auto simp add: residualInject)
next
  case(cComm2 Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ C α Q'')
  thus ?case using rComm2
    apply(drule_tac x="M⦇ν*xvec⦈⟨N" in meta_spec)
    apply(drule_tac x="KN" in meta_spec)
    apply(drule_tac x=P' in meta_spec)
    apply(drule_tac x=Q' in meta_spec)
    apply auto
    apply(drule_tac x=Ψ in meta_spec)
    apply(drule_tac x=ΨQ in meta_spec)
    apply(drule_tac x=P in meta_spec)
    apply(drule_tac x=M in meta_spec)
    apply(drule_tac x=xvec in meta_spec)
    apply(drule_tac x=N in meta_spec)
    apply(drule_tac x=P' in meta_spec)
    apply(drule_tac x=AP in meta_spec)
    apply(drule_tac x=ΨP in meta_spec)
    apply(drule_tac x=Q in meta_spec)
    apply(drule_tac x=K in meta_spec)
    apply(drule_tac x=Q' in meta_spec)
    apply(drule_tac x=AQ in meta_spec)
    apply auto
    apply(subgoal_tac "C. Prop C (Ψ  ΨQ) P (M⦇ν*xvec⦈⟨N) P' AP ΨP")
    apply(subgoal_tac "C. Prop C (Ψ  ΨP) Q (KN) Q' AQ ΨQ")
    by(auto simp add: residualInject)
next
  case(cOpen Ψ P M xvec yvec N P' x AP ΨP C α P'')
  note M⦇ν*(xvec@x#yvec)⦈⟨N  P' = α  P''
  moreover from xvec ♯* α x  α yvec ♯* α have "(xvec@x#yvec) ♯* (bn α)"
    by auto
  moreover from xvec ♯* yvec x  xvec x  yvec distinct xvec distinct yvec
  have "distinct(xvec@x#yvec)"
    by(auto simp add: fresh_star_def) (simp add: fresh_def name_list_supp)
  moreover note distinct(bn α)
  moreover from xvec ♯* M x  M yvec ♯* M have "(xvec@x#yvec) ♯* M" by auto
  hence "(xvec@x#yvec) ♯* (M⦇ν*(xvec@x#yvec)⦈⟨N  P')" by auto
  moreover from bn α ♯* subject α have "bn α ♯* (α  P'')" by simp
  ultimately obtain p where S: "(set p)  (set(xvec@x#yvec)) × (set(p  (xvec@x#yvec)))" and "distinctPerm p"
             and αeq: "α = (p  M)⦇ν*(p  (xvec@x#yvec))⦈⟨(p  N)" and P'eq: "P'' = (p  P')"
             and A: "(xvec@x#yvec) ♯* ((p  M)⦇ν*(p  (xvec@x#yvec))⦈⟨(p  N))"
             and B: "(p  (xvec@x#yvec)) ♯* (M⦇ν*(xvec@x#yvec)⦈⟨N)"
             and C: "(p  (xvec@x#yvec)) ♯* P'"
    by(rule_tac residualEq) (assumption | simp)+

  note Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P' x  (supp N)

  moreover {
    fix C
    from xvec ♯* M yvec ♯* M have "(xvec@yvec) ♯* M" by simp
    moreover from distinct xvec distinct yvec xvec ♯* yvec have "distinct(xvec@yvec)"
      by auto (simp add: fresh_star_def name_list_supp fresh_def) 
    ultimately have "Prop C Ψ P (M⦇ν*(xvec@yvec)⦈⟨N) P' AP ΨP" using AP ♯* xvec AP ♯* yvec AP ♯* M AP ♯* N
      by(rule_tac cOpen) auto
  }
  moreover obtain y::name where "y  Ψ" and "y  x" and "y  P" and "y  xvec" and "y  yvec" and "y  α" and "y  P'" and "y  AP" and "y  ΨP" and "y  M" and "y  N" and "y  C" and "y  p"
    by(generate_fresh "name") auto
  moreover note x  Ψ x  M x  xvec x  yvec xvec ♯* Ψ xvec ♯* P xvec ♯* M
                 yvec ♯* Ψ yvec ♯* P yvec ♯* M yvec ♯* C x  C xvec ♯* C distinct xvec distinct yvec
                 extractFrame P = AP, ΨP distinct AP x  AP xvec ♯* yvec xvec ♯* ΨP
                 AP ♯* Ψ AP ♯* P AP ♯* M AP ♯* xvec AP ♯* yvec AP ♯* N AP ♯* P' AP ♯* C 
  ultimately have "Prop C Ψ (⦇νxP) (M⦇ν*(xvec@y#yvec)⦈⟨([(x, y)]  N)) ([(x, y)]  P') (x#AP) ΨP"
    by(rule_tac rOpen)
  moreover have "(([(x, y)]  p)  [(x, y)]  M) = [(x, y)]  p  M"
    by(subst perm_compose[symmetric]) simp
  with y  M x  α αeq y  p x  M have D: "(([(x, y)]  p)  M) = p  M"
    by(auto simp add: eqvts freshChainSimps)
  moreover have "(([(x, y)]  p)  [(x, y)]  xvec) = [(x, y)]  p  xvec"
    by(subst perm_compose[symmetric]) simp
  with y  xvec x  α αeq y  p x  xvec have E: "(([(x, y)]  p)  xvec) = p  xvec"
    by(auto simp add: eqvts freshChainSimps)
  moreover have "(([(x, y)]  p)  [(x, y)]  yvec) = [(x, y)]  p  yvec"
    by(subst perm_compose[symmetric]) simp
  with y  yvec x  α αeq y  p x  yvec have F: "(([(x, y)]  p)  yvec) = p  yvec"
    by(auto simp add: eqvts freshChainSimps)
  moreover have "(([(x, y)]  p)  [(x, y)]  x) = [(x, y)]  p  x"
    by(subst perm_compose[symmetric]) simp
  with y  x y  p have G: "(([(x, y)]  p)  y) = p  x"
    apply(simp add: freshChainSimps calc_atm)
    apply(subgoal_tac "y  p  x")
    apply(clarsimp)
    using A αeq
    apply(simp add: eqvts)
    apply(subst fresh_atm[symmetric])
    apply(simp only: freshChainSimps)
    by simp
  moreover have "(([(x, y)]  p)  [(x, y)]  N) = [(x, y)]  p  N"
    by(subst perm_compose[symmetric]) simp
  with y  N x  α y  p αeq have H: "(([(x, y)]  p)  [(x, y)]  N) = p  N"
    by(auto simp add: eqvts freshChainSimps)
  moreover have "(([(x, y)]  p)  [(x, y)]  P') = [(x, y)]  p  P'"
    by(subst perm_compose[symmetric]) simp
  with y  P' x  P'' y  p P'eq have I: "(([(x, y)]  p)  [(x, y)]  P') = p  P'"
    by(auto simp add: eqvts freshChainSimps)
  from y  p y  x have "y  p  x"
    apply(subst fresh_atm[symmetric])
    apply(simp only: freshChainSimps)
    by simp
  moreover from S have "([(x, y)]  set p)  [(x, y)]  (set(xvec@x#yvec) × set(p  (xvec@x#yvec)))"
    by(simp)
  with y  p  x (([(x, y)]  p)  y) = p  x x  xvec y  xvec x  yvec y  yvec y  p x  α αeq have 
    "set([(x, y)]  p)  set(xvec@y#yvec) × set(([(x, y)]  p)  (xvec@y#yvec))"
    by(simp add: eqvts calc_atm perm_compose)
  moreover note xvec ♯* Ψ yvec ♯* Ψ xvec ♯* P yvec ♯* P xvec ♯* M yvec ♯* M 
                yvec ♯* C  S distinctPerm p x  C xvec ♯* C xvec ♯* ΨP yvec ♯* ΨP x  Ψ
                AP ♯* xvec x  AP AP ♯* yvec AP ♯* M x  xvec x  yvec x  M x  AP AP ♯* N
                 A B C  αeq AP ♯* α y  Ψ y  x y  P y  M y  ΨP y  C xvec ♯* α x  α yvec ♯* α y  α AP ♯* P AP ♯* Ψ y  AP y  N AP ♯* P' y  P' AP ♯* C P'eq
  ultimately have "Prop C Ψ (⦇νxP) (([(x, y)]  p)  (M⦇ν*(xvec@y#yvec)⦈⟨([(x, y)]  N))) (([(x, y)]  p)  [(x, y)]  P') (x#AP) ΨP"
    apply(rule_tac α="M⦇ν*(xvec@y#yvec)⦈⟨([(x, y)]  N)" in rAlpha)
    apply(assumption | simp)+
    apply(simp add: eqvts)
    apply(assumption | simp add: abs_fresh)+
    apply(simp add: fresh_left calc_atm)
    apply(assumption | simp)+
    apply(simp add: fresh_left calc_atm)
    apply(assumption | simp)+
    by(simp add: eqvts fresh_left)+
  with αeq P'eq D E F G H I show ?case 
    by(simp add: eqvts)
next    
 case(cScope Ψ P α P' x AP ΨP C α' P'')
  note α  (⦇νxP') = α'  P''
  moreover from bn α ♯* α' have "bn α ♯* (bn α')" by auto
  moreover note distinct (bn α) distinct(bn α')
  moreover from bn α ♯* subject α bn α' ♯* subject α'
  have "bn α ♯* (α  ⦇νxP')" and "bn α' ♯* (α'  P'')" by simp+
  ultimately obtain p where S: "(set p)  (set(bn α)) × (set(bn(p  α)))" and "distinctPerm p"
                        and αEq: "α' = p  α" and P'eq: "P'' = p  (⦇νxP')" and "(bn(p  α)) ♯* α"
                        and "(bn(p  α)) ♯* (⦇νxP')"
    by(rule residualEq)
    
  note Ψ  P α  P'
  moreover from bn α ♯* subject α distinct(bn α)
  have "C. Prop C Ψ P α P' AP ΨP" by(rule_tac cScope) auto

  moreover note x  Ψ x  α bn α ♯* Ψ bn α ♯* P bn α ♯* subject α bn α ♯* ΨP
                x  C bn α ♯* C distinct(bn α) extractFrame P = AP, ΨP
                distinct AP x  AP AP ♯* Ψ AP ♯* P AP ♯* α AP ♯* P' AP ♯* C
  ultimately have "Prop C Ψ (⦇νxP) α (⦇νxP') (x#AP) ΨP"
    by(rule_tac rScope) 
  with bn α ♯* Ψ bn α ♯* P x  α bn α ♯* subject α bn α ♯* C bn α ♯* (bn α') S distinctPerm p bn(p  α) ♯* α bn(p  α) ♯* (⦇νxP') AP ♯* α AP ♯* α' αEq x  α' bn α ♯* ΨP bn α ♯* α' x  Ψ AP ♯* Ψ x  AP AP ♯* P AP ♯* P' x  C AP ♯* C
  have "Prop C Ψ (⦇νxP) (p  α) (p  (⦇νxP'))  (x#AP) ΨP" 
    by(rule_tac rAlpha) (simp add: abs_fresh)+
  with αEq P'eq distinctPerm p show ?case by simp
next
  case(cBang Ψ P Rs AP ΨP C α)
  thus ?case by(rule_tac rBang) auto 
qed

lemma inputFrameInduct[consumes 3, case_names cAlpha cInput cCase cPar1 cPar2 cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 'a  'a  ('a, 'b, 'c) psi  name list  'b  bool"
  and   C    :: "'d::fs_name"

  assumes Trans: "Ψ  P MN  P'"
  and     FrP: "extractFrame P = AP, ΨP"
  and     "distinct AP"
  and     rAlpha: "Ψ P M N P' AP ΨP p C. AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; AP ♯* (p  AP); AP ♯* C;
                                            set p  set AP × set(p  AP); distinctPerm p;
                                             Prop C Ψ P M N P' AP ΨP  Prop C Ψ P M N P' (p  AP) (p  ΨP)"
  and     rInput: "Ψ M K xvec N Tvec P C.
                   Ψ  M  K; distinct xvec; set xvec  supp N;
                    length xvec = length Tvec; xvec ♯* Ψ;
                    xvec ♯* M; xvec ♯* K; xvec ♯* C 
                    Prop C Ψ (M⦇λ*xvec N⦈.P)
                              K (N[xvec::=Tvec]) (P[xvec::=Tvec]) ([]) (𝟭)"
  and     rCase: "Ψ P M N P' φ Cs AP ΨP C. Ψ  P MN  P'; extractFrame P = AP, ΨP; distinct AP; C. Prop C Ψ P M N P' AP ΨP;
                                              (φ, P) mem Cs; Ψ  φ; guarded P;  ΨP  𝟭; (supp ΨP) = ({}::name set);
                                              AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; AP ♯* C  Prop C Ψ (Cases Cs) M N P' ([]) (𝟭)"
  and     rPar1: "Ψ ΨQ P M N P' AQ Q AP ΨP C.
                   Ψ  ΨQ  P MN  P';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨQ) P M N P' AP ΨP;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* M; AP ♯* N; AP ♯* P'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* M; AQ ♯* N; AQ ♯* P'; AQ ♯* ΨP;
                   AP ♯* C; AQ ♯* C 
                   Prop C Ψ (P  Q) M N (P'  Q) (AP@AQ) (ΨP  ΨQ)"
  and     rPar2: "Ψ ΨP Q M N Q' AP P AQ ΨQ C.
                   Ψ  ΨP  Q MN  Q';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨP) Q M N Q' AQ ΨQ;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* M; AP ♯* N; AP ♯* Q'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* M; AQ ♯* N; AQ ♯* Q'; AQ ♯* ΨP;
                   AP ♯* C; AQ ♯* C 
                   Prop C Ψ (P  Q) M N (P  Q') (AP@AQ) (ΨP  ΨQ)"
  and     rScope: "Ψ P M N P' x AP ΨP C.
                    Ψ  P MN  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P M N P' AP ΨP; x  Ψ; x  M; x  N; 
                     x  AP; AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P';
                     AP ♯* C; x  C 
                     Prop C Ψ (⦇νxP) M N (⦇νxP') (x#AP) ΨP"
  and     rBang:    "Ψ P M N P' AP ΨP C.
                     Ψ  P  !P MN  P'; guarded P; extractFrame P = AP, ΨP;  distinct AP;
                      C. Prop C Ψ (P  !P) M N P' AP (ΨP  𝟭); ΨP  𝟭; (supp ΨP) = ({}::name set);
                      AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; AP ♯* C  Prop C Ψ (!P) M N P' ([]) (𝟭)"
  shows "Prop C Ψ P M N P' AP ΨP"
using assms
by(nominal_induct Ψ P Rs=="MN  P'" AP ΨP avoiding: C arbitrary: P' rule: semanticsFrameInduct)
  (auto simp add: residualInject)

lemma outputFrameInduct[consumes 3, case_names cAlpha cOutput cCase cPar1 cPar2 cOpen cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   B    :: "('a, 'b, 'c) boundOutput"
  and   AP   :: "name list"
  and   ΨP   :: 'b
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 'a  ('a, 'b, 'c) boundOutput  name list  'b  bool"
  and   C    :: "'d::fs_name"

  assumes Trans: "Ψ  P ROut M B"
  and     FrP: "extractFrame P = AP, ΨP"
  and     "distinct AP"
  and     rAlpha: "Ψ P M AP ΨP p B C. AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* (p  AP); AP ♯* B; AP ♯* C;
                                         set p  set AP × set(p  AP); distinctPerm p;
                                          Prop C Ψ P M B AP ΨP  Prop C Ψ P M B (p  AP) (p  ΨP)"
  and     rOutput: "Ψ M K N P C. Ψ  M  K  Prop C Ψ (MN⟩.P) K (N ≺' P) ([]) (𝟭)"
  and     rCase: "Ψ P M B φ Cs AP ΨP C. Ψ  P (ROut M B); extractFrame P = AP, ΨP; distinct AP; C. Prop C Ψ P M B AP ΨP;
                                            (φ, P) mem Cs; Ψ  φ; guarded P;  ΨP  𝟭; (supp ΨP) = ({}::name set);
                                            AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* B; AP ♯* C  Prop C Ψ (Cases Cs) M B ([]) (𝟭)"
  and     rPar1: "Ψ ΨQ P M xvec N P' AQ Q AP ΨP C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨQ) P M (⦇ν*xvecN ≺' P') AP ΨP;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* M;  AP ♯* xvec; AP ♯* N; AP ♯* P'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* M; AQ ♯* xvec; AQ ♯* N; AQ ♯* P'; AQ ♯* ΨP;
                   xvec ♯* Ψ; xvec ♯* P; xvec ♯* Q; xvec ♯* M; xvec ♯* ΨP; xvec ♯* ΨQ;
                   AP ♯* C; AQ ♯* C; xvec ♯* C 
                   Prop C Ψ (P  Q) M (⦇ν*xvecN ≺' (P'  Q)) (AP@AQ) (ΨP  ΨQ)"
  and     rPar2: "Ψ ΨP Q M xvec N Q' AP P AQ ΨQ C.
                   Ψ  ΨP  Q M⦇ν*xvec⦈⟨N  Q';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨP) Q M (⦇ν*xvecN ≺' Q') AQ ΨQ;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* M; AP ♯* xvec; AP ♯* N; AP ♯* Q'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* M; AQ ♯* xvec; AQ ♯* N; AQ ♯* Q'; AQ ♯* ΨP;
                   xvec ♯* Ψ; xvec ♯* P; xvec ♯* Q; xvec ♯* M; xvec ♯* ΨP; xvec ♯* ΨQ;
                   AP ♯* C; AQ ♯* C; xvec ♯* C 
                   Prop C Ψ (P  Q) M (⦇ν*xvecN ≺' (P  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rOpen: "Ψ P M xvec yvec N P' x AP ΨP C.
                    Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P M (⦇ν*(xvec@yvec)N ≺' P') AP ΨP; x  supp N; x  Ψ; x  M;
                     x  AP; x  xvec; x  yvec; AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P';
                     AP ♯* xvec; AP ♯* yvec;
                     xvec ♯* Ψ; xvec ♯* P; xvec ♯* M; xvec ♯* ΨP; 
                     yvec ♯* Ψ; yvec ♯* P; yvec ♯* M; AP ♯* C; x  C; xvec ♯* C; yvec ♯* C 
                     Prop C Ψ (⦇νxP) M (⦇ν*(xvec@x#yvec)N ≺' P') (x#AP) ΨP"
  and     rScope: "Ψ P M xvec N P' x AP ΨP C.
                    Ψ  P M⦇ν*xvec⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P M (⦇ν*xvecN ≺' P') AP ΨP;
                     x  Ψ; x  M; x  xvec; x  N; x  AP; AP ♯* Ψ; AP ♯* P;
                     AP ♯* M; AP ♯* N; AP ♯* P'; AP ♯* xvec;
                     xvec ♯* Ψ; xvec ♯* P; xvec ♯* M; xvec ♯* ΨP;
                     AP ♯* C; x  C; xvec ♯* C 
                     Prop C Ψ (⦇νxP) M (⦇ν*xvecN ≺' (⦇νxP')) (x#AP) ΨP"
  and     rBang:    "Ψ P M B AP ΨP C.
                     Ψ  P  !P ROut M B; guarded P; extractFrame P = AP, ΨP; distinct AP;
                      C. Prop C Ψ (P  !P) M B AP (ΨP  𝟭); ΨP  𝟭; supp ΨP = ({}::name set);
                      AP ♯* Ψ; AP ♯* P; AP ♯* M; AP ♯* C  Prop C Ψ (!P) M B ([]) (𝟭)"
  shows "Prop C Ψ P M B AP ΨP"
proof -
  {
    fix B
    assume "Ψ  P ROut M B"
    hence "Prop C Ψ P M B AP ΨP" using FrP distinct AP
    proof(nominal_induct Ψ P Rs=="ROut M B" AP ΨP avoiding: C arbitrary: B rule: semanticsFrameInduct)
      case cAlpha
      thus ?case by(fastforce intro: rAlpha) 
    next
      case cInput 
      thus ?case by(simp add: residualInject)
    next
      case cOutput
      thus ?case by(force intro: rOutput simp add: residualInject)
    next
      case cCase
      thus ?case by(force intro: rCase simp add: residualInject)
    next
      case cPar1
      thus ?case
        by(fastforce intro: rPar1 simp add: residualInject)
    next
      case cPar2
      thus ?case
        by(fastforce intro: rPar2 simp add: residualInject)
    next
      case cComm1
      thus ?case by(simp add: residualInject)
    next
      case cComm2
      thus ?case by(simp add: residualInject)
    next
      case cOpen
      thus ?case by(fastforce intro: rOpen simp add: residualInject)
    next
      case cScope
      thus ?case by(force intro: rScope simp add: residualInject)
    next
      case cBang
      thus ?case by(force intro: rBang simp add: residualInject)
    qed
  }
  with Trans show ?thesis by(simp add: residualInject)
qed

lemma tauFrameInduct[consumes 3, case_names cAlpha cCase cPar1 cPar2 cComm1 cComm2 cScope cBang]:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   P'   :: "('a, 'b, 'c) psi"
  and   Prop :: "'d::fs_name  'b  ('a, 'b, 'c) psi 
                 ('a, 'b, 'c) psi  name list  'b  bool"
  and   C    :: "'d::fs_name"

  assumes Trans: "Ψ  P τ  P'"
  and     FrP: "extractFrame P = AP, ΨP"
  and     "distinct AP"
  and     rAlpha: "Ψ P P' AP ΨP p C. AP ♯* Ψ; AP ♯* P; AP ♯* P'; AP ♯* (p  AP); AP ♯* C;
                                        set p  set AP × set (p  AP); distinctPerm p;
                                         Prop C Ψ P P' AP ΨP  Prop C Ψ P P' (p  AP) (p  ΨP)"
  and     rCase: "Ψ P P' φ Cs AP ΨP C. Ψ  P τ  P'; extractFrame P = AP, ΨP; distinct AP; C. Prop C Ψ P P' AP ΨP;
                                          (φ, P) mem Cs; Ψ  φ; guarded P;  ΨP  𝟭; (supp ΨP) = ({}::name set);
                                          AP ♯* Ψ; AP ♯* P; AP ♯* P'; AP ♯* C  Prop C Ψ (Cases Cs) P' ([]) (𝟭)"
  and     rPar1: "Ψ ΨQ P P' AQ Q AP ΨP C.
                   Ψ  ΨQ  P τ  P';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨQ) P P' AP ΨP;
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* P'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* P'; AQ ♯* ΨP;
                   AP ♯* C; AQ ♯* C 
                   Prop C Ψ (P  Q) (P'  Q) (AP@AQ) (ΨP  ΨQ)"
  and     rPar2: "Ψ ΨP Q Q' AP P AQ ΨQ C.
                   Ψ  ΨP  Q τ  Q';
                   extractFrame P = AP, ΨP; distinct AP;
                   extractFrame Q = AQ, ΨQ; distinct AQ;
                   C. Prop C (Ψ  ΨP) Q Q' AQ ΨQ; 
                   AP ♯* P; AP ♯* Q; AP ♯* Ψ; AP ♯* Q'; AP ♯* AQ; AP ♯* ΨQ;
                   AQ ♯* P; AQ ♯* Q; AQ ♯* Ψ; AQ ♯* Q'; AQ ♯* ΨP;
                   AP ♯* C; AQ ♯* C 
                   Prop C Ψ (P  Q) (P  Q') (AP@AQ) (ΨP  ΨQ)"
  and     rComm1: "Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ C.
                   Ψ  ΨQ  P MN  P'; extractFrame P = AP, ΨP; distinct AP;
                    Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K; distinct xvec;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rComm2: "Ψ ΨQ P M xvec N P' AP ΨP Q K Q' AQ C.
                   Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P'; extractFrame P = AP, ΨP; distinct AP;
                    Ψ  ΨP  Q KN  Q'; extractFrame Q = AQ, ΨQ; distinct AQ;
                    Ψ  ΨP  ΨQ  M  K; distinct xvec;
                    AP ♯* Ψ; AP ♯* ΨQ; AP ♯* P; AP ♯* M; AP ♯* N; AP ♯* P'; 
                    AP ♯* Q; AP ♯* Q'; AP ♯* AQ; AP ♯* xvec; AQ ♯* Ψ; AQ ♯* ΨP; 
                    AQ ♯* P; AQ ♯* N; AQ ♯* P'; AQ ♯* Q; AQ ♯* K; AQ ♯* Q';
                    AQ ♯* xvec; xvec ♯* Ψ; xvec ♯* ΨP; xvec ♯* ΨQ; xvec ♯* P; xvec ♯* M; 
                    xvec ♯* Q; xvec ♯* K; AP ♯* C; AQ ♯* C; xvec ♯* C 
                    Prop C Ψ (P  Q) (⦇ν*xvec(P'  Q')) (AP@AQ) (ΨP  ΨQ)"
  and     rScope: "Ψ P P' x AP ΨP C.
                    Ψ  P τ  P'; extractFrame P = AP, ΨP; distinct AP;
                    C. Prop C Ψ P P' AP ΨP; x  Ψ;
                     x  AP; AP ♯* Ψ; AP ♯* P; AP ♯* P';
                     AP ♯* C; x  C 
                     Prop C Ψ (⦇νxP) (⦇νxP') (x#AP) ΨP"
  and     rBang:    "Ψ P P' AP ΨP C.
                     Ψ  P  !P τ  P'; guarded P; extractFrame P = AP, ΨP;  distinct AP;
                      C. Prop C Ψ (P  !P) P' AP (ΨP  𝟭); ΨP  𝟭; supp ΨP = ({}::name set);
                      AP ♯* Ψ; AP ♯* P; AP ♯* P'; AP ♯* C  Prop C Ψ (!P) P' ([]) (𝟭)"
  shows "Prop C Ψ P P' AP ΨP"
using Trans FrP distinct AP
proof(nominal_induct Ψ P Rs=="τ  P'" AP ΨP avoiding: C arbitrary: P' rule: semanticsFrameInduct)
  case cAlpha
  thus ?case by(force intro: rAlpha simp add: residualInject)
next
  case cInput 
  thus ?case by(simp add: residualInject)
next
  case cOutput
  thus ?case by(simp add: residualInject)
next
  case cCase
  thus ?case by(force intro: rCase simp add: residualInject)
next
  case cPar1
  thus ?case by(force intro: rPar1 simp add: residualInject)
next
  case cPar2
  thus ?case by(force intro: rPar2 simp add: residualInject)
next
  case cComm1
  thus ?case by(force intro: rComm1 simp add: residualInject)
next
  case cComm2
  thus ?case by(force intro: rComm2 simp add: residualInject)
next
  case cOpen
  thus ?case by(simp add: residualInject)
next
  case cScope
  thus ?case by(force intro: rScope simp add: residualInject)
next
  case cBang
  thus ?case by(force intro: rBang simp add: residualInject)
qed

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

  assumes "Ψ  P MN  P'"
  and     "x  P"
  and     "x  N"

  shows "x  P'"
proof -
  have "bn(MN) ♯* subject(MN)" and "distinct(bn(MN))" by simp+
  with Ψ  P MN  P' show ?thesis using x  P x  N
  proof(nominal_induct Ψ P α=="MN" P' avoiding: x rule: semanticsInduct)
    case(cAlpha Ψ P α P' p x)
    thus ?case by simp
  next
    case(cInput Ψ M' K xvec N' Tvec P x)
    from K(N'[xvec::=Tvec]) = MN have "M = K" and NeqN': "N = N'[xvec::=Tvec]" by(simp add: action.inject)+ 
    note length xvec = length Tvec distinct xvec then
    moreover have "x  Tvec" using set xvec  supp N' x  N NeqN'
      by(blast intro: substTerm.subst3)
    moreover from xvec ♯* x x  M'⦇λ*xvec N'⦈.P
    have "x  P" by(simp add: inputChainFresh) (simp add: name_list_supp fresh_def)
    ultimately show ?case using xvec ♯* x by auto
  next
    case(cOutput Ψ M  K N P x)
    thus ?case by simp
  next
    case(cCase Ψ P P' φ Cs x)
    thus ?case by(induct Cs, auto)
  next
    case(cPar1 Ψ ΨQ P P' xvec Q x)
    thus ?case by simp
  next
    case(cPar2 Ψ ΨP Q Q' xvec P x)
    thus ?case by simp
  next
    case(cComm1 Ψ ΨQ P M N P' AP ΨP Q K xvec Q' AQ x)
    thus ?case by simp
  next
    case(cComm2 Ψ ΨQ P M xwec N P' AP ΨP Q K Q' AQ x)
    thus ?case by simp
  next
    case(cOpen Ψ P M xvec yvec N P' x y)
    thus ?case by simp
  next
    case(cScope Ψ P P' x y)
    thus ?case by(simp add: abs_fresh)
  next
    case(cBang Ψ P P' x)
    thus ?case by simp
  qed
qed
  
lemma inputFreshChainDerivative:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   xvec :: "name list"

  assumes "Ψ  P MN  P'"
  and     "xvec ♯* P"
  and     "xvec ♯* N"
  
  shows "xvec ♯* P'"
using assms
by(induct xvec)
  (auto intro: inputFreshDerivative)

lemma outputFreshDerivative:
  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   x    :: name

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     "xvec ♯* M"
  and     "distinct xvec"
  and     "x  P"
  and     "x  xvec"

  shows "x  N"
  and   "x  P'"
proof -
  note Ψ  P M⦇ν*xvec⦈⟨N  P'
  moreover from xvec ♯* M have "bn(M⦇ν*xvec⦈⟨N) ♯* subject(M⦇ν*xvec⦈⟨N)" by simp
  moreover from distinct xvec have "distinct(bn(M⦇ν*xvec⦈⟨N))" by simp
  ultimately show "x  N" using x  P x  xvec
  proof(nominal_induct Ψ P α=="M⦇ν*xvec⦈⟨N" P' avoiding: x arbitrary: M xvec N rule: semanticsInduct)
    case(cAlpha Ψ P α P' p x M xvec N)
    have S: "set p  set(bn α) × set(bn(p  α))" by fact
    from (p  α) = M⦇ν*xvec⦈⟨N have "(p  p  α) = p  (M⦇ν*xvec⦈⟨N)" by(simp add: fresh_star_bij)
    with distinctPerm p have "α  = (p  M)⦇ν*(p  xvec)⦈⟨(p  N)" by simp
    moreover from (p  α) = M⦇ν*xvec⦈⟨N x  xvec have "x  (bn(p  α))" by simp
    with (bn α) ♯* x x  xvec S have "x  (p  xvec)"
      by(drule_tac pt_fresh_bij1[OF pt_name_inst, OF at_name_inst, where pi=p and x=xvec]) simp
    ultimately have "x  (p  N)" using x  P by(rule_tac cAlpha)
    hence "(p  x)  (p  p  N)" by(simp add: pt_fresh_bij1[OF pt_name_inst, OF at_name_inst])
    with distinctPerm p bn(α) ♯* x x  (bn(p  α))S show ?case by simp
  next
    case cInput
    thus ?case by simp
  next
    case cOutput
    thus ?case by(simp add: action.inject)
  next
    case cCase
    thus ?case
      by(rule_tac cCase) (auto dest: memFresh)
  next
    case cPar1
    thus ?case by simp
  next
    case cPar2
    thus ?case by simp
  next
    case cComm1
    thus ?case by simp
  next
    case cComm2
    thus ?case by simp
  next
    case(cOpen Ψ P M xvec yvec N P' x y M' zvec N')
    from M⦇ν*(xvec@x#yvec)⦈⟨N = M'⦇ν*zvec⦈⟨N' have "zvec = xvec@x#yvec" and "N = N'"
      by(simp add: action.inject)+
    from y  ⦇νxP x  y  have "y  P" by(simp add: abs_fresh)
    moreover from y  zvec zvec = xvec@x#yvechave "y  (xvec@yvec)"
      by simp
    ultimately have "y  N" by(rule_tac cOpen) auto
    with N = N' show ?case by simp
  next
    case cScope
    thus ?case by(auto simp add: abs_fresh)
  next
    case cBang
    thus ?case by simp
  qed
next
  note Ψ  P M⦇ν*xvec⦈⟨N  P'
  moreover from xvec ♯* M have "bn(M⦇ν*xvec⦈⟨N) ♯* subject(M⦇ν*xvec⦈⟨N)" by simp
  moreover from distinct xvec have "distinct(bn(M⦇ν*xvec⦈⟨N))" by simp
  ultimately show "x  P'" using x  P x  xvec
  proof(nominal_induct Ψ P α=="M⦇ν*xvec⦈⟨N" P' avoiding: x arbitrary: M xvec N rule: semanticsInduct)
    case(cAlpha Ψ P α P' p x M xvec N)
    have S: "set p  set(bn α) × set(bn(p  α))" by fact
    from (p  α) = M⦇ν*xvec⦈⟨N have "(p  p  α) = p  (M⦇ν*xvec⦈⟨N)" by(simp add: fresh_star_bij)
    with distinctPerm p have "α  = (p  M)⦇ν*(p  xvec)⦈⟨(p  N)" by simp
    moreover from (p  α) = M⦇ν*xvec⦈⟨N x  xvec have "x  (bn(p  α))" by simp
    with (bn α) ♯* x x  xvec S have "x  (p  xvec)"
      by(drule_tac pt_fresh_bij1[OF pt_name_inst, OF at_name_inst, where pi=p and x=xvec]) simp
    ultimately have "x  P'" using x  P by(rule_tac cAlpha)
    hence "(p  x)  (p  P')" by(simp add: pt_fresh_bij1[OF pt_name_inst, OF at_name_inst])
    with distinctPerm p bn(α) ♯* x x  (bn(p  α))S show ?case by simp
  next
    case cInput
    thus ?case by simp
  next
    case cOutput
    thus ?case by(simp add: action.inject)
  next
    case cCase
    thus ?case by(fastforce simp add: action.inject dest: memFresh)
  next
    case cPar1
    thus ?case by simp
  next
    case cPar2
    thus ?case by simp
  next
    case cComm1
    thus ?case by simp
  next
    case cComm2
    thus ?case by simp
  next
    case(cOpen Ψ P M xvec yvec N P' x y M' zvec N')
    from M⦇ν*(xvec@x#yvec)⦈⟨N = M'⦇ν*zvec⦈⟨N' have "zvec = xvec@x#yvec" 
      by(simp add: action.inject)
    from y  ⦇νxP x  y  have "y  P" by(simp add: abs_fresh)
    moreover from y  zvec zvec = xvec@x#yvechave "y  (xvec@yvec)"
      by simp
    ultimately show "y  P'" by(rule_tac cOpen) auto
  next
    case cScope
    thus ?case by(auto simp add: abs_fresh)
  next
    case cBang
    thus ?case by simp
  qed
qed

lemma outputFreshChainDerivative:
  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   yvec :: "name list"

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     "xvec ♯* M"
  and     "distinct xvec"
  and     "yvec ♯* P"
  and     "yvec ♯* xvec"

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

lemma tauFreshDerivative:
  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'"
proof -
  have "bn(τ) ♯* subject(τ)" and "distinct(bn(τ))" by simp+
  with Ψ  P τ  P' show ?thesis using x  P
  proof(nominal_induct Ψ P α=="(τ::('a action))" P' avoiding: x rule: semanticsInduct)
    case cAlpha
    thus ?case by simp
  next
    case cInput
    thus ?case by simp
  next
    case cOutput
    thus ?case by simp
  next 
    case cCase
    thus ?case by(auto dest: memFresh)
  next
    case cPar1
    thus ?case by simp
  next
    case cPar2
    thus ?case by simp
  next
    case cComm1
    thus ?case
      by(fastforce dest: inputFreshDerivative outputFreshDerivative simp add: resChainFresh)
  next
    case cComm2
    thus ?case
      by(fastforce dest: inputFreshDerivative outputFreshDerivative simp add: resChainFresh)
  next
    case cOpen
    thus ?case by simp
  next
    case cScope
    thus ?case by(simp add: abs_fresh)
  next
    case cBang
    thus ?case by simp
  qed
qed

lemma tauFreshChainDerivative:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   N    :: 'a
  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: tauFreshDerivative)

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

  assumes "Ψ  P α  P'"
  and     "bn α ♯* subject α"
  and     "distinct(bn α)"
  and     "x  α"
  and     "x  P"

  shows   "x  P'"
using assms
by(rule_tac actionCases[where α=α])
  (auto intro: inputFreshDerivative tauFreshDerivative outputFreshDerivative)

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

  assumes "Ψ  P α  P'"
  and     "bn α ♯* subject α"
  and     "distinct(bn α)"
  and     "xvec ♯* P"
  and     "xvec ♯* α"

  shows   "xvec ♯* P'"
using assms
by(auto intro: freeFreshDerivative simp add: fresh_star_def)

lemma Input:
  fixes Ψ    :: 'b
  and   M    :: 'a
  and   K    :: 'a
  and   xvec :: "name list"
  and   N    :: 'a
  and   Tvec :: "'a list"

  assumes "Ψ  M  K"
  and     "distinct xvec"
  and     "set xvec  supp N"
  and     "length xvec = length Tvec"

  shows "Ψ  M⦇λ*xvec N⦈.P KN[xvec::=Tvec]  P[xvec::=Tvec]"
proof -
  obtain p where xvecFreshPsi: "((p::name prm)  (xvec::name list)) ♯* Ψ"
             and xvecFreshM: "(p  xvec) ♯* M"
             and xvecFreshN: "(p  xvec) ♯* N"
             and xvecFreshK: "(p  xvec) ♯* K"
             and xvecFreshTvec: "(p  xvec) ♯* Tvec"
             and xvecFreshP: "(p  xvec) ♯* P"
             and S: "(set p)  (set xvec) × (set(p  xvec))"
             and dp: "distinctPerm p"
    by(rule_tac xvec=xvec and c="(Ψ, M, K, N, P, Tvec)" in name_list_avoiding)
      (auto simp add: eqvts fresh_star_prod)  
  note Ψ  M  K
  moreover from distinct xvec have "distinct(p  xvec)"
    by simp
  moreover from (set xvec)  (supp N) have "(p  (set xvec))  (p  (supp N))"
    by simp
  hence "set(p  xvec)  supp(p  N)"
    by(simp add: eqvts)
  moreover from length xvec = length Tvec have "length(p  xvec) = length Tvec"
    by simp
  ultimately have "Ψ  M⦇λ*(p  xvec) (p  N)⦈.(p  P) K(p  N)[(p  xvec)::=Tvec]  (p  P)[(p  xvec)::=Tvec]"
    using xvecFreshPsi xvecFreshM xvecFreshK xvecFreshTvec
    by(rule_tac cInput)
  thus ?thesis using xvecFreshN xvecFreshP S length xvec = length Tvec dp
    by(auto simp add: inputChainAlpha' substTerm.renaming renaming)
qed

lemma residualAlpha:
  fixes p :: "name prm"
  and   α :: "'a action"
  and   P :: "('a, 'b, 'c) psi"

  assumes "bn(p  α) ♯* object  α"
  and     "bn(p  α) ♯* P"
  and     "bn α ♯* subject α"
  and     "bn(p  α) ♯* subject α"
  and     "set p  set(bn α) × set(bn(p  α))"

  shows "α  P = (p  α)  (p  P)"
using assms
apply(rule_tac α=α in actionCases)
apply(simp only: eqvts bn.simps)
apply simp
apply(simp add: boundOutputChainAlpha'' residualInject)
by simp

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

  assumes Trans: "Ψ  ΨQ  P α  P'"
  and     "extractFrame Q = AQ, ΨQ"
  and     "bn α ♯* Q"
  and     "AQ ♯* Ψ"
  and     "AQ ♯* P"
  and     "AQ ♯* α"
  
  shows "Ψ  P  Q α  (P'  Q)"
proof -
  {
    fix Ψ    :: 'b
    and ΨQ   :: 'b
    and P    :: "('a, 'b, 'c) psi"
    and α    :: "'a action"
    and P'   :: "('a, 'b, 'c) psi"
    and AQ   :: "name list"
    and Q    :: "('a, 'b, 'c) psi"

    assume "Ψ  ΨQ  P α  P'"
    and     "extractFrame Q = AQ, ΨQ"
    and     "bn α ♯* Q"
    and     "bn α ♯* subject α"
    and     "AQ ♯* Ψ"
    and     "AQ ♯* P"
    and     "AQ ♯* α"
    and     "distinct AQ"
  
    have  "Ψ  P  Q α  (P'  Q)"
    proof -
      from Ψ  ΨQ  P α  P' have "distinct(bn α)" by(rule boundOutputDistinct)
      obtain q::"name prm" where "bn(q  α) ♯* Ψ" and "bn(q  α) ♯* P" and "bn(q  α) ♯* Q" and "bn(q  α) ♯* α"
                             and "bn(q  α) ♯* AQ" and "bn(q  α) ♯* P'" and "bn(q  α) ♯* ΨQ"
                             and Sq: "(set q)  (set (bn α)) × (set(bn(q  α)))"
        by(rule_tac xvec="bn α" and c="(Ψ, P, Q, α, AQ, ΨQ, P')" in name_list_avoiding) (auto simp add: eqvts)
      obtain p::"name prm" where "(p  AQ) ♯* Ψ" and "(p  AQ) ♯* P" and "(p  AQ) ♯* Q" and "(p  AQ) ♯* α" 
                              and "(p  AQ) ♯* α" and "(p  AQ) ♯* (q  α)" and "(p  AQ) ♯* P'" 
                             and "(p  AQ) ♯* (q  P')" and "(p  AQ) ♯* ΨQ" and Sp: "(set p)  (set AQ) × (set(p  AQ))"
        by(rule_tac xvec=AQ and c="(Ψ, P, Q, α, bn α, q  α, P', (q  P'), ΨQ)" in name_list_avoiding) auto
      from distinct(bn α) have "distinct(bn(q  α))" 
        by(rule_tac α=α in actionCases) (auto simp add: eqvts)
      from AQ ♯* α bn(q  α) ♯* AQ Sq have "AQ ♯* (q  α)"
        apply(rule_tac α=α in actionCases)
        apply(simp only: bn.simps eqvts, simp)
        apply(simp add: freshChainSimps)
        by simp
      from bn α ♯* subject α have "(q  (bn α)) ♯* (q  (subject α))"
        by(simp add: fresh_star_bij)
      hence "bn(q  α) ♯* subject(q  α)" by(simp add: eqvts)
      from Ψ  ΨQ  P α  P' bn(q  α) ♯* α bn(q  α) ♯* P' bn α ♯* (subject α) Sq
      have Trans: "Ψ  ΨQ  P (q  α)  (q  P')"
        by(force simp add: residualAlpha)
      hence "AQ ♯* (q  P')" using  bn(q  α) ♯* subject(q  α) distinct(bn(q  α)) AQ ♯* P AQ ♯* (q  α)
        by(auto intro: freeFreshChainDerivative)
      from Trans have "(p  (Ψ  ΨQ))  (p  P) p  ((q  α)  (q  P'))"
        by(rule semantics.eqvt)
      with AQ ♯* Ψ AQ ♯* P AQ ♯* (q  α) (p  AQ) ♯* (q  α) AQ ♯* (q  P')
           (p  AQ) ♯* Ψ (p  AQ) ♯* P (p  AQ) ♯* (q  P') Sp
      have "Ψ  (p  ΨQ)  P (q  α)  (q  P')" by(simp add: eqvts)
      moreover from extractFrame Q = AQ, ΨQ (p  AQ) ♯* ΨQ Sp have  "extractFrame Q = (p  AQ), (p  ΨQ)"
        by(simp add: frameChainAlpha' eqvts)
      moreover from (bn(q  α)) ♯* ΨQ (bn(q  α)) ♯* AQ (p  AQ) ♯* (q  α) Sp 
      have "(bn(q  α)) ♯* (p  ΨQ)"
        by(simp add: freshAlphaPerm)
      moreover from distinct AQ have "distinct(p  AQ)" by simp
      ultimately have "Ψ  P  Q (q  α)  ((q  P')  Q)"
        using (p  AQ) ♯* P (p  AQ) ♯* Q (p  AQ) ♯* Ψ (p  AQ) ♯* (q  α)
              (p  AQ) ♯* (q  P') (bn(q  α)) ♯* Ψ (bn(q  α)) ♯* Q (bn(q  α)) ♯* P 
              (bn(q  α)) ♯* (subject (q  α)) distinct(bn(q  α))
        by(rule_tac cPar1)
        
      thus ?thesis using bn(q  α) ♯* α bn(q  α) ♯* P' bn α ♯* subject α bn(q  α) ♯* Q bn α ♯* Q Sq
        by(force simp add: residualAlpha) 
    qed
  }
  note Goal = this
  from extractFrame Q = AQ, ΨQ AQ ♯* Ψ AQ ♯* P AQ ♯* α
  obtain AQ' where FrQ: "extractFrame Q = AQ', ΨQ" and "distinct AQ'" and "AQ' ♯* Ψ" and "AQ' ♯* P" and "AQ' ♯* α"
    by(rule_tac C="(Ψ, P, α)" in distinctFrame) auto
  show ?thesis
  proof(induct rule: actionCases[where α=α])
    case(cInput M N)
    from Trans FrQ AQ' ♯* Ψ AQ' ♯* P AQ' ♯* α distinct AQ' bn α ♯* Q
    show ?case using α = MN by(force intro: Goal)
  next
    case cTau 
    from Trans FrQ AQ' ♯* Ψ AQ' ♯* P AQ' ♯* α distinct AQ' bn α ♯* Q
    show ?case using α = τ by(force intro: Goal)
  next
    case(cOutput M xvec N)
    from α = M⦇ν*xvec⦈⟨N AQ' ♯* α bn α ♯* Q have "xvec ♯* AQ'" and "xvec ♯* Q"
      by simp+
    obtain p where "(p  xvec) ♯* N" and "(p  xvec) ♯* P'" and "(p  xvec) ♯* Q"
               and "(p  xvec) ♯* M" and "(p  xvec) ♯* AQ'" 
               and S: "set p  set xvec × set(p  xvec)"
      by(rule_tac xvec=xvec and c="(N, P', Q, M, AQ')" in name_list_avoiding) auto
    from Trans α=M⦇ν*xvec⦈⟨N have "Ψ  ΨQ  P M⦇ν*xvec⦈⟨N  P'" by simp
    with (p  xvec) ♯* N (p  xvec) ♯* P' S
    have "Ψ  ΨQ  P M⦇ν*(p  xvec)⦈⟨(p  N)  (p  P')"
      by(simp add: boundOutputChainAlpha'' create_residual.simps)
    moreover from xvec ♯* AQ' (p  xvec) ♯* AQ' AQ' ♯* α S
    have "AQ' ♯* (p  α)" by(simp add: freshChainSimps del: actionFreshChain)
    ultimately have "Ψ  P  Q M⦇ν*(p  xvec)⦈⟨(p  N)  (p  P')  Q"
      using FrQ AQ' ♯* Ψ AQ' ♯* P distinct AQ' (p  xvec) ♯* Q AQ' ♯* α
           (p  xvec) ♯* M α = M⦇ν*xvec⦈⟨N
      by(force intro: Goal)
    with (p  xvec) ♯* N (p  xvec) ♯* P' (p  xvec) ♯* Q xvec ♯* Q S α = M⦇ν*xvec⦈⟨N
    show ?case
      by(simp add: boundOutputChainAlpha'' eqvts create_residual.simps)
  qed
qed

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

  assumes Trans: "Ψ  ΨP  Q α  Q'"
  and     "extractFrame P = AP, ΨP"
  and     "bn α ♯* P"
  and     "AP ♯* Ψ"
  and     "AP ♯* Q"
  and     "AP ♯* α"
  
  shows "Ψ  P  Q α  (P  Q')"
proof -
  {
    fix Ψ    :: 'b
    and ΨP   :: 'b
    and Q    :: "('a, 'b, 'c) psi"
    and α    :: "'a action"
    and Q'   :: "('a, 'b, 'c) psi"
    and AP   :: "name list"
    and P    :: "('a, 'b, 'c) psi"

    assume "Ψ  ΨP  Q α  Q'"
    and     "extractFrame P = AP, ΨP"
    and     "bn α ♯* P"
    and     "bn α ♯* subject α"
    and     "AP ♯* Ψ"
    and     "AP ♯* Q"
    and     "AP ♯* α"
    and     "distinct AP"
  
    have  "Ψ  P  Q α  (P  Q')"
    proof -
      from Ψ  ΨP  Q α  Q' have "distinct(bn α)" by(rule boundOutputDistinct)
      obtain q::"name prm" where "bn(q  α) ♯* Ψ" and "bn(q  α) ♯* P" and "bn(q  α) ♯* Q" and "bn(q  α) ♯* α"
                             and "bn(q  α) ♯* AP" and "bn(q  α) ♯* Q'" and "bn(q  α) ♯* ΨP"
                             and Sq: "(set q)  (set (bn α)) × (set(bn(q  α)))"
        by(rule_tac xvec="bn α" and c="(Ψ, P, Q, α, AP, ΨP, Q')" in name_list_avoiding) (auto simp add: eqvts)
      obtain p::"name prm" where "(p  AP) ♯* Ψ" and "(p  AP) ♯* P" and "(p  AP) ♯* Q" and "(p  AP) ♯* α" 
                              and "(p  AP) ♯* α" and "(p  AP) ♯* (q  α)" and "(p  AP) ♯* Q'" 
                              and "(p  AP) ♯* (q  Q')" and "(p  AP) ♯* ΨP" 
                              and Sp: "(set p)  (set AP) × (set(p  AP))"
        by(rule_tac xvec=AP and c="(Ψ, P, Q, α, q  α, Q', (q  Q'), ΨP)" in name_list_avoiding) auto
      from distinct(bn α) have "distinct(bn(q  α))" 
        by(rule_tac α=α in actionCases) (auto simp add: eqvts)
      from AP ♯* α bn(q  α) ♯* AP Sq have "AP ♯* (q  α)"
        apply(rule_tac α=α in actionCases)
        apply(simp only: bn.simps eqvts, simp)
        apply(simp add: freshChainSimps)
        by simp
      from bn α ♯* subject α have "(q  (bn α)) ♯* (q  (subject α))"
        by(simp add: fresh_star_bij)
      hence "bn(q  α) ♯* subject(q  α)" by(simp add: eqvts)
      from Ψ  ΨP  Q α  Q' bn(q  α) ♯* α bn(q  α) ♯* Q' bn α ♯* (subject α) Sq
      have Trans: "Ψ  ΨP  Q (q  α)  (q  Q')"
        by(force simp add: residualAlpha)
      hence "AP ♯* (q  Q')" using  bn(q  α) ♯* subject(q  α) distinct(bn(q  α)) AP ♯* Q AP ♯* (q  α)
        by(auto intro: freeFreshChainDerivative)
      from Trans have "(p  (Ψ  ΨP))  (p  Q) p  ((q  α)  (q  Q'))"
        by(rule semantics.eqvt)
      with AP ♯* Ψ AP ♯* Q AP ♯* (q  α) (p  AP) ♯* (q  α) AP ♯* (q  Q')
           (p  AP) ♯* Ψ (p  AP) ♯* Q (p  AP) ♯* (q  Q') Sp
      have "Ψ  (p  ΨP)  Q (q  α)  (q  Q')" by(simp add: eqvts)
      moreover from extractFrame P = AP, ΨP (p  AP) ♯* ΨP Sp have  "extractFrame P = (p  AP), (p  ΨP)"
        by(simp add: frameChainAlpha' eqvts)
      moreover from (bn(q  α)) ♯* ΨP (bn(q  α)) ♯* AP (p  AP) ♯* (q  α) Sp 
      have "(bn(q  α)) ♯* (p  ΨP)"
        by(simp add: freshAlphaPerm)
      moreover from distinct AP have "distinct(p  AP)" by simp
      ultimately have "Ψ  P  Q (q  α)  (P  (q  Q'))"
        using (p  AP) ♯* P (p  AP) ♯* Q (p  AP) ♯* Ψ (p  AP) ♯* (q  α)
              (p  AP) ♯* (q  Q') (bn(q  α)) ♯* Ψ (bn(q  α)) ♯* Q (bn(q  α)) ♯* P 
              (bn(q  α)) ♯* (subject (q  α)) distinct(bn(q  α))
        by(rule_tac cPar2)
        
      thus ?thesis using bn(q  α) ♯* α bn(q  α) ♯* Q' bn α ♯* subject α bn(q  α) ♯* P bn α ♯* P Sq
        by(force simp add: residualAlpha) 
    qed
  }
  note Goal = this
  from extractFrame P = AP, ΨP AP ♯* Ψ AP ♯* Q AP ♯* α
  obtain AP' where FrP: "extractFrame P = AP', ΨP" and "distinct AP'" and "AP' ♯* Ψ" and "AP' ♯* Q" and "AP' ♯* α"
    by(rule_tac C="(Ψ, Q, α)" in distinctFrame) auto
  show ?thesis
  proof(induct rule: actionCases[where α=α])
    case(cInput M N)
    from Trans FrP AP' ♯* Ψ AP' ♯* Q AP' ♯* α distinct AP' bn α ♯* P
    show ?case using α = MN by(force intro: Goal)
  next
    case cTau 
    from Trans FrP AP' ♯* Ψ AP' ♯* Q AP' ♯* α distinct AP' bn α ♯* P
    show ?case using α = τ by(force intro: Goal)
  next
    case(cOutput M xvec N)
    from α = M⦇ν*xvec⦈⟨N AP' ♯* α bn α ♯* P have "xvec ♯* AP'" and "xvec ♯* P"
      by simp+
    obtain p where "(p  xvec) ♯* N" and "(p  xvec) ♯* Q'" and "(p  xvec) ♯* P"
               and "(p  xvec) ♯* M" and "(p  xvec) ♯* AP'" 
               and S: "set p  set xvec × set(p  xvec)"
      by(rule_tac xvec=xvec and c="(N, Q', P, M, AP')" in name_list_avoiding) auto
    from Trans α=M⦇ν*xvec⦈⟨N have "Ψ  ΨP  Q M⦇ν*xvec⦈⟨N  Q'" by simp
    with (p  xvec) ♯* N (p  xvec) ♯* Q' S
    have "Ψ  ΨP  Q M⦇ν*(p  xvec)⦈⟨(p  N)  (p  Q')"
      by(simp add: boundOutputChainAlpha'' create_residual.simps)
    moreover from xvec ♯* AP' (p  xvec) ♯* AP' AP' ♯* α S
    have "AP' ♯* (p  α)" by(simp add: freshChainSimps del: actionFreshChain)
    ultimately have "Ψ  P  Q M⦇ν*(p  xvec)⦈⟨(p  N)  P  (p  Q')"
      using FrP AP' ♯* Ψ AP' ♯* Q distinct AP' (p  xvec) ♯* P AP' ♯* α
           (p  xvec) ♯* M α = M⦇ν*xvec⦈⟨N
      by(force intro: Goal)
    with (p  xvec) ♯* N (p  xvec) ♯* Q' (p  xvec) ♯* P xvec ♯* P S α = M⦇ν*xvec⦈⟨N
    show ?case
      by(simp add: boundOutputChainAlpha'' eqvts create_residual.simps)
  qed
qed

lemma Open:
  fixes Ψ    :: 'b
  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"
  and   x    :: name

  assumes Trans: "Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'"
  and     "x  supp N"
  and     "x  Ψ"
  and     "x  M"
  and     "x  xvec"
  and     "x  yvec"

  shows "Ψ  ⦇νxP M⦇ν*(xvec@x#yvec)⦈⟨N  P'"
proof -
  from Trans have "distinct(xvec@yvec)" by(force dest: boundOutputDistinct)
  hence "xvec ♯* yvec" by(induct xvec) auto
  
  obtain p where "(p  yvec) ♯* Ψ" and "(p  yvec) ♯* P"  and "(p  yvec) ♯* M"
             and "(p  yvec) ♯* yvec" and "(p  yvec) ♯* N" and "(p  yvec) ♯* P'"
             and "x  (p  yvec)" and "(p  yvec) ♯* xvec"
             and Sp: "(set p)  (set yvec) × (set(p  yvec))"
    by(rule_tac xvec=yvec and c="(Ψ, P, M, xvec, yvec, N, P', x)" in name_list_avoiding)
      (auto simp add: eqvts fresh_star_prod)
  obtain q where "(q  xvec) ♯* Ψ" and "(q  xvec) ♯* P"  and "(q  xvec) ♯* M"
             and "(q  xvec) ♯* xvec" and "(q  xvec) ♯* N" and "(q  xvec) ♯* P'"
             and "x  (q  xvec)" and "(q  xvec) ♯* yvec"
             and "(q  xvec) ♯* p" and "(q  xvec) ♯* (p  yvec)"
             and Sq: "(set q)  (set xvec) × (set(q  xvec))"
    by(rule_tac xvec=xvec and c="(Ψ, P, M, xvec, yvec, p  yvec, N, P', x, p)" in name_list_avoiding)
      (auto simp add: eqvts fresh_star_prod)

  note Ψ  P M⦇ν*(xvec@yvec)⦈⟨N  P'
  moreover from (p  yvec) ♯* N (q  xvec) ♯* N xvec ♯* yvec (q  xvec) ♯* yvec (q  xvec) ♯* (p  yvec) (p  yvec) ♯* xvec Sp Sq 
  have "((p@q)  (xvec @ yvec)) ♯* N" apply(simp only: eqvts) apply(simp only: pt2[OF pt_name_inst])
    by simp
  moreover from (p  yvec) ♯* P' (q  xvec) ♯* P' xvec ♯* yvec (q  xvec) ♯* yvec (q  xvec) ♯* (p  yvec) (p  yvec) ♯* xvec Sp Sq 
  have "((p@q)  (xvec @ yvec)) ♯* P'" by(simp del: freshAlphaPerm add: eqvts pt2[OF pt_name_inst])
  moreover from Sp Sq xvec ♯* yvec (q  xvec) ♯* yvec (q  xvec) ♯* (p  yvec) (p  yvec) ♯* xvec
  have Spq: "set(p@q)  set(xvec@yvec) × set((p@q)  (xvec@yvec))"
    by(simp add: pt2[OF pt_name_inst] eqvts) blast
  ultimately have "Ψ  P M⦇ν*((p@q)  (xvec@yvec))⦈⟨((p@q)  N)  ((p@q)  P')"
    apply(simp add: create_residual.simps)
    by(erule_tac rev_mp) (subst boundOutputChainAlpha, auto)

  with  Sp Sq xvec ♯* yvec (q  xvec) ♯* yvec (q  xvec) ♯* (p  yvec) (p  yvec) ♯* xvec
  have "Ψ  P M⦇ν*((q  xvec)@(p  yvec))⦈⟨((p@q)  N)  ((p@q)  P')"
    by(simp add: eqvts pt2[OF pt_name_inst] del: freshAlphaPerm)
  moreover from x  supp N have "((p@q)  x)  (p@q)  (supp N)"
    by(simp add: pt_set_bij[OF pt_name_inst, OF at_name_inst])
  with x  xvec x  yvec x  (q  xvec) x  (p  yvec) Sp Sq
  have "x  supp((p@q) N)" by(simp add: eqvts pt2[OF pt_name_inst])
  moreover from distinct(xvec@yvec) have "distinct(q  xvec)" and "distinct(p  yvec)"
    by auto
  moreover note x  (q  xvec) x  (p  yvec) x  M x  Ψ 
                (q  xvec) ♯* Ψ (q  xvec) ♯* P (q  xvec) ♯* M (q  xvec) ♯* (p  yvec)
                (p  yvec) ♯* Ψ (p  yvec) ♯* P (p  yvec) ♯* M distinct(q  xvec)
  ultimately have "Ψ  ⦇νxP M⦇ν*((q  xvec)@x#(p  yvec))⦈⟨((p@q)  N)  ((p@q)  P')"
    by(rule_tac cOpen) 
  with x  xvec x  yvec x  (q  xvec) x  (p  yvec)
       xvec ♯* yvec (q  xvec) ♯* yvec (q  xvec) ♯* (p  yvec) (p  yvec) ♯* xvec Sp Sq
  have "Ψ  ⦇νxP M⦇ν*((p@q)  (xvec@x#yvec))⦈⟨((p@q)  N)  ((p@q)  P')"
    by(simp add: eqvts pt2[OF pt_name_inst] del: freshAlphaPerm)
  thus ?thesis using ((p@q)  (xvec @ yvec)) ♯* N ((p@q)  (xvec @ yvec)) ♯* P' Spq
    apply(simp add: create_residual.simps)
    by(erule_tac rev_mp) (subst boundOutputChainAlpha, auto)
qed

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

  assumes "Ψ  P α  P'"
  and     "x  Ψ"
  and     "x  α"

  shows "Ψ  ⦇νxP α  ⦇νxP'"
proof -
  {
    fix Ψ P M xvec N P' x

    assume "Ψ  P M⦇ν*xvec⦈⟨N  P'"
    and    "(x::name)  Ψ"
    and    "x  M"
    and    "x  xvec"
    and    "x  N"

    obtain p::"name prm" where "(p  xvec) ♯* Ψ" and "(p  xvec) ♯* P" and "(p  xvec) ♯* M" and "(p  xvec) ♯* xvec" 
                           and "(p  xvec) ♯* N" and "(p  xvec) ♯* P'" and "x  (p  xvec)"
                           and S: "(set p)  (set xvec) × (set(p  xvec))"
      by(rule_tac xvec=xvec and c="(Ψ, P, M, xvec, N, P', x)" in name_list_avoiding)
        (auto simp add: eqvts fresh_star_prod)
    from Ψ  P M⦇ν*xvec⦈⟨N  P' (p  xvec) ♯* N (p  xvec) ♯* P' S
    have "Ψ  P M⦇ν*(p  xvec)⦈⟨(p  N)  (p  P')"
      by(simp add: boundOutputChainAlpha'' create_residual.simps)
    moreover hence "distinct(p  xvec)" by(force dest: boundOutputDistinct)
    moreover note x  Ψ x  M x  (p  xvec)
    moreover from x  xvec x  p  xvec x  N S have "x  (p  N)"
      by(simp add: fresh_left del: freshAlphaSwap)
    ultimately have "Ψ  ⦇νxP M⦇ν*(p  xvec)⦈⟨(p  N)  ⦇νx(p  P')" using (p  xvec) ♯* Ψ (p  xvec) ♯* P (p  xvec) ♯* M
      by(rule_tac cScope) auto
    moreover from x  xvec x  p  xvec S have "p  x = x" by simp
    ultimately have "Ψ  ⦇νxP M⦇ν*(p  xvec)⦈⟨(p  N)  (p  (⦇νxP'))" by simp
    moreover from (p  xvec) ♯* P' x  xvec x  (p  xvec) have "(p  xvec) ♯* ⦇νxP'" 
      by(simp add: abs_fresh_star)
    ultimately have"Ψ  ⦇νxP M⦇ν*xvec⦈⟨N  ⦇νxP'" using (p  xvec) ♯* N S
      by(simp add: boundOutputChainAlpha'' create_residual.simps)
  }
  note Goal = this
  show ?thesis
  proof(induct rule: actionCases[where α=α])
    case(cInput M N)
    with assms show ?case by(force intro: cScope)
  next
    case(cOutput M xvec N)
    with assms show ?case by(force intro: Goal)
  next
    case cTau
    with assms show ?case by(force intro: cScope)
  qed
qed

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

  assumes "Ψ  P MN  P'"
  and     "x  P"
  and     "y  P"

  shows "([(x, y)]  Ψ)  P  ([(x, y)]  M)N  P'"
using assms
proof(nominal_induct avoiding: x y rule: inputInduct)
  case(cInput Ψ M K xvec N Tvec P x y)
  from x  M⦇λ*xvec N⦈.P have "x  M" by simp
  from y  M⦇λ*xvec N⦈.P have "y  M" by simp
  from Ψ  M  K have "([(x, y)]  Ψ)  ([(x, y)]  M)  ([(x, y)]  K)"
    by(rule chanEqClosed)
  with x  M y  M  have "([(x, y)]  Ψ)  M  ([(x, y)]  K)"
    by(simp)
  thus ?case using distinct xvec set xvec  supp N length xvec = length Tvec
    by(rule Input)
next
  case(cCase Ψ P M N P' φ Cs x y)
  from x  Cases Cs y  Cases Cs (φ, P) mem Cs have "x  φ" and "x  P" and "y  φ" and "y  P"
    by(auto dest: memFresh)
  from x  P y  P have "([(x ,y)]  Ψ)  P  ([(x, y)]  M)N  P'" by(rule cCase)
  moreover note (φ, P) mem Cs
  moreover from Ψ  φ have "([(x, y)]  Ψ)  ([(x, y)]  φ)" by(rule statClosed)
  with x  φ y  φ have "([(x, y)]  Ψ)  φ" by simp
  ultimately show ?case using guarded P by(rule Case)
next
  case(cPar1 Ψ ΨQ P M N P' AQ Q x y)
  from x  P  Q have "x  P" and "x  Q" by simp+
  from y  P  Q have "y  P" and "y  Q" by simp+
  from x  P y  P x y. x  P; y  P  ([(x, y)]  (Ψ  ΨQ))  P ([(x, y)]  M)N  P'
  have "([(x, y)]  Ψ)  ([(x, y)]  ΨQ)  P ([(x, y)]  M)N  P'"
    by(simp add: eqvts)

  moreover from extractFrame Q = AQ, ΨQ have "([(x, y)]  (extractFrame Q)) = ([(x, y)]  AQ, ΨQ)"
    by simp
  with AQ ♯* x x  Q AQ ♯* y y  Q have "AQ, ([(x, y)]  ΨQ) = extractFrame Q"
    by(simp add: eqvts)
  moreover from AQ ♯* Ψ have "([(x, y)]  AQ) ♯* ([(x, y)]  Ψ)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AQ ♯* x AQ ♯* y have "AQ ♯* ([(x, y)]  Ψ)" by simp
  moreover from AQ ♯* M have "([(x, y)]  AQ) ♯* ([(x, y)]  M)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AQ ♯* x AQ ♯* y have "AQ ♯* ([(x, y)]  M)" by simp
  ultimately show ?case using AQ ♯* P AQ ♯* N
    by(rule_tac Par1) auto
next
  case(cPar2 Ψ ΨP Q M N Q' AP P x y)
  from x  P  Q have "x  P" and "x  Q" by simp+
  from y  P  Q have "y  P" and "y  Q" by simp+
  from x  Q y  Q x y. x  Q; y  Q  ([(x, y)]  (Ψ  ΨP))  Q ([(x, y)]  M)N  Q'
  have "([(x, y)]  Ψ)  ([(x, y)]  ΨP)  Q ([(x, y)]  M)N  Q'"
    by(simp add: eqvts)

  moreover from extractFrame P = AP, ΨP have "([(x, y)]  (extractFrame P)) = ([(x, y)]  AP, ΨP)"
    by simp
  with AP ♯* x x  P AP ♯* y y  P have "AP, ([(x, y)]  ΨP) = extractFrame P"
    by(simp add: eqvts)
  moreover from AP ♯* Ψ have "([(x, y)]  AP) ♯* ([(x, y)]  Ψ)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AP ♯* x AP ♯* y have "AP ♯* ([(x, y)]  Ψ)" by simp
  moreover from AP ♯* M have "([(x, y)]  AP) ♯* ([(x, y)]  M)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AP ♯* x AP ♯* y have "AP ♯* ([(x, y)]  M)" by simp
  ultimately show ?case using AP ♯* Q AP ♯* N
    by(rule_tac Par2) auto
next
  case(cScope Ψ P M N P' z x y)
  from x  ⦇νzP z  x have "x  P" by(simp add: abs_fresh)
  from y  ⦇νzP z  y have "y  P" by(simp add: abs_fresh)
  from x  P y  P x y. x  P; y  P  ([(x, y)]  Ψ)  P ([(x, y)]  M)N  P'
  have "([(x, y)]  Ψ)  P ([(x, y)]  M)N  P'" by simp
  moreover with z  Ψ have "([(x, y)]  z)  [(x, y)]  Ψ"
    by(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst])
  with z  x z  y have "z  [(x, y)]  Ψ" by simp
  moreover with z  M have "([(x, y)]  z)  [(x, y)]  M"
    by(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst])
  with z  x z  y have "z  [(x, y)]  M" by simp
  ultimately show ?case using z  N
    by(rule_tac Scope) (assumption | simp)+
next
  case(cBang Ψ P M N P' x y)
  thus ?case by(force intro: Bang)
qed

lemma inputPermFrameSubject:
  fixes Ψ  :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   M  :: 'a
  and   N  :: 'a
  and   P' :: "('a, 'b, 'c) psi"
  and   p  :: "name prm"
  and   Xs :: "name set"
  and   Ys :: "name set"

  assumes "Ψ  P MN  P'"
  and     S: "set p  Xs × Ys"
  and     "Xs ♯* P"
  and     "Ys ♯* P"

  shows "(p  Ψ)  P  (p  M)N  P'"
using S
proof(induct p)
  case Nil
  from Ψ  P MN  P'
  show ?case by simp
next
  case(Cons a p)
  from set(a#p)  Xs × Ys have "set p  Xs × Ys" by auto
  with set p  Xs × Ys  (p  Ψ)  P  (p  M)N  P'
  have Trans: "(p  Ψ)  P  (p  M)N  P'" by simp
  from set(a#p)  Xs × Ys show ?case
  proof(cases a, clarsimp)
    fix a b
    assume "a  Xs" and "b  Ys"
    with Xs ♯* P Ys ♯* P
    have "a  P" and "b  P"
      by(auto simp add: fresh_star_def)
    with Trans show "([(a, b)]  p  Ψ)  P  ([(a, b)]  p  M)N  P'"
      by(rule inputSwapFrameSubject)
  qed  
qed

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

  assumes "Ψ  P MN  P'"
  and     "x  P"
  and     "y  P"
  and     "x  Ψ"
  and     "y  Ψ"

  shows "Ψ  P  ([(x, y)]  M)N  P'"
proof -
  from Ψ  P MN  P' x  P y  P
  have "([(x, y)]  Ψ)  P ([(x, y)]  M)N  P'"
    by(rule inputSwapFrameSubject)
  with x  Ψ y  Ψ show ?thesis
    by simp
qed

lemma inputPermSubject:
  fixes Ψ  :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   M  :: 'a
  and   N  :: 'a
  and   P' :: "('a, 'b, 'c) psi"
  and   p  :: "name prm"
  and   Xs :: "name set"
  and   Ys :: "name set"

  assumes "Ψ  P MN  P'"
  and     S: "set p  Xs × Ys"
  and     "Xs ♯* P"
  and     "Ys ♯* P"
  and     "Xs ♯* Ψ"
  and     "Ys ♯* Ψ"

  shows "Ψ  P  (p  M)N  P'"
proof -
  from Ψ  P MN  P' S Xs ♯* P Ys ♯* P
  have "(p  Ψ)  P (p  M)N  P'"
    by(rule inputPermFrameSubject)
  with Xs ♯* Ψ Ys ♯* Ψ S show ?thesis
    by simp
qed

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

  assumes "Ψ  P MN  P'"
  and     "x  P"
  and     "y  P"
  and     "x  M"
  and     "y  M"

  shows "([(x, y)]  Ψ)  P  MN  P'"
proof -
  from Ψ  P MN  P' x  P y  P
  have "([(x, y)]  Ψ)  P ([(x, y)]  M)N  P'"
    by(rule inputSwapFrameSubject)
  with x  M y  M show ?thesis
    by simp
qed

lemma inputPermFrame:
  fixes Ψ  :: 'b
  and   P  :: "('a, 'b, 'c) psi"
  and   M  :: 'a
  and   N  :: 'a
  and   P' :: "('a, 'b, 'c) psi"
  and   p  :: "name prm"
  and   Xs :: "name set"
  and   Ys :: "name set"

  assumes "Ψ  P MN  P'"
  and     S: "set p  Xs × Ys"
  and     "Xs ♯* P"
  and     "Ys ♯* P"
  and     "Xs ♯* M"
  and     "Ys ♯* M"

  shows "(p  Ψ)  P  MN  P'"
proof -
  from Ψ  P MN  P' S Xs ♯* P Ys ♯* P
  have "(p  Ψ)  P (p  M)N  P'"
    by(rule inputPermFrameSubject)
  with Xs ♯* M Ys ♯* M S show ?thesis
    by simp
qed

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

  assumes "Ψ  P MN  P'"
  and     "set p  (set xvec) × (set (p  xvec))"
  and     "distinctPerm p"
  and     "xvec ♯* P"
  and     "(p  xvec) ♯* P"

  shows "Ψ  P M(p  N)  (p  P')"
proof -
  from Ψ  P MN  P' set p  (set xvec) × (set (p  xvec)) xvec ♯* P (p  xvec) ♯* P
  have "(p  Ψ)  P (p  M)N  P'" by(rule_tac inputPermFrameSubject) auto
  hence "(p  p  Ψ)  (p  P) (p  ((p  M)N  P'))" by(rule eqvts)
  with distinctPerm p xvec ♯* P (p  xvec) ♯* P set p  (set xvec) × (set (p  xvec)) 
  show ?thesis by(simp add: eqvts)
qed

lemma frameFresh[dest]:
  fixes x  :: name
  and   AF :: "name list"
  and   ΨF :: 'b

  assumes "x  AF"
  and     "x  AF, ΨF"

  shows "x  ΨF"
using assms
by(simp add: frameResChainFresh) (simp add: fresh_def name_list_supp)

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

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     "xvec ♯* M"
  and     "x  P"
  and     "y  P"

  shows "([(x, y)]  Ψ)  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'"
using assms
proof(nominal_induct avoiding: x y rule: outputInduct')
  case cAlpha
  thus ?case by(simp add: create_residual.simps boundOutputChainAlpha'')
next
  case(cOutput Ψ M K N P x y)
  from x  MN⟩.P have "x  M" by simp
  from y  MN⟩.P have "y  M" by simp
  from Ψ  M  K have "([(x, y)]  Ψ)  ([(x, y)]  M)  ([(x, y)]  K)"
    by(rule chanEqClosed)
  with x  M y  M  have "([(x, y)]  Ψ)  M  ([(x, y)]  K)"
    by(simp)
  thus ?case by(rule Output)
next
  case(cCase Ψ P M xvec N P' φ Cs x y)
  from x  Cases Cs y  Cases Cs (φ, P) mem Cs have "x  φ" and "x  P" and "y  φ" and "y  P"
    by(auto dest: memFresh)
  from x  P y  P have "([(x ,y)]  Ψ)  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'" by(rule cCase)
  moreover note (φ, P) mem Cs
  moreover from Ψ  φ have "([(x, y)]  Ψ)  ([(x, y)]  φ)" by(rule statClosed)
  with x  φ y  φ have "([(x, y)]  Ψ)  φ" by simp
  ultimately show ?case using guarded P by(rule Case)
next
  case(cPar1 Ψ ΨQ P M xvec N P' AQ Q x y)
  from x  P  Q have "x  P" and "x  Q" by simp+
  from y  P  Q have "y  P" and "y  Q" by simp+
  from x  P y  P x y. x  P; y  P  ([(x, y)]  (Ψ  ΨQ))  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'
  have "([(x, y)]  Ψ)  ([(x, y)]  ΨQ)  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'"
    by(simp add: eqvts)

  moreover from extractFrame Q = AQ, ΨQ have "([(x, y)]  AQ, ΨQ) = ([(x, y)]  (extractFrame Q))"
    by simp
  with AQ ♯* x x  Q AQ ♯* y y  Q have "AQ, ([(x, y)]  ΨQ) = extractFrame Q"
    by(simp add: eqvts)
  moreover from AQ ♯* Ψ have "([(x, y)]  AQ) ♯* ([(x, y)]  Ψ)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AQ ♯* x AQ ♯* y have "AQ ♯* ([(x, y)]  Ψ)" by simp
  moreover from AQ ♯* M have "([(x, y)]  AQ) ♯* ([(x, y)]  M)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AQ ♯* x AQ ♯* y have "AQ ♯* ([(x, y)]  M)" by simp
  ultimately show ?case using AQ ♯* P AQ ♯* N xvec ♯* Q AQ ♯* xvec
    by(rule_tac Par1) auto
next
  case(cPar2 Ψ ΨP Q M xvec N Q' AP P x y)
  from x  P  Q have "x  P" and "x  Q" by simp+
  from y  P  Q have "y  P" and "y  Q" by simp+
  from x  Q y  Q x y. x  Q; y  Q  ([(x, y)]  (Ψ  ΨP))  Q ([(x, y)]  M)⦇ν*xvec⦈⟨N  Q'
  have "([(x, y)]  Ψ)  ([(x, y)]  ΨP)  Q ([(x, y)]  M)⦇ν*xvec⦈⟨N  Q'"
    by(simp add: eqvts)

  moreover from extractFrame P = AP, ΨP have "([(x, y)]  AP, ΨP) = ([(x, y)]  (extractFrame P))"
    by simp
  with AP ♯* x x  P AP ♯* y y  P have "AP, ([(x, y)]  ΨP) = extractFrame P"
    by(simp add: eqvts)
  moreover from AP ♯* Ψ have "([(x, y)]  AP) ♯* ([(x, y)]  Ψ)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AP ♯* x AP ♯* y have "AP ♯* ([(x, y)]  Ψ)" by simp
  moreover from AP ♯* M have "([(x, y)]  AP) ♯* ([(x, y)]  M)"
    by(simp add: pt_fresh_star_bij[OF pt_name_inst, OF at_name_inst])
  with AP ♯* x AP ♯* y have "AP ♯* ([(x, y)]  M)" by simp
  ultimately show ?case using AP ♯* Q AP ♯* N xvec ♯* P AP ♯* xvec
    by(rule_tac Par2) auto
next
  case(cOpen Ψ P M xvec yvec N P' z x y)
  from x  ⦇νzP z  x have "x  P" by(simp add: abs_fresh)
  from y  ⦇νzP z  y have "y  P" by(simp add: abs_fresh)
  from x  P y  P x y. x  P; y  P  ([(x, y)]  Ψ)  P ([(x, y)]  M)⦇ν*(xvec@yvec)⦈⟨N  P'
  have "([(x, y)]  Ψ)  P ([(x, y)]  M)⦇ν*(xvec@yvec)⦈⟨N  P'" by simp
  moreover with z  Ψ have "([(x, y)]  z)  [(x, y)]  Ψ"
    by(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst])
  with z  x z  y have "z  [(x, y)]  Ψ" by simp
  moreover with z  M have "([(x, y)]  z)  [(x, y)]  M"
    by(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst])
  with z  x z  y have "z  [(x, y)]  M" by simp
  ultimately show ?case using z  supp N z  xvec z  yvec
    by(rule_tac Open) (assumption | simp)+
next
  case(cScope Ψ P M xvec N P' z x y)
  from x  ⦇νzP z  x have "x  P" by(simp add: abs_fresh)
  from y  ⦇νzP z  y have "y  P" by(simp add: abs_fresh)
  from x  P y  P x y. x  P; y  P  ([(x, y)]  Ψ)  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'
  have "([(x, y)]  Ψ)  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'" by simp
  moreover with z  Ψ have "([(x, y)]  z)  [(x, y)]  Ψ"
    by(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst])
  with z  x z  y have "z  [(x, y)]  Ψ" by simp
  moreover with z  M have "([(x, y)]  z)  [(x, y)]  M"
    by(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst])
  with z  x z  y have "z  [(x, y)]  M" by simp
  ultimately show ?case using z  N z  xvec
    by(rule_tac Scope) (assumption | simp)+
next
  case(cBang Ψ P M B x y)
  thus ?case by(force intro: Bang)
qed

lemma outputPermFrameSubject:
  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 "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     S: "set p  set yvec × set zvec"
  and     "yvec ♯* P"
  and     "zvec ♯* P"

  shows "(p  Ψ)  P (p  M)⦇ν*xvec⦈⟨N  P'"
proof -
  {
    fix xvec N P' Xs YS
    assume "Ψ  P M⦇ν*xvec⦈⟨N  P'" and "xvec ♯* M" and "xvec ♯* yvec" and "xvec ♯* zvec"
    have "(p  Ψ)  P (p  M)⦇ν*xvec⦈⟨N  P'" using S
    proof(induct p)
      case Nil
      from Ψ  P M⦇ν*xvec⦈⟨N  P'
      show ?case by simp
    next
      case(Cons a p)
      from set(a#p)  set yvec × set zvec have "set p  set yvec × set zvec" by auto
      then have Trans: "(p  Ψ)  P (p  M)⦇ν*xvec⦈⟨N  P'" by(rule Cons)
      from set(a#p)  set yvec × set zvec show ?case
      proof(cases a, clarsimp)
        fix x y
        note Trans
        moreover from xvec ♯* yvec xvec ♯* zvec set p  set yvec × set zvec xvec ♯* M have "xvec ♯* (p  M)"
          by(simp add: freshChainSimps)
        moreover assume "x  set yvec" and "y  set zvec"
        with yvec ♯* P zvec ♯* P have "x  P" and "y  P"
          by(auto simp add: fresh_star_def)
        ultimately show "([(x, y)]  p  Ψ)  P ([(x, y)]  p  M)⦇ν*xvec⦈⟨N  P'"
          by(rule outputSwapFrameSubject)
      qed
    qed
  }
  note Goal = this
  obtain q::"name prm" where "(q  xvec) ♯* yvec" and "(q  xvec) ♯* zvec" and "(q  xvec) ♯* xvec" 
                         and "(q  xvec) ♯* N" and "(q  xvec) ♯* P'" and "(q  xvec) ♯* M" 
                         and Sq: "(set q)  (set xvec) × (set(q  xvec))"
    by(rule_tac xvec=xvec and c="(P, xvec, yvec, zvec, N, M, P')" in name_list_avoiding) auto
  with Ψ  P M⦇ν*xvec⦈⟨N  P' have "Ψ  P M⦇ν*(q  xvec)⦈⟨(q  N)  (q  P')"
    by(simp add: boundOutputChainAlpha'' residualInject)
  hence "(p  Ψ)  P (p  M)⦇ν*(q  xvec)⦈⟨(q  N)  (q  P')"
    using (q  xvec) ♯* M (q  xvec) ♯* yvec (q  xvec) ♯* zvec
    by(rule Goal)
  with (q  xvec) ♯* N (q  xvec) ♯* P' Sq show ?thesis
    by(simp add: boundOutputChainAlpha'' residualInject)
qed   

lemma outputSwapSubject:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   B    :: "('a, 'b, 'c) boundOutput"
  and   x    :: name
  and   y    :: name

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     "xvec ♯* M"
  and     "x  P"
  and     "y  P"
  and     "x  Ψ"
  and     "y  Ψ"

  shows "Ψ  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'"
proof -
  from Ψ  P M⦇ν*xvec⦈⟨N  P' xvec ♯* M x  P y  P
  have "([(x, y)]  Ψ)  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'"
    by(rule outputSwapFrameSubject)
  with x  Ψ y  Ψ show ?thesis
    by simp
qed

lemma outputPermSubject:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   B    :: "('a, 'b, 'c) boundOutput"
  and   p    :: "name prm"
  and   yvec :: "name list"
  and   zvec :: "name list"

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     S: "set p  set yvec × set zvec"
  and     "yvec ♯* P"
  and     "zvec ♯* P"
  and     "yvec ♯* Ψ"
  and     "zvec ♯* Ψ"

  shows "Ψ  P (p  M)⦇ν*xvec⦈⟨N  P'"
proof -
  from assms have "(p  Ψ)  P (p  M)⦇ν*xvec⦈⟨N  P'"
   by(rule_tac outputPermFrameSubject)
  with S yvec ♯* Ψ zvec ♯* Ψ show ?thesis
    by simp
qed
 
lemma outputSwapFrame:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   B    :: "('a, 'b, 'c) boundOutput"
  and   x    :: name
  and   y    :: name

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     "xvec ♯* M"
  and     "x  P"
  and     "y  P"
  and     "x  M"
  and     "y  M"

  shows "([(x, y)]  Ψ)  P M⦇ν*xvec⦈⟨N  P'"
proof -
  from Ψ  P M⦇ν*xvec⦈⟨N  P' xvec ♯* M x  P y  P
  have "([(x, y)]  Ψ)  P ([(x, y)]  M)⦇ν*xvec⦈⟨N  P'"
    by(rule outputSwapFrameSubject)
  with x  M y  M show ?thesis
    by simp
qed

lemma outputPermFrame:
  fixes Ψ    :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   B    :: "('a, 'b, 'c) boundOutput"
  and   p    :: "name prm"
  and   yvec :: "name list"
  and   zvec :: "name list"

  assumes "Ψ  P M⦇ν*xvec⦈⟨N  P'"
  and     S: "set p  set yvec × set zvec"
  and     "yvec ♯* P"
  and     "zvec ♯* P"
  and     "yvec ♯* M"
  and     "zvec ♯* M"

  shows "(p  Ψ)  P M⦇ν*xvec⦈⟨N  P'"
proof -
  from assms have "(p  Ψ)  P (p  M)⦇ν*xvec⦈⟨N  P'"
    by(rule_tac outputPermFrameSubject)
  with S yvec ♯* M zvec ♯* M show ?thesis
    by simp
qed

lemma Comm1:
  fixes Ψ    :: 'b
  and   ΨQ  :: 'b
  and   P    :: "('a, 'b, 'c) psi"
  and   M    :: 'a
  and   N    :: 'a
  and   P'   :: "('a, 'b, 'c) psi"
  and   AP   :: "name list"
  and   ΨP  :: 'b
  and   Q    :: "('a, 'b, 'c) psi"
  and   K    :: 'a
  and   xvec :: "name list"
  and   Q'   :: "('a, 'b, 'c) psi"
  and   AQ   :: "name list"
  
  assumes "Ψ  ΨQ  P MN  P'"
  and     "extractFrame P = AP, ΨP"
  and     "Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q'"
  and     "extractFrame Q = AQ, ΨQ"
  and     "Ψ  ΨP  ΨQ  M  K"
  and     "AP ♯* Ψ"
  and     "AP ♯* P"
  and     "AP ♯* Q"
  and     "AP ♯* M"
  and     "AP ♯* AQ"
  and     "AQ ♯* Ψ"
  and     "AQ ♯* P"
  and     "AQ ♯* Q"
  and     "AQ ♯* K"
  and     "xvec ♯* P"

  shows "Ψ  P  Q τ  ⦇ν*xvec(P'  Q')"
proof -
  {
    fix Ψ    :: 'b
    and ΨQ  :: 'b
    and P    :: "('a, 'b, 'c) psi"
    and M    :: 'a
    and N    :: 'a
    and P'   :: "('a, 'b, 'c) psi"
    and AP   :: "name list"
    and ΨP  :: 'b
    and Q    :: "('a, 'b, 'c) psi"
    and K    :: 'a
    and xvec :: "name list"
    and Q'   :: "('a, 'b, 'c) psi"
    and AQ   :: "name list"
 
    assume "Ψ  ΨQ  P MN  P'"
    and    "extractFrame P = AP, ΨP"
    and    "distinct AP"
    and    "Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q'"
    and    "extractFrame Q = AQ, ΨQ"
    and    "distinct AQ"
    and    "Ψ  ΨP  ΨQ  M  K"
    and    "AP ♯* Ψ"
    and    "AP ♯* P"
    and    "AP ♯* Q"
    and    "AP ♯* M"
    and    "AP ♯* AQ"
    and    "AQ ♯* Ψ"
    and    "AQ ♯* P"
    and    "AQ ♯* Q"
    and    "AQ ♯* K"
    and    "xvec ♯* P"

    have "Ψ  P  Q τ  ⦇ν*xvec(P'  Q')"
    proof -

      obtain r::"name prm" where "(r  xvec) ♯* Ψ" and "(r  xvec) ♯* P" and "(r  xvec) ♯* Q" and "(r  xvec) ♯* M"
                             and "(r  xvec) ♯* K" and "(r  xvec) ♯* N" and "(r  xvec) ♯* AP" and "(r  xvec) ♯* AQ"
                             and "(r  xvec) ♯* P'" and "(r  xvec) ♯* Q'" and "(r  xvec) ♯* ΨP" and "(r  xvec) ♯* ΨQ"
                             and Sr: "(set r)  (set xvec) × (set(r  xvec))" and "distinctPerm r"
        by(rule_tac xvec=xvec and c="(Ψ, P, Q, M, K, N, AP, AQ, ΨP, ΨQ, P', Q')" in name_list_avoiding)
          (auto simp add: eqvts fresh_star_prod)
      obtain q::"name prm" where "(q  AQ) ♯* Ψ" and "(q  AQ) ♯* P" and "(q  AQ) ♯* Q" and "(q  AQ) ♯* K"
                             and "(q  AQ) ♯* (r  N)" and "(q  AQ) ♯* (r  xvec)" and "(q  AQ) ♯* (r  Q')"
                             and "(q  AQ) ♯* (r  P')" and "(q  AQ) ♯* ΨP" and "(q  AQ) ♯* AP" and "(q  AQ) ♯* ΨQ"
                             and Sq: "set q  set AQ × set(q  AQ)"
        by(rule_tac xvec=AQ and c="(Ψ, P, Q, K, r  N, r  xvec, ΨQ, AP, ΨP, r  Q', r  P')" in name_list_avoiding)
          (auto simp add: eqvts fresh_star_prod)
      obtain p::"name prm" where "(p  AP) ♯* Ψ" and "(p  AP) ♯* P" and "(p  AP) ♯* Q" and "(p  AP) ♯* M"
                             and "(p  AP) ♯* (r  N)" and "(p  AP) ♯* (r  xvec)" and "(p  AP) ♯* (r  Q')" 
                             and "(p  AP) ♯* (r  P')" and "(p  AP) ♯* ΨP" and "(p  AP) ♯* ΨQ" and "(p  AP) ♯* AQ"
                             and "(p  AP) ♯* (q  AQ)" and Sp: "(set p)  (set AP) × (set(p  AP))"
        by(rule_tac xvec=AP and c="(Ψ, P, Q, M, r  N, r  xvec, AQ, q  AQ, ΨQ, ΨP, r  Q', r  P')" in name_list_avoiding)
          (auto simp add: eqvts fresh_star_prod)

      have FrP: "extractFrame P = AP, ΨP" by fact
      have FrQ: "extractFrame Q = AQ, ΨQ" by fact
      
      from AP ♯* Q FrQ AP ♯* AQ have "AP ♯* ΨQ"
        by(drule_tac extractFrameFreshChain) auto
      from AQ ♯* P FrP AP ♯* AQ have "AQ ♯* ΨP"
        by(drule_tac extractFrameFreshChain) auto
      from (r  xvec) ♯* AP (p  AP) ♯* (r  xvec) (r  xvec) ♯* AP Sp have "(r  xvec) ♯* (p  AP)"
        by(simp add: freshChainSimps)

      from Ψ  ΨQ  P MN  P' Sr distinctPerm r xvec ♯* P (r  xvec) ♯* P
      have "Ψ  ΨQ  P M(r  N)  (r  P')"
        by(rule inputAlpha)
      hence "(q  (Ψ  ΨQ))  P (q  M)(r  N)  (r  P')" using Sq AQ ♯* P (q  AQ) ♯* P
        by(rule_tac inputPermFrameSubject) (assumption | simp)+
      hence PTrans: "Ψ  (q  ΨQ)  P (q  M)(r  N)  (r  P')" using Sq AQ ♯* Ψ (q  AQ) ♯* Ψ
        by(simp add: eqvts)
  
      moreover from extractFrame P = AP, ΨP  Sp (p  AP) ♯* ΨP
      have FrP: "extractFrame P = (p  AP), (p  ΨP)"
        by(simp add: frameChainAlpha)
      moreover from distinct AP have "distinct(p  AP)"  by simp
      
      moreover from Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q' Sr (r  xvec) ♯* N (r  xvec) ♯* Q'
      have "Ψ  ΨP  Q K⦇ν*(r  xvec)⦈⟨(r  N)  (r  Q')"
        by(simp add: boundOutputChainAlpha'' create_residual.simps)
      hence "(p  (Ψ  ΨP))  Q (p  K)⦇ν*(r  xvec)⦈⟨(r  N)  (r  Q')" using Sp AP ♯* Q (p  AP) ♯* Q (r  xvec) ♯* K (r  xvec) ♯* AP (r  xvec) ♯* (p  AP)
        by(rule_tac outputPermFrameSubject) (assumption | auto)
      hence QTrans: "Ψ  (p  ΨP)  Q (p  K)⦇ν*(r  xvec)⦈⟨(r  N)  (r  Q')" using Sp AP ♯* Ψ (p  AP) ♯* Ψ
        by(simp add: eqvts)
      moreover hence "distinct(r  xvec)" by(force dest: boundOutputDistinct)
      moreover from extractFrame Q = AQ, ΨQ  Sq (q  AQ) ♯* ΨQ
      have FrQ: "extractFrame Q = (q  AQ), (q  ΨQ)"
        by(simp add: frameChainAlpha)
      moreover from distinct AQ have "distinct(q  AQ)"  by simp
  
      moreover from Ψ  ΨP  ΨQ  M  K have "(p  q  (Ψ  ΨP  ΨQ))  (p  q  M)  (p  q  K)"
        by(rule_tac chanEqClosed)+
      with AP ♯* Ψ (p  AP) ♯* Ψ AQ ♯* Ψ (q  AQ) ♯* Ψ AQ ♯* ΨP (q  AQ) ♯* ΨP
           AP ♯* ΨQ (p  AP) ♯* ΨQ AP ♯* M (p  AP) ♯* M (q  AQ) ♯* AP (p  AP) ♯* (q  AQ)
           AQ ♯* K (q  AQ) ♯* K AP ♯* AQ (p  AP) ♯* AQ  Sp Sq
      have "Ψ  (p  ΨP)  (q  ΨQ)  (q  M)  (p  K)" by(simp add: eqvts freshChainSimps)
      moreover note (p  AP) ♯* Ψ
      moreover from (p  AP) ♯* AQ (p  AP) ♯* (q  AQ) (p  AP) ♯* ΨQ Sq have "(p  AP) ♯* (q  ΨQ)" 
        by(simp add: freshChainSimps)
      moreover note (p  AP) ♯* P 
      moreover from (p  AP) ♯* AQ (p  AP) ♯* (q  AQ) (p  AP) ♯* M Sq have "(p  AP) ♯* (q  M)"
        by(simp add: freshChainSimps)
      moreover note  (p  AP) ♯* (r  N) (p  AP) ♯* (r  P') (p  AP) ♯* Q (p  AP) ♯* (r  Q') (p  AP) ♯* (q  AQ)
                     (p  AP) ♯* (r  xvec) (q  AQ) ♯* Ψ
      moreover from (q  AQ) ♯* AP (p  AP) ♯* AQ (q  AQ) ♯* ΨP (p  AP) ♯* (q  AQ) Sp Sq have "(q  AQ) ♯* (p  ΨP)"
        by(simp add: freshChainSimps)
      moreover note (q  AQ) ♯* P (q  AQ) ♯* (r  N)(q  AQ) ♯* (r  P') (q  AQ) ♯* Q 
      moreover from (q  AQ) ♯* AP (p  AP) ♯* AQ (q  AQ) ♯* K (p  AP) ♯* (q  AQ) Sp Sq have "(q  AQ) ♯* (p  K)"
        by(simp add: freshChainSimps)
      moreover note  (q  AQ) ♯* (r  Q') (q  AQ) ♯* (r  xvec) (r  xvec) ♯* Ψ
      moreover from (r  xvec) ♯* AP (p  AP) ♯* (r  xvec) (r  xvec) ♯* ΨP Sp have "(r  xvec) ♯* (p  ΨP)"
        by(simp add: freshChainSimps)
      moreover from (r  xvec) ♯* AQ (q  AQ) ♯* (r  xvec) (r  xvec) ♯* ΨQ Sq have "(r  xvec) ♯* (q  ΨQ)"
        by(simp add: freshChainSimps)
      moreover note (r  xvec) ♯* P 
      moreover from (r  xvec) ♯* AQ (q  AQ) ♯* (r  xvec) (r  xvec) ♯* M Sq have "(r  xvec) ♯* (q  M)"
      by(simp add: freshChainSimps)
      moreover note (r  xvec) ♯* Q
      moreover from (r  xvec) ♯* AP (p  AP) ♯* (r  xvec) (r  xvec) ♯* K Sp have "(r  xvec) ♯* (p  K)"  
        by(simp add: freshChainSimps)
      ultimately have "Ψ  P  Q τ  ⦇ν*(r  xvec)((r  P')  (r  Q'))"
        by(rule_tac cComm1)
      with (r  xvec) ♯* P' (r  xvec) ♯* Q' Sr 
      show ?thesis
        by(subst resChainAlpha) auto
    qed
  }
  note Goal = this
  note Ψ  ΨQ  P MN  P' Ψ  ΨP  Q K⦇ν*xvec⦈⟨N  Q' Ψ  ΨP  ΨQ  M  K
  moreover from extractFrame P = AP, ΨP AP ♯* Ψ AP ♯* P AP ♯* Q AP ♯* M AP ♯* AQ
  obtain AP' where "extractFrame P = AP', ΨP" and "distinct AP'" and "AP' ♯* Ψ" and "AP' ♯* P" and "AP' ♯* Q" and "AP' ♯* M" and "AP' ♯* AQ"
    by(rule_tac C="(Ψ, P, Q, M, AQ)" in distinctFrame) auto
  moreover from extractFrame Q = AQ, ΨQ AQ ♯* Ψ AQ ♯* P AQ ♯* Q AQ ♯* K AP' ♯* AQ
  obtain AQ' where "extractFrame Q = AQ', ΨQ