Theory After_CSP_PTick_Laws

(***********************************************************************************
 * Copyright (c) 2025 Université Paris-Saclay
 *
 * Author: Benoît Ballenghien, Université Paris-Saclay,
 *         CNRS, ENS Paris-Saclay, LMF
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * SPDX-License-Identifier: BSD-2-Clause
 ***********************************************************************************)


chapter ‹Operational Semantics Laws›

(*<*)
theory After_CSP_PTick_Laws
  imports Basic_CSP_PTick_Laws
    "HOL-CSP_OpSem"
begin
  (*>*)



section ‹Behaviour of constinitials

subsection constTickSwap

lemma initials_TickSwap :
  (TickSwap P)0 = (  if P =  then UNIV
                    else {ev a |a. ev a  P0}  {✓((s, r)) |r s. ✓((r, s))  P0})
  by (auto simp add: TickSwap_is_Renaming initials_Renaming image_iff
      map_eventptick_eq_tick_iff map_eventptick_eq_ev_iff 
      tick_eq_map_eventptick_iff ev_eq_map_eventptick_iff)
    (metis tick_swap.elims)



subsection ‹Sequential Composition›

lemma initials_Seqptick : 
  (P ; Q)0 = (  if P =  then UNIV
                else {ev a |a. ev a  P0}  (r{r. ✓(r)  P0}. (Q r)0))
  (is _ = (if _ then _ else ?rhs))
proof (split if_split, intro conjI impI)
  show P =   (P ; Q)0 = UNIV by simp
next
  show (P ; Q)0 = {ev a |a. ev a  P0}  (r{r. ✓(r)  P0}. (Q r)0) if P  
  proof (intro subset_antisym subsetI)
    fix e assume e  (P ; Q)0
    from eventptick.exhaust consider a where e = ev a | r where e = ✓(r) by blast
    thus e  ?rhs
    proof cases
      from e  (P ; Q)0 P   show e = ev a  e  ?rhs for a
        by (auto simp add: image_iff initials_def Seqptick_projs Cons_eq_append_conv BOT_iff_Nil_D intro: D_T dest: initials_memD)
          (use initials_memI in blast dest: initials_memD)
    next
      from e  (P ; Q)0 P   show e = ✓(r)  e  ?rhs for r
        by (auto simp add: image_iff initials_def Seqptick_projs BOT_iff_Nil_D Cons_eq_append_conv)
    qed
  next
    show e  ?rhs  e  (P ; Q)0 for e
      by (simp add: initials_def Seqptick_projs, elim disjE exE conjE)
        (fastforce, metis list.simps(8) self_append_conv2 tickFree_Nil)
  qed
qed



subsection ‹Synchronization Product›

lemma (in Syncptick_locale) initials_Syncptick :
  (P S Q)0 =
   (if P =   Q =  then UNIV else
    {ev a |a. a  S  ev a  P0  ev a  Q0  a  S  (ev a  P0  ev a  Q0)} 
    {✓(r_s) |r_s r s. tick_join r s = Some r_s  ✓(r)  P0  ✓(s)  Q0})
  (is (P S Q)0 = (if P =   Q =  then UNIV else ?rhs_ev  ?rhs_tick))
proof (split if_split, intro conjI impI)
  show P =   Q =   (P S Q)0 = UNIV
    by (metis Syncptick_is_BOT_iff initials_BOT)
next
  show (P S Q)0 = ?rhs_ev  ?rhs_tick if non_BOT : ¬ (P =   Q = )
  proof (intro subset_antisym subsetI)
    show e  ?rhs_ev  ?rhs_tick  e  (P S Q)0 for e
    proof (elim UnE)
      assume e  ?rhs_ev
      then consider a where e = ev a a  S ev a  P0 ev a  Q0
        | a where e = ev a a  S ev a  P0  ev a  Q0 by blast
      thus e  (P S Q)0
      proof cases
        fix a assume e = ev a a  S ev a  P0 ev a  Q0
        have * : [ev a] setinterleavestick_join(([ev a], [ev a]), S)
          by (simp add: a  S)
        from ev a  P0 ev a  Q0 show e  (P S Q)0
          by (simp add: e = ev a initials_def T_Syncptick) (use "*" in blast)
      next
        fix a assume e = ev a a  S ev a  P0  ev a  Q0
        from ev a  P0  ev a  Q0 show e  (P S Q)0
        proof (elim disjE)
          assume ev a  P0
          have * : [ev a] setinterleavestick_join(([ev a], []), S)
            by (simp add: a  S)
          from ev a  P0 show e  (P S Q)0
            by (simp add: e = ev a initials_def T_Syncptick) (meson "*" is_processT1_TR)
        next
          assume ev a  Q0
          have * : [ev a] setinterleavestick_join(([], [ev a]), S)
            by (simp add: a  S)
          from ev a  Q0 show e  (P S Q)0
            by (simp add: e = ev a initials_def T_Syncptick) (meson "*" is_processT1_TR)
        qed
      qed
    next
      assume e  ?rhs_tick
      then obtain r_s r s where tick_join r s = Some r_s
        e = ✓(r_s) ✓(r)  P0 ✓(s)  Q0 by blast
      have * : [✓(r_s)] setinterleavestick_join(([✓(r)], [✓(s)]), S)
        by (simp add: tick_join r s = Some r_s)
      from ✓(r)  P0 ✓(s)  Q0 show e  (P S Q)0
        by (simp add: e = ✓(r_s) initials_def T_Syncptick) (use "*" in blast)
    qed
  next
    fix e assume e  (P S Q)0
    then consider t_P t_Q where t_P  𝒯 P t_Q  𝒯 Q
      [e] setinterleavestick_join((t_P, t_Q), S) 
    | (div) t u t_P t_Q
    where [e] = t @ u ftF u tF t  u = []
      t setinterleavestick_join((t_P, t_Q), S)
      t_P  𝒟 P  t_Q  𝒯 Q  t_P  𝒯 P  t_Q  𝒟 Q
      unfolding initials_def T_Syncptick by blast
    thus e  ?rhs_ev  ?rhs_tick
    proof cases
      show t_P  𝒯 P  t_Q  𝒯 Q 
            [e] setinterleavestick_join((t_P, t_Q), S) 
            e  ?rhs_ev  ?rhs_tick for t_P t_Q
        by (cases e; cases t_P; cases t_Q)
          (auto simp add: initials_def setinterleavingptick_simps
            split: if_split_asm option.split_asm eventptick.splits
            dest!: Nil_setinterleavesptick)
    next
      case div
      have t  [] by (metis BOT_iff_Nil_D Nil_setinterleavesptick div(4,5) non_BOT)
      hence t = [e]  u = []
        by (metis append_Cons append_Nil div(1) list.inject neq_Nil_conv)
      with div(4, 5) non_BOT show e  ?rhs_ev  ?rhs_tick
        by (cases e; cases t_P; cases t_Q)
          (auto simp add: initials_def setinterleavingptick_simps BOT_iff_Nil_D
            split: if_split_asm eventptick.splits option.split_asm 
            dest!: Nil_setinterleavesptick intro: D_T)
    qed
  qed
qed



section ‹Laws of After›

subsection ‹Sequential Composition›

locale AfterDuplicated_same_events = AfterDuplicated Ψα Ψβ
  for Ψα :: ('a, 'r ) processptick  'a  ('a, 'r ) processptick
    and Ψβ :: ('a, 's) processptick  'a  ('a, 's) processptick
begin

notation Afterα.After (infixl afterα 86)
notation Afterβ.After (infixl afterβ 86)


lemma not_skippable_or_not_initialR_After_Seqptick:
  (P ; Q) afterβ a = (if ev a  P0 then P  afterα a ; Q else Ψβ (P ; Q) a)
  if range tick  P0 = {}  (r. ✓(r)  P0  ev a  (Q r)0)
proof (cases P = )
  show P =   (P ; Q) afterβ a =
        (if ev a  P0 then P afterα a ; Q else Ψβ (P ; Q) a)
    by (simp add: After.After_BOT)
next
  note denot_projs = After.After_projs Seqptick_projs
  assume non_BOT: P  
  with that have $ : ev a  (P ; Q)0  ev a  P0
    by (auto simp add: initials_Seqptick)
  show (P ; Q) afterβ a = (if ev a  P0 then P afterα a ; Q else Ψβ (P ; Q) a)
  proof (split if_split, intro conjI impI)
    from "$" show ev a  P0  (P ; Q) afterβ a = Ψβ (P ; Q) a
      by (simp add: Afterβ.not_initial_After)
  next
    assume initial_P : ev a  P0
    show (P ; Q) afterβ a = P afterα a ; Q
    proof (rule Process_eq_optimizedI)
      fix t assume t  𝒟 ((P ; Q) afterβ a)
      then consider (D_P) t' u where ev a # t = map (ev  of_ev) t' @ u t'  𝒟 P tF t' ftF u
        | (D_Q) t' r u where ev a # t = map (ev  of_ev) t' @ u t' @ [✓(r)]  𝒯 P tF t' u  𝒟 (Q r)
        by (auto simp add: denot_projs "$" initial_P)
      thus t  𝒟 (P afterα a ; Q)
      proof cases
        case D_P with non_BOT initial_P show t  𝒟 (P afterα a ; Q)
          by (cases t') (auto simp add: BOT_iff_Nil_D denot_projs)
      next
        case D_Q with initial_P show t  𝒟 (P afterα a ; Q)
          by (cases t', simp_all add: BOT_iff_Nil_D denot_projs)
            (metis D_T disjoint_iff initials_memI rangeI that, blast)
      qed
    next
      fix t assume t  𝒟 (P afterα a ; Q)
      then consider (D_P) t' u where t = map (ev  of_ev) t' @ u ev a # t'  𝒟 P tF t' ftF u
        | (D_Q) t' r u where t = map (ev  of_ev) t' @ u ev a # t' @ [✓(r)]  𝒯 P tF t' u  𝒟 (Q r)
        by (auto simp add: denot_projs initial_P)
      thus t  𝒟 ((P ; Q) afterβ a)
      proof cases
        case D_P thus t  𝒟 ((P ; Q) afterβ a)
          by (simp add: denot_projs "$" initial_P Cons_eq_append_conv Cons_eq_map_conv)
            (metis eventptick.disc(1) eventptick.sel(1) tickFree_Cons_iff)
      next
        case D_Q thus t  𝒟 ((P ; Q) afterβ a)
          by (simp add: denot_projs "$" initial_P Cons_eq_append_conv Cons_eq_map_conv)
            (metis append_Cons eventptick.sel(1) is_ev_def tickFree_Cons_iff)
      qed
    next
      fix t X assume (t, X)   ((P ; Q) afterβ a) t  𝒟 ((P ; Q) afterβ a)
      then consider (F_P) t' where ev a # t = map (ev  of_ev) t'
        (t', ref_Seqptick X)   P tF t'
      | (F_Q) t' r u where ev a # t = map (ev  of_ev) t' @ u t' @ [✓(r)]  𝒯 P
        tF t' (u, X)   (Q r)
        by (auto simp add: denot_projs "$" initial_P)
          (metis (mono_tags, lifting) comp_apply list.simps(9) tickFree_Cons_iff)
      thus (t, X)   (P afterα a ; Q)
      proof cases
        case F_P thus (t, X)   (P afterα a ; Q)
          by (auto simp add: denot_projs initial_P)
      next
        case F_Q thus (t, X)   (P afterα a ; Q)
          by (cases t', auto simp add:denot_projs initial_P intro: initials_memI)
            (metis F_T Int_iff empty_iff initials_memI rangeI that)
      qed
    next
      fix t X assume (t, X)   (P afterα a ; Q) t  𝒟 (P afterα a ; Q)
      then consider (F_P) t' where t = map (ev  of_ev) t'
        (ev a # t', ref_Seqptick X)   P tF t'
      | (F_Q) t' r u where t = map (ev  of_ev) t' @ u ev a # t' @ [✓(r)]  𝒯 P
        tF t' (u, X)   (Q r)
        by (auto simp add: denot_projs initial_P)
      thus (t, X)   ((P ; Q) afterβ a)
      proof cases
        case F_P thus (t, X)   ((P ; Q) afterβ a)
          by (simp add: denot_projs "$" initial_P Cons_eq_map_conv)
            (metis eventptick.disc(1) eventptick.sel(1) tickFree_Cons_iff)
      next
        case F_Q thus (t, X)   ((P ; Q) afterβ a)
          by (simp add: denot_projs "$" initial_P Cons_eq_append_conv Cons_eq_map_conv)
            (metis append_Cons eventptick.disc(1) eventptick.sel(1) tickFree_Cons_iff)
      qed
    qed
  qed
qed


lemma skippable_not_initialL_After_Seqptick:
  (P ; Q) afterβ a = (  if (r. ✓(r)  P0  ev a  (Q r)0)
                       then r{r. ✓(r)  P0  ev a  (Q r)0}. Q r afterβ a
                       else Ψβ (P ; Q) a)
  (is (P ; Q) afterβ a = (if ?prem then ?rhs else _)) if ev a  P0
proof -
  note denot_projs = After.After_projs Seqptick_projs GlobalNdet_projs
  from initials_BOT ev a  P0 have non_BOT : P   by blast
  with ev a  P0 have $ : ev a  (P ; Q)0  ?prem
    by (auto simp add: initials_Seqptick)
  show (P ; Q) afterβ a = (if ?prem then ?rhs else Ψβ (P ; Q) a)
  proof (split if_split, intro conjI impI)
    show ¬ ?prem  (P ; Q) afterβ a = Ψβ (P ; Q) a
      by (rule Afterβ.not_initial_After, use "$" in blast)
  next
    show (P ; Q) afterβ a = ?rhs if ?prem
    proof (rule Process_eq_optimizedI)
      fix t assume t  𝒟 ((P ; Q) afterβ a)
      then consider (D_P) t' u where ev a # t = map (ev  of_ev) t' @ u t'  𝒟 P tF t' ftF u
        | (D_Q) t' r u where ev a # t = map (ev  of_ev) t' @ u t' @ [✓(r)]  𝒯 P tF t' u  𝒟 (Q r)
        by (auto simp add: denot_projs ?prem "$" ev a  P0)
      thus t  𝒟 ?rhs
      proof cases
        case D_P with non_BOT ev a  P0 show t  𝒟 ?rhs
          by (simp add: denot_projs Cons_eq_append_conv Cons_eq_map_conv BOT_iff_Nil_D)
            (metis D_T eventptick.collapse(1) initials_memI tickFree_Cons_iff)
      next
        case D_Q with ev a  P0 show t  𝒟 ?rhs
          by (simp add: denot_projs Cons_eq_append_conv Cons_eq_map_conv)
            (metis D_T append_Nil eventptick.collapse(1) initials_memI
              is_processT3_TR_append tickFree_Cons_iff)
      qed
    next
      from ?prem show t  𝒟 ?rhs  t  𝒟 ((P ; Q) afterβ a) for t
        by (simp add: denot_projs "$" Cons_eq_append_conv)
          (metis append_Nil initials_memD tickFree_Nil)
    next
      fix t X assume (t, X)   ((P ; Q) afterβ a) t  𝒟 ((P ; Q) afterβ a)
      then consider (F_P) t' where ev a # t = map (ev  of_ev) t'
        (t', ref_Seqptick X)   P tF t'
      | (F_Q) t' r u where ev a # t = map (ev  of_ev) t' @ u
        t' @ [✓(r)]  𝒯 P tF t' (u, X)   (Q r)
        by (simp add: denot_projs "$" ?prem) metis
      thus (t, X)   ?rhs
      proof cases
        case F_P with ev a  P0 show (t, X)   ?rhs
          by (cases t', simp_all add: denot_projs ?prem)
            (use F_T initials_memI in blast)
      next
        case F_Q with ev a  P0 ?prem show (t, X)   ?rhs
          by (cases t', auto simp add: denot_projs intro: initials_memI)
            (metis F_T initials_memI)
      qed
    next
      from ?prem show (t, X)   ?rhs  t  𝒟 ?rhs 
                         (t, X)   ((P ; Q) afterβ a) for t X
        by (simp add: denot_projs "$" Cons_eq_append_conv Cons_eq_map_conv split: if_split_asm)
          (metis initials_memD self_append_conv2 tickFree_Nil)
    qed
  qed
qed



lemma skippable_initialL_initialR_After_Seqptick:
  (P ; Q) afterβ a = (P afterα a ; Q)  (r{r. ✓(r)  P0  ev a  (Q r)0}. Q r afterβ a)
  (is (P ; Q) afterβ a = (P afterα a ; Q)  ?rhs)
  if assms : r. ✓(r)  P0  ev a  (Q r)0 ev a  P0
proof (cases P = )
  show P =   (P ; Q) afterβ a = (P afterα a ; Q)  ?rhs
    by (simp add: After.After_BOT)
next
  note denot_projs = After.After_projs Seqptick_projs GlobalNdet_projs Ndet_projs
  show (P ; Q) afterβ a = (P afterα a ; Q)  ?rhs if P  
  proof (rule Process_eq_optimizedI)
    fix t assume t  𝒟 ((P ; Q) afterβ a)
    then consider (D_P) t' u where ev a # t = map (ev  of_ev) t' @ u t'  𝒟 P tF t' ftF u
      | (D_Q) t' r u where ev a # t = map (ev  of_ev) t' @ u t' @ [✓(r)]  𝒯 P tF t' u  𝒟 (Q r)
      by (auto simp add: denot_projs initials_Seqptick assms split: if_split_asm)
    thus t  𝒟 ((P afterα a ; Q)  ?rhs)
    proof cases
      case D_P with P   show t  𝒟 ((P afterα a ; Q)  ?rhs)
        by (auto simp add: denot_projs assms Cons_eq_append_conv BOT_iff_Nil_D)
    next
      case D_Q thus t  𝒟 ((P afterα a ; Q)  ?rhs)
        by (auto simp add: denot_projs assms Cons_eq_append_conv)
          (meson D_T initials_memI, blast)
    qed
  next
    from P   show t  𝒟 ((P afterα a ; Q)  ?rhs)  t  𝒟 ((P ; Q) afterβ a) for t
      by (auto simp add: denot_projs assms initials_Seqptick Cons_eq_append_conv Cons_eq_map_conv)
        (metis eventptick.disc(1) eventptick.sel(1) tickFree_Cons_iff,
          metis Cons_eq_appendI append_T_imp_tickFree eventptick.sel(1) list.distinct(1),
          metis append_Nil initials_memD tickFree_Nil)
  next
    fix t X assume (t, X)   ((P ; Q) afterβ a) t  𝒟 ((P ; Q) afterβ a)
    then consider (F_P) t' where ev a # t = map (ev  of_ev) t'
      (t', ref_Seqptick X)   P tF t'
    | (F_Q) t' r u where ev a # t = map (ev  of_ev) t' @ u
      t' @ [✓(r)]  𝒯 P tF t' (u, X)   (Q r)
      by (simp add: denot_projs assms initials_Seqptick split: if_split_asm) meson+
    thus (t, X)   ((P afterα a ; Q)  ?rhs)
    proof cases
      case F_P thus (t, X)   ((P afterα a ; Q)  ?rhs)
        by (auto simp add: denot_projs assms)
    next
      case F_Q with assms show (t, X)   ((P afterα a ; Q)  ?rhs)
        by (cases t', simp_all add: denot_projs)
          (meson F_T initials_memI, blast)
    qed
  next
    fix t X assume (t, X)   ((P afterα a ; Q)  ?rhs) t  𝒟 ((P afterα a ; Q)  ?rhs)
    hence (t, X)   (P afterα a ; Q)  t  𝒟 (P afterα a ; Q) 
           (t, X)   ?rhs  t  𝒟 ?rhs by (simp add: Ndet_projs)
    thus (t, X)   ((P ; Q) afterβ a)
    proof (elim disjE conjE)
      show (t, X)   (P afterα a ; Q)  t  𝒟 (P afterα a ; Q) 
            (t, X)   ((P ; Q) afterβ a)
        by (simp add: denot_projs assms initials_Seqptick P   Cons_eq_append_conv Cons_eq_map_conv)
          (metis (no_types, lifting) Cons_eq_appendI eventptick.sel(1) is_ev_def tickFree_Cons_iff)
    next
      from assms show (t, X)   ?rhs  t  𝒟 ?rhs  (t, X)   ((P ; Q) afterβ a)
        by (simp add: denot_projs initials_Seqptick P  
            Cons_eq_append_conv Cons_eq_map_conv split: if_split_asm)
          (metis append_Nil initials_memD tickFree_Nil)
    qed
  qed
qed


lemma not_initialL_not_initialR_After_Seqptick:
  ev a  P0  (r. ✓(r)  P0  ev a  (Q r)0)  
   (P ; Q) afterβ a = Ψβ (P ; Q) a
  by (meson skippable_not_initialL_After_Seqptick)


lemma After_Seqptick:
  (P ; Q) afterβ a =
   (  if r. ✓(r)  P0  ev a  (Q r)0
    then   if ev a  P0 then P afterα a ; Q else Ψβ (P ; Q) a
    else   if ev a  P0
         then (P afterα a ; Q)  (r{r. ✓(r)  P0  ev a  (Q r)0}. Q r afterβ a)
         else r{r. ✓(r)  P0  ev a  (Q r)0}. Q r afterβ a)
  by (simp add: not_skippable_or_not_initialR_After_Seqptick
      skippable_initialL_initialR_After_Seqptick skippable_not_initialL_After_Seqptick)

end



subsection ‹Synchronization Product›

text ‹Because of the types, we have to extend the locale.›

locale After_Syncptick_locale = Syncptick_locale tick_join +
  Afterlhs : After Ψlhs + Afterrhs : After Ψrhs + Afterptick : After Ψptick
  for tick_join :: 'r  's  't option
    and Ψlhs :: [('a, 'r) processptick, 'a]  ('a, 'r) processptick
    and Ψrhs :: [('a, 's) processptick, 'a]  ('a, 's) processptick
    and Ψptick :: [('a, 't) processptick, 'a]  ('a, 't) processptick
begin

notation Afterlhs.After (infixl afterlhs 86)
notation Afterrhs.After (infixl afterrhs 86)
notation Afterptick.After (infixl afterptick 86)

sublocale After_Syncptick_locale_sym :
  After_Syncptick_locale λs r. tick_join r s Ψrhs Ψlhs Ψptick
  by unfold_locales



lemma initialL_not_initialR_not_in_After_Syncptick:
  (P S Q) afterptick a = P afterlhs a S Q (is ?lhs = ?rhs)
  if initial_hyps: ev a  P0 ev a  Q0 and notin: a  S
proof (cases P =   Q = )
  show P =   Q =   ?lhs = ?rhs
    by (elim disjE) (simp_all add: Afterptick.After_BOT Afterlhs.After_BOT)
next
  from initial_hyps and notin have init : ev a  (P S Q)0
    by (simp add: initials_Syncptick)
  show ?lhs = ?rhs if non_BOT : ¬ (P =   Q = )
  proof (rule Process_eq_optimizedI)
    fix t assume t  𝒟 ?lhs
    with init have ev a # t  𝒟 (P S Q) by (simp add: Afterptick.D_After)
    then obtain u v t_P t_Q
      where * : ev a # t = u @ v tF u ftF v
        u setinterleavestick_join((t_P, t_Q), S)
        t_P  𝒟 P  t_Q  𝒯 Q  t_P  𝒯 P  t_Q  𝒟 Q
      unfolding D_Syncptick by blast
    from "*"(4, 5) non_BOT have u  []
      by (auto simp add: BOT_iff_Nil_D dest: Nil_setinterleavesptick)
    with "*"(1) obtain u' where u = ev a # u' t = u' @ v
      by (cases u) simp_all
    from "*"(4, 5) initial_hyps(2) obtain t_P'
      where t_P = ev a # t_P' u' setinterleavestick_join((t_P', t_Q), S)
      by (cases t_P; cases t_Q)
        (auto simp add: setinterleavingptick_simps u = ev a # u'
          split: eventptick.splits if_split_asm option.split_asm
          intro: D_T initials_memI)
    moreover from t_P = ev a # t_P' "*"(2, 5)
    have t_P'  𝒟 (P afterlhs a)  t_Q  𝒯 Q 
          t_P'  𝒯 (P afterlhs a)  t_Q  𝒟 Q
      by (simp add: Afterlhs.After_projs initial_hyps(1))
    moreover from "*"(2) have tF u' by (simp add: u = ev a # u')
    ultimately show t  𝒟 ?rhs
      using "*"(3) by (auto simp add: t = u' @ v D_Syncptick)
  next
    fix t assume t  𝒟 ?rhs
    then obtain u v t_P t_Q
      where * : t = u @ v tF u ftF v
        u setinterleavestick_join((t_P, t_Q), S)
        t_P  𝒟 (P afterlhs a)  t_Q  𝒯 Q 
         t_P  𝒯 (P afterlhs a)  t_Q  𝒟 Q
      unfolding D_Syncptick by blast
    have ev a # t = (ev a # u) @ v by (simp add: "*"(1))
    moreover from "*"(2) have tF (ev a # u) by simp
    moreover from "*"(4)
    have ev a # u setinterleavestick_join((ev a # t_P, t_Q), S)
      by (metis notin rev.simps(2) rev_setinterleavesptick_rev_rev_iff
          setinterleavesptick_snoc_notinL)
    moreover from "*"(5) have ev a # t_P  𝒟 P  t_Q  𝒯 Q 
                               ev a # t_P  𝒯 P  t_Q  𝒟 Q
      by (simp add: Afterlhs.After_projs initial_hyps(1))
    ultimately have ev a # t  𝒟 (P S Q)
      using "*"(3) unfolding D_Syncptick by blast
    thus t  𝒟 ?lhs
      by (simp add: Afterptick.D_After init)
  next
    fix t X assume (t, X)   ?lhs
      t  𝒟 ?lhs
    hence (ev a # t, X)   (P S Q) ev a # t  𝒟 (P S Q)
      by (simp_all add: Afterptick.After_projs init)
    then obtain t_P t_Q X_P X_Q
      where * : (t_P, X_P)   P (t_Q, X_Q)   Q
        ev a # t setinterleavestick_join((t_P, t_Q), S)
        X  super_ref_Syncptick tick_join X_P S X_Q
      unfolding Syncptick_projs by blast
    from "*"(2, 3) initial_hyps(2) obtain t_P'
      where t_P = ev a # t_P' t setinterleavestick_join((t_P', t_Q), S)
      by (metis Cons_ev_setinterleavesptickE F_T initials_memI)
    moreover from "*"(1) have (t_P', X_P)   (P afterlhs a)
      by (simp add: t_P = ev a # t_P' Afterlhs.F_After initial_hyps(1))
    ultimately show (t, X)   ?rhs
      using "*"(2, 4) by (auto simp add: Syncptick_projs)
  next
    fix t X assume (t, X)   ?rhs
      t  𝒟 ?rhs
    then obtain t_P t_Q X_P X_Q
      where * : (t_P, X_P)   (P afterlhs a) (t_Q, X_Q)   Q
        t setinterleavestick_join((t_P, t_Q), S)
        X  super_ref_Syncptick tick_join X_P S X_Q
      unfolding Syncptick_projs by blast
    from "*"(1) have (ev a # t_P, X_P)   P
      by (simp add: Afterlhs.F_After initial_hyps(1))
    moreover from "*"(3)
    have ev a # t setinterleavestick_join((ev a # t_P, t_Q), S)
      by (metis notin rev.simps(2) rev_setinterleavesptick_rev_rev_iff
          setinterleavesptick_snoc_notinL)
    ultimately have (ev a # t, X)   (P S Q)
      using "*"(2, 4) by (auto simp add: F_Syncptick)
    thus (t, X)   ?lhs by (simp add: Afterptick.F_After init)
  qed
qed


lemma (in After_Syncptick_locale) not_initialL_initialR_not_in_After_Syncptick:
  (P S Q) afterptick a = P S Q afterrhs a (is ?lhs = ?rhs)
  if initial_hyps: ev a  P0 ev a  Q0 and notin: a  S
  using After_Syncptick_locale_sym.initialL_not_initialR_not_in_After_Syncptick
    [OF ev a  Q0 ev a  P0 a  S]
  by (simp add: Syncptick_sym)


lemma not_initialL_in_After_Syncptick:
  ev a  P0  a  S  
   (P S Q) afterptick a = (if Q =  then  else Ψptick (P S Q) a)
  by (simp add: Afterptick.After_BOT, rule impI)
    (subst Afterptick.not_initial_After, auto simp add: initials_Syncptick)

lemma not_initialR_in_After_Syncptick:
  ev a  Q0  a  S  
   (P S Q) afterptick a = (if P =  then  else Ψptick (P S Q) a)
  by (simp add: Afterptick.After_BOT, rule impI)
    (subst Afterptick.not_initial_After, auto simp add: initials_Syncptick)


lemma initialL_initialR_in_After_Syncptick:
  (P S Q) afterptick a = P afterlhs a S Q afterrhs a (is ?lhs = ?rhs)
  if initial_hyps: ev a  P0 ev a  Q0 and inside: a  S
proof (cases P =   Q = )
  show P =   Q =   ?lhs = ?rhs
    by (elim disjE) (simp_all add: After.After_BOT)
next
  from initial_hyps inside have init : ev a  (P S Q)0
    by (simp add: initials_Syncptick)
  show ?lhs = ?rhs if non_BOT : ¬ (P =   Q = )
  proof (rule Process_eq_optimizedI)
    fix t assume t  𝒟 ((P S Q) afterptick a)
    hence ev a # t  𝒟 (P S Q) by (simp add: Afterptick.D_After init)
    then obtain u v t_P t_Q
      where * : ev a # t = u @ v tF u ftF v
        u setinterleavestick_join((t_P, t_Q), S)
        t_P  𝒟 P  t_Q  𝒯 Q  t_P  𝒯 P  t_Q  𝒟 Q
      unfolding D_Syncptick by blast
    from "*"(4, 5) non_BOT have u  []
      by (auto simp add: BOT_iff_Nil_D dest: Nil_setinterleavesptick)
    with "*"(1) obtain u' where u = ev a # u' t = u' @ v
      by (cases u) simp_all
    from "*"(4) inside initial_hyps(1, 2) u = ev a # u'
    obtain t_P' t_Q' where t_P = ev a # t_P' t_Q = ev a # t_Q'
      u' setinterleavestick_join((t_P', t_Q'), S)
      by (metis (no_types, opaque_lifting) Cons_ev_setinterleavesptickE)
    moreover from "*"(2) have tF u' by (simp add: u = ev a # u')
    moreover from "*"(5)
    have t_P'  𝒟 (P afterlhs a)  t_Q'  𝒯 (Q afterrhs a) 
          t_P'  𝒯 (P afterlhs a)  t_Q'  𝒟 (Q afterrhs a)
      by (simp add: t_P = ev a # t_P' t_Q = ev a # t_Q'
          After.After_projs initial_hyps)
    ultimately show t  𝒟 ?rhs
      using "*"(3) by (auto simp add: t = u' @ v D_Syncptick)
  next
    fix t assume t  𝒟 ?rhs
    then obtain u v t_P t_Q
      where * : t = u @ v tF u ftF v
        u setinterleavestick_join((t_P, t_Q), S)
        t_P  𝒟 (P afterlhs a)  t_Q  𝒯 (Q afterrhs a) 
                 t_P  𝒯 (P afterlhs a)  t_Q  𝒟 (Q afterrhs a)
      unfolding D_Syncptick by blast
    from "*"(1) have ev a # t = (ev a # u) @ v by simp
    moreover from "*"(2) have tF (ev a # u) by simp
    moreover from "*"(4) have ev a # u setinterleavestick_join((ev a # t_P, ev a # t_Q), S)
      by (simp add: inside)
    moreover from "*"(5) have ev a # t_P  𝒟 P  ev a # t_Q  𝒯 Q 
                               ev a # t_P  𝒯 P  ev a # t_Q  𝒟 Q
      by (simp add: After.After_projs initial_hyps)
    ultimately have ev a # t  𝒟 (P S Q)
      unfolding D_Syncptick using "*"(3) by blast
    thus t  𝒟 ?lhs by (simp add: Afterptick.D_After init)
  next
    fix t X assume (t, X)   ?lhs t  𝒟 ?lhs
    hence (ev a # t, X)   (P S Q) ev a # t  𝒟 (P S Q)
      by (simp_all add: After.After_projs init)
    then obtain t_P t_Q X_P X_Q
      where * : (t_P, X_P)   P (t_Q, X_Q)   Q
        ev a # t setinterleavestick_join((t_P, t_Q), S)
        X  super_ref_Syncptick tick_join X_P S X_Q
      unfolding Syncptick_projs by blast
    from "*"(3) obtain t_P' t_Q'
      where t_P = ev a # t_P' t_Q = ev a # t_Q'
        t setinterleavestick_join((t_P', t_Q'), S)
      by (metis (no_types) Cons_ev_setinterleavesptickE inside)
    moreover from "*"(1, 2) have (t_P', X_P)   (P afterlhs a)
      (t_Q', X_Q)   (Q afterrhs a)
      by (simp_all add: t_P = ev a # t_P' t_Q = ev a # t_Q' 
          After.F_After initial_hyps)
    ultimately show (t, X)   ?rhs
      by (auto simp add: F_Syncptick intro!: "*"(4))
  next
    fix t X assume (t, X)   ?rhs t  𝒟 ?rhs
    then obtain t_P t_Q X_P X_Q
      where * : (t_P, X_P)   (P afterlhs a)
        (t_Q, X_Q)   (Q afterrhs a)
        t setinterleavestick_join((t_P, t_Q), S)
        X  super_ref_Syncptick tick_join X_P S X_Q
      unfolding Syncptick_projs by blast
    from "*"(1, 2) have (ev a # t_P, X_P)   P
      (ev a # t_Q, X_Q)   Q
      by (simp_all add: After.F_After initial_hyps)
    moreover from "*"(3) have ev a # t setinterleavestick_join((ev a # t_P, ev a # t_Q), S)
      by (simp add: inside)
    ultimately have (ev a # t, X)   (P S Q)
      using "*"(4) by (simp (no_asm) add: F_Syncptick) blast
    thus (t, X)   ?lhs by (simp add: Afterptick.F_After init)
  qed
qed



lemma initialL_initialR_not_in_After_Syncptick: 
  (P S Q) afterptick a = (P afterlhs a S Q)  (P S Q afterrhs a)
  (is ?lhs = ?rhs1  ?rhs2)
  if initial_hyps: ev a  P0 ev a  Q0 and notin: a  S
proof (cases P =   Q = )
  show P =   Q =   ?lhs = ?rhs1  ?rhs2
    by (elim disjE) (simp_all add: After.After_BOT)
next
  from initial_hyps(1) notin have init : ev a  (P S Q)0
    by (simp add: initials_Syncptick)
  show ?lhs = ?rhs1  ?rhs2 if non_BOT : ¬ (P =   Q = )
  proof (rule Process_eq_optimizedI)
    fix t assume t  𝒟 ?lhs
    hence ev a # t  𝒟 (P S Q)
      by (simp add: Afterptick.D_After init)
    then obtain u v t_P t_Q
      where * : ev a # t = u @ v tF u ftF v
        u setinterleavestick_join((t_P, t_Q), S)
        t_P  𝒟 P  t_Q  𝒯 Q  t_P  𝒯 P  t_Q  𝒟 Q
      unfolding D_Syncptick by blast
    from "*"(4, 5) non_BOT have u  []
      by (auto simp add: BOT_iff_Nil_D dest: Nil_setinterleavesptick)
    with "*"(1) obtain u' where u = ev a # u' t = u' @ v
      by (cases u) simp_all
    from "*"(2) have tF u' by (simp add: u = ev a # u')
    from "*"(4) notin u = ev a # u'
    consider t_P' where t_P = ev a # t_P'
      u' setinterleavestick_join((t_P', t_Q), S)
    | t_Q' where t_Q = ev a # t_Q'
      u' setinterleavestick_join((t_P, t_Q'), S)
      by (metis (no_types) Cons_ev_setinterleavesptickE)
    thus t  𝒟 (?rhs1  ?rhs2)
    proof cases
      fix t_P' assume $ : t_P = ev a # t_P'
        u' setinterleavestick_join((t_P', t_Q), S)
      from "*"(5) have t_P'  𝒟 (P afterlhs a)  t_Q  𝒯 Q 
                        t_P'  𝒯 (P afterlhs a)  t_Q  𝒟 Q
        by (simp add: "$"(1) Afterlhs.After_projs initial_hyps(1))
      with "$"(2) "*"(3) tF u' have t  𝒟 ?rhs1
        by (auto simp add: t = u' @ v D_Syncptick)
      thus t  𝒟 (?rhs1  ?rhs2) by (simp add: D_Ndet)
    next
      fix t_Q' assume $ : t_Q = ev a # t_Q'
        u' setinterleavestick_join((t_P, t_Q'), S)
      from "*"(5) have t_P  𝒟 P  t_Q'  𝒯 (Q afterrhs a) 
                        t_P  𝒯 P  t_Q'  𝒟 (Q afterrhs a)
        by (simp add: "$"(1) Afterrhs.After_projs initial_hyps(2))
      with "$"(2) "*"(3) tF u' have t  𝒟 ?rhs2
        by (auto simp add: t = u' @ v D_Syncptick)
      thus t  𝒟 (?rhs1  ?rhs2) by (simp add: D_Ndet)
    qed
  next
    fix t assume t  𝒟 (?rhs1  ?rhs2)
    then consider t  𝒟 ?rhs1 | t  𝒟 ?rhs2
      by (auto simp add: D_Ndet)
    hence ev a # t  𝒟 (P S Q)
    proof cases
      assume t  𝒟 ?rhs1
      then obtain u v t_P t_Q
        where * : t = u @ v tF u ftF v
          u setinterleavestick_join((t_P, t_Q), S)
          t_P  𝒟 (P afterlhs a)  t_Q  𝒯 Q 
                   t_P  𝒯 (P afterlhs a)  t_Q  𝒟 Q
        unfolding D_Syncptick by blast
      from "*"(1) have ev a # t = (ev a # u) @ v by simp
      moreover from "*"(2) have tF (ev a # u) by simp
      moreover from "*"(4)
      have ev a # u setinterleavestick_join((ev a # t_P, t_Q), S)
        by (metis notin rev.simps(2) rev_setinterleavesptick_rev_rev_iff
            setinterleavesptick_snoc_notinL)
      moreover from "*"(5) have ev a # t_P  𝒟 P  t_Q  𝒯 Q 
                                 ev a # t_P  𝒯 P  t_Q  𝒟 Q
        by (simp add: Afterlhs.After_projs initial_hyps(1))
      ultimately show ev a # t  𝒟 (P S Q)
        using "*"(3) unfolding D_Syncptick by blast
    next
      assume t  𝒟 ?rhs2
      then obtain u v t_P t_Q
        where * : t = u @ v tF u ftF v
          u setinterleavestick_join((t_P, t_Q), S)
          t_P  𝒟 P  t_Q  𝒯 (Q afterrhs a) 
                   t_P  𝒯 P  t_Q  𝒟 (Q afterrhs a)
        unfolding D_Syncptick by blast
      from "*"(1) have ev a # t = (ev a # u) @ v by simp
      moreover from "*"(2) have tF (ev a # u) by simp
      moreover from "*"(4) have ev a # u setinterleavestick_join((t_P, ev a # t_Q), S)
        by (metis notin rev.simps(2) rev_setinterleavesptick_rev_rev_iff
            setinterleavesptick_snoc_notinR)
      moreover from "*"(5) have t_P  𝒟 P  ev a # t_Q  𝒯 Q 
                                 t_P  𝒯 P  ev a # t_Q  𝒟 Q
        by (simp add: Afterrhs.After_projs initial_hyps(2))
      ultimately show ev a # t  𝒟 (P S Q)
        using "*"(3) unfolding D_Syncptick by blast
    qed
    thus t  𝒟 ?lhs by (simp add: Afterptick.D_After init)
  next  
    fix t X assume (t, X)   ?lhs t  𝒟 ?lhs
    hence (ev a # t, X)   (P S Q) ev a # t  𝒟 (P S Q)
      by (simp_all add: Afterptick.After_projs init)
    then obtain t_P t_Q X_P X_Q
      where * : (t_P, X_P)   P (t_Q, X_Q)   Q
        ev a # t setinterleavestick_join((t_P, t_Q), S)
        X  super_ref_Syncptick tick_join X_P S X_Q
      unfolding Syncptick_projs by blast
    from "*"(3) notin
    consider t_P' where t_P = ev a # t_P'
      t setinterleavestick_join((t_P', t_Q), S)
    | t_Q' where t_Q = ev a # t_Q'
      t setinterleavestick_join((t_P, t_Q'), S)
      by (metis (no_types) Cons_ev_setinterleavesptickE)
    thus (t, X)   (?rhs1  ?rhs2)
    proof cases
      fix t_P' assume $ : t_P = ev a # t_P'
        t setinterleavestick_join((t_P', t_Q), S)
      from "*"(1) have (t_P', X_P)   (P afterlhs a)
        by (simp add: "$"(1) Afterlhs.F_After initial_hyps(1))
      with "$"(2) "*"(2, 4) have (t, X)   ?rhs1
        by (auto simp add: F_Syncptick)
      thus (t, X)   (?rhs1  ?rhs2) by (simp add: F_Ndet)
    next
      fix t_Q' assume $ : t_Q = ev a # t_Q'
        t setinterleavestick_join((t_P, t_Q'), S)
      from "*"(2) have (t_Q', X_Q)   (Q afterrhs a)
        by (simp add: "$"(1) Afterrhs.F_After initial_hyps(2))
      with "$"(2) "*"(1, 4) have (t, X)   ?rhs2
        by (auto simp add: F_Syncptick)
      thus (t, X)   (?rhs1  ?rhs2) by (simp add: F_Ndet)
    qed
  next
    fix t X assume (t, X)   (?rhs1  ?rhs2) t  𝒟 (?rhs1  ?rhs2)
    then consider (t, X)   ?rhs1 t  𝒟 ?rhs1
      | (t, X)   ?rhs2 t  𝒟 ?rhs2
      by (auto simp add: Ndet_projs)
    hence (ev a # t, X)   (P S Q)
    proof cases
      assume (t, X)   ?rhs1 t  𝒟 ?rhs1
      then obtain t_P t_Q X_P X_Q
        where * : (t_P, X_P)   (P afterlhs a) (t_Q, X_Q)   Q
          t setinterleavestick_join((t_P, t_Q), S)
          X  super_ref_Syncptick tick_join X_P S X_Q
        unfolding Syncptick_projs by blast
      from "*"(1) have (ev a # t_P, X_P)   P
        by (simp add: Afterlhs.F_After initial_hyps(1))
      moreover from "*"(3)
      have ev a # t setinterleavestick_join((ev a # t_P, t_Q), S)
        by (metis notin rev.simps(2) rev_setinterleavesptick_rev_rev_iff
            setinterleavesptick_snoc_notinL)
      ultimately show (ev a # t, X)   (P S Q)
        by (auto simp add: F_Syncptick intro!: "*"(2, 4))
    next
      assume (t, X)   ?rhs2 t  𝒟 ?rhs2
      then obtain t_P t_Q X_P X_Q
        where * : (t_P, X_P)   P (t_Q, X_Q)   (Q afterrhs a)
          t setinterleavestick_join((t_P, t_Q), S)
          X  super_ref_Syncptick tick_join X_P S X_Q
        unfolding Syncptick_projs by blast
      from "*"(2) have (ev a # t_Q, X_Q)   Q
        by (simp add: Afterrhs.F_After initial_hyps(2))
      moreover from "*"(3)
      have ev a # t setinterleavestick_join((t_P, ev a # t_Q), S)
        by (metis notin rev.simps(2) rev_setinterleavesptick_rev_rev_iff
            setinterleavesptick_snoc_notinR)
      ultimately show (ev a # t, X)   (P S Q)
        by (auto simp add: F_Syncptick intro!: "*"(1, 4))
    qed
    thus (t, X)   ?lhs by (simp add: Afterptick.F_After init)
  qed
qed



lemma not_initialL_not_initialR_After_Syncptick :
  ev a  P0  ev a  Q0  (P S Q) afterptick a = Ψptick (P S Q) a
  by (subst Afterptick.not_initial_After) (auto simp add: initials_Syncptick)



text ‹Finally, the monster theorem !›

theorem After_Syncptick: 
  (P S Q) afterptick a =
   (  if P =   Q =  then 
    else   if ev a  P0  ev a  Q0
         then   if a  S then P afterlhs a S Q afterrhs a
              else (P afterlhs a S Q)  (P S Q afterrhs a)
         else   if ev a  P0  a  S then P afterlhs a S Q
              else   if ev a  Q0  a  S then P S Q afterrhs a
                   else Ψptick (P S Q) a)
  by (auto simp add: Afterptick.After_BOT initialL_not_initialR_not_in_After_Syncptick
      initialL_initialR_in_After_Syncptick initialL_initialR_not_in_After_Syncptick
      not_initialL_initialR_not_in_After_Syncptick not_initialL_not_initialR_After_Syncptick
      not_initialR_in_After_Syncptick not_initialL_in_After_Syncptick)


end


(*<*)
end
  (*>*)