Theory Union_Find_Impl

(*
  File: Union_Find_Impl.thy
  Author: Bohua Zhan
*)

section ‹Implementation of union find›

theory Union_Find_Impl
  imports SepAuto "../Functional/Union_Find"
begin

text ‹
  Development follows theory Union\_Find in
  cite"Separation_Logic_Imperative_HOL-AFP" by Lammich and Meis.
›

type_synonym uf = "nat array × nat array"
  
definition is_uf :: "nat  (nat×nat) set  uf  assn" where [rewrite_ent]:
  "is_uf n R u = (Al szl. snd u a l * fst u a szl *
        (ufa_invar l) * (ufa_α l = R) * (length l = n) * (length szl = n))"

definition uf_init :: "nat  uf Heap" where
  "uf_init n = do {
     l  Array.of_list [0..<n];
     szl  Array.new n (1::nat);
     return (szl, l)
   }"

text ‹Correctness of uf\_init.›
theorem uf_init_rule [hoare_triple]:
  "<emp> uf_init n <is_uf n (uf_init_rel n)>" by auto2
  
partial_function (heap) uf_rep_of :: "nat array  nat  nat Heap" where
  "uf_rep_of p i = do {
     n  Array.nth p i;
     if n = i then return i else uf_rep_of p n
   }"
  
lemma uf_rep_of_rule [hoare_triple]:
  "ufa_invar l  i < length l 
   <p a l>
   uf_rep_of p i
   <λr. p a l * (r = rep_of l i)>"
@proof @prop_induct "ufa_invar l  i < length l" @qed

partial_function (heap) uf_compress :: "nat  nat  nat array  unit Heap" where
  "uf_compress i ci p = (
    if i = ci then return ()
    else do {
      ni  Array.nth p i;
      uf_compress ni ci p;
      Array.upd i ci p;
      return ()
    })"

lemma uf_compress_rule [hoare_triple]:
  "ufa_invar l  i < length l 
   <p a l>
    uf_compress i (rep_of l i) p
   <λ_. Al'. p a l' * (ufa_invar l'  length l' = length l 
              (i<length l. rep_of l' i = rep_of l i))>"
@proof @prop_induct "ufa_invar l  i < length l" @qed

definition uf_rep_of_c :: "nat array  nat  nat Heap" where
  "uf_rep_of_c p i = do {
    ci  uf_rep_of p i;
    uf_compress i ci p;
    return ci
  }"

lemma uf_rep_of_c_rule [hoare_triple]:
  "ufa_invar l  i < length l 
   <p a l>
   uf_rep_of_c p i
   <λr. Al'. p a l' * (r = rep_of l i  ufa_invar l'  length l' = length l 
                          (i<length l. rep_of l' i = rep_of l i))>"
  by auto2

definition uf_cmp :: "uf  nat  nat  bool Heap" where
  "uf_cmp u i j = do {
    n  Array.len (snd u);
    if (in  jn) then return False
    else do {
      ci  uf_rep_of_c (snd u) i;
      cj  uf_rep_of_c (snd u) j;
      return (ci = cj)
    }
  }"

text ‹Correctness of compare.›
theorem uf_cmp_rule [hoare_triple]:
  "<is_uf n R u>
   uf_cmp u i j
   <λr. is_uf n R u * (r  (i,j)R)>" by auto2

definition uf_union :: "uf  nat  nat  uf Heap" where
  "uf_union u i j = do {
    ci  uf_rep_of (snd u) i;
    cj  uf_rep_of (snd u) j;
    if (ci = cj) then return u
    else do {
      si  Array.nth (fst u) ci;
      sj  Array.nth (fst u) cj;
      if si < sj then do {
        Array.upd ci cj (snd u);
        Array.upd cj (si+sj) (fst u);
        return u
      } else do { 
        Array.upd cj ci (snd u);
        Array.upd ci (si+sj) (fst u);
        return u
      }
    }
  }"

text ‹Correctness of union.›
theorem uf_union_rule [hoare_triple]:
  "i < n  j < n 
   <is_uf n R u>
   uf_union u i j
   <is_uf n (per_union R i j)>" by auto2

setup del_prfstep_thm @{thm is_uf_def}

end