(* Priority queue, implemented as a binary heap within a fixed capacity array Authors: Aymeric Walch (ENS Lyon) Jean-Christophe FilliĆ¢tre (CNRS) *) use int.Int use mach.int.Int use seq.Seq use array.Array use bag.Bag use option.Option type elt = int predicate heap_order (a: array elt) (len: int) = forall i. 0 <= i < len -> (0 < 2*i + 1 < len -> a[i] <= a[2*i + 1]) /\ (0 < 2*i + 2 < len -> a[i] <= a[2*i + 2]) type t = { cap: int; mutable len: int; a: array elt; } invariant { 0 <= len <= length a = cap } invariant { heap_order a len } by { cap = 0; len = 0; a = Array.make 0 0; } let create (cap: int) : t requires { 0 <= cap } = { cap = cap; len = 0; a = Array.make cap 0 } (* proving that h.a[0] is the minimum requires induction *) let rec lemma first_is_min (h: t) (i: int) requires { 0 <= i < h.len } ensures { h.a[0] <= h.a[i] } variant { i } = if i > 0 then first_is_min h (div (i-1) 2) let rec move_down (a: array elt) (i: int) (x: elt) (len: int) : unit requires { heap_order a len } requires { 0 <= i < len <= length a } requires { i > 0 -> a[div (i - 1) 2] <= x } ensures { heap_order a len } variant { len - i } = if 2*i + 1 < len then begin let j = let j = 2 * i + 1 in if j + 1 < len && a[j+1] < a[j] then j+1 else j in if a[j] < x then begin a[i] <- a[j]; move_down a j x len end else begin a[i] <- x; end end else begin (* 2i+1 outside *) a[i] <- x; end exception Empty let extract_min_exn (h : t) : elt raises { Empty -> h.len = old h.len = 0 } ensures { result = old h.a[0] } ensures { h.len = old h.len - 1 } = if h.len = 0 then raise Empty; h.len <- h.len - 1; let x = h.a[h.len] in if h.len <> 0 then begin let min = h.a[0] in move_down h.a 0 x h.len; min end else begin x end let rec move_up (a: array elt) (i: int) (x: elt) (len: int) : unit requires { 0 <= i < len <= length a } requires { heap_order a len } requires { 0 < 2*i + 1 < len -> x <= a[2*i + 1] } requires { 0 < 2*i + 2 < len -> x <= a[2*i + 2] } variant { i } ensures { heap_order a len } = if i = 0 then begin a[i] <- x; end else begin let j = (i-1) / 2 in let y = a[j] in if y > x then begin a[i] <- y; move_up a j x len end else begin a[i] <- x; end end exception Full let insert (x: elt) (h: t) : unit raises { Full -> h.len = old h.len = h.cap } ensures { h.len = old h.len + 1 } = if h.len = h.cap then raise Full; let n = h.len in h.len <- h.len + 1; if n = 0 then h.a[0] <- x else let j = (n - 1) / 2 in let y = h.a[j] in if y > x then begin h.a[n] <- y; move_up h.a j x h.len end else h.a[n] <- x
Generated by why3doc 1.3.3+git