Theory Liveness_Subsumption_Impl
subsection ‹Imperative Implementation›
theory Liveness_Subsumption_Impl
  imports Liveness_Subsumption_Map Heap_Hash_Map Worklist_Algorithms_Tracing
begin
no_notation Ref.update (‹_ := _› 62)
locale Liveness_Search_Space_Key_Impl_Defs =
  Liveness_Search_Space_Key_Defs _ _ _ _ _ _ key for key :: "'a ⇒ 'k" +
  fixes A :: "'a ⇒ ('ai :: heap) ⇒ assn"
  fixes succsi :: "'ai ⇒ 'ai list Heap"
  fixes a⇩0i :: "'ai Heap"
  fixes Lei :: "'ai ⇒ 'ai ⇒ bool Heap"
  fixes keyi :: "'ai ⇒ 'ki :: {hashable, heap} Heap"
  fixes copyi :: "'ai ⇒ 'ai Heap"
locale Liveness_Search_Space_Key_Impl =
  Liveness_Search_Space_Key_Impl_Defs +
  Liveness_Search_Space_Key +
  fixes K
  assumes pure_K[safe_constraint_rules]: "is_pure K"
    assumes left_unique_K[safe_constraint_rules]: "IS_LEFT_UNIQUE (the_pure K)"
    assumes right_unique_K[safe_constraint_rules]: "IS_RIGHT_UNIQUE (the_pure K)"
  assumes refinements[sepref_fr_rules]:
    "(uncurry0 a⇩0i, uncurry0 (RETURN (PR_CONST a⇩0))) ∈ unit_assn⇧k →⇩a A"
    "(uncurry Lei,uncurry (RETURN oo PR_CONST (⊴))) ∈ A⇧k *⇩a A⇧k →⇩a bool_assn"
    "(succsi,RETURN o PR_CONST succs) ∈ A⇧k →⇩a list_assn A"
    "(keyi,RETURN o PR_CONST key) ∈ A⇧k →⇩a K"
    "(copyi, RETURN o COPY) ∈ A⇧k →⇩a A"
context Liveness_Search_Space_Key_Defs
begin
lemma insert_map_set_alt_def: "((), insert_map_set v S) = (
  let
    k = key v; (S', S) = op_map_extract k S
  in
    case S' of
      Some S1 ⇒ ((), S(k ↦ (insert v S1)))
    | None ⇒ ((), S(k ↦ {v}))
)
"
  unfolding insert_map_set_def op_map_extract_def by (auto simp: Let_def split: option.split)
lemma check_subsumption_map_set_alt_def: "check_subsumption_map_set v S = (
  let
    k = key v; (S', S) = op_map_extract k S;
    S1' = (case S' of Some S1 ⇒ S1 | None ⇒ {})
  in (∃ x ∈ S1'. v ⊴ x)
)
"
  unfolding check_subsumption_map_set_def op_map_extract_def by (auto simp: Let_def)
lemma : "(S, check_subsumption_map_set v S) = (
  let
    k = key v; (S', S) = op_map_extract k S
  in (
    case S' of
      Some S1 ⇒ (let r = (∃ x ∈ S1. v ⊴ x) in (op_map_update k S1 S, r))
    | None ⇒ (S, False)
  )
)
"
  unfolding check_subsumption_map_set_def op_map_extract_def op_map_update_def op_map_delete_def
  by (auto simp: Let_def split: option.split)
lemma : "(S, check_subsumption_map_list v S) = (
  let
    k = key v; (S', S) = op_map_extract k S
  in (
    case S' of
      Some S1 ⇒ (let r = (∃ x ∈ set S1. x ⊴ v) in (op_map_update k S1 S, r))
    | None ⇒ (S, False)
  )
)
"
  unfolding check_subsumption_map_list_def op_map_extract_def op_map_update_def op_map_delete_def
  by (auto simp: Let_def split: option.split)
lemma push_map_list_alt_def: "((), push_map_list v S) = (
  let
    k = key v; (S', S) = op_map_extract k S
  in
    case S' of
      Some S1 ⇒ ((), S(k ↦ v # S1))
    | None ⇒ ((), S(k ↦ [v]))
)
"
  unfolding push_map_list_def op_map_extract_def by (auto simp: Let_def split: option.split)
lemma pop_map_list_alt_def: "((), pop_map_list v S) = (
  let
    k = key v; (S', S) = op_map_extract k S
  in
    case S' of
      Some S1 ⇒ ((), S(k ↦ if op_list_is_empty S1 then [] else tl S1))
    | None ⇒ ((), S(k ↦ []))
)
"
  unfolding pop_map_list_def op_map_extract_def by (auto simp: Let_def split: option.split)
lemmas alt_defs =
  insert_map_set_alt_def check_subsumption_map_set_extract
  check_subsumption_map_list_extract pop_map_list_alt_def push_map_list_alt_def
lemma dfs_map_alt_def:
  "dfs_map = (λ P. do {
    (P,ST,r) ← RECT (λdfs (P,ST,v).
      let (ST, b) = (ST, check_subsumption_map_list v ST) in
      if b then RETURN (P, ST, True)
      else do {
        let (P, b1) = (P, check_subsumption_map_set v P) in
        if b1 then
          RETURN (P, ST, False)
        else do {
            let (_, ST1) = ((), push_map_list (COPY v) ST);
            (P1, ST2, r) ←
              nfoldli (succs v) (λ(_,_,b). ¬b) (λv' (P,ST,_). dfs (P,ST,v')) (P,ST1,False);
            let (_, ST') = ((), pop_map_list (COPY v) ST2);
            let (_, P')  = ((), insert_map_set (COPY v) P1);
            TRACE (ExploredState);
            RETURN (P', ST', r)
          }
      }
    ) (P,Map.empty,a⇩0);
    RETURN (r, P)
  })"
  unfolding dfs_map_def
  unfolding Let_def
  unfolding COPY_def
  unfolding TRACE_bind
  by auto
definition dfs_map' where
  "dfs_map' a P ≡ do {
    (P,ST,r) ← RECT (λdfs (P,ST,v).
      let (ST, b) = (ST, check_subsumption_map_list v ST) in
      if b then RETURN (P, ST, True)
      else do {
        let (P, b1) = (P, check_subsumption_map_set v P) in
        if b1 then
          RETURN (P, ST, False)
        else do {
            let (_, ST1) = ((), push_map_list (COPY v) ST);
            (P1, ST2, r) ←
              nfoldli (succs v) (λ(_,_,b). ¬b) (λv' (P,ST,_). dfs (P,ST,v')) (P,ST1,False);
            let (_, ST') = ((), pop_map_list (COPY v) ST2);
            let (_, P')  = ((), insert_map_set (COPY v) P1);
            TRACE (ExploredState);
            RETURN (P', ST', r)
          }
      }
    ) (P,Map.empty,a);
    RETURN (r, P)
  }"
lemma dfs_map'_id:
  "dfs_map' a⇩0 = dfs_map"
  apply (subst dfs_map_alt_def)
  unfolding dfs_map'_def TRACE_bind ..
end 
definition (in imp_map_delete) [code_unfold]: "hms_delete = delete"
lemma (in imp_map_delete) hms_delete_rule [sep_heap_rules]:
  "<hms_assn A m mi> hms_delete k mi <hms_assn A (m(k := None))>⇩t"
  unfolding hms_delete_def hms_assn_def
  apply (sep_auto eintros del: exI)
  subgoal for mh
    apply (rule exI[where x = "mh(k := None)"])
    apply (rule ent_frame_fwd[OF map_assn_delete[where A = A]], frame_inference)
    by (sep_auto simp: map_upd_eq_restrict)
  done
context imp_map_delete
begin
lemma hms_delete_hnr:
  "(uncurry hms_delete, uncurry (RETURN oo op_map_delete)) ∈
  id_assn⇧k *⇩a (hms_assn A)⇧d →⇩a hms_assn A"
  by sepref_to_hoare sep_auto
sepref_decl_impl delete: hms_delete_hnr uses op_map_delete.fref[where V = Id] .
end
lemma fold_insert_set:
  "fold insert xs S = set xs ∪ S"
  by (induction xs arbitrary: S) auto
lemma set_alt_def:
  "set xs = fold insert xs {}"
  by (simp add: fold_insert_set)
context Liveness_Search_Space_Key_Impl
begin
sepref_register
  "PR_CONST a⇩0" "PR_CONST (⊴)" "PR_CONST succs" "PR_CONST key"
lemma [def_pat_rules]:
  "a⇩0 ≡ UNPROTECT a⇩0" "(⊴) ≡ UNPROTECT (⊴)" "succs ≡ UNPROTECT succs" "key ≡ UNPROTECT key"
  by simp_all
abbreviation "passed_assn ≡ hm.hms_assn' K (lso_assn A)"
lemma [intf_of_assn]:
  "intf_of_assn (hm.hms_assn' a b) TYPE(('aa, 'bb) i_map)"
  by simp
sepref_definition dfs_map_impl is
  "PR_CONST dfs_map" :: "passed_assn⇧d →⇩a prod_assn bool_assn passed_assn"
  unfolding PR_CONST_def
  apply (subst dfs_map_alt_def)
  unfolding TRACE'_def[symmetric]
  unfolding alt_defs
  unfolding Bex_set list_ex_foldli
  unfolding fold_lso_bex
  unfolding lso_fold_custom_empty hm.hms_fold_custom_empty HOL_list.fold_custom_empty
  by sepref
sepref_register dfs_map
lemmas [sepref_fr_rules] = dfs_map_impl.refine_raw
lemma passed_empty_refine[sepref_fr_rules]:
  "(uncurry0 hm.hms_empty, uncurry0 (RETURN (PR_CONST hm.op_hms_empty))) ∈ unit_assn⇧k →⇩a passed_assn"
proof -
  have "hn_refine emp hm.hms_empty emp (hm.hms_assn' K (lso_assn A)) (RETURN hm.op_hms_empty)"
    using sepref_fr_rules(17)[simplified] .
  then show ?thesis
    by - (rule hfrefI, auto simp: pure_unit_rel_eq_empty)
qed
sepref_register hm.op_hms_empty
sepref_thm dfs_map_impl' is
  "uncurry0 (do {(r, p) ← dfs_map Map.empty; RETURN r})" :: "unit_assn⇧k →⇩a bool_assn"
  unfolding hm.hms_fold_custom_empty by sepref
sepref_definition dfs_map'_impl is
  "uncurry dfs_map'"
  :: "A⇧d *⇩a (hm.hms_assn' K (lso_assn A))⇧d →⇩a bool_assn ×⇩a hm.hms_assn' K (lso_assn A)"
  unfolding dfs_map'_def
  unfolding PR_CONST_def TRACE'_def[symmetric]
  unfolding alt_defs
  unfolding Bex_set list_ex_foldli
  unfolding fold_lso_bex
  unfolding lso_fold_custom_empty hm.hms_fold_custom_empty HOL_list.fold_custom_empty
  by sepref
concrete_definition (in -) dfs_map_impl'
  uses Liveness_Search_Space_Key_Impl.dfs_map_impl'.refine_raw is "(uncurry0 ?f,_)∈_"
lemma (in Liveness_Search_Space_Key) dfs_map_empty:
  "dfs_map Map.empty ≤ ⇓ (bool_rel ×⇩r map_set_rel) dfs_spec" if "V a⇩0"
proof -
  have "liveness_compatible {}"
    unfolding liveness_compatible_def by auto
  have "(Map.empty, {}) ∈ map_set_rel"
    unfolding map_set_rel_def by auto
  note dfs_map_dfs_refine[OF this ‹V a⇩0›]
  also note dfs_correct[OF ‹V a⇩0› ‹liveness_compatible {}›]
  finally show ?thesis
    by auto
qed
lemma (in Liveness_Search_Space_Key) dfs_map_empty_correct:
  "do {(r, p) ← dfs_map Map.empty; RETURN r} ≤ SPEC (λ r. r ⟷ (∃ x. a⇩0 →* x ∧ x →⇧+ x))"
  if "V a⇩0"
  supply dfs_map_empty[OF ‹V a⇩0›, THEN Orderings.order.trans, refine_vcg]
  apply refine_vcg
  unfolding dfs_spec_def pw_le_iff by (auto simp: refine_pw_simps)
lemma dfs_map_impl'_hnr:
  "(uncurry0 (dfs_map_impl' succsi a⇩0i Lei keyi copyi),
    uncurry0 (SPEC (λr. r = (∃x. a⇩0 →* x ∧ x →⇧+ x)))
   ) ∈ unit_assn⇧k →⇩a bool_assn" if "V a⇩0"
  using
    dfs_map_impl'.refine[
      OF Liveness_Search_Space_Key_Impl_axioms,
      FCOMP dfs_map_empty_correct[THEN Id_SPEC_refine, THEN nres_relI],
      OF ‹V a⇩0›
      ] .
lemma dfs_map_impl'_hoare_triple:
  "<↑(V a⇩0)> 
    dfs_map_impl' succsi a⇩0i Lei keyi copyi 
  <λr. ↑(r ⟷ (∃ x. a⇩0 →* x ∧ x →⇧+ x))>⇩t"
  using dfs_map_impl'_hnr[to_hnr]
  unfolding hn_refine_def
  apply clarsimp
  apply (erule cons_post_rule)
  by (sep_auto simp: pure_def)
end 
end