Thm*  E:EventStruct, P:((Label  (|E| List))  Prop).
( f,g:(Label  (|E| List)). ( p:Label. g(p)   f(p))    P(f)    P(g))    
( f,g:(Label  (|E| List)).
 ( a:|E|.  p:Label. g(p) = filter( b.  (b =msg=(E) a);f(p)))    P(f)    P(g))
  
( f,g,h:(Label  (|E| List)).
 ( p,q:Label. ( x f(p).( y g(q). (x =msg=(E) y))))    
 ( p:Label. h(p) = ((f(p)) @ (g(p))))    P(f)    P(g)    P(h))
  
switchable0(E)(local_deliver_property(E;P)) | [local_deliver_switchable] | 
 Thm*  E:EventStruct, P:TraceProperty(E), L,L1:|E| List.
memorylessR(E) preserves P    P(L)    P((L -x =msg=(E) y L1)) | [memoryless_remove_msgs] | 
 Thm*  E:EventStruct, tr:|E| List.
No-dup-deliver(E)(tr)
  
( x,y:|E|.
  is-send(E)(x)    
  is-send(E)(y)    (y =msg=(E) x)    loc(E)(x) = loc(E)(y)     sublist(|E|;[x; y];tr)) | [P_no_dup_iff] | 
 Thm*  E:EventStruct, tr:|E| List.
Causal(E)(tr)    ( tr':|E| List. tr'   tr    ( x tr'.( y tr'.is-send(E)(y)  &  (y =msg=(E) x)))) | [P_causal_iff] | 
 Def delayableR(E)
== swap adjacent[  (x =msg=(E) y)
  &    (is-send(E)(x))  &   (is-send(E)(y))    (is-send(E)(x))  &    (is-send(E)(y))] | [R_delayable] | 
 Def AD-normal(E)(tr)
==  i: (||tr||-1). 
 ( (is-send(E)(tr[i]))      (is-send(E)(tr[(i+1)]))     (tr[i] =msg=(E) tr[(i+1)]))
  &  (( x,y: ||tr||.
 x < y
  &   (is-send(E)(tr[x]))
  &   (is-send(E)(tr[y]))
  &  tr[x] delivered at time i+1
  &  tr[y] delivered at time i)
   
 loc(E)(tr[i]) = loc(E)(tr[(i+1)])) | [switch_normal] | 
 Def Macro
 x R_del(E) y
 ==   (x =msg=(E) y)
  &  is-deliver(E)(x)  &   (is-send(E)(y))    (is-send(E)(x))  &  is-deliver(E)(y) | [R_del] | 
 Def memorylessR(E)(L_1,L_2)
==  a:|E|. L_2 = filter( b.  (b =msg=(E) a);L_1)   |E| List | [R_memoryless] | 
 Def composableR(E)(L_1,L_2,L)
== ( x L_1.( y L_2.  (x =msg=(E) y)))  &  L = (L_1 @ L_2)   |E| List | [R_composable] | 
 Def R_ad_normal(tr)(a,b)
== ( (is-send(E)(a))      (is-send(E)(b))     (a =msg=(E) b))
  &  (  (is-send(E)(a))    
   (is-send(E)(b))    
 ( x,y: ||tr||.
 x < y
  &   (is-send(E)(tr[x]))
  &   (is-send(E)(tr[y]))
  &   (tr[x] =msg=(E) b)
  &   (tr[y] =msg=(E) a))
   
 loc(E)(a) = loc(E)(b)) | [R_ad_normal] | 
 Def single-tag-decomposable(E)(L)
==  L = nil   |E| List    
 ( L_1,L_2:Trace(E).
 L = (L_1 @ L_2)   |E| List
  &   L_2 = nil   |E| List
  &  ( x L_1.( y L_2.  (x =msg=(E) y)))
  &  ( m:Label. ( x L_2.tag(E)(x) = m))) | [single_tag_decomposable] | 
 Def C(Q)(i) ==  k: ||L||. Q(k)  &   (L[k] =msg=(E) L[i]) | [message_closure] | 
 Def Causal(E)(tr)
==  i: ||tr||.  j: ||tr||. j i  &   (is-send(E)(tr[j]))  &   (tr[j] =msg=(E) tr[i]) | [P_causal] | 
 Def No-dup-deliver(E)(tr)
==  i,j: ||tr||.
   (is-send(E)(tr[i]))    
   (is-send(E)(tr[j]))     (tr[j] =msg=(E) tr[i])    loc(E)(tr[i]) = loc(E)(tr[j])    i = j | [P_no_dup] | 
 Def Tag-by-msg(E)(tr)
==  i,j: ||tr||.  (tr[i] =msg=(E) tr[j])    tag(E)(tr[i]) = tag(E)(tr[j]) | [P_tag_by_msg] | 
 Def x delivered at time k ==  (x =msg=(E) tr[k])  &    (is-send(E)(tr[k])) | [delivered_at] | 
 Def switch_inv(E; tr)
==  i,j,k: ||tr||.
 i < j    
  (is-send(E)(tr[i]))    
  (is-send(E)(tr[j]))    
  tag(E)(tr[i]) = tag(E)(tr[j])    
  (tr[j] =msg=(E) tr[k])    
   (is-send(E)(tr[k]))    
 ( k': ||tr||. 
 k' < k  &  loc(E)(tr[k']) = loc(E)(tr[k])  &   (tr[i] =msg=(E) tr[k'])  &    (is-send(E)(tr[k']))) | [switch_inv2001_03_15_DASH_PM_DASH_12_53_21] |