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 const‹initials››

subsection ‹const‹TickSwap››

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] setinterleaves✓⇘tick_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] setinterleaves✓⇘tick_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] setinterleaves✓⇘tick_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)] setinterleaves✓⇘tick_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] setinterleaves✓⇘tick_join⇙ ((t_P, t_Q), S)› 
    | (div) t u t_P t_Q
    where ‹[e] = t @ u› ‹ftF u› ‹tF t ∨ u = []›
      ‹t setinterleaves✓⇘tick_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] setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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' setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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' setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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' setinterleaves✓⇘tick_join⇙ ((t_P', t_Q), S)›
    | t_Q' where ‹t_Q = ev a # t_Q'›
      ‹u' setinterleaves✓⇘tick_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' setinterleaves✓⇘tick_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' setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_join⇙ ((t_P', t_Q), S)›
    | t_Q' where ‹t_Q = ev a # t_Q'›
      ‹t setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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 setinterleaves✓⇘tick_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
  (*>*)