Theory Strong_Late_Bisim_Subst_SC

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

lemma matchId:
  fixes a :: name
  and   P :: pi

  shows "[aa]P s P"
by(auto simp add: substClosed_def intro: Strong_Late_Bisim_SC.matchId)

lemma mismatchNil:
  fixes a :: name
  and   P :: pi
  
  shows "[aa]P s 𝟬"
by(auto simp add: substClosed_def intro: Strong_Late_Bisim_SC.mismatchNil)

lemma scopeFresh:
  fixes P :: pi
  and   x :: name

  assumes xFreshP: "x  P"

  shows "x>P s P"
proof(auto simp add: substClosed_def)
  fix s :: "(name × name) list"

  have "c::name. c  (P, s)" by(blast intro: name_exists_fresh)
  then obtain c::name where cFreshP: "c  P" and cFreshs: "c  s" by(force simp add: fresh_prod)

  have "x>P = c>P"
  proof -
    from cFreshP have "x>P = c>([(x, c)]  P)" by(simp add: alphaRes)
    with cFreshP xFreshP show ?thesis by(simp add: name_fresh_fresh)
  qed

  with cFreshP cFreshs show "(x>P)[<s>]  P[<s>]"
    by(force intro: Strong_Late_Bisim_SC.scopeFresh)
qed

lemma resComm:
  fixes P :: pi
  and   x :: name
  and   y :: name

  shows "x>y>P s y>x>P"
proof(cases "x=y")
  assume xeqy: "x=y"
  have "P s P" by(rule Strong_Late_Bisim_Subst.reflexive)
  hence "x>P s x>P" by(rule resPres)
  hence "x>x>P s x>x>P" by(rule resPres)
  with xeqy show ?thesis by simp
next
  assume xineqy: "x  y"
  show ?thesis
  proof(auto simp add: substClosed_def)
    fix s::"(name × name) list"
    
    have "c::name. c  (P, s, y)" by(blast intro: name_exists_fresh)
    then obtain c::name where cFreshP: "c  P" and cFreshs: "c  s" and cineqy: "c  y"
      by(force simp add: fresh_prod)
    
    have "d::name. d  (P, s, c, x, y)" by (blast intro: name_exists_fresh)
    then obtain d::name where dFreshP: "d  P" and dFreshs: "d  s" and dineqc: "d  c"
                          and dineqx: "d  x" and dineqy: "d  y"
      by(force simp add: fresh_prod)

    have "x>y>P = c>d>([(x, c)]  [(y, d)]  P)"
    proof -
      from cineqy cFreshP have cFreshyP: "c  y>P" by(simp add: name_fresh_abs)
      from dFreshP have "y>P = d>([(y, d)]  P)" by(rule alphaRes)
      moreover from cFreshyP have "x>y>P = c>([(x, c)]  (y>P))" by(rule alphaRes)
      ultimately show ?thesis using dineqc dineqx by(simp add: name_calc)
    qed
    moreover have "y>x>P = d>c>([(x, c)]  [(y, d)]  P)"
    proof -
      from dineqx dFreshP have dFreshxP: "d  x>P" by(simp add: name_fresh_abs)
      from cFreshP have "x>P = c>([(x, c)]  P)" by(rule alphaRes)
      moreover from dFreshxP have "y>x>P = d>([(y, d)]  (x>P))" by(rule alphaRes)
      ultimately have "y>x>P = d>c>([(y, d)]  [(x, c)]  P)" using dineqc cineqy
        by(simp add: name_calc)
      thus ?thesis using dineqx dineqc cineqy xineqy
        by(subst name_perm_compose, simp add: name_calc)
    qed

    ultimately show "(x>y>P)[<s>]  (y>x>P)[<s>]" using cFreshs dFreshs
      by(force intro: Strong_Late_Bisim_SC.resComm)
  qed
qed

lemma sumZero:
  fixes P :: pi
  
  shows "P  𝟬 s P"
by(force simp add: substClosed_def intro: Strong_Late_Bisim_SC.sumZero)
    
lemma sumSym:
  fixes P :: pi
  and   Q :: pi

  shows "P  Q s Q  P"
by(force simp add: substClosed_def intro: Strong_Late_Bisim_SC.sumSym)

lemma sumAssoc:
  fixes P :: pi
  and   Q :: pi
  and   R :: pi
  
  shows "(P  Q)  R s P  (Q  R)"
by(force simp add: substClosed_def intro: Strong_Late_Bisim_SC.sumAssoc)

lemma sumRes:
  fixes P :: pi
  and   Q :: pi
  and   x :: name

  shows "x>(P  Q) s x>P  x>Q"
proof(auto simp add: substClosed_def)
  fix s :: "(name × name) list"

  have "c::name. c  (P, Q, s)" by(blast intro: name_exists_fresh)
  then obtain c::name where cFreshP: "c  P" and cFreshQ: "c  Q" and cFreshs: "c  s"
    by(force simp add: fresh_prod)

  have "x>(P  Q) = c>(([(x, c)]  P)  ([(x, c)]  Q))"
  proof -
    from cFreshP cFreshQ have "c  P  Q" by simp
    hence "x>(P  Q) = c>([(x, c)]  (P  Q))" by(simp add: alphaRes)
    thus ?thesis by(simp add: name_fresh_fresh)
  qed

  moreover from cFreshP have "x>P = c>([(x, c)]  P)" by(simp add: alphaRes)
  moreover from cFreshQ have "x>Q = c>([(x, c)]  Q)" by(simp add: alphaRes)
  
  ultimately show "(x>(P  Q))[<s>]  (x>P)[<s>]  (x>Q)[<s>]" using cFreshs
    by(force intro: Strong_Late_Bisim_SC.sumRes)
qed

lemma scopeExtSum:
  fixes P :: pi
  and   Q :: pi
  and   x :: name

  assumes xFreshP: "x  P"

  shows "x>(P  Q) s P  x>Q"
proof(auto simp add: substClosed_def)
  fix s :: "(name × name) list"

  have "c::name. c  (P, Q, s)" by(blast intro: name_exists_fresh)
  then obtain c::name where cFreshP: "c  P" and cFreshQ: "c  Q" and cFreshs: "c  s"
    by(force simp add: fresh_prod)

  have "x>(P  Q) = c>(P  ([(x, c)]  Q))"
  proof -
    from cFreshP cFreshQ have "c  P  Q" by simp
    hence "x>(P  Q) = c>([(x, c)]  (P  Q))" by(simp add: alphaRes)
    with xFreshP cFreshP show ?thesis by(simp add: name_fresh_fresh)
  qed

  moreover from cFreshQ have "x>Q = c>([(x, c)]  Q)" by(simp add: alphaRes)
  
  ultimately show "(x>(P  Q))[<s>]  P[<s>]  (x>Q)[<s>]" using cFreshs cFreshP
    by(force intro: Strong_Late_Bisim_SC.scopeExtSum)
qed

lemma parZero:
  fixes P :: pi
  
  shows "P  𝟬 s P"
by(force simp add: substClosed_def intro: Strong_Late_Bisim_SC.parZero)

lemma parSym:
  fixes P :: pi
  and   Q :: pi

  shows "P  Q s Q  P"
by(force simp add: substClosed_def intro: Strong_Late_Bisim_SC.parSym)

lemma parAssoc:
  fixes P :: pi
  and   Q :: pi
  and   R :: pi
  
  shows "(P  Q)  R s P  (Q  R)"
  by(force simp add: substClosed_def intro: Strong_Late_Bisim_SC.parAssoc)

lemma scopeExtPar:
  fixes P :: pi
  and   Q :: pi
  and   x :: name

  assumes xFreshP: "x  P"

  shows "x>(P  Q) s P  x>Q"
proof(auto simp add: substClosed_def)
  fix s :: "(name × name) list"

  have "c::name. c  (P, Q, s)" by(blast intro: name_exists_fresh)
  then obtain c::name where cFreshP: "c  P" and cFreshQ: "c  Q" and cFreshs: "c  s"
    by(force simp add: fresh_prod)

  have "x>(P  Q) = c>(P  ([(x, c)]  Q))"
  proof -
    from cFreshP cFreshQ have "c  P  Q" by simp
    hence "x>(P  Q) = c>([(x, c)]  (P  Q))" by(simp add: alphaRes)
    with xFreshP cFreshP show ?thesis by(simp add: name_fresh_fresh)
  qed

  moreover from cFreshQ have "x>Q = c>([(x, c)]  Q)" by(simp add: alphaRes)
  
  ultimately show "(x>(P  Q))[<s>]  P[<s>]  (x>Q)[<s>]" using cFreshs cFreshP
    by(force intro: Strong_Late_Bisim_SC.scopeExtPar)
qed

lemma scopeExtPar':
  fixes P :: pi
  and   Q :: pi
  and   x :: name

  assumes xFreshP: "x  Q"

  shows "x>(P  Q) s (x>P)  Q"
proof -
  have "x>(P  Q) s x>(Q  P)" by(blast intro: parSym resPres)
  moreover from xFreshP have "x>(Q  P) s Q  x>P" by(rule scopeExtPar)
  moreover have "Q  x>P s (x>P)  Q" by(rule parSym)
  ultimately show ?thesis by (blast intro: transitive)
qed

lemma bangSC:
  fixes P :: pi

  shows "!P s P  !P"
by(auto simp add: substClosed_def intro: Strong_Late_Bisim_SC.bangSC)

lemma nilRes:
  fixes x :: name
  
  shows "x>𝟬 s 𝟬"
proof(auto simp add: substClosed_def)
  fix σ::"(name × name) list"
  obtain y::name where "y  σ"
    by(generate_fresh "name") auto
  have "y>𝟬  𝟬" by (rule Strong_Late_Bisim_SC.nilRes)
  with y  σ have "(y>𝟬)[<σ>]  𝟬" by simp
  thus "(x>𝟬)[<σ>]  𝟬"
    by(subst alphaRes[where c=y]) auto
qed

lemma resTau:
  fixes x :: name
  and   P :: pi

  shows "x>(τ.(P)) s τ.(x>P)"
proof(auto simp add: substClosed_def)
  fix σ::"(name × name) list"
  obtain y::name where "y  P" and "y  σ"
    by(generate_fresh "name", auto)
  have "y>(τ.(([(x, y)]  P)[<σ>]))  τ.(y>(([(x, y)]  P)[<σ>]))"
    by(rule resTau)
  with y  σ have "(y>(τ.([(x, y)]  P)))[<σ>]  (τ.(y>([(x, y)]  P)))[<σ>]"
    by simp
  with y  P show "(x>τ.(P))[<σ>]  τ.((x>P)[<σ>])"
    apply(subst alphaRes[where c=y])
    apply simp
    apply(subst alphaRes[where c=y and a=x])
    by simp+
qed

lemma resOutput:
  fixes x :: name
  and   a :: name
  and   b :: name
  and   P :: pi

  assumes "x  a"
  and     "x  b"

  shows "x>(a{b}.(P)) s a{b}.(x>P)"
proof(auto simp add: substClosed_def)
  fix σ::"(name × name) list"
  obtain y::name where "y  P" and "y  σ" and "y  a" and "y  b"
    by(generate_fresh "name", auto)
  have "y>((seq_subst_name a σ){seq_subst_name b σ}.(([(x, y)]  P)[<σ>]))  seq_subst_name a σ{seq_subst_name b σ}.(y>(([(x, y)]  P)[<σ>]))"
    using y  a y  b y  σ freshSeqSubstName
    by(rule_tac resOutput) auto
  with y  σ have "(y>(a{b}.([(x, y)]  P)))[<σ>]  (a{b}.(y>([(x, y)]  P)))[<σ>]"
    by simp
  with y  P y  a y  b x  a x  b show "(x>a{b}.(P))[<σ>]  seq_subst_name a σ{seq_subst_name b σ}.((x>P)[<σ>])"
    apply(subst alphaRes[where c=y])
    apply simp
    apply(subst alphaRes[where c=y and a=x])
    by simp+
qed

lemma resInput:
  fixes x :: name
  and   a :: name
  and   b :: name
  and   P :: pi

  assumes "x  a"
  and     "x  y"

  shows "x>(a<y>.(P)) s a<y>.(x>P)"
proof(auto simp add: substClosed_def)
  fix σ::"(name × name) list"
  obtain x'::name where "x'  P" and "x'  σ" and "x'  a" and "x'  x" and "x'  y"
    by(generate_fresh "name", auto)
  obtain y'::name where "y'  P" and "y'  σ" and "y'  a" and "y'  x" and "y'  y" and "x'  y'"
    by(generate_fresh "name", auto)
  have "x'>((seq_subst_name a σ)<y'>.(([(y, y')]  [(x, x')]  P)[<σ>]))  seq_subst_name a σ<y'>.(x'>(([(y, y')]  [(x, x')]  P)[<σ>]))"
    using x'  a x'  y' x'  σ y'  σ freshSeqSubstName
    by(rule_tac resInput) auto
  with x'  σ y'  σ have "(x'>(a<y'>.([(y, y')]  [(x, x')]  P)))[<σ>]  (a<y'>.(x'>([(y, y')]  [(x, x')]  P)))[<σ>]"
    by simp
  with x'  P y'  x x'  y y'  P x'  y' x'  a y'  a x  a x  y show "(x>a<y>.(P))[<σ>]  a<y>.(x>P)[<σ>]"
    apply(subst alphaInput[where c=y'])
    apply simp
    apply(subst alphaRes[where c=x'])
    apply(simp add: abs_fresh fresh_left calc_atm)
    apply(simp add: eqvts calc_atm)
    apply(subst alphaRes[where c=x' and a=x])
    apply simp
    apply(subst alphaInput[where c=y' and x=y])
    apply(simp add: abs_fresh fresh_left calc_atm)
    apply(simp add: eqvts calc_atm)
    apply(subst perm_compose)
    by(simp add: eqvts calc_atm)
qed

lemma bisimSubstStructCong:
  fixes P :: pi
  and   Q :: pi

  assumes "P s Q"
  shows "P s Q"

using assms
apply(induct rule: structCong.induct)
by(auto intro: reflexive symmetric transitive sumSym sumAssoc sumZero parSym parAssoc parZero
               nilRes resComm resInput resOutput resTau sumRes scopeExtPar bangSC matchId mismatchId)


end