Theory Weak_Late_Step_Semantics

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

definition inputTransition :: "pi  name  pi  name  name  pi  bool" (‹_ l_ in __<_>  _› [80, 80, 80, 80, 80] 80)
where "P lu in P'' a<x>  P'  P'''. P τ P'''  P''' a<x>  P''  P''[x::=u] τ P'"

definition transition :: "(pi × Late_Semantics.residual) set" where
  "transition  {x. P P' α P'' P'''. P τ P'  P' α  P''  P'' τ P'''  x = (P, α  P''')}  
                {x. P P' a y P'' P'''. P τ P'  (P' (ay>  P''))  P'' τ P'''  x = (P, (ay>  P'''))}"

abbreviation weakTransition_judge :: "pi  Late_Semantics.residual  bool" (‹_ l _› [80, 80] 80)
  where "P l Rs  (P, Rs)  transition"

lemma weakNonInput[dest]:
  fixes P  :: pi
  and   a  :: name
  and   x  :: name
  and   P' :: pi

  assumes "P la<x>  P'"
 
  shows False
using assms
by(auto simp add: transition_def residual.inject)

lemma transitionI:
  fixes P    :: pi
  and   P''' :: pi
  and   α    :: freeRes
  and   P''  :: pi
  and   P'   :: pi
  and   a    :: name
  and   x    :: name
  and   u    :: name

  shows "P τ P'''; P''' α  P''; P'' τ P'  P lα  P'"
  and   "P τ P'''; P''' ax>  P''; P'' τ P'  P lax>  P'"
  and   "P τ P'''; P''' a<x>  P''; P''[x::=u] τ P'  P lu in P''a<x>  P'"
proof -
  assume "P τ P'''" and "P'''  α  P''" and "P'' τ P'"
  thus "P l α  P'"
    by(force simp add: transition_def)
next
  assume "P τ P'''" and "P''' ax>  P''" and "P'' τ P'"
  thus "P lax>  P'"
    by(force simp add: transition_def)
next
  assume "P τ P'''" and "P''' a<x>  P''" and "P''[x::=u] τ P'"
  thus "P lu in P''a<x>  P'" 
    by(force simp add: inputTransition_def)
qed

lemma transitionE:
  fixes P  :: pi
  and   α  :: freeRes
  and   P'  :: pi
  and   P'' :: pi
  and   a   :: name
  and   u   :: name
  and   x   :: name

  shows "P lα  P'  P'' P'''. P τ P''  P'' α  P'''  P''' τ P'" (is "_  ?thesis1")
  and   "P lax>  P'; x  P  P'' P'''. P τ P'''  P''' ax>  P''  P'' τ P'"
  and   "P lu in P''a<x>  P'  P'''. P τ P'''  P''' a<x>  P''  P''[x::=u] τ P'"
proof -
  assume "P lα  P'"
  thus ?thesis1 by(auto simp add: transition_def residual.inject)
next
  assume "P lax>  P'" and "x  P"
  thus "P'' P'''. P τ P'''  P''' ax>  P''  P'' τ P'"
  using [[hypsubst_thin = true]]
    apply(auto simp add: transition_def residualInject name_abs_eq)
    apply(rule_tac x="[(x, y)]  P''" in exI)
    apply(rule_tac x=P' in exI)
    apply(clarsimp)
    apply(auto)
    apply(subgoal_tac "x  P''")
    apply(simp add: alphaBoundResidual name_swap)
    using freshChain
    apply(force dest: freshBoundDerivative)
    using eqvtChainI
    by simp
next
  assume PTrans: "P lu in P''a<x>  P'"
  thus "P'''. P τ P'''  P'''  a<x>  P''  P''[x::=u] τ P'"
    by(auto simp add: inputTransition_def)
qed

lemma alphaInput:
  fixes P   :: pi
  and   u   :: name
  and   P'' :: pi
  and   a   :: name
  and   x   :: name
  and   P'  :: pi
  and   y   :: name

  assumes PTrans:  "P lu in P''a<x>  P'"
  and     yFreshP: "y  P"

  shows "P lu in ([(x, y)]  P'')a<y>  P'"
proof(cases "x=y")
  assume "x=y"
  with PTrans show ?thesis by simp
next
  assume xineqy: "xy"
  from PTrans obtain P''' where PChain: "P τ P'''"
                            and P'''Trans: "P''' a<x>  P''"
                            and P''Chain: "P''[x::=u] τ P'"
    by(blast dest: transitionE)

  from PChain yFreshP have "y  P'''" by(rule freshChain)
  with P'''Trans xineqy have yFreshP'': "y  P''" by(blast dest: freshBoundDerivative)

  with P'''Trans have "P''' a<y>  [(x, y)]  P''" by(simp add: alphaBoundResidual)
  moreover from P''Chain yFreshP'' have "([(x, y)]  P'')[y::=u] τ P'"
    by(simp add: renaming name_swap)
  ultimately show ?thesis using PChain by(blast intro: transitionI)
qed

lemma tauActionChain:
  fixes P  :: pi
  and   P' :: pi
  
  shows "P lτ  P'  P τ P'"
  and   "P  P'  P τ P'  P lτ  P'"
proof -
  assume "P lτ  P'"
  then obtain P'' P''' where "P τ P''"
                         and "P'' τ  P'''"
                         and "P''' τ P'"
    by(blast dest: transitionE)
  thus "P τ P'" by auto
next
  assume "P τ P'" and "P  P'" 
  thus "P lτ  P'"
  proof(induct rule: tauChainInduct)
    case id
    thus ?case by simp
  next
    case(ih P'' P''')
    have "P τ P''" and "P''  τ  P'''" by fact+
    moreover have "P''' τ P'''" by simp
    ultimately show ?case by(rule transitionI)
  qed
qed

lemma singleActionChain:
  fixes P  :: pi
  and   a  :: name
  and   x  :: name
  and   α  :: freeRes
  and   u  :: name
 
  shows "P ax>  P'  P lax>  P'"
  and   "P a<x>  P'  P lu in P'a<x>  P'[x::=u]"
  and   "P α  P'  P lα  P'"
proof -  
  assume "P ax>  P'"
  moreover have "P τ P" by simp
  moreover have "P' τ P'" by simp
  ultimately show "P lax>  P'" by(blast intro: transitionI)
next
  assume "P a<x>  P'"
  moreover have "P τ P" by simp
  moreover have "P'[x::=u] τ P'[x::=u]" by simp
  ultimately show "P lu in P'a<x>  P'[x::=u]" by(blast intro: transitionI)
next
  assume "P α  P'"
  moreover have "P τ P" by simp
  moreover have "P' τ P'" by simp
  ultimately show "P lα  P'"  by(blast intro: transitionI)
qed

lemma Tau:
  fixes P :: pi

  shows "τ.(P) l τ   P"
proof -
  have "τ.(P) τ τ.(P)" by simp
  moreover have "τ.(P) τ  P" by(rule transitions.Tau)
  moreover have "P τ P" by simp
  ultimately show ?thesis by(rule transitionI)
qed

lemma Input:
  fixes a :: name
  and   x :: name
  and   u :: name
  and   P :: pi

  shows "a<x>.P lu in Pa<x>  P[x::=u]"
proof -
  have "a<x>.P τ a<x>.P" by simp
  moreover have "a<x>.P  a<x>  P" by(rule Input)
  moreover have "P[x::=u] τ P[x::=u]" by simp
  ultimately show ?thesis by(rule transitionI)
qed

lemma Output:
  fixes a :: name
  and   b :: name
  and   P :: pi

  shows "a{b}.P la[b]  P"
proof -
  have "a{b}.P τ a{b}.P" by simp
  moreover have "a{b}.P a[b]  P" by(rule transitions.Output)
  moreover have "P τ P" by simp
  ultimately show ?thesis by(rule transitionI)
qed

lemma Match:
  fixes P  :: pi
  and   Rs :: residual
  and   a  :: name
  and   u  :: name
  and   b  :: name
  and   x  :: name
  and   P' :: pi

  shows "P l Rs  [aa]P l Rs"
  and   "P lu in P''b<x>  P'  [aa]P lu in P''b<x>  P'"
proof -
  assume PTrans: "P l Rs"
  thus "[aa]P l Rs"
  proof(nominal_induct avoiding: P rule: residual.strong_inducts)
    case(BoundR b x P')
    have PTrans: "P l b«x»  P'" and xFreshP: "x  P" by fact+
    from PTrans obtain b' where beq: "b = BoundOutputS b'" by(cases b) auto
    with PTrans xFreshP obtain P'' P''' where PTrans: "P τ P''"
                                          and P''Trans: "P'' b'x>  P'''"
                                          and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "P = P''")
      assume "P = P''"
      moreover have "[aa]P τ [aa]P" by simp
      moreover from P''Trans have "[aa]P''  b'x>  P'''" by(rule Match)
      ultimately show ?thesis using beq P'''Trans by(blast intro: transitionI)
    next
      assume "P  P''"
      with PTrans have "[aa]P τ P''" by(rule matchChain)
      thus ?thesis using beq P''Trans P'''Trans by(blast intro: transitionI)
    qed
  next
    case(FreeR α P')
    have "P l α  P'" by fact

    then obtain P'' P''' where PTrans: "P τ P''"
                           and P''Trans: "P''  α  P'''"
                           and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "P = P''")
      assume "P = P''"
      moreover have "[aa]P τ [aa]P" by simp
      moreover from P''Trans have "[aa]P''  α  P'''" by(rule transitions.Match)
      ultimately show ?thesis using P'''Trans by(blast intro: transitionI)
    next
      assume "P  P''"
      with PTrans have "[aa]P τ P''" by(rule matchChain)
      thus ?thesis using P''Trans P'''Trans by(rule transitionI)
    qed
  qed
next
  assume "P lu in P''b<x>  P'"
  then obtain P''' where PChain: "P τ P'''"
                     and P'''Trans: "P''' b<x>  P''"
                     and P''Chain: "P''[x::=u] τ P'"
    by(blast dest: transitionE)
  show "[aa]P lu in P''b<x>  P'"
  proof(cases "P=P'''")
    assume "P=P'''"
    moreover have "[aa]P τ [aa]P" by simp
    moreover from P'''Trans have "[aa]P''' b<x>  P''" by(rule Late_Semantics.Match)
    ultimately show ?thesis using P''Chain by(blast intro: transitionI)
  next
    assume "P  P'''"
    with PChain have "[aa]P τ P'''" by(rule matchChain)
    thus ?thesis using P'''Trans P''Chain by(rule transitionI)
  qed
qed

lemma Mismatch:
  fixes P  :: pi
  and   Rs :: residual
  and   a  :: name
  and   c  :: name
  and   u  :: name
  and   b  :: name
  and   x  :: name
  and   P' :: pi

  shows "P l Rs; a  c  [ac]P l Rs"
  and   "P lu in P''b<x>  P'; a  c  [ac]P lu in P''b<x>  P'"
proof -
  assume PTrans: "P l Rs"
     and aineqc: "a  c"
  thus "[ac]P l Rs"
  proof(nominal_induct avoiding: P rule: residual.strong_inducts)
    case(BoundR b x P')
    have PTrans: "P l b«x»  P'" and xFreshP: "x  P" by fact+
    from PTrans obtain b' where beq: "b = BoundOutputS b'" by(cases b, auto)
    with PTrans xFreshP obtain P'' P''' where PTrans: "P τ P''"
                                          and P''Trans: "P'' b'x>  P'''"
                                          and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "P = P''")
      assume "P = P''"
      moreover have "[ac]P τ [ac]P" by simp
      moreover from P''Trans aineqc have "[ac]P'' b'x>  P'''" by(rule transitions.Mismatch)
      ultimately show ?thesis using beq P'''Trans by(blast intro: transitionI)
    next
      assume "P  P''"
      with PTrans aineqc have "[ac]P τ P''" by(rule mismatchChain)
      thus ?thesis using beq P''Trans P'''Trans by(blast intro: transitionI)
    qed
  next
    case(FreeR α P')
    have "P l α  P'" by fact

    then obtain P'' P''' where PTrans: "P τ P''"
                           and P''Trans: "P''  α  P'''"
                           and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "P = P''")
      assume "P = P''"
      moreover have "[ac]P τ [ac]P" by simp
      moreover from P''Trans a  c have "[ac]P''  α  P'''" by(rule transitions.Mismatch)
      ultimately show ?thesis using P'''Trans by(blast intro: transitionI)
    next
      assume "P  P''"
      with PTrans aineqc have "[ac]P τ P''" by(rule mismatchChain)
      thus ?thesis using P''Trans P'''Trans by(rule transitionI)
    qed
  qed
next
  assume aineqc: "a  c"
  assume "P lu in P''b<x>  P'"
  then obtain P''' where PChain: "P τ P'''"
                     and P'''Trans: "P''' b<x>  P''"
                     and P''Chain: "P''[x::=u] τ P'"
    by(blast dest: transitionE)
  show "[ac]P lu in P''b<x>  P'"
  proof(cases "P=P'''")
    assume "P=P'''"
    moreover have "[ac]P τ [ac]P" by simp
    moreover from P'''Trans aineqc have "[ac]P''' b<x>  P''" by(rule Late_Semantics.Mismatch)
    ultimately show ?thesis using P''Chain by(blast intro: transitionI)
  next
    assume "P  P'''"
    with PChain aineqc have "[ac]P τ P'''" by(rule mismatchChain)
    thus ?thesis using P'''Trans P''Chain by(rule transitionI)
  qed
qed

lemma Open:
  fixes P  :: pi
  and   a  :: name
  and   b  :: name
  and   P' :: pi

  assumes Trans:  "P la[b]  P'"
  and     aInEqb: "a  b"

  shows "b>P lab>  P'"
proof -
  from Trans obtain P'' P''' where A: "P τ P''"
                               and B: "P'' a[b]  P'''"
                               and C: "P''' τ P'"
    by(force dest: transitionE)
  from A have "b>P τ b>P''" by(rule ResChain)
  moreover from B aInEqb have "b>P'' ab>  P'''" by(rule Open)
  ultimately show ?thesis using C by(force simp add: transition_def)
qed

lemma Sum1:
  fixes P   :: pi
  and   Rs  :: residual
  and   Q   :: pi
  and   u   :: name
  and   P'' :: pi
  and   a   :: name
  and   x   :: name
  and   P'  :: pi

  shows "P l Rs  P  Q l Rs"
  and   "P lu in P''a<x>  P'  P  Q lu in P''a<x>  P'"
proof -
  assume "P l Rs"
  thus "P  Q l Rs"
  proof(nominal_induct avoiding: P rule: residual.strong_inducts)
    case(BoundR a x P' P)
    have PTrans: "P la«x»  P'"
     and xFreshP: "x  P" by fact+
    from PTrans obtain a' where aeq: "a = BoundOutputS a'" by(cases a, auto)
    with PTrans xFreshP obtain P'' P''' where PTrans: "P τ P''"
                                          and P''Trans: "P'' a'x>  P'''"
                                          and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "P = P''")
      assume "P = P''"
      moreover have "P  Q τ P  Q" by simp
      moreover from P''Trans have "P''  Q a'x>  P'''" by(rule transitions.Sum1)
      ultimately show ?thesis using P'''Trans aeq by(blast intro: transitionI)
    next
      assume "P  P''"
      with PTrans have "P  Q τ P''" by(rule sum1Chain)
      thus ?thesis using P''Trans P'''Trans aeq by(blast intro: transitionI)
    qed
  next
    case(FreeR α P')
    have "P l α  P'" by fact

    then obtain P'' P''' where PTrans: "P τ P''"
                           and P''Trans: "P''  α  P'''"
                           and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "P = P''")
      assume "P = P''"
      moreover have "P  Q τ P  Q" by simp
      moreover from P''Trans have "P''  Q  α  P'''" by(rule transitions.Sum1)
      ultimately show ?thesis using P'''Trans by(blast intro: transitionI)
    next
      assume "P  P''"
      with PTrans have "P  Q τ P''" by(rule sum1Chain)
      thus ?thesis using P''Trans P'''Trans by(rule transitionI)
    qed
  qed
next
  assume "P lu in P''a<x>  P'"
  then obtain P''' where PChain: "P τ P'''"
                     and P'''Trans: "P''' a<x>  P''"
                     and P''Chain: "P''[x::=u] τ P'"
    by(blast dest: transitionE)
  show "P  Q lu in P''a<x>  P'"
  proof(cases "P = P'''")
    assume "P = P'''"
    moreover have "P  Q τ P  Q" by simp
    moreover from P'''Trans have "P'''  Q a<x>  P''" by(rule transitions.Sum1)
    ultimately show ?thesis using P''Chain by(blast intro: transitionI)
  next
    assume "P  P'''"
    with PChain have "P  Q τ P'''" by(rule sum1Chain)
    thus ?thesis using P'''Trans P''Chain by(blast intro: transitionI)
  qed
qed

lemma Sum2:
  fixes Q  :: pi
  and   Rs :: residual
  and   P  :: pi
  and   u  :: name
  and   Q'' :: pi
  and   a  :: name
  and   x  :: name
  and   Q' :: pi

  shows "Q l Rs  P  Q l Rs"
  and   "Q lu in Q''a<x>  Q'  P  Q lu in Q''a<x>  Q'"
proof -
  assume "Q l Rs"
  thus "P  Q l Rs"
  proof(nominal_induct avoiding: Q rule: residual.strong_inducts)
    case(BoundR a x Q' Q)
    have QTrans: "Q la«x»  Q'"
     and xFreshQ: "x  Q" by fact+
    from QTrans obtain a' where aeq: "a = BoundOutputS a'" by(cases a, auto)
    with QTrans xFreshQ obtain Q'' Q''' where QTrans: "Q τ Q''"
                                          and Q''Trans: "Q'' a'x>  Q'''"
                                          and Q'''Trans: "Q''' τ Q'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "Q = Q''")
      assume "Q = Q''"
      moreover have "P  Q τ P  Q" by simp
      moreover from Q''Trans have "P  Q'' a'x>  Q'''" by(rule transitions.Sum2)
      ultimately show ?thesis using Q'''Trans aeq by(blast intro: transitionI)
    next
      assume "Q  Q''"
      with QTrans have "P  Q τ Q''" by(rule sum2Chain)
      thus ?thesis using Q''Trans Q'''Trans aeq by(blast intro: transitionI)
    qed
  next
    case(FreeR α Q')
    have "Q l α  Q'" by fact

    then obtain Q'' Q''' where QTrans: "Q τ Q''"
                           and Q''Trans: "Q''  α  Q'''"
                           and Q'''Trans: "Q''' τ Q'"
      by(blast dest: transitionE)
    show ?case
    proof(cases "Q = Q''")
      assume "Q = Q''"
      moreover have "P  Q τ P  Q" by simp
      moreover from Q''Trans have "P  Q''  α  Q'''" by(rule transitions.Sum2)
      ultimately show ?thesis using Q'''Trans by(blast intro: transitionI)
    next
      assume "Q  Q''"
      with QTrans have "P  Q τ Q''" by(rule sum2Chain)
      thus ?thesis using Q''Trans Q'''Trans by(rule transitionI)
    qed
  qed
next
  assume "Q lu in Q''a<x>  Q'"
  then obtain Q''' where QChain: "Q τ Q'''"
                     and Q'''Trans: "Q''' a<x>  Q''"
                     and Q''Chain: "Q''[x::=u] τ Q'"
    by(blast dest: transitionE)
  show "P  Q lu in Q''a<x>  Q'"
  proof(cases "Q = Q'''")
    assume "Q = Q'''"
    moreover have "P  Q τ P  Q" by simp
    moreover from Q'''Trans have "P  Q''' a<x>  Q''" by(rule transitions.Sum2)
    ultimately show ?thesis using Q''Chain by(blast intro: transitionI)
  next
    assume "Q  Q'''"
    with QChain have "P  Q τ Q'''" by(rule sum2Chain)
    thus ?thesis using Q'''Trans Q''Chain by(blast intro: transitionI)
  qed
qed

lemma Par1B:
  fixes P  :: pi
  and   a  :: name
  and   x  :: name
  and   P' :: pi
  and   u  :: name
  and   P'' :: pi

  shows "P lax>  P'; x  Q  P  Q lax>  (P'  Q)"
  and   "P lu in P''a<x>  P'; x  Q  P  Q lu in (P''  Q)a<x>  P'  Q"
proof -
  assume PTrans: "P l ax>  P'"
  assume xFreshQ: "x  Q"

  have Goal: "P a x P' Q. P lax>  P'; x  P; x  Q  P  Q lax>  (P'  Q)"
  proof -
    fix P a x P' Q
    assume PTrans: "P lax>  P'"
    assume xFreshP: "x  P"
    assume xFreshQ: "x  (Q::pi)"

    from PTrans xFreshP obtain P'' P''' where PTrans: "P τ P''"
                                          and P''Trans: "P'' ax>  P'''"
                                          and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)
    from PTrans have "P  Q τ P''  Q" by(rule Par1Chain)
    moreover from P''Trans xFreshQ have "P''  Q ax>  (P'''  Q)" by(rule Par1B)
    moreover from P'''Trans have "P'''  Q τ P'  Q" by(rule Par1Chain)
    ultimately show "P  Q lax>  (P'  Q)" by(rule transitionI)
  qed
  
  have "c::name. c  (P, P', Q)" by(blast intro: name_exists_fresh)
  then obtain c::name where cFreshP: "c  P" and cFreshP': "c  P'" and cFreshQ: "c  Q"
    by(force simp add: fresh_prod)

  from cFreshP' have "ax>  P' = ac>  ([(x, c)]  P')" by(rule alphaBoundResidual)
  moreover have "ax>  (P'  Q) = ac>  (([(x, c)]  P')  Q)"
  proof -
    from cFreshP' cFreshQ have "c  P'  Q" by simp
    hence "ax>  (P'  Q) = ac>  ([(x, c)]  (P'  Q))" by(rule alphaBoundResidual)
    with cFreshQ xFreshQ show ?thesis by(simp add: name_fresh_fresh)
  qed
  ultimately show "P  Q l ax>  P'  Q" using PTrans cFreshP cFreshQ by(force intro: Goal)
next
  assume PTrans: "P lu in P''a<x>  P'"
     and xFreshQ: "x  Q"
  from PTrans obtain P''' where PChain: "P τ P'''"
                            and P'''Trans: "P''' a<x>  P''"
                            and P''Chain: "P''[x::=u] τ P'"
    by(blast dest: transitionE)
  from PChain have "P  Q τ P'''  Q" by(rule Par1Chain)
  moreover from P'''Trans xFreshQ have "P'''  Q a<x>  (P''  Q)" by(rule Par1B)
  moreover have "(P''  Q)[x::=u] τ P'  Q"
  proof - 
    from P''Chain have "P''[x::=u]  Q τ P'  Q" by(rule Par1Chain)
    with xFreshQ show ?thesis by(simp add: forget)
  qed
  ultimately show "P  Q lu in (P''  Q)a<x>  (P'  Q)" by(rule transitionI)
qed

lemma Par1F:
  fixes P  :: pi
  and   α  :: freeRes
  and   P' :: pi

  assumes PTrans: "P lα  P'"

  shows "P  Q lα  (P'  Q)"
proof -
  from PTrans obtain P'' P''' where PTrans: "P τ P''"
                                and P''Trans: "P'' α  P'''"
                                and P'''Trans: "P''' τ P'"
    by(blast dest: transitionE)
  from PTrans have "P  Q τ P''  Q" by(rule Par1Chain)
  moreover from P''Trans have "P''  Q α  (P'''  Q)" by(rule transitions.Par1F)
  moreover from P'''Trans have "P'''  Q τ P'  Q" by(rule Par1Chain)
  ultimately show ?thesis by(rule transitionI)
qed

lemma Par2B:
  fixes Q  :: pi
  and   a  :: name
  and   x  :: name
  and   Q' :: pi
  and   P  :: pi
  and   u  :: name
  and   Q'' :: pi

  shows "Q lax>  Q'  x  P  P  Q lax>  (P  Q')"
  and   "Q lu in Q''a<x>  Q'  x  P  P  Q lu in (P  Q'')a<x>  P  Q'"
proof -
  assume QTrans: "Q l ax>  Q'"
  assume xFreshP: "x  P"

  have Goal: "Q a x Q' P. Q lax>  Q'; x  Q; x  P  P  Q lax>  (P  Q')"
  proof -
    fix Q a x Q' P
    assume QTrans: "Q lax>  Q'"
    assume xFreshQ: "x  Q"
    assume xFreshP: "x  (P::pi)"

    from QTrans xFreshQ obtain Q'' Q''' where QTrans: "Q τ Q''"
                                          and Q''Trans: "Q'' ax>  Q'''"
                                          and Q'''Trans: "Q''' τ Q'"
      by(blast dest: transitionE)
    from QTrans have "P  Q τ P  Q''" by(rule Par2Chain)
    moreover from Q''Trans xFreshP have "P  Q'' ax>  (P  Q''')" by(rule Par2B)
    moreover from Q'''Trans have "P  Q''' τ P  Q'" by(rule Par2Chain)
    ultimately show "P  Q lax>  (P  Q')" by(rule transitionI)
  qed
  
  have "c::name. c  (Q, Q', P)" by(blast intro: name_exists_fresh)
  then obtain c::name where cFreshQ: "c  Q" and cFreshQ': "c  Q'" and cFreshP: "c  P"
    by(force simp add: fresh_prod)

  from cFreshQ' have "ax>  Q' = ac>  ([(x, c)]  Q')" by(rule alphaBoundResidual)
  moreover have "ax>  (P  Q') = ac>  (P  ([(x, c)]  Q'))"
  proof -
    from cFreshQ' cFreshP have "c  P  Q'" by simp
    hence "ax>  (P  Q') = ac>  ([(x, c)]  (P  Q'))" by(rule alphaBoundResidual)
    with cFreshP xFreshP show ?thesis by(simp add: name_fresh_fresh)
  qed
  ultimately show "P  Q l ax>  P  Q'" using QTrans cFreshQ cFreshP by(force intro: Goal)
next
  assume QTrans: "Q lu in Q''a<x>  Q'"
     and xFreshP: "x  P"
  from QTrans obtain Q''' where QChain: "Q τ Q'''"
                            and Q'''Trans: "Q''' a<x>  Q''"
                            and Q''Chain: "Q''[x::=u] τ Q'"
    by(blast dest: transitionE)
  from QChain have "P  Q τ P  Q'''" by(rule Par2Chain)
  moreover from Q'''Trans xFreshP have "P  Q''' a<x>  (P  Q'')" by(rule Par2B)
  moreover have "(P  Q'')[x::=u] τ P  Q'"
  proof - 
    from Q''Chain have "P  (Q''[x::=u]) τ P  Q'" by(rule Par2Chain)
    with xFreshP show ?thesis by(simp add: forget)
  qed
  ultimately show "P  Q lu in (P  Q'')a<x>  (P  Q')" by(rule transitionI)
qed

lemma Par2F:
  fixes Q :: pi
  and   α  :: freeRes
  and   Q' :: pi

  assumes QTrans: "Q lα  Q'"

  shows "P  Q lα  (P  Q')"
proof -
  from QTrans obtain Q'' Q''' where QTrans: "Q τ Q''"
                                and Q''Trans: "Q'' α  Q'''"
                                and Q'''Trans: "Q''' τ Q'"
    by(blast dest: transitionE)
  from QTrans have "P  Q τ P  Q''" by(rule Par2Chain)
  moreover from Q''Trans have "P  Q'' α  (P  Q''')" by(rule transitions.Par2F)
  moreover from Q'''Trans have "P  Q''' τ P  Q'" by(rule Par2Chain)
  ultimately show ?thesis by(rule transitionI)
qed

lemma Comm1:
  fixes P  :: pi
  and   b  :: name
  and   P'' :: pi
  and   a  :: name
  and   x  :: name
  and   P' :: pi
  and   Q  :: pi
  and   Q' :: pi
  
  assumes PTrans: "P lb in P'' a<x>  P'"
  and     QTrans: "Q la[b]  Q'"

  shows "P  Q lτ  P'  Q'"
proof -
  from PTrans obtain P''' where PChain: "P τ P'''"
                            and P'''Trans: "P''' a<x>  P''"
                            and P''Chain: "P''[x::=b] τ P'"
    by(blast dest: transitionE)
  from QTrans obtain Q'' Q''' where QChain: "Q τ Q'''"
                                and Q'''Trans: "Q''' a[b]  Q''"
                                and Q''Chain: "Q'' τ Q'"
    by(blast dest: transitionE)

  from PChain QChain have "P  Q τ P'''  Q'''" by(rule chainPar)
  moreover from P'''Trans Q'''Trans have "P'''  Q''' τ  P''[x::=b]  Q''"
    by(rule Comm1)
  moreover from P''Chain Q''Chain have "P''[x::=b]  Q'' τ P'  Q'" by(rule chainPar)
  ultimately show ?thesis by(rule transitionI)
qed

lemma Comm2:
  fixes P  :: pi
  and   a  :: name
  and   b  :: name
  and   P' :: pi
  and   Q  :: pi
  and   x  :: name
  and   Q'' :: pi
  and   Q' :: pi
  
  assumes PTrans: "P la[b]  P'"
  and     QTrans: "Q lb in Q''a<x>  Q'"

  shows "P  Q lτ  P'  Q'"
proof -
  from PTrans obtain P'' P''' where PChain: "P τ P'''"
                                and P'''Trans: "P''' a[b]  P''"
                                and P''Chain: "P'' τ P'"
    by(blast dest: transitionE)
  from QTrans obtain Q''' where QChain: "Q τ Q'''"
                            and Q'''Trans: "Q''' a<x>  Q''"
                            and Q''Chain: "Q''[x::=b] τ Q'"
    by(blast dest: transitionE)

  from PChain QChain have "P  Q τ P'''  Q'''" by(rule chainPar)
  moreover from P'''Trans Q'''Trans have "P'''  Q''' τ  P''  (Q''[x::=b])"
    by(rule Comm2)
  moreover from P''Chain Q''Chain have "P''  (Q''[x::=b]) τ P'  Q'" by(rule chainPar)
  ultimately show ?thesis by(rule transitionI)
qed

lemma Close1:
  fixes P  :: pi
  and   y  :: name
  and   P'' :: pi
  and   a  :: name
  and   x  :: name
  and   P' :: pi
  and   Q  :: pi
  and   Q' :: pi
  
  assumes PTrans: "P ly in P''a<x>  P'"
  and     QTrans: "Q lay>  Q'"
  and     yFreshP: "y  P"
  and     yFreshQ: "y  Q"

  shows "P  Q lτ  y>(P'  Q')"
proof -
  from PTrans obtain P''' where PChain: "P τ P'''"
                            and P'''Trans: "P''' a<x>  P''"
                            and P''Chain: "P''[x::=y] τ P'"
    by(blast dest: transitionE)
  from QTrans yFreshQ obtain Q'' Q''' where QChain: "Q τ Q'''"
                                        and Q'''Trans: "Q''' ay>  Q''"
                                        and Q''Chain: "Q'' τ Q'"
    by(blast dest: transitionE)
  
  from PChain yFreshP have yFreshP''': "y  P'''" by(rule freshChain)
  
  from PChain QChain have "P  Q τ P'''  Q'''" by(rule chainPar)
  moreover from P'''Trans Q'''Trans yFreshP''' have "P'''  Q''' τ  y>(P''[x::=y]  Q'')"
    by(rule Close1)
  moreover have "y>(P''[x::=y]  Q'') τ y>(P'  Q')"
  proof -
    from P''Chain Q''Chain have "P''[x::=y]  Q'' τ P'  Q'" by(rule chainPar)
    thus ?thesis by(rule ResChain)
  qed
  ultimately show "P  Q lτ  y>(P'  Q')" by(rule transitionI)
qed

lemma Close2:
  fixes P  :: pi
  and   y  :: name
  and   a  :: name
  and   x  :: name
  and   P' :: pi
  and   Q  :: pi
  and   Q'' :: pi
  and   Q' :: pi
  
  assumes PTrans: "P lay>  P'"
  and     QTrans: "Q ly in Q''a<x>  Q'"
  and     yFreshP: "y  P"
  and     yFreshQ: "y  Q"

  shows "P  Q lτ  y>(P'  Q')"
proof -
  from PTrans yFreshP obtain P'' P''' where PChain: "P τ P'''"
                                        and P'''Trans: "P''' ay>  P''"
                                        and P''Chain: "P'' τ P'"
    by(blast dest: transitionE)

  from QTrans obtain Q''' where QChain: "Q τ Q'''"
                            and Q'''Trans: "Q''' a<x>  Q''"
                            and Q''Chain: "Q''[x::=y] τ Q'"
    by(blast dest: transitionE)
  
  from QChain yFreshQ have yFreshQ''': "y  Q'''" by(rule freshChain)
  
  from PChain QChain have "P  Q τ P'''  Q'''" by(rule chainPar)
  moreover from P'''Trans Q'''Trans yFreshQ''' have "P'''  Q''' τ  y>(P''  (Q''[x::=y]))"
    by(rule Close2)
  moreover have "y>(P''  (Q''[x::=y])) τ y>(P'  Q')"
  proof -
    from P''Chain Q''Chain have "P''  (Q''[x::=y]) τ P'  Q'" by(rule chainPar)
    thus ?thesis by(rule ResChain)
  qed
  ultimately show "P  Q lτ  y>(P'  Q')" by(rule transitionI)
qed

lemma ResF:
  fixes P  :: pi
  and   α  :: freeRes
  and   P' :: pi
  and   x  :: name

  assumes PTrans: "P lα  P'"
  and     xFreshAlpha: "x  α"

  shows "x>P lα  x>P'"
proof -
  from PTrans obtain P'' P''' where PChain: "P τ P''"
                                and P''Trans: "P'' α  P'''"
                                and P'''Chain: "P''' τ P'"
    by(blast dest: transitionE)

  from PChain have "x>P τ x>P''" by(rule ResChain)
  moreover from P''Trans xFreshAlpha have "x>P'' α  x>P'''"
    by(rule transitions.ResF)
  moreover from P'''Chain have "x>P''' τ x>P'" by(rule ResChain)
  ultimately show ?thesis by(rule transitionI)
qed

lemma ResB:
  fixes P  :: pi
  and   a  :: name
  and   x  :: name
  and   P' :: pi
  and   y  :: name
  and   u  :: name
  and   P'' :: pi

  shows "P lax>  P'; y  a; y  x; x  P  y>P lax>  (y>P')"
  and   "P lu in P''a<x>  P'; y  a; y  x; y  u  y>P lu in (y>P'')a<x>  (y>P')"
proof -
  assume PTrans: "P lax>  P'"
     and yineqa: "y  a"
     and yineqx: "y  x"
     and xFreshP: "x  P"

  from PTrans xFreshP obtain P'' P''' where PChain: "P τ P''"
                                        and P''Trans: "P'' ax>  P'''"
                                        and P'''Chain: "P''' τ P'"
    by(blast dest: transitionE)

  from PChain have "y>P τ y>P''" by(rule ResChain)
  moreover from P''Trans yineqa yineqx have "y>P'' ax>  (y>P''')"
    by(force intro: ResB)
  moreover from P'''Chain have "y>P''' τ y>P'" by(rule ResChain)
  ultimately show "y>P l ax>  y>P'" by(rule transitionI)
next
  assume PTrans: "P lu in P''a<x>  P'"
     and yineqa: "y  a"
     and yineqx: "y  x"
     and yinequ: "y  u" 

  from PTrans obtain P''' where PChain: "P τ P'''"
                            and P'''Trans: "P''' a<x>  P''"
                            and P''Chain: "P''[x::=u] τ P'"
    by(blast dest: transitionE)

  from PChain have "y>P τ y>P'''" by(rule ResChain)
  moreover from P'''Trans yineqa yineqx have "y>P''' a<x>  (y>P'')"
    by(force intro: ResB)
  moreover have "(y>P'')[x::=u] τ y>P'"
  proof -
    from P''Chain have "y>(P''[x::=u]) τ y>P'" by(rule ResChain)
    with yineqx yinequ show ?thesis by(simp add: eqvt_subs[THEN sym])
  qed
  ultimately show "y>P lu in (y>P'')a<x>  y>P'" by(rule transitionI)
qed

lemma Bang:
  fixes P  :: pi
  and   Rs :: residual
  and   u  :: name
  and   P'' :: pi
  and   a  :: name
  and   x  :: name
  and   P' :: pi

  shows "P  !P l Rs  !P l Rs"
  and   "P  !P lu in P''a<x>  P'  !P lu in P''a<x>  P'"
proof -
  assume "P  !P l Rs"
  thus "!P l Rs"
  proof(nominal_induct avoiding: P rule: residual.strong_inducts)
    case(BoundR a x P' P)
    assume xFreshP: "x  P"
    assume PTrans: "P  !P la«x»  P'"
    from PTrans obtain a' where aeq: "a = BoundOutputS a'" by(cases a, auto)

    with PTrans xFreshP obtain P'' P''' where PChain: "P  !P τ P''"
                                          and P''Trans: "P'' a'x>  P'''"
                                          and P'''Chain: "P''' τ P'"
      by(force dest: transitionE)

    show "!P la«x»  P'"
    proof(cases "P'' = P  !P")
      assume "P'' = P  !P"
      moreover with P''Trans have "!P a'x>  P'''" by(blast intro: transitions.Bang)
      ultimately show ?thesis using PChain P'''Chain aeq by(simp, rule_tac transitionI, auto)
    next
      assume "P''  P  !P"
      with PChain have "!P τ P''" by(rule bangChain)
      with P''Trans P'''Chain aeq show ?thesis by(blast intro: transitionI)
    qed
  next
    fix α P' P
    assume "P  !P lα  P'"
    
    then obtain P'' P''' where PChain: "P  !P τ P''"
                           and P''Trans: "P'' α  P'''"
                           and P'''Chain: "P''' τ P'"
      by(force dest: transitionE)


    show "!P lα  P'"
    proof(cases "P'' = P  !P")
      assume "P'' = P  !P"
      moreover with P''Trans have "!P α  P'''" by(blast intro: transitions.Bang)
      ultimately show ?thesis using PChain P'''Chain by(rule_tac transitionI, auto)
    next
      assume "P''  P  !P"
      with PChain have "!P τ P''" by(rule bangChain)
      with P''Trans P'''Chain show ?thesis by(blast intro: transitionI)
    qed
  qed
next
  assume "P  !P lu in P''a<x>  P'"

  then obtain P''' where PChain: "P  !P τ P'''"
                     and P'''Trans: "P''' a<x>  P''"
                     and P''Chain: "P''[x::=u] τ P'"
    by(force dest: transitionE)
  
  show "!P lu in P''a<x>  P'"
  proof(cases "P''' = P  !P")
    assume "P''' = P  !P"
    moreover with P'''Trans have "!P a<x>  P''" by(blast intro: transitions.Bang)
    ultimately show ?thesis using PChain P''Chain by(rule_tac transitionI, auto)
  next
    assume "P'''  P  !P"
    with PChain have "!P τ P'''" by(rule bangChain)
    with P'''Trans P''Chain show ?thesis by(blast intro: transitionI)
  qed
qed

lemma tauTransitionChain:
  fixes P  :: pi
  and   P' :: pi

  assumes "P lτ  P'"

  shows "P τ P'"
using assms
by(auto simp add: transition_def residualInject)

lemma chainTransitionAppend:
  fixes P   :: pi
  and   P'  :: pi
  and   Rs  :: residual
  and   a   :: name
  and   x   :: name
  and   P'' :: pi
  and   u   :: name
  and   P''' :: pi
  and   α   :: freeRes

  shows "P τ P'  P' l Rs  P l Rs"
  and   "P τ P''  P'' lu in P'''a<x>  P'  P lu in P'''a<x>  P'"
  and   "P lax>  P''  P'' τ P'  x  P  P lax>  P'"
  and   "P lu in P'''a<x>  P''  P'' τ P'  P lu in P'''a<x>  P'"
  and   "P lα  P''  P'' τ P'  P lα  P'"
proof -
  assume "P τ P'" and "P' l Rs"
  thus "P l Rs"
    by(auto simp add: transition_def residualInject) (blast dest: rtrancl_trans)+
next
  assume "P τ P''" and "P'' lu in P'''a<x>  P'"
  thus "P lu in P'''a<x>  P'"
    apply(auto simp add: inputTransition_def residualInject)
    by(blast dest: rtrancl_trans)+
next
  assume PTrans: "P l ax>  P''" 
  assume P''Chain: "P'' τ P'"
  assume xFreshP: "x  P"

  from PTrans xFreshP obtain P''' P'''' where PChain: "P τ P'''"
                                          and P'''Trans: "P''' ax>  P''''"
                                          and P''''Chain: "P'''' τ P''"
    by(blast dest: transitionE)

  from P''''Chain P''Chain have "P'''' τ P'" by auto
  with PChain P'''Trans show "P lax>  P'" by(rule transitionI)
next
  assume PTrans: "P lu in P'''a<x>  P''" 
  assume P''Chain: "P'' τ P'"

  from PTrans obtain P'''' where PChain: "P τ P''''"
                             and P''''Trans: "P'''' a<x>  P'''"
                             and P'''Chain: "P'''[x::=u] τ P''"
    by(blast dest: transitionE)

  from P'''Chain P''Chain have "P'''[x::=u] τ P'" by auto
  with PChain P''''Trans show "P lu in P'''a<x>  P'" by(blast intro: transitionI)
next
  assume PTrans: "P lα  P''" 
  assume P''Chain: "P'' τ P'"

  from PTrans obtain P''' P'''' where PChain: "P τ P'''"
                                  and P'''Trans: "P''' α  P''''"
                                  and P''''Chain: "P'''' τ P''"
    by(blast dest: transitionE)

  from P''''Chain P''Chain have "P'''' τ P'" by auto
  with PChain P'''Trans show "P lα  P'" by(rule transitionI)
qed

lemma freshInputTransition:
  fixes P  :: pi
  and   a  :: name
  and   x  :: name
  and   u  :: name
  and   P'' :: pi
  and   P' :: pi
  and   c  :: name

  assumes PTrans: "P lu in P''a<x>  P'"
  and     cFreshP: "c  P"
  and     cinequ: "c  u"

  shows "c  P'"
proof -

  from PTrans obtain P''' where PChain: "P τ P'''"
                            and P'''Trans: "P''' a<x>  P''"
                            and P''Chain: "P''[x::=u] τ P'"
    by(blast dest: transitionE)

  from PChain cFreshP have cFreshP''': "c  P'''" by(rule freshChain)
  show "c  P'"
  proof(cases "x=c")
    assume xeqc: "x=c"
    from cinequ have "c  P''[c::=u]" apply - by(rule fresh_fact2)
    with P''Chain xeqc show ?thesis by(force intro: freshChain)
  next
    assume xineqc: "xc"
    with P'''Trans cFreshP''' have "c  P''" by(blast dest: freshBoundDerivative)
    with cinequ have "c  P''[x::=u]"
      apply -
      apply(rule fresh_fact1)
      by simp
    with P''Chain show ?thesis by(rule freshChain)
  qed
qed

lemma freshBoundOutputTransition:
  fixes P  :: pi
  and   a  :: name
  and   x  :: name
  and   P' :: pi
  and   c  :: name

  assumes PTrans: "P lax>  P'"
  and     cFreshP: "c  P"
  and     cineqx: "c  x"

  shows "c  P'"
proof -
  have Goal: "P a x P' c. P lax>  P'; x  P; c  P; c  x  c  P'"
  proof -
    fix P a x P' c
    assume PTrans: "P lax>  P'"
    assume xFreshP: "x  P"
    assume cFreshP: "(c::name)  P"
    assume cineqx: "c  x"

    from PTrans xFreshP obtain P'' P''' where PTrans: "P τ P''"
                                          and P''Trans: "P'' ax>  P'''"
                                          and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)

    from PTrans cFreshP have "c  P''" by(rule freshChain)
    with P''Trans cineqx have "c  P'''" by(blast dest: Late_Semantics.freshBoundDerivative)
    with P'''Trans show "c  P'" by(rule freshChain)
  qed

  have "d::name. d  (P, P', c)" by(blast intro: name_exists_fresh)
  then obtain d::name where dFreshP: "d  P" and dFreshP': "d  P'" and cineqd: "c  d"
    by(force simp add: fresh_prod)

  from PTrans dFreshP' have "P lad>  ([(x, d)]  P')" by(simp add: alphaBoundResidual)
  hence "c  [(x, d)]  P'" using dFreshP cFreshP cineqd by(rule Goal)
  with cineqd cineqx show ?thesis by(simp add: name_fresh_left name_calc)
qed

lemma freshTauTransition:
  fixes P :: pi
  and   c :: name

  assumes PTrans: "P lτ  P'"
  and     cFreshP: "c  P"

  shows "c  P'"
proof -
  from PTrans have "P τ P'" by(rule tauTransitionChain)
  thus ?thesis using cFreshP by(rule freshChain)
qed

lemma freshOutputTransition:
  fixes P  :: pi
  and   a  :: name
  and   b  :: name
  and   P' :: pi
  and   c  :: name

  assumes PTrans: "P la[b]  P'"
  and     cFreshP: "c  P"

  shows "c  P'"
proof -
  from PTrans obtain P'' P''' where PTrans: "P τ P''"
                                and P''Trans: "P'' a[b]  P'''"
                                and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)

    from PTrans cFreshP have "c  P''" by(rule freshChain)
    with P''Trans have "c  P'''" by(blast dest: Late_Semantics.freshFreeDerivative)
    with P'''Trans show ?thesis by(rule freshChain)
qed

lemma eqvtI:
  fixes P    :: pi
  and   Rs   :: residual
  and   perm :: "name prm"
  and   u    :: name
  and   P''  :: pi
  and   a    :: name
  and   x    :: name
  and   P'   :: pi

  shows "P l Rs  (perm  P) l (perm  Rs)"
  and   "P lu in P''a<x>  P'  (perm  P) l(perm  u) in (perm  P'')(perm  a)<(perm  x)>  (perm  P')"
proof -
  assume "P l Rs"
  thus "(perm  P) l (perm  Rs)"
  proof(nominal_induct Rs avoiding: P rule: residual.strong_inducts)
    case(BoundR a x P' P)
    have PTrans: "P la«x»  P'" by fact
    moreover then obtain b where aeqb: "a = BoundOutputS b" by(cases a, auto)
    moreover have "x  P" by fact
    ultimately obtain P'' P''' where PTrans: "P τ P''"
                               and P''Trans: "P'' bx>  P'''"
                              and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)

    from PTrans have "(perm  P) τ (perm  P'')" by(rule eqvtChainI)
    moreover from P''Trans have "(perm  P'')  (perm  (bx>  P'''))"
      by(rule eqvts)
    moreover from P'''Trans have "(perm  P''') τ (perm  P')" by(rule eqvtChainI)
    ultimately show ?case using aeqb by(force intro: transitionI)
  next
    case(FreeR α P' P)
    have "P lα  P'" by fact
    then obtain P'' P''' where PTrans: "P τ P''"
                           and P''Trans: "P'' α  P'''"
                           and P'''Trans: "P''' τ P'"
      by(blast dest: transitionE)

    from PTrans have "(perm  P) τ (perm  P'')" by(rule eqvtChainI)
    moreover from P''Trans have "(perm  P'')  (perm  (α  P'''))"
      by(rule eqvts)
    moreover from P'''Trans have "(perm  P''') τ (perm  P')" by(rule eqvtChainI)
    ultimately show ?case by(force intro: transitionI)
  qed
next
  assume "P lu in P''a<x>  P'"

  then obtain P''' where PChain: "P τ P'''"
                     and P'''Trans: "P''' a<x>  P''"
                     and P''Chain: "P''[x::=u] τ P'"
      by(blast dest: transitionE)

    from PChain have "(perm  P) τ (perm  P''')" by(rule eqvtChainI)
    moreover from P'''Trans have "(perm  P''')  (perm  (a<x>  P''))"
      by(rule eqvts)
    moreover from P''Chain have "(perm  P''[x::=u]) τ (perm  P')" by(rule eqvtChainI)
    ultimately show "(perm  P) l(perm  u) in (perm  P'')(perm  a)<(perm  x)>  (perm  P')"
      by(force intro: transitionI simp add: eqvt_subs[THEN sym] perm_bij)
qed

lemmas freshTransition = freshBoundOutputTransition freshOutputTransition
                         freshInputTransition freshTauTransition


end