Theory Bin_Search

theory Bin_Search
imports "Isabelle_LLVM.IICF" "List-Index.List_Index"
begin

  subsection Binary Search
    
  subsubsection Abstract Algorithm
  
  abbreviation "bin_search_invar xs x  (λ(l,h). 
        0l  lh  hlength xs 
       (i<l. xs!i<x)  (i{h..<length xs}. x  xs!i))"
  
  definition "bin_search xs x  do {
    (l,h)  WHILEIT (bin_search_invar xs x)
      (λ(l,h). l<h) 
      (λ(l,h). do {
        ASSERT (l<length xs  hlength xs  lh);
        let m = l + (h-l) div 2;
        if xs!m < x then RETURN (m+1,h) else RETURN (l,m)
      }) 
      (0,length xs);
    RETURN l
  }"

  
  definition "fi_spec xs x = SPEC (λi. i=find_index (λy. xy) xs)"
  
  lemma bin_search_correct:
    assumes "sorted xs"
    shows "bin_search xs x  SPEC (λi. i=find_index (λy. xy) xs)"
    unfolding bin_search_def
    apply (refine_vcg WHILEIT_rule[where R="measure (λ(l,h). h-l)"])
    apply (all (auto;fail)?)

    apply (clarsimp simp: less_Suc_eq_le)
    subgoal for l h i 
      apply (frule sorted_nth_mono[OF assms, of i "l + (h-l) div 2"])
      by auto
    subgoal
      by clarsimp (meson assms leI le_less_trans sorted_iff_nth_mono)
    
    apply clarsimp
    subgoal for i
      by (simp add: find_index_eqI less_le_not_le)
      
    done

  lemma bin_search_correct': "(uncurry bin_search,uncurry fi_spec)
    [λ(xs,_). sorted xs]f Id ×r Id  nat_relnres_rel"  
    using bin_search_correct unfolding fi_spec_def
    by (fastforce intro!: frefI nres_relI)
    
    
  subsubsection Implementation
    
  type_synonym size_t = 64
  type_synonym elem_t = 64

  sepref_def bin_search_impl is "uncurry bin_search"  
    :: "(larray_assn' TYPE(size_t) (sint_assn' TYPE(elem_t)))k 
        *a (sint_assn' TYPE(elem_t))k 
       a snat_assn' TYPE(size_t)"
    unfolding bin_search_def
    apply (rule hfref_with_rdomI)
    apply (annot_snat_const "TYPE(size_t)")
    apply sepref    
    done

  definition [llvm_code, llvm_inline]: "bin_search_impl' a x  doM {
    a  ll_load a;
    bin_search_impl a x
  }"  
    
    
  export_llvm bin_search_impl' is int64_t bin_search(larray_t*, elem_t) 
  defines 
    typedef uint64_t elem_t;
    typedef struct {
      int64_t len;
      elem_t *data;
    } larray_t;
  
  file "../../regression/gencode/bin_search.ll"
    
  export_llvm bin_search_impl' is int64_t bin_search(larray_t*, elem_t) 
  defines 
    typedef uint64_t elem_t;
    typedef struct {
      int64_t len;
      elem_t *data;
    } larray_t;
  
  file "code/bin_search.ll"
  
  
  lemmas bs_impl_correct = bin_search_impl.refine[FCOMP bin_search_correct']
  
  subsubsection Combined Correctness Theorem
  
  theorem bin_search_impl_correct:
    "llvm_htriple 
      (larray_assn sint_assn xs xsi ** sint_assn x xi ** (sorted xs)) 
      (bin_search_impl xsi xi)
      (λii. EXS i. larray_assn sint_assn xs xsi ** sint_assn x xi ** snat_assn i ii 
                  ** (i=find_index (λy. xy) xs))"
  proof -
  
    from bin_search_correct have R: 
        "(uncurry bin_search, uncurry (λxs x. SPEC (λi. i = find_index ((≤) x) xs))) 
       [λ(xs,x). sorted xs]f Id  Idnres_rel"
      apply (intro frefI nres_relI)
      apply fastforce 
      done
  
    note bin_search_impl.refine  
    note R = bin_search_impl.refine[FCOMP R]
    note R = R[THEN hfrefD, THEN hn_refineD, of "(xs,x)" "(xsi,xi)", simplified]
    note [vcg_rules] = R
    
    show ?thesis by vcg'
  qed

  theorem bin_search_impl'_correct:
    "llvm_htriple 
      (ll_pto xsi xsip ** larray_assn sint_assn xs xsi ** sint_assn x xi ** (sorted xs)) 
      (bin_search_impl' xsip xi)
      (λii. EXS i. ll_pto xsi xsip ** larray_assn sint_assn xs xsi ** sint_assn x xi ** snat_assn i ii 
                  ** (i=find_index (λy. xy) xs))"
  proof -
    interpret llvm_prim_setup .
    show ?thesis
      unfolding bin_search_impl'_def
      supply [vcg_rules] = bin_search_impl_correct
      by vcg
  qed
  
end