Theory CSP_New_Laws

(*<*)
―‹ ******************************************************************** 
 * Project         : HOL-CSP_OpSem - Operational semantics for HOL-CSP
 *
 * Author          : Benoît Ballenghien, Burkhart Wolff.
 *
 * This file       : New laws
 *
 * Copyright (c) 2025 Université Paris-Saclay, France
 *
 * 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 list of conditions and the following disclaimer.
 *
 *     * 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.
 *
 *     * Neither the name of the copyright holders nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * 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
 * OWNER 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.
 ******************************************************************************›
(*>*)

chapter‹ Bonus: powerful new Laws ›

(*<*)
theory  CSP_New_Laws
  imports Initials
begin
(*>*)

section ‹Powerful Results about constSync

lemma add_complementary_events_of_in_failure:
  (t, X)   P  (t, X  ev ` (- α(P)))   P
  by (erule is_processT5) (auto simp add: events_of_def, metis F_T in_set_conv_decomp)

lemma add_complementary_initials_in_refusal: X   P  X  - P0   P
  unfolding Refusals_iff by (erule is_processT5) (auto simp add: initials_def F_T)

lemma TickRightSync: 
  ✓(r)  S  ftF u  t setinterleaves ((u, [✓(r)]), S)  t = u  last u = ✓(r)
  by (simp add: TickLeftSync setinterleaving_sym)

  

theorem Sync_is_Sync_restricted_superset_events:
  fixes S A :: 'a set and P Q :: ('a, 'r) processptick
  assumes superset : α(P)  α(Q)  A
  defines S'  S  A
  shows P S Q = P S' Q
proof (subst Process_eq_spec_optimized, safe)
  show s  𝒟 (P S Q)  s  𝒟 (P S' Q) for s
    by (simp add: D_Sync S'_def)
       (metis Un_UNIV_left Un_commute equals0D events_of_is_strict_events_of_or_UNIV
              inf_top.right_neutral sup.orderE superset)
next
  show s  𝒟 (P S' Q)  s  𝒟 (P S Q) for s
    by (simp add: D_Sync S'_def)
       (metis Un_UNIV_left Un_commute equals0D events_of_is_strict_events_of_or_UNIV
              inf_top.right_neutral sup.orderE superset)
next
  let ?S  = range tick  ev ` S  :: ('a, 'r) eventptick set
  and ?S' = range tick  ev ` S' :: ('a, 'r) eventptick set
  fix s X
  assume same_div : 𝒟 (P S Q) = 𝒟 (P S' Q)
  assume (s, X)   (P S' Q)
  then consider s  𝒟 (P S' Q)
    | s_P X_P s_Q X_Q where (rev s_P, X_P)   P (rev s_Q, X_Q)   Q
                            s setinterleaves ((rev s_P, rev s_Q), ?S')
                            X = (X_P  X_Q)  ?S'  X_P  X_Q
    by (simp add: F_Sync D_Sync) (metis rev_rev_ident)
  thus (s, X)   (P S Q)
  proof cases
    from same_div D_F show s  𝒟 (P S' Q)  (s, X)   (P S Q) by blast
  next
    fix s_P s_Q and X_P X_Q :: ('a, 'r) eventptick set
    let ?X_P' = X_P  ev ` (- α(P)) and ?X_Q' = X_Q  ev ` (- α(Q))
    assume assms : (rev s_P, X_P)   P (rev s_Q, X_Q)   Q
                   s setinterleaves ((rev s_P, rev s_Q), ?S')
                   X = (X_P  X_Q)  ?S'  X_P  X_Q
    
    from assms(1, 2)[THEN F_T] and assms(3)
    have assms_3_bis : s setinterleaves ((rev s_P, rev s_Q), ?S)
    proof (induct (s_P, ?S, s_Q) arbitrary: s_P s_Q s rule: setinterleaving.induct)
      case 1
      thus s setinterleaves ((rev [], rev []), ?S) by simp
    next
      case (2 y s_Q)
      from "2.prems"(3)[THEN doubleReverse] obtain s' b 
        where * : y = ev b b  S' s = rev (y # s')
                  s' setinterleaves (([], s_Q), ?S')
        by (simp add: image_iff split: if_split_asm) (metis eventptick.exhaust)
      from "2.prems"(2)[unfolded y = ev b]
      have b  α(Q) by (force simp add: events_of_def)
      with b  S' superset have b  S by (simp add: S'_def subset_iff)
      from "2.prems"(2)[simplified, THEN is_processT3_TR] have rev s_Q  𝒯 Q by auto
      have y  ?S by (simp add: "*"(1) b  S image_iff)
      have rev s' setinterleaves ((rev [], rev s_Q), ?S)
        by (fact "2.hyps"[OF y  ?S "2.prems"(1) rev s_Q  𝒯 Q "*"(4)[THEN doubleReverse]])
      from this[THEN addNonSync, OF y  ?S]
      show s setinterleaves ((rev [], rev (y # s_Q)), ?S)
        by (simp add: s = rev (y # s'))
    next
      case (3 x s_P)
      from "3.prems"(3)[THEN doubleReverse] obtain s' a 
        where * : x = ev a a  S' s = rev (x # s')
                  s' setinterleaves ((s_P, []), ?S')
        by (simp add: image_iff split: if_split_asm) (metis eventptick.exhaust)
      from "3.prems"(1)[unfolded x = ev a]
      have a  α(P) by (force simp add: events_of_def)
      with a  S' superset have a  S by (simp add: S'_def subset_iff)
      from "3.prems"(1)[simplified, THEN is_processT3_TR] have rev s_P  𝒯 P by auto
      have x  ?S by (simp add: "*"(1) a  S image_iff)
      have rev s' setinterleaves ((rev s_P, rev []), ?S)
        by (fact "3.hyps"[OF x  ?S rev s_P  𝒯 P "3.prems"(2) "*"(4)[THEN doubleReverse]])
      from this[THEN addNonSync, OF x  ?S]
      show s setinterleaves ((rev (x # s_P), rev []), ?S)
        by (simp add: s = rev (x # s'))
    next
      case (4 x s_P y s_Q)
      from "4.prems"(1)[simplified, THEN is_processT3_TR] have rev s_P  𝒯 P by auto
      from "4.prems"(2)[simplified, THEN is_processT3_TR] have rev s_Q  𝒯 Q by auto
      from "4.prems"(1) have x  range tick  ev ` α(P)
        by (cases x; force simp add: events_of_def image_iff split: eventptick.split)
      from "4.prems"(2) have y  range tick  ev ` α(Q)
        by (cases y; force simp add: events_of_def image_iff split: eventptick.split)
      consider x  ?S and y  ?S | x  ?S and y  ?S
        | x  ?S and y  ?S | x  ?S and y  ?S by blast
      thus s setinterleaves ((rev (x # s_P), rev (y # s_Q)), ?S)
      proof cases
        assume x  ?S and y  ?S
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q) superset
        have x  ?S' and y  ?S' by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse] obtain s'
        where * : x = y s = rev (x # s') s' setinterleaves ((s_P, s_Q), ?S')
          by (simp split: if_split_asm) blast

        from "4.hyps"(1)[OF x  ?S y  ?S x = y rev s_P  𝒯 P rev s_Q  𝒯 Q
                            s' setinterleaves ((s_P, s_Q), ?S')[THEN doubleReverse]]
        have rev s' setinterleaves ((rev s_P, rev s_Q), ?S) .
        from this[THEN doubleReverse] x  ?S
        have (x # s') setinterleaves ((x # s_P, x # s_Q), ?S) by simp
        from this[THEN doubleReverse] show ?case by (simp add: "*"(1, 2))
      next
        assume x  ?S and y  ?S
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q) superset
        have x  ?S' and y  ?S' by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse, simplified] obtain s'
        where * : s = rev (y # s') s' setinterleaves ((x # s_P, s_Q), ?S')
          by (simp split: if_split_asm) blast
        from "4.hyps"(2)[OF x  ?S y  ?S rev (x # s_P)  𝒯 P rev s_Q  𝒯 Q
                            s' setinterleaves ((x # s_P, s_Q), ?S')[THEN doubleReverse]]
        have rev s' setinterleaves ((rev (x # s_P), rev s_Q), ?S) .
        from this[THEN doubleReverse] x  ?S y  ?S
        have (y # s') setinterleaves ((x # s_P, y # s_Q), ?S) by simp
        from this[THEN doubleReverse] show ?case by (simp add: s = rev (y # s'))
      next
        assume x  ?S and y  ?S
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q) superset
        have x  ?S' and y  ?S' by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse] obtain s'
        where * : s = rev (x # s') s' setinterleaves ((s_P, y # s_Q), ?S')
          by (simp split: if_split_asm) blast
        from "4.hyps"(5)[OF x  ?S _ rev s_P  𝒯 P rev (y # s_Q)  𝒯 Q
                            s' setinterleaves ((s_P, y # s_Q), ?S')[THEN doubleReverse]] y  ?S
        have rev s' setinterleaves ((rev s_P, rev (y # s_Q)), ?S) by simp
        from this[THEN doubleReverse] x  ?S y  ?S
        have (x # s') setinterleaves ((x # s_P, y # s_Q), ?S) by simp
        from this[THEN doubleReverse] show ?case by (simp add: s = rev (x # s'))
      next
        assume x  ?S and y  ?S
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q)
        have x  ?S' and y  ?S' by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse, simplified] consider
          s' where s = rev (x # s') s' setinterleaves ((s_P, y # s_Q), ?S')
        | s' where s = rev (y # s') s' setinterleaves ((x # s_P, s_Q), ?S')
          by (simp split: if_split_asm) blast
        thus ?case
        proof cases
          fix s' assume s = rev (x # s') s' setinterleaves ((s_P, y # s_Q), ?S')
          from "4.hyps"(3)[OF x  ?S y  ?S rev s_P  𝒯 P rev (y # s_Q)  𝒯 Q
                              s' setinterleaves ((s_P, y # s_Q), ?S')[THEN doubleReverse]]
          have rev s' setinterleaves ((rev s_P, rev (y # s_Q)), ?S) .
          from this[THEN doubleReverse] x  ?S y  ?S
          have (x # s') setinterleaves ((x # s_P, y # s_Q), ?S) by simp
          from this[THEN doubleReverse] show ?case by (simp add: s = rev (x # s'))
        next
          fix s' assume s = rev (y # s') s' setinterleaves ((x # s_P, s_Q), ?S')
          from "4.hyps"(4)[OF x  ?S y  ?S rev (x # s_P)  𝒯 P rev s_Q  𝒯 Q
                              s' setinterleaves ((x # s_P, s_Q), ?S')[THEN doubleReverse]]
          have rev s' setinterleaves ((rev (x # s_P), rev s_Q), ?S) .
          from this[THEN doubleReverse] x  ?S y  ?S
          have (y # s') setinterleaves ((x # s_P, y # s_Q), ?S) by simp
          from this[THEN doubleReverse] show ?case by (simp add: s = rev (y # s'))
        qed
      qed
    qed
  
    from add_complementary_events_of_in_failure[OF assms(1)]
    have (rev s_P, ?X_P')   P .
    moreover from add_complementary_events_of_in_failure[OF assms(2)]
    have (rev s_Q, ?X_Q')   Q .
    ultimately have (s, (?X_P'  ?X_Q')  ?S  ?X_P'  ?X_Q')   (P S Q)
      using assms_3_bis by (simp add: F_Sync) blast
    moreover have X  (?X_P'  ?X_Q')  ?S  ?X_P'  ?X_Q'
      by (auto simp add: assms(4) S'_def image_iff)
    ultimately show (s, X)   (P S Q) by (rule is_processT4)
  qed
next
  let ?S  = range tick  ev ` S  :: ('a, 'r) eventptick set
  and ?S' = range tick  ev ` S' :: ('a, 'r) eventptick set
  fix s X
  assume same_div : 𝒟 (P S Q) = 𝒟 (P S' Q)
  assume (s, X)   (P S Q)
  then consider s  𝒟 (P S Q)
    | s_P X_P s_Q X_Q where (rev s_P, X_P)   P (rev s_Q, X_Q)   Q
                            s setinterleaves ((rev s_P, rev s_Q), ?S)
                            X = (X_P  X_Q)  ?S  X_P  X_Q
    by (simp add: F_Sync D_Sync) (metis rev_rev_ident)
  thus (s, X)   (P S' Q)
  proof cases
    from same_div D_F show s  𝒟 (P S Q)  (s, X)   (P S' Q) by blast
  next
    fix s_P s_Q and X_P X_Q :: ('a, 'r) eventptick set
    let ?X_P' = X_P  ev ` (- α(P)) and ?X_Q' = X_Q  ev ` (- α(Q))
    assume assms : (rev s_P, X_P)   P (rev s_Q, X_Q)   Q
                   s setinterleaves ((rev s_P, rev s_Q), ?S)
                   X = (X_P  X_Q)  ?S  X_P  X_Q
    
    from assms(1, 2)[THEN F_T] and assms(3)
    have assms_3_bis : s setinterleaves ((rev s_P, rev s_Q), ?S')
    proof (induct (s_P, ?S', s_Q) arbitrary: s_P s_Q s rule: setinterleaving.induct)
      case 1
      thus s setinterleaves ((rev [], rev []), ?S') by simp
    next
      case (2 y s_Q)
      from "2.prems"(3)[THEN doubleReverse] obtain s' b 
        where * : y = ev b b  S s = rev (y # s')
                  s' setinterleaves (([], s_Q), ?S)
        by (simp add: image_iff split: if_split_asm) (metis eventptick.exhaust)
      from "2.prems"(2)[unfolded y = ev b]
      have b  α(Q) by (force simp add: events_of_def)
      with b  S have b  S' by (simp add: S'_def)
      from "2.prems"(2)[simplified, THEN is_processT3_TR] have rev s_Q  𝒯 Q by auto
      have y  ?S' by (simp add: "*"(1) b  S' image_iff)
      have rev s' setinterleaves ((rev [], rev s_Q), ?S')
        by (fact "2.hyps"[OF y  ?S' "2.prems"(1) rev s_Q  𝒯 Q "*"(4)[THEN doubleReverse]])
      from this[THEN addNonSync, OF y  ?S']
      show s setinterleaves ((rev [], rev (y # s_Q)), ?S')
        by (simp add: s = rev (y # s'))
    next
      case (3 x s_P)
      from "3.prems"(3)[THEN doubleReverse] obtain s' a 
        where * : x = ev a a  S s = rev (x # s')
                  s' setinterleaves ((s_P, []), ?S)
        by (simp add: image_iff split: if_split_asm) (metis eventptick.exhaust)
      from "3.prems"(1)[unfolded x = ev a]
      have a  α(P) by (force simp add: events_of_def)
      with a  S have a  S' by (simp add: S'_def)
      from "3.prems"(1)[simplified, THEN is_processT3_TR] have rev s_P  𝒯 P by auto
      have x  ?S' by (simp add: "*"(1) a  S' image_iff)
      have rev s' setinterleaves ((rev s_P, rev []), ?S')
        by (fact "3.hyps"[OF x  ?S' rev s_P  𝒯 P "3.prems"(2) "*"(4)[THEN doubleReverse]])
      from this[THEN addNonSync, OF x  ?S']
      show s setinterleaves ((rev (x # s_P), rev []), ?S')
        by (simp add: s = rev (x # s'))
    next
      case (4 x s_P y s_Q)
      from "4.prems"(1)[simplified, THEN is_processT3_TR] have rev s_P  𝒯 P by auto
      from "4.prems"(2)[simplified, THEN is_processT3_TR] have rev s_Q  𝒯 Q by auto
      from "4.prems"(1) have x  range tick  ev ` α(P)
        by (cases x; force simp add: events_of_def image_iff split: eventptick.split)
      from "4.prems"(2) have y  range tick  ev ` α(Q)
        by (cases y; force simp add: events_of_def image_iff split: eventptick.split)
      consider x  ?S' and y  ?S' | x  ?S' and y  ?S'
        | x  ?S' and y  ?S' | x  ?S' and y  ?S' by blast
      thus s setinterleaves ((rev (x # s_P), rev (y # s_Q)), ?S')
      proof cases
        assume x  ?S' and y  ?S'
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q)
        have x  ?S and y  ?S by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse] obtain s'
        where * : x = y s = rev (x # s') s' setinterleaves ((s_P, s_Q), ?S)
          by (simp split: if_split_asm) blast

        from "4.hyps"(1)[OF x  ?S' y  ?S' x = y rev s_P  𝒯 P rev s_Q  𝒯 Q
                            s' setinterleaves ((s_P, s_Q), ?S)[THEN doubleReverse]]
        have rev s' setinterleaves ((rev s_P, rev s_Q), ?S') .
        from this[THEN doubleReverse] x  ?S'
        have (x # s') setinterleaves ((x # s_P, x # s_Q), ?S') by simp
        from this[THEN doubleReverse] show ?case by (simp add: "*"(1, 2))
      next
        assume x  ?S' and y  ?S'
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q) superset
        have x  ?S and y  ?S by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse, simplified] obtain s'
        where * : s = rev (y # s') s' setinterleaves ((x # s_P, s_Q), ?S)
          by (simp split: if_split_asm) blast
        from "4.hyps"(2)[OF x  ?S' y  ?S' rev (x # s_P)  𝒯 P rev s_Q  𝒯 Q
                            s' setinterleaves ((x # s_P, s_Q), ?S)[THEN doubleReverse]]
        have rev s' setinterleaves ((rev (x # s_P), rev s_Q), ?S') .
        from this[THEN doubleReverse] x  ?S' y  ?S'
        have (y # s') setinterleaves ((x # s_P, y # s_Q), ?S') by simp
        from this[THEN doubleReverse] show ?case by (simp add: s = rev (y # s'))
      next
        assume x  ?S' and y  ?S'
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q) superset
        have x  ?S and y  ?S by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse] obtain s'
        where * : s = rev (x # s') s' setinterleaves ((s_P, y # s_Q), ?S)
          by (simp split: if_split_asm) blast
        from "4.hyps"(5)[OF x  ?S' _ rev s_P  𝒯 P rev (y # s_Q)  𝒯 Q
                            s' setinterleaves ((s_P, y # s_Q), ?S)[THEN doubleReverse]] y  ?S'
        have rev s' setinterleaves ((rev s_P, rev (y # s_Q)), ?S') by simp
        from this[THEN doubleReverse] x  ?S' y  ?S'
        have (x # s') setinterleaves ((x # s_P, y # s_Q), ?S') by simp
        from this[THEN doubleReverse] show ?case by (simp add: s = rev (x # s'))
      next
        assume x  ?S' and y  ?S'
        with x  range tick  ev ` α(P) y  range tick  ev ` α(Q) superset
        have x  ?S and y  ?S by (auto simp add: S'_def)
        with "4.prems"(3)[THEN doubleReverse, simplified] consider
          s' where s = rev (x # s') s' setinterleaves ((s_P, y # s_Q), ?S)
        | s' where s = rev (y # s') s' setinterleaves ((x # s_P, s_Q), ?S)
          by (simp split: if_split_asm) blast
        thus ?case
        proof cases
          fix s' assume s = rev (x # s') s' setinterleaves ((s_P, y # s_Q), ?S)
          from "4.hyps"(3)[OF x  ?S' y  ?S' rev s_P  𝒯 P rev (y # s_Q)  𝒯 Q
                              s' setinterleaves ((s_P, y # s_Q), ?S)[THEN doubleReverse]]
          have rev s' setinterleaves ((rev s_P, rev (y # s_Q)), ?S') .
          from this[THEN doubleReverse] x  ?S' y  ?S'
          have (x # s') setinterleaves ((x # s_P, y # s_Q), ?S') by simp
          from this[THEN doubleReverse] show ?case by (simp add: s = rev (x # s'))
        next
          fix s' assume s = rev (y # s') s' setinterleaves ((x # s_P, s_Q), ?S)
          from "4.hyps"(4)[OF x  ?S' y  ?S' rev (x # s_P)  𝒯 P rev s_Q  𝒯 Q
                              s' setinterleaves ((x # s_P, s_Q), ?S)[THEN doubleReverse]]
          have rev s' setinterleaves ((rev (x # s_P), rev s_Q), ?S') .
          from this[THEN doubleReverse] x  ?S' y  ?S'
          have (y # s') setinterleaves ((x # s_P, y # s_Q), ?S') by simp
          from this[THEN doubleReverse] show ?case by (simp add: s = rev (y # s'))
        qed
      qed
    qed
  
    from add_complementary_events_of_in_failure[OF assms(1)]
    have (rev s_P, ?X_P')   P .
    moreover from add_complementary_events_of_in_failure[OF assms(2)]
    have (rev s_Q, ?X_Q')   Q .
    ultimately have (s, (?X_P'  ?X_Q')  ?S'  ?X_P'  ?X_Q')   (P S' Q)
      using assms_3_bis by (simp add: F_Sync) blast
    moreover from superset have X  (?X_P'  ?X_Q')  ?S'  ?X_P'  ?X_Q'
      by (auto simp add: assms(4) S'_def image_iff)
    ultimately show (s, X)   (P S' Q) by (rule is_processT4)
  qed
qed

corollary Sync_is_Sync_restricted_events : P S Q = P S  (α(P)  α(Q)) Q
  by (simp add: Sync_is_Sync_restricted_superset_events)

text ‹This version is closer to the intuition that we may have, but the first one would be more
useful if we don't want to compute the events of a process but know a superset approximation.›


(* lemma Sync_with_SKIP_eq_itself_if_disjoint_events:
  ‹α(P) ∩ S = {} ⟹ P ⟦S⟧ SKIP r = P›
  oops
  by (metis Int_commute Inter_SKIP Sync_is_Sync_restricted_events events_Inter)

lemma Sync_with_STOP_eq_itself_Seq_STOP_if_disjoint_events:
  ‹α(P) ∩ S = {} ⟹ P ⟦S⟧ STOP = P ; (λr. STOP)›
  oops
  by (metis Int_Un_eq(3) Int_commute Inter_STOP_Seq_STOP Sync_is_Sync_restricted_events events_STOP) *)


corollary deadlock_free P  deadlock_free Q 
           S  (α(P)  α(Q)) = {}  deadlock_free (P S Q)
  by (subst Sync_is_Sync_restricted_events) (simp add: Inter_deadlock_free)
    (* but we already had this with data_independence_deadlock_free_Sync *)






text ‹This is a result similar to @{thm [source] Hiding_Mprefix_disjoint}
      when we add a @{const [source] Sliding} in the expression.›

theorem Hiding_Mprefix_Sliding_disjoint:
  ((a  A  P a)  Q) \ S = (a  A  (P a \ S))  (Q \ S)
  if disjoint: A  S = {}
proof (subst Hiding_Mprefix_disjoint[OF disjoint, symmetric])
  show ((a  A  P a)  Q) \ S = (a  A  P a \ S)  (Q \ S)
   (is ?lhs = ?rhs)
  proof (subst Process_eq_spec_optimized, safe)
    fix s
    assume s  𝒟 ?lhs
    hence s  𝒟 (Mprefix A P  Q \ S)
      by (simp add: D_Hiding D_Sliding D_Ndet T_Sliding T_Ndet)
    thus s  𝒟 ?rhs
      by (rule set_rev_mp) (simp add: D_Ndet D_Sliding Hiding_distrib_Ndet)
  next
    fix s
    assume s  𝒟 ?rhs
    hence s  𝒟 (Q \ S)  s  𝒟 (a  A  P a \ S)
      by (simp add: Hiding_Mprefix_disjoint[OF disjoint]
                    D_Ndet D_Sliding) blast
    thus s  𝒟 ?lhs
      by (auto simp add: D_Hiding D_Sliding T_Sliding)
  next
    fix s X
    assume same_div : 𝒟 ?lhs = 𝒟 ?rhs
    assume (s, X)   ?lhs
    then consider s  𝒟 ?lhs
      |t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   (Mprefix A P  Q)
      by (simp add: F_Hiding D_Hiding) blast
    thus (s, X)   ?rhs
    proof cases
      from same_div D_F show s  𝒟 ?lhs  (s, X)   ?rhs by blast
    next
      assume t. s = trace_hide t (ev ` S) 
                  (t, X  ev ` S)   (Mprefix A P  Q)
      then obtain t
        where * : s = trace_hide t (ev ` S)
                  (t, X  ev ` S)   (Mprefix A P  Q) by blast
      from "*"(2) consider (t, X  ev ` S)   Q
        | t  [] (t, X  ev ` S)   (Mprefix A P)
        by (simp add: F_Sliding D_Mprefix) blast
      thus (s, X)   ?rhs
      proof cases
        have (t, X  ev ` S)   Q  (s, X)   (Q \ S)
          by (auto simp add: F_Hiding "*"(1))
        thus (t, X  ev ` S)   Q  (s, X)   ?rhs
          by (simp add: F_Ndet F_Sliding "*"(1))
      next
        assume assms : t  [] (t, X  ev ` S)   (Mprefix A P)
        with disjoint have trace_hide t (ev ` S)  []
          by (cases t, auto simp add: F_Mprefix)
        also have (s, X)   (Mprefix A P \ S)
          using assms by (auto simp: F_Hiding "*"(1))
        ultimately show (s, X)   ?rhs
          by (simp add: F_Sliding "*"(1))
      qed
    qed
  next
    have * : t  𝒯 (Mprefix A P)  trace_hide t (ev ` S) = []  t = [] for t
      using disjoint by (cases t, auto simp add: T_Mprefix)
    have ** : []  𝒟 (Mprefix A P \ S)
      apply (rule ccontr, simp add: D_Hiding, elim exE conjE disjE)
      by (use "*" D_T Nil_notin_D_Mprefix in blast)
         (metis (no_types, lifting) "*" UNIV_I f_inv_into_f old.nat.distinct(2) strict_mono_on_eqD)
    fix s X
    assume same_div : 𝒟 ?lhs = 𝒟 ?rhs
    assume (s, X)   ?rhs
    with ** consider (s, X)   (Q \ S)
      | s  [] (s, X)   (Mprefix A P \ S)
      by (simp add: Hiding_Mprefix_disjoint[OF disjoint] F_Sliding D_Mprefix) blast
    thus (s, X)   ?lhs
    proof cases
      assume (s, X)   (Q \ S)
      then consider s  𝒟 (Q \ S)
        | t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   Q
        by (simp add: F_Hiding D_Hiding) blast
      thus (s, X)   ?lhs
      proof cases
        assume s  𝒟 (Q \ S)
        hence s  𝒟 ?rhs by (simp add: D_Ndet D_Sliding)
        with same_div D_F show (s, X)   ?lhs by blast
      next
        assume t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   Q
        thus (s, X)   ?lhs
          by (simp add: F_Hiding F_Sliding) blast
      qed
    next
      assume assms : s  [] (s, X)   (Mprefix A P \ S)
      then consider s  𝒟 (Mprefix A P \ S)
        | t. t  []  s = trace_hide t (ev ` S)  (t, X  ev ` S)   (Mprefix A P)
        by (simp add: F_Hiding D_Hiding) (metis filter.simps(1))
      thus (s, X)   ?lhs
      proof cases
        assume s  𝒟 (Mprefix A P \ S)
        hence s  𝒟 ?rhs by (simp add: D_Ndet D_Sliding)
        with same_div D_F show (s, X)   ?lhs by blast
      next
        show t. t  []  s = trace_hide t (ev ` S) 
                  (t, X  ev ` S)   (Mprefix A P)  (s, X)   ?lhs
          by (auto simp add: F_Sliding F_Hiding)
      qed
    qed
  qed
qed



subsection ‹Non-disjoint Sets›

― ‹Just a small lemma to understand why the nonempty hypothesis is necessary.›
lemma A :: nat set. P S.
       A  S = {}  a  A  P a \ S  
       (a  (A - S)  (P a \ S))  (a  (A  S). (P a \ S))
proof (intro exI)
  show {0}  {Suc 0} = {}  
        a  {0}  SKIP undefined \ {Suc 0}  
        (a  ({0} - {Suc 0})  (SKIP undefined \ {Suc 0}))  (a  ({0}  {Suc 0}). (SKIP undefined \ {Suc 0}))
    apply (simp add: write0_def[symmetric] Hiding_write0_disjoint)
    using UNIV_I list.discI by (auto simp add: Process_eq_spec write0_def F_Ndet
                                               F_Mprefix F_Sliding F_STOP set_eq_iff)
qed


text ‹This is a result similar to @{thm [source] Hiding_Mprefix_non_disjoint}
      when we add a @{const [source] Sliding} in the expression.›

lemma Hiding_Mprefix_Sliding_non_disjoint:
  (a  A  P a)  Q \ S = (a  (A - S)  (P a \ S))  
                              (Q \ S)  (a  (A  S). (P a \ S))
  if non_disjoint: A  S  {}
proof (subst Sliding_distrib_Ndet_left,
       subst Hiding_Mprefix_non_disjoint[OF non_disjoint, symmetric])
  show Mprefix A P  Q \ S =
        ((a  (A - S)  (P a \ S))  (Q \ S))  (a  A  P a \ S)
   (is ?lhs = ?rhs)
  proof (subst Process_eq_spec_optimized, safe)
    fix s
    assume s  𝒟 ?lhs
    hence s  𝒟 (Mprefix A P  Q \ S)
      by (simp add: D_Hiding D_Sliding D_Ndet T_Sliding T_Ndet)
    thus s  𝒟 ?rhs
      by (rule set_rev_mp)
         (simp add: D_Ndet D_Sliding Hiding_distrib_Ndet subsetI)
  next
    fix s
    assume s  𝒟 ?rhs
    hence s  𝒟 (Q \ S)  s  𝒟 (a  A  P a \ S)
      by (simp add: Hiding_Mprefix_non_disjoint[OF non_disjoint]
                    D_Ndet D_Sliding) blast
    thus s  𝒟 ?lhs
      by (auto simp add: D_Hiding D_Sliding T_Sliding)
  next
    fix s X
    assume same_div : 𝒟 ?lhs = 𝒟 ?rhs
    assume (s, X)   ?lhs
    then consider s  𝒟 ?lhs
      |t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   (Mprefix A P  Q)
      by (simp add: F_Hiding D_Hiding) blast
    thus (s, X)   ?rhs
    proof cases
      from same_div D_F show s  𝒟 ?lhs  (s, X)   ?rhs by blast
    next
      assume t. s = trace_hide t (ev ` S) 
                  (t, X  ev ` S)   (Mprefix A P  Q)
      then obtain t
        where * : s = trace_hide t (ev ` S)
                  (t, X  ev ` S)   (Mprefix A P  Q) by blast
      from "*"(2) consider (t, X  ev ` S)   Q
        | (t, X  ev ` S)   (Mprefix A P)
        by (simp add: F_Sliding D_Mprefix) blast
      thus (s, X)   ?rhs
      proof cases
        have (t, X  ev ` S)   Q  (s, X)   (Q \ S)
          by (auto simp add: F_Hiding "*"(1))
        thus (t, X  ev ` S)   Q  (s, X)   ?rhs
          by (simp add: F_Ndet F_Sliding "*"(1))
      next
        assume (t, X  ev ` S)   (Mprefix A P)
        hence (s, X)   (Mprefix A P \ S) by (auto simp: F_Hiding "*"(1))
        thus (s, X)   ?rhs by (simp add: F_Ndet "*"(1))
      qed
    qed
  next
    fix s X
    have * : s  []  (s, X)   (a  (A - S)  (P a \ S))  
                          (s, X)   (a  A  P a \ S)
      by (simp add: Hiding_Mprefix_non_disjoint[OF non_disjoint] F_Sliding)
    assume same_div : 𝒟 ?lhs = 𝒟 ?rhs
    assume (s, X)   ?rhs
    with "*" consider (s, X)   (Q \ S) | (s, X)   (Mprefix A P \ S)
      by (auto simp add: F_Ndet F_Sliding)
    thus (s, X)   ?lhs
    proof cases
      assume (s, X)   (Q \ S)
      then consider s  𝒟 (Q \ S)
        | t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   Q
        by (simp add: F_Hiding D_Hiding) blast
      thus (s, X)   ?lhs
      proof cases
        assume s  𝒟 (Q \ S)
        hence s  𝒟 ?rhs by (simp add: D_Ndet D_Sliding)
        with same_div D_F show (s, X)   ?lhs by blast
      next
        assume t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   Q
        thus (s, X)   ?lhs
          by (simp add: F_Hiding F_Sliding) blast
      qed
    next
      assume (s, X)   (Mprefix A P \ S)
      then consider s  𝒟 (Mprefix A P \ S)
        | t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   (Mprefix A P)
        by (simp add: F_Hiding D_Hiding) blast
      thus (s, X)   ?lhs
      proof cases
        assume s  𝒟 (Mprefix A P \ S)
        hence s  𝒟 ?rhs by (simp add: D_Ndet D_Sliding)
        with same_div D_F show (s, X)   ?lhs by blast
      next
        assume t. s = trace_hide t (ev ` S)  (t, X  ev ` S)   (Mprefix A P)
        then obtain t where * : s = trace_hide t (ev ` S)
                                (t, X  ev ` S)   (Mprefix A P) by blast
        from "*"(2) non_disjoint have t  [] by (simp add: F_Mprefix) blast
        with "*" show (s, X)   ?lhs
          by (simp add: F_Hiding F_Sliding) blast
      qed
    qed
  qed
qed
       


section constSliding behaviour›

text ‹We already proved several laws for the constSliding operator.
      Here we give other results in the same spirit as
      @{thm [source] Hiding_Mprefix_Sliding_disjoint} and
      @{thm [source] Hiding_Mprefix_Sliding_non_disjoint}.›

lemma Mprefix_Sliding_Mprefix_Sliding:
  (a  A  P a)  (b  B  Q b)  R =
   ( x  (A  B)  (if x  A  B then P x  Q x else if x  A then P x else Q x))  R
  (is (a  A  P a)  (b  B  Q b)  R = ?term  R)
proof (subst Sliding_def, subst Mprefix_Det_Mprefix)
  have Mprefix B Q  (Mprefix A P  Mprefix B Q)  R = Mprefix A P  Mprefix B Q  R
    by (metis (no_types, opaque_lifting) Det_assoc Det_commute Ndet_commute
              Ndet_distrib_Det_left Ndet_id Sliding_Det Sliding_assoc Sliding_def)
  thus ?term  Mprefix B Q  R = ?term  R
    by (simp add: Mprefix_Det_Mprefix Ndet_commute)
qed


lemma Mprefix_Sliding_Seq: 
  (a  A  P a)  P' ; Q = (a  A  (P a ; Q))  (P' ; Q)
proof (subst Mprefix_Seq[symmetric])
  show ((a  A  P a)  P') ; Q = 
        ((a  A  P a) ; Q)  (P' ; Q) (is ?lhs = ?rhs)
  proof (subst Process_eq_spec, safe)
    show s  𝒟 ?lhs  s  𝒟 ?rhs for s
      by (simp add: D_Sliding D_Seq T_Sliding) blast
  next
    show s  𝒟 ?rhs  s  𝒟 ?lhs for s
      by (auto simp add: D_Sliding D_Seq T_Sliding)
  next
    show (s, X)   ?lhs  (s, X)   ?rhs for s X
      by (cases s; simp add: F_Sliding D_Sliding T_Sliding F_Seq) metis
  next
    show (s, X)   ?rhs  (s, X)   ?lhs for s X
      by (cases s; simp add: F_Sliding D_Sliding T_Sliding
                             F_Seq D_Seq T_Seq D_Mprefix T_Mprefix)
         (metis eventptick.simps(4) hd_append list.sel(1), blast)
  qed
qed



lemma Throw_Sliding :
  (a  A  P a)  P' Θ b  B. Q b = 
   (a  A  (if a  B then Q a else P a Θ b  B. Q b))  (P' Θ b  B. Q b)
  (is ?lhs = ?rhs)
proof (subst Process_eq_spec_optimized, safe)
  fix s
  assume s  𝒟 ?lhs
  then consider t1 t2 where s = t1 @ t2 t1  𝒟 (Mprefix A P  P')
                            tF t1 set t1  ev ` B = {} ftF t2
    | t1 b t2 where s = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (Mprefix A P  P')
                    set t1  ev ` B = {} b  B t2  𝒟 (Q b)
    by (simp add: D_Throw) blast
  thus s  𝒟 ?rhs
  proof cases
    fix t1 t2 assume * : s = t1 @ t2 t1  𝒟 (Mprefix A P  P') tF t1
                         set t1  ev ` B = {} ftF t2
    from "*"(2) consider t1  𝒟 (Mprefix A P) | t1  𝒟 P'
      by (simp add: D_Sliding) blast
    thus s  𝒟 ?rhs
    proof cases
      assume t1  𝒟 (Mprefix A P)
      then obtain a t1' where t1 = ev a # t1' a  A t1'  𝒟 (P a)
        by (auto simp add: D_Mprefix image_iff)
      with "*"(1, 3, 4, 5) show s  𝒟 ?rhs
        by (simp add: D_Sliding D_Mprefix D_Throw) (metis image_eqI)
    next
      from "*"(1, 3, 4, 5)  show t1  𝒟 P'  s  𝒟 ?rhs
        by (simp add: D_Sliding D_Throw) blast
    qed
  next
    fix t1 b t2 assume * : s = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (Mprefix A P  P')
                           set t1  ev ` B = {} b  B t2  𝒟 (Q b)
    from "*"(2) consider t1 @ [ev b]  𝒯 (Mprefix A P) | t1 @ [ev b]  𝒯 P'
      by (simp add: T_Sliding) blast
    thus s  𝒟 ?rhs
    proof cases
      assume t1 @ [ev b]  𝒯 (Mprefix A P)
      then obtain a t1'
        where t1 @ [ev b] = ev a # t1' a  A t1'  𝒯 (P a)
        by (auto simp add: T_Mprefix)
      with "*"(1, 3-5) show s  𝒟 ?rhs
        by (cases t1; simp add: "*"(1) D_Sliding D_Mprefix D_Throw)
           (metis image_eqI)
    next
      from "*"(1, 3-5) show t1 @ [ev b]  𝒯 P'  s  𝒟 ?rhs
        by (simp add: D_Sliding D_Mprefix D_Throw) blast
    qed
  qed
next
  fix s
  assume s  𝒟 ?rhs
  then consider s  𝒟 (Throw P' B Q)
    | s  𝒟 (aA  (if a  B then Q a else Throw (P a) B Q))
    by (simp add: D_Sliding) blast
  thus s  𝒟 ?lhs
  proof cases
    show s  𝒟 (Throw P' B Q)  s  𝒟 ?lhs
      by (simp add: D_Throw D_Sliding T_Sliding) blast
  next
    assume s  𝒟 (aA  (if a  B then Q a else Throw (P a) B Q))
    then obtain a s' 
      where * : s = ev a # s' a  A
                s'  𝒟 (if a  B then Q a else Throw (P a) B Q)
      by (cases s; simp add: D_Mprefix) blast
    show s  𝒟 ?lhs
    proof (cases a  B)
      from "*" show a  B  s  𝒟 ?lhs
        by (simp add: D_Throw T_Sliding T_Mprefix disjoint_iff)
           (metis Nil_elem_T emptyE empty_set self_append_conv2)
    next
      assume a  B
      with "*"(3) consider 
        t1 t2 where s' = t1 @ t2 t1  𝒟 (P a) tF t1
                    set t1  ev ` B = {} ftF t2
        | t1 b t2 where s' = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (P a)
                        set t1  ev ` B = {} b  B t2  𝒟 (Q b)
        by (simp add: D_Throw) blast
      thus s  𝒟 ?lhs
      proof cases
        fix t1 t2 assume ** : s' = t1 @ t2 t1  𝒟 (P a) tF t1
                              set t1  ev ` B = {} ftF t2
        have *** : s = (ev a # t1) @ t2  set (ev a # t1)  ev ` B = {}
          by (simp add: "*"(1) "**"(1, 4) image_iff a  B)
        from "*" "**"(1, 2, 3, 5) show s  𝒟 ?lhs
          by (simp add: D_Throw D_Sliding D_Mprefix image_iff)
             (metis "***" eventptick.disc(1) tickFree_Cons_iff)
      next
        fix t1 b t2 assume ** : s' = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (P a)
                                set t1  ev ` B = {} b  B t2  𝒟 (Q b)
        have *** : s = (ev a # t1 @ [ev b]) @ t2  set (ev a # t1)  ev ` B = {}
          by (simp add: "*"(1) "**"(1, 3) image_iff a  B)
        from "*" "**"(1, 2, 4, 5) show s  𝒟 ?lhs
          by (simp add: D_Throw T_Sliding T_Mprefix) (metis "***" Cons_eq_appendI)
      qed
    qed
  qed
next
  fix s X
  assume same_div : 𝒟 ?lhs = 𝒟 ?rhs
  assume (s, X)   ?lhs
  then consider s  𝒟 ?lhs
    | (s, X)   (Mprefix A P  P') set s  ev ` B = {}
    | t1 b t2 where s = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (Mprefix A P  P')
                    set t1  ev ` B = {} b  B (t2, X)   (Q b)
    by (auto simp add: F_Throw D_Throw)
  thus (s, X)   ?rhs
  proof cases
    from same_div D_F show s  𝒟 ?lhs  (s, X)   ?rhs by blast
  next
    show (s, X)   (Mprefix A P  P')  set s  ev ` B = {}  (s, X)   ?rhs
      by (cases s; simp add: F_Sliding F_Mprefix F_Throw) blast
  next
    fix t1 b t2 assume * : s = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (Mprefix A P  P')
                           set t1  ev ` B = {} b  B (t2, X)   (Q b)
    from "*"(2) consider t1 @ [ev b]  𝒯 (Mprefix A P) | t1 @ [ev b]  𝒯 P'
      by (simp add: T_Sliding) blast
    thus (s, X)   ?rhs
    proof cases
      assume t1 @ [ev b]  𝒯 (Mprefix A P)
      then obtain a t1'
        where t1 @ [ev b] = ev a # t1' a  A t1'  𝒯 (P a)
        by (auto simp add: T_Mprefix)
      with "*"(1, 3, 4, 5) show (s, X)   ?rhs
        by (cases t1; simp add: "*"(1) F_Sliding F_Mprefix F_Throw) blast
    next
      from "*"(1, 3, 4, 5) show t1 @ [ev b]  𝒯 P'  (s, X)   ?rhs
        by (simp add: F_Sliding F_Mprefix F_Throw) blast
    qed
  qed
next
  fix s X
  assume same_div : 𝒟 ?lhs = 𝒟 ?rhs
  assume (s, X)   ?rhs
  then consider s  𝒟 ?rhs | (s, X)   (Throw P' B Q)
    | s  [] (s, X)   (a  A  (if a  B then Q a else Throw (P a) B Q))
    by (simp add: F_Sliding D_Sliding) blast
  thus (s, X)   ?lhs
  proof cases
    from same_div D_F show s  𝒟 ?rhs  (s, X)   ?lhs by blast
  next
    show (s, X)   (Throw P' B Q)  (s, X)   ?lhs
      by (simp add: F_Throw F_Sliding D_Sliding T_Sliding) blast
  next
    assume s  [] (s, X)   (a  A  (if a  B then Q a else Throw (P a) B Q))
    then obtain a s'
      where * : s = ev a # s' a  A 
                (s', X)   (if a  B then Q a else Throw (P a) B Q)
      by (auto simp add: F_Mprefix image_iff)
    show (s, X)   ?lhs
    proof (cases a  B)
      assume a  B
      have [ev a]  𝒯 (Mprefix A P  P')
        by (simp add: T_Sliding T_Mprefix "*"(2))
      with "*"(1, 3) a  B show (s, X)   ?lhs
        by (simp add: F_Throw) (metis append_Nil empty_set inf_bot_left)
    next
      assume a  B
      with "*"(3) consider s'  𝒟 (Throw (P a) B Q)
        | (s', X)   (P a) set s'  ev ` B = {}
        | t1 b t2 where s' = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (P a)
                        set t1  ev ` B = {} b  B (t2, X)   (Q b)
        by (auto simp add: F_Throw D_Throw)
      thus (s, X)   ?lhs
      proof cases
        assume s'  𝒟 (Throw (P a) B Q)
        hence s  𝒟 ?rhs by (simp add: "*"(1, 2) D_Sliding D_Mprefix a  B)
        with same_div D_F show (s, X)   ?lhs by blast
      next
        show (s', X)   (P a)  set s'  ev ` B = {}  (s, X)   ?lhs
          using "*"(1, 2) a  B by (simp add: F_Throw F_Sliding F_Mprefix) blast
      next
        fix t1 b t2 assume ** : s' = t1 @ ev b # t2 t1 @ [ev b]  𝒯 (P a)
                                set t1  ev ` B = {} b  B (t2, X)   (Q b)
        from "**" have *** : (ev a # t1) @ [ev b]  𝒯 (Mprefix A P)  
                              set (ev a # t1)  ev ` B = {}
          by (simp add: T_Mprefix "*"(2) image_iff a  B)
        from "*"(1) "**"(1, 4, 5) "**"(5) show (s, X)   ?lhs
          by (simp add: F_Throw T_Sliding) (metis "***" Cons_eq_appendI)
      qed
    qed
  qed
qed



section ‹Dealing with constSKIP

lemma Renaming_Mprefix_Det_SKIP:
  Renaming (( a  A  P a)  SKIP r) f g =
   (yf ` A   a  {x  A. y = f x}. Renaming (P a) f g)  SKIP (g r)
  by (simp add: Renaming_Det Renaming_Mprefix)


lemma Mprefix_Sliding_SKIP_Seq: (( a  A  P a)  SKIP r) ; Q = ( a  A  (P a ; Q))  Q
  (* TODO: see if we leave Sliding_SKIP in simp *)
  by (simp del: Sliding_SKIP add: Mprefix_Sliding_Seq)

lemma Mprefix_Det_SKIP_Seq: (( a  A  P a)  SKIP r) ; Q = ( a  A  (P a ; Q))  Q
  by (fold Sliding_SKIP) (fact Mprefix_Sliding_SKIP_Seq)


lemma Sliding_Ndet_pseudo_assoc : (P  Q)  R = P  Q  R
  by (metis Ndet_assoc Ndet_distrib_Det_right Ndet_id Sliding_def)

lemma Hiding_Mprefix_Det_SKIP:
  ( a  A  P a)  SKIP r \ S =
   (if A  S = {} then ( a  A  (P a \ S))  SKIP r
    else (( a  (A - S)  (P a \ S))  SKIP r)  ( a  (A  S). (P a \ S)))
  by (fold Sliding_SKIP)
     (simp del: Sliding_SKIP add: Hiding_Mprefix_Sliding_disjoint
           Hiding_Mprefix_Sliding_non_disjoint Sliding_Ndet_pseudo_assoc)


lemma s  []  (s, X)   (P  Q)  (s, X)   (P  Q)
  by (simp add: F_Det F_Ndet)


lemma Mprefix_Det_SKIP_Sync_SKIP :
  (( a  A  P a)  SKIP res) S SKIP res' = 
   (if res = res' then ( a  (A - S)  (P a S SKIP res'))  SKIP res'
    else ( a  (A - S)  (P a S SKIP res'))  STOP)
  (is ?lhs = (if res = res' then ?rhs1 else ?rhs2))
proof (subst Process_eq_spec_optimized, safe)
  fix s
  assume s  𝒟 ?lhs
  then obtain a t u r v
    where * : ftF v tF r  v = [] s = r @ v
              r setinterleaves ((ev a # t, u), range tick  ev ` S)
              a  A t  𝒟 (P a) u  𝒯 (SKIP res')
    by (simp add: D_Sync D_SKIP D_Det D_Mprefix T_SKIP image_iff) blast
  from "*"(3, 4, 5, 7) have ** : a  A - S s = ev a # tl r @ v
                                 tl r setinterleaves ((t, u), range tick  ev ` S)
    by (auto simp add: image_iff T_SKIP split: if_split_asm)
  have tl s  𝒟 (P a S SKIP res')
    by (simp add: D_Sync)
       (metis "*"(1, 2, 6, 7) "**"(2, 3) list.sel(3) tickFree_tl)
  with "**"(1) show s  𝒟 (if res = res' then ?rhs1 else ?rhs2)
    by (simp add: D_Det D_Ndet D_Mprefix "**"(2))
next
  fix s
  assume s  𝒟 (if res = res' then ?rhs1 else ?rhs2)
  then obtain a s' where * : s = ev a # s' a  A - S s'  𝒟 (P a S SKIP res')
    by (auto simp add: D_Det D_Ndet D_SKIP D_STOP D_Mprefix image_iff split: if_split_asm)
  then obtain t u r v
    where ** : ftF v tF r  v = [] s' = r @ v
               r setinterleaves ((t, u), range tick  ev ` S)
               t  𝒟 (P a) u  𝒯 (SKIP res')
    by (simp add: D_Sync D_SKIP) blast
  have (ev a # r) setinterleaves ((ev a # t, u), range tick  ev ` S)
    using "*"(2) "**"(4, 6) by (auto simp add: T_SKIP)
  with "*"(2) "**"(1, 2, 3, 5, 6) show s  𝒟 ?lhs
    by (simp add: D_Sync D_SKIP D_Det D_Mprefix T_SKIP image_iff)
       (metis (no_types, opaque_lifting) "*"(1) Cons_eq_appendI eventptick.disc(1) tickFree_Cons_iff)
next
  fix s Z
  assume same_div : 𝒟 ?lhs = 𝒟 (if res = res' then ?rhs1 else ?rhs2)
  assume (s, Z)   ?lhs
  then consider s  𝒟 ?lhs
    | t u X Y where (t, X)   (Mprefix A P  SKIP res) (u, Y)   (SKIP res')
                    s setinterleaves ((t, u), range tick  ev ` S)
                    Z = (X  Y)  (range tick  ev ` S)  X  Y
    by (simp add: F_Sync D_Sync) blast
  thus (s, Z)   (if res = res' then ?rhs1 else ?rhs2)
  proof cases
    from same_div D_F show s  𝒟 ?lhs  (s, Z)   (if res = res' then ?rhs1 else ?rhs2) by blast
  next
    fix t u X Y
    assume * : (t, X)   (Mprefix A P  SKIP res) (u, Y)   (SKIP res')
               s setinterleaves ((t, u), range tick  ev ` S)
               Z = (X  Y)  (range tick  ev ` S)  X  Y    
    from "*"(1) consider t = [] | t = [✓(res)] | a t' where t = ev a # t'
      by (auto simp add: F_Det F_SKIP F_Mprefix)
    thus (s, Z)   (if res = res' then ?rhs1 else ?rhs2)
    proof cases
      assume t = []
      with "*"(2, 3) have s = [] by (auto simp add: F_SKIP)
      with t = [] "*"(3)[simplified t = [], THEN emptyLeftProperty] "*"(1, 2, 3, 4)
      show (s, Z)   (if res = res' then ?rhs1 else ?rhs2)
        by (auto simp add: F_Det F_Ndet F_Mprefix F_STOP F_SKIP D_SKIP T_SKIP)
    next
      assume t = [✓(res)]
      with "*"(2, 3) have res' = res  s = [✓(res)]
        by (cases u; auto simp add: F_SKIP split: if_split_asm)
      with t = [✓(res)] show (s, Z)   (if res = res' then ?rhs1 else ?rhs2)
        by (simp add: F_Det F_Ndet F_STOP F_SKIP)      
    next
      fix a t' assume t = ev a # t'
      with "*"(1, 2, 3) empty_setinterleaving obtain s'
        where ** : s' setinterleaves ((t', u), range tick  ev ` S)
                   s = ev a # s' (t', X)   (P a) a  A - S
        by (auto simp add: F_SKIP F_Det F_Mprefix image_iff split: if_split_asm)
      from "*"(2, 4) "**"(1, 3) have (s', Z)   (P a S SKIP res')
        by (simp add: F_Sync) blast  
      with "**"(4) show (s, Z)   (if res = res' then ?rhs1 else ?rhs2)
        by (simp add: F_Det F_Ndet s = ev a # s' F_SKIP F_Mprefix)
    qed
  qed
next
  fix s Z
  assume same_div : 𝒟 ?lhs = 𝒟 (if res = res' then ?rhs1 else ?rhs2)
  assume (s, Z)   (if res = res' then ?rhs1 else ?rhs2)
  then consider res = res' (s, Z)   ?rhs1
    | res  res' (s, Z)   ?rhs2 by presburger
  thus (s, Z)   ?lhs
  proof cases
    assume res = res' (s, Z)   ?rhs1
    then consider s = [] | s = [✓(res')] | a s' where s = ev a # s'
      by (auto simp add: F_Det F_SKIP F_Mprefix)
    thus (s, Z)   ?lhs
    proof cases
      assume s = []
      with (s, Z)   ?rhs1 have tick res'  Z
        by (auto simp add: F_Det F_Mprefix F_SKIP D_SKIP T_SKIP)
      with s = [] show (s, Z)   ?lhs
        by (simp add: F_Sync F_Det T_SKIP F_SKIP res = res')
           (metis Int_Un_eq(3) si_empty1 Un_Int_eq(4) Un_commute insertI1)
    next
      assume s = [✓(res')]
      hence * : ([✓(res')], Z)   (Mprefix A P  SKIP res')  
                 s setinterleaves (([✓(res')], [✓(res')]), range tick  ev ` S)  
                 ([✓(res')], Z)   (SKIP res')  Z = (Z  Z)  (range tick  ev ` S)  Z  Z
        by (simp add: F_Det F_SKIP)
      show (s, Z)   ?lhs by (simp add: F_Sync res = res') (meson "*")
    next
      fix a s' assume s = ev a # s'
      with (s, Z)   ?rhs1 have * : a  A a  S (s', Z)   (P a S SKIP res')
        by (simp_all add: F_Det F_SKIP F_Mprefix image_iff)
      from "*"(3) consider s'  𝒟 (P a S SKIP res')
        | t u X Y where (t, X)   (P a) (u, Y)   (SKIP res')
                        s' setinterleaves ((t, u), range tick  ev ` S)
                        Z = (X  Y)  (range tick  ev ` S)  X  Y
        by (simp add: F_Sync D_Sync) blast
      thus (s, Z)   ?lhs
      proof cases
        assume s'  𝒟 (P a S SKIP res')
        hence s  𝒟 ?rhs1
          by (simp add: D_Det D_Mprefix image_iff "*"(1, 2) s = ev a # s')
        with same_div show (s, Z)   ?lhs by (simp add: res = res' is_processT8)
      next
        fix t u X Y assume ** : (t, X)   (P a) (u, Y)   (SKIP res')
                                s' setinterleaves ((t, u), range tick  ev ` S)
                                Z = (X  Y)  (range tick  ev ` S)  X  Y
        from "**"(2, 3) have (ev a # s') setinterleaves ((ev a # t, u), range tick  ev ` S)
          by (auto simp add: "*"(1, 2) F_SKIP image_iff)
        thus (s, Z)   ?lhs
          by (simp add: F_Sync F_Det F_Mprefix image_iff)
             (metis "*"(1) "**"(1, 2, 4) s = ev a # s' list.distinct(1))
      qed
    qed
  next
    assume res  res' (s, Z)   ?rhs2
    then consider s = []
      | a s' where a  A a  S s = ev a # s' (s', Z)   (P a S SKIP res')
      by (auto simp add: F_Ndet F_STOP F_Mprefix)
    thus (s, Z)   ?lhs
    proof cases
      have ([], UNIV)   ?lhs
        apply (simp add: F_Sync, rule disjI1)
        apply (rule_tac x = [] in exI, simp add: F_Det F_Mprefix F_SKIP T_SKIP D_SKIP)
        apply (rule_tac x = [] in exI, rule_tac x = UNIV - {✓(res)} in exI)
        apply (simp, rule_tac x = UNIV - {✓(res')} in exI)
        using res  res' by auto
      thus s = []  (s, Z)   ?lhs by (auto intro: is_processT4)
    next
      fix a s' assume * : a  A a  S s = ev a # s' (s', Z)   (P a S SKIP res')
      from "*"(4) consider s'  𝒟 (P a S SKIP res')
        | t u X Y where (t, X)   (P a) (u, Y)   (SKIP res')
                        s' setinterleaves ((t, u), range tick  ev ` S)
                        Z = (X  Y)  (range tick  ev ` S)  X  Y
        by (auto simp add: F_Sync D_Sync)
      thus (s, Z)   ?lhs
      proof cases
        assume s'  𝒟 (P a S SKIP res')
        hence s  𝒟 ?rhs2 by (simp add: "*"(1, 2, 3) D_Ndet D_Mprefix)
        with same_div show (s, Z)   ?lhs by (simp add: res  res' is_processT8)
      next
        fix t u X Y assume ** : (t, X)   (P a) (u, Y)   (SKIP res')
                                s' setinterleaves ((t, u), range tick  ev ` S)
                                Z = (X  Y)  (range tick  ev ` S)  X  Y
        show (s, Z)   ?lhs
          apply (simp add: F_Sync, rule disjI1)
          apply (rule_tac x = ev a # t in exI)
          apply (rule_tac x = u in exI)
          apply (rule_tac x = X in exI)
          apply (rule conjI, solves simp add: F_Det F_Mprefix "*"(1) "**"(1))
          apply (rule_tac x = Y in exI)
          apply (simp add: "**"(2, 4))
          using "**"(2, 3) by (auto simp add: "*"(1, 2, 3) F_SKIP)
      qed
    qed
  qed
qed


lemma Sliding_def_bis : P  Q = (P  Q)  Q
  by (simp add: Det_distrib_Ndet_right Sliding_def)





section ‹Powerful Results about constHiding

theorem Hiding_is_Hiding_restricted_superset_events:
  fixes S :: 'a set and P :: ('a, 'r) processptick
  assumes superset : α(P)  A
  defines S'  S  A
  shows P \ S = P \ S'
proof -
  have set_trace_subset : t  𝒯 P  set t  range tick  ev ` α(P) for t
    by (simp add: events_of_def subset_iff image_iff) (metis eventptick.exhaust)
  moreover from superset
  have set t  range tick  ev ` α(P) 
        trace_hide t (ev ` S) = trace_hide t (ev ` S') for t :: ('a, 'r) traceptick
    by (induct t) (auto simp add: S'_def image_iff subset_iff)
  ultimately have same_trace_hide :
    t  𝒯 P  trace_hide t (ev ` S) = trace_hide t (ev ` S') for t by blast

  have isInfHidden_seqRun_strong x P S t  seqRun t x i  𝒯 P for x t S i by simp
  from this[THEN set_trace_subset]
  have isInfHidden_seqRun_strong x P S t  x i  ev ` α(P) for x t S i
    by (simp add: seqRun_def subset_iff image_iff)
      (metis atLeastLessThan_iff eventptick.simps(4) le0 lessI)
  moreover have isInfHidden_seqRun_strong x P S t 
                 trace_hide t (ev ` S) = trace_hide t (ev ` S') for x t
    by (metis same_trace_hide seqRun_0)
  ultimately have IH_strong_iff :
    isInfHidden_seqRun_strong x P S t  isInfHidden_seqRun_strong x P S' t for x t
    by (safe, auto simp add: S'_def)
      (metis (no_types, lifting) ext S'_def lessI same_trace_hide trace_hide_seqRun_eq_iff)

  show P \ S = P \ S'
  proof (subst Process_eq_spec_optimized, safe)
    show t  𝒟 (P \ S)  t  𝒟 (P \ S') for t
    proof (elim D_Hiding_seqRunE disjE exE)
      fix u v assume ftF v tF u t = trace_hide u (ev ` S) @ v u  𝒟 P
      from u  𝒟 P D_T same_trace_hide
      have trace_hide u (ev ` S) = trace_hide u (ev ` S') by blast
      with ftF v tF u u  𝒟 P t = trace_hide u (ev ` S) @ v
      show t  𝒟 (P \ S') unfolding D_Hiding by blast
    next
      fix u v x assume ftF v tF u t = trace_hide u (ev ` S) @ v
        and IH_strong : isInfHidden_seqRun_strong x P S u
      have trace_hide u (ev ` S) = trace_hide u (ev ` S')
        by (metis IH_strong same_trace_hide seqRun_0)
      moreover from IH_strong have isInfHidden_seqRun_strong x P S' u
        by (simp add: IH_strong_iff)
      ultimately show t  𝒟 (P \ S')
        using ftF v tF u t = trace_hide u (ev ` S) @ v
        by (blast intro: D_Hiding_seqRunI)
    qed
  next
    show t  𝒟 (P \ S')  t  𝒟 (P \ S) for t
    proof (elim D_Hiding_seqRunE disjE exE)
      fix u v assume ftF v tF u t = trace_hide u (ev ` S') @ v u  𝒟 P
      from u  𝒟 P D_T same_trace_hide
      have trace_hide u (ev ` S') = trace_hide u (ev ` S) by metis
      with ftF v tF u u  𝒟 P t = trace_hide u (ev ` S') @ v
      show t  𝒟 (P \ S) unfolding D_Hiding by blast
    next
      fix u v x assume ftF v tF u t = trace_hide u (ev ` S') @ v
        and IH_strong : isInfHidden_seqRun_strong x P S' u
      have trace_hide u (ev ` S') = trace_hide u (ev ` S)
        by (metis IH_strong same_trace_hide seqRun_0)
      moreover from IH_strong have isInfHidden_seqRun_strong x P S u
        by (simp flip: IH_strong_iff)
      ultimately show t  𝒟 (P \ S)
        using ftF v tF u t = trace_hide u (ev ` S') @ v
        by (blast intro: D_Hiding_seqRunI)
    qed
  next
    fix t X assume same_div : 𝒟 (P \ S) = 𝒟 (P \ S')
    assume (t, X)   (P \ S)
    then consider t  𝒟 (P \ S)
      | u where t = trace_hide u (ev ` S) (u, X  ev ` S)   P
      unfolding F_Hiding D_Hiding by blast
    thus (t, X)   (P \ S')
    proof cases
      from same_div D_F show t  𝒟 (P \ S)  (t, X)   (P \ S') by blast
    next
      fix u assume t = trace_hide u (ev ` S) (u, X  ev ` S)   P
      with F_T same_trace_hide have t = trace_hide u (ev ` S') by blast
      moreover have (u, X  ev ` S')   P
      proof (rule is_processT4)
        show (u, X  ev ` S)   P by (fact (u, X  ev ` S)   P)
      next
        show X  ev ` S'  X  ev ` S unfolding S'_def by blast
      qed
      ultimately show (t, X)   (P \ S') unfolding F_Hiding by blast
    qed
  next
    fix t X assume same_div : 𝒟 (P \ S) = 𝒟 (P \ S')
    assume (t, X)   (P \ S')
    then consider t  𝒟 (P \ S')
      | u where t = trace_hide u (ev ` S') (u, X  ev ` S')   P
      unfolding F_Hiding D_Hiding by blast
    thus (t, X)   (P \ S)
    proof cases
      from same_div D_F show t  𝒟 (P \ S')  (t, X)   (P \ S) by blast
    next
      fix u assume t = trace_hide u (ev ` S') (u, X  ev ` S')   P
      with F_T same_trace_hide have t = trace_hide u (ev ` S) by metis
      moreover have (u, X  ev ` S)   P
      proof (rule is_processT4[OF add_complementary_events_of_in_failure])
        show (u, X  ev ` S')   P by (fact (u, X  ev ` S')   P)
      next
        from superset show X  ev ` S  X  ev ` S'  ev ` (- α(P))
          unfolding S'_def by blast
      qed
      ultimately show (t, X)   (P \ S) unfolding F_Hiding by blast
    qed
  qed
qed




corollary Hiding_is_Hiding_restricted_events : P \ S = P \ S  α(P)
  by (simp add: Hiding_is_Hiding_restricted_superset_events)

text ‹This version is closer to the intuition that we may have, but the first one would be more
useful if we don't want to compute the events of a process but know a superset approximation.›



(*<*)
end 
(*>*)