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).
0≤l ∧ l≤h ∧ h≤length 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 ∧ h≤length xs ∧ l≤h);
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. x≤y) xs)"
lemma bin_search_correct:
assumes "sorted xs"
shows "bin_search xs x ≤ SPEC (λi. i=find_index (λy. x≤y) 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_rel⟩nres_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. x≤y) 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 → ⟨Id⟩nres_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. x≤y) xs))"
proof -
interpret llvm_prim_setup .
show ?thesis
unfolding bin_search_impl'_def
supply [vcg_rules] = bin_search_impl_correct
by vcg
qed
end