Theory IMAP-proof

section ‹Convergence of the IMAP-CRDT›

text‹In this final section show that concurrent updates commute and thus Strong Eventual 
Convergence is achieved.›

theory
  "IMAP-proof"
  imports
    "IMAP-def"
    "IMAP-proof-commute"
    "IMAP-proof-helpers"
    "IMAP-proof-independent"
begin

corollary (in imap) concurrent_create_delete_independent:
  assumes "¬ hb (i, Create i e1) (ir, Delete is e2)" 
    and "¬ hb (ir, Delete is e2) (i, Create i e1)"
    and "xs prefix of j"
    and "(i, Create i e1)  set (node_deliver_messages xs)" 
    and "(ir, Delete is e2)  set (node_deliver_messages xs)"
  shows "i  is"
  using assms create_delete_ids_imply_messages_same concurrent_create_delete_independent_technical 
  by fastforce

corollary (in imap) concurrent_append_delete_independent:
  assumes "¬ hb (i, Append i e1) (ir, Delete is e2)" 
    and "¬ hb (ir, Delete is e2) (i, Append i e1)"
    and "xs prefix of j"
    and "(i, Append i e1)  set (node_deliver_messages xs)" 
    and "(ir, Delete is e2)  set (node_deliver_messages xs)"
  shows "i  is"
  using assms append_delete_ids_imply_messages_same concurrent_append_delete_independent_technical 
  by fastforce

corollary (in imap) concurrent_append_expunge_independent:
  assumes "¬ hb (i, Append i e1) (r, Expunge e2 mo r)" 
    and "¬ hb (r, Expunge e2 mo r) (i, Append i e1)"
    and "xs prefix of j"
    and "(i, Append i e1)  set (node_deliver_messages xs)" 
    and "(r, Expunge e2 mo r)  set (node_deliver_messages xs)"
  shows "i  mo"
  using assms append_expunge_ids_imply_messages_same concurrent_append_expunge_independent_technical 
  by fastforce

corollary (in imap) concurrent_append_store_independent:
  assumes "¬ hb (i, Append i e1) (r, Store e2 mo r)" 
    and "¬ hb (r, Store e2 mo r) (i, Append i e1)"
    and "xs prefix of j"
    and "(i, Append i e1)  set (node_deliver_messages xs)" 
    and "(r, Store e2 mo r)  set (node_deliver_messages xs)"
  shows "i  mo"
  using assms append_store_ids_imply_messages_same concurrent_append_store_independent_technical 
  by fastforce

corollary (in imap) concurrent_expunge_delete_independent:
  assumes "¬ hb (i, Expunge e1 mo i) (ir, Delete is e2)" 
    and "¬ hb (ir, Delete is e2) (i, Expunge e1 mo i)"
    and "xs prefix of j"
    and "(i, Expunge e1 mo i)  set (node_deliver_messages xs)" 
    and "(ir, Delete is e2)  set (node_deliver_messages xs)"
  shows "i  is"
  using assms expunge_delete_ids_imply_messages_same concurrent_expunge_delete_independent_technical 
  by fastforce

corollary (in imap) concurrent_store_delete_independent:
  assumes "¬ hb (i, Store e1 mo i) (ir, Delete is e2)" 
    and "¬ hb (ir, Delete is e2) (i, Store e1 mo i)"
    and "xs prefix of j"
    and "(i, Store e1 mo i)  set (node_deliver_messages xs)" 
    and "(ir, Delete is e2)  set (node_deliver_messages xs)"
  shows "i  is"
  using assms store_delete_ids_imply_messages_same concurrent_store_delete_independent_technical 
  by fastforce

corollary (in imap) concurrent_store_expunge_independent:
  assumes "¬ hb (i, Store e1 mo i) (r, Expunge e2 mo2 r)" 
    and "¬ hb (r, Expunge e2 mo2 r) (i, Store e1 mo i)"
    and "xs prefix of j"
    and "(i, Store e1 mo i)  set (node_deliver_messages xs)" 
    and "(r, Expunge e2 mo2 r)  set (node_deliver_messages xs)"
  shows "i  mo2  r  mo"
  using assms expunge_store_ids_imply_messages_same concurrent_store_expunge_independent_technical2 
    concurrent_store_expunge_independent_technical by metis


corollary (in imap) concurrent_store_store_independent:
  assumes "¬ hb (i, Store e1 mo i) (r, Store e2 mo2 r)" 
    and "¬ hb (r, Store e2 mo2 r) (i, Store e1 mo i)"
    and "xs prefix of j"
    and "(i, Store e1 mo i)  set (node_deliver_messages xs)" 
    and "(r, Store e2 mo2 r)  set (node_deliver_messages xs)"
  shows "i  mo2  r  mo"
  using assms store_store_ids_imply_messages_same concurrent_store_store_independent_technical 
  by metis

lemma (in imap) concurrent_operations_commute:
  assumes "xs prefix of i"
  shows "hb.concurrent_ops_commute (node_deliver_messages xs)"                     
proof -
  { fix a b x y
    assume "(a, b)  set (node_deliver_messages xs)"
      "(x, y)  set (node_deliver_messages xs)"
      "hb.concurrent (a, b) (x, y)"
    hence "interp_msg (a, b)  interp_msg (x, y) = interp_msg (x, y)  interp_msg (a, b)" 
      apply(unfold interp_msg_def, case_tac "b"; case_tac "y"; 
          simp add: create_create_commute delete_delete_commute append_append_commute 
          create_append_commute create_expunge_commute create_store_commute 
          expunge_expunge_commute hb.concurrent_def)
      using assms prefix_contains_msg apply (metis (full_types) 
          create_id_valid create_delete_commute concurrent_create_delete_independent)
      using assms prefix_contains_msg apply (metis (full_types) 
          create_id_valid create_delete_commute concurrent_create_delete_independent)
      using assms prefix_contains_msg apply (metis 
          append_id_valid append_delete_ids_imply_messages_same 
          concurrent_append_delete_independent_technical delete_append_commute)
      using assms prefix_contains_msg apply (metis 
          concurrent_expunge_delete_independent expunge_id_valid imap.delete_expunge_commute 
          imap_axioms)
      using assms prefix_contains_msg apply (metis 
          concurrent_store_delete_independent delete_store_commute store_id_valid)
      using assms prefix_contains_msg apply (metis 
          append_id_valid append_delete_ids_imply_messages_same 
          concurrent_append_delete_independent_technical delete_append_commute)
      using assms prefix_contains_msg apply (metis 
          append_id_valid expunge_id_valid append_expunge_ids_imply_messages_same 
          concurrent_append_expunge_independent_technical append_expunge_commute)
      using assms prefix_contains_msg apply (metis 
          append_id_valid append_store_commute concurrent_append_store_independent store_id_valid)
      using assms prefix_contains_msg apply (metis 
          concurrent_expunge_delete_independent expunge_id_valid delete_expunge_commute)
      using assms prefix_contains_msg apply (metis 
          append_expunge_commute append_id_valid concurrent_append_expunge_independent 
          expunge_id_valid)
      using assms prefix_contains_msg apply (metis 
          expunge_id_valid expunge_store_commute imap.concurrent_store_expunge_independent 
          imap_axioms store_id_valid)
      using assms prefix_contains_msg apply (metis 
          concurrent_store_delete_independent delete_store_commute store_id_valid)
      using assms prefix_contains_msg apply (metis 
          append_id_valid append_store_commute imap.concurrent_append_store_independent imap_axioms 
          store_id_valid)
      using assms prefix_contains_msg apply (metis 
          expunge_id_valid expunge_store_commute imap.concurrent_store_expunge_independent 
          imap_axioms store_id_valid)
      using assms prefix_contains_msg by (metis concurrent_store_store_independent store_id_valid 
          store_store_commute)   
  } thus ?thesis
    by(fastforce simp: hb.concurrent_ops_commute_def)
qed

theorem (in imap) convergence:
  assumes "set (node_deliver_messages xs) = set (node_deliver_messages ys)"
    and "xs prefix of i" 
    and "ys prefix of j"
  shows "apply_operations xs = apply_operations ys"
  using assms by(auto simp add: apply_operations_def intro: hb.convergence_ext 
      concurrent_operations_commute node_deliver_messages_distinct hb_consistent_prefix)

context imap begin

sublocale sec: strong_eventual_consistency weak_hb hb interp_msg
  "λops.xs i. xs prefix of i  node_deliver_messages xs = ops" "λx.({},{})"
  apply(standard; clarsimp simp add: hb_consistent_prefix node_deliver_messages_distinct
      concurrent_operations_commute)
  apply(metis (no_types, lifting) apply_operations_def bind.bind_lunit not_None_eq
      hb.apply_operations_Snoc kleisli_def apply_operations_never_fails interp_msg_def)
  using drop_last_message apply blast
  done

end
end