From 68b48a25cbf8a8aa29e5131dd39555f42776a40e Mon Sep 17 00:00:00 2001 From: Claude Marche <Claude.Marche@inria.fr> Date: Sun, 17 Jul 2011 09:41:54 +0200 Subject: [PATCH] Heap implementation --- bench/bench | 7 +- .../programs/vacid_0_binary_heaps/heap.why | 94 ++++++++++++++ .../vacid_0_binary_heaps/heap_implem.mlw | 116 ++++++++++++++++++ .../vacid_0_binary_heaps/heap_model.why | 35 ++++++ 4 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 examples/programs/vacid_0_binary_heaps/heap.why create mode 100644 examples/programs/vacid_0_binary_heaps/heap_implem.mlw create mode 100644 examples/programs/vacid_0_binary_heaps/heap_model.why diff --git a/bench/bench b/bench/bench index e048a9296b..0b7d1907a2 100755 --- a/bench/bench +++ b/bench/bench @@ -58,10 +58,10 @@ drivers () { programs () { for f in $1/*.mlw; do echo -n " "$f"... " - if ! $pgml -L modules $pgml_options $f > /dev/null 2>&1; then + if ! $pgml -L modules $pgml_options $f $2 > /dev/null 2>&1; then echo - echo "$pgml $pgml_options $f" - $pgml -L modules $pgml_options $f + echo "$pgml $pgml_options $f $2" + $pgml -L modules $pgml_options $f $2 echo "FAILED!" exit 1 else @@ -147,6 +147,7 @@ echo "=== VC generation on good programs ===" pgml_options= programs bench/programs/good programs examples/programs +programs examples/programs/vacid_0_binary_heaps "-I examples/programs/vacid_0_binary_heaps" echo "" echo "=== Checking valid goals ===" diff --git a/examples/programs/vacid_0_binary_heaps/heap.why b/examples/programs/vacid_0_binary_heaps/heap.why new file mode 100644 index 0000000000..b08cde60a2 --- /dev/null +++ b/examples/programs/vacid_0_binary_heaps/heap.why @@ -0,0 +1,94 @@ + + +theory Heap + +use import int.Int +use import int.ComputerDivision + +function left(i:int) : int = 2*i+1 +function right(i:int) : int = 2*i+2 +function parent(i:int) : int = div (i-1) 2 + +lemma Parent_inf: forall i:int. 0 < i -> parent i < i +lemma Left_sup: forall i:int. 0 <= i -> i < left i +lemma Right_sup: forall i:int. 0 <= i -> i < right i +lemma Parent_right:forall i:int. 0 <= i -> parent (right i) = i +lemma Parent_left:forall i:int. 0 <= i -> parent (left i) = i +lemma Inf_parent: forall i j: int. 0 < j <= right i -> parent j <= i +lemma Child_parent:forall i:int. 0 < i -> + i = left (parent i) || i = right (parent i) +lemma Parent_pos: forall j: int. 0 < j -> 0 <= parent j + +predicate parentChild (i: int) (j: int) = + 0 <= i < j -> (j = left i) || (j = right i) + + +use map.Map as A +type map = A.map int int +type logic_heap = (map, int) + +predicate is_heap_array (a: map) (idx: int) (sz: int) = + 0 <= idx -> forall i j: int. + idx <= i < j < sz -> + parentChild i j -> + A.get a i <= A.get a j + +predicate is_heap (h : logic_heap) = + let (a, sz) = h in sz >= 0 /\ is_heap_array a 0 sz + +lemma Is_heap_when_no_element : + forall a:map, idx n: int. 0 <= n <= idx -> is_heap_array a idx n + +lemma Is_heap_sub : + forall a:map, i n :int. + is_heap_array a i n -> + forall j: int. i <= j <= n -> is_heap_array a i j + +lemma Is_heap_sub2 : + forall a:map, n :int. + is_heap_array a 0 n -> + forall j: int. 0 <= j <= n -> is_heap_array a j n + +lemma Is_heap_when_node_modified : + forall a:map, n e idx:int. + is_heap_array a idx n + -> forall i : int. 0 <= i < n + -> (i > 0 -> A.get a (parent i) <= e ) + -> (left i < n -> e <= A.get a (left i)) + -> (right i < n -> e <= A.get a (right i)) + -> is_heap_array (A.set a i e) idx n + +lemma Is_heap_add_last : + forall a:map, n e:int. n > 0 -> + is_heap_array a 0 n /\ (e >= A.get a (parent n)) -> + is_heap_array (A.set a n e) 0 (n + 1) + +lemma Parent_inf_el: + forall a: map, n: int. + is_heap_array a 0 n -> + forall j:int. 0 < j < n -> A.get a (parent j) <= A.get a j + +lemma Left_sup_el: + forall a: map, n: int. + is_heap_array a 0 n -> + forall j: int. 0 <= j < n -> left j < n -> + A.get a j <= A.get a (left j) + +lemma Right_sup_el: + forall a: map, n: int. + is_heap_array a 0 n -> + forall j: int. 0 <= j < n -> right j < n -> + A.get a j <= A.get a (right j) + +lemma Is_heap_relation: + forall a:map, n :int. n > 0 -> + is_heap_array a 0 n -> + forall j: int. 0 <= j -> j < n -> A.get a 0 <= A.get a j + +end + +(* +Local Variables: +compile-command: "why3ide -I . vacid0_binary_heaps" +End: +*) diff --git a/examples/programs/vacid_0_binary_heaps/heap_implem.mlw b/examples/programs/vacid_0_binary_heaps/heap_implem.mlw new file mode 100644 index 0000000000..902f998fb7 --- /dev/null +++ b/examples/programs/vacid_0_binary_heaps/heap_implem.mlw @@ -0,0 +1,116 @@ + +module Implementation + +use import int.Int +use import int.ComputerDivision +use import heap.Heap +use import heap_model.Model +use import bag_of_integers.Bag_integers + +lemma Is_heap_min: + forall a:map, n :int. n > 0 -> + is_heap_array a 0 n -> A.get a 0 = min_bag (model (a, n)) + +use import module ref.Ref + +(* implementation of heaps *) +let create () : ref logic_heap = + { true } + let x = (A.const 0, 0) in ref x + { is_heap !result /\ + model !result = empty_bag } + +exception Break + +let insert (this : ref logic_heap) (e : int) : unit = +{ is_heap !this } + let (a, n) = !this in + let arr = ref a in + let i = ref n in + try + while (!i > 0) do + invariant { + 0 <= !i <= n /\ + (!i = n -> + is_heap_array !arr 0 n /\ + model (!arr, n) = model (a, n)) /\ + (!i < n -> + is_heap_array !arr 0 (n + 1) /\ + A.get !arr !i > e /\ + model (!arr, n+1) = add (A.get !arr !i) (model (a, n))) + } + variant { !i } + let parent = div (!i - 1) 2 in + let p = A.get !arr parent in + if (e >= p) then raise Break; + arr := A.set !arr !i p; + i := parent; + assert { is_heap_array !arr 0 (n + 1) } + done + with Break -> () + end; + arr := A.set !arr !i e; + this := (!arr, n + 1); + assert { !i = n -> is_heap !this }; + assert { !i < n -> is_heap !this } +{ is_heap !this /\ + model !this = add e (model (old !this)) } + +let extractMin (this : ref logic_heap) : int = +{ model !this <> empty_bag /\ is_heap !this } + let (a, n) = !this in + assert {n > 0}; + let arr = ref a in + let min = A.get !arr 0 in + let n' = n-1 in + let last = A.get !arr n' in + let i = ref 0 in + try + while ( !i < n') do + invariant { + !i >= 0 /\ + is_heap_array !arr 0 n' /\ + (!i = 0 -> + a = !arr /\ + (model !this) = add last (model (a, n'))) /\ + (0 < !i < n' -> + add (A.get !arr !i) (model !this) = + add last (add min (model (!arr, n')))) /\ + (!i > 0 -> A.get !arr (parent !i) < last) } + variant {n' - !i} + let left = 2 * !i + 1 in + let right = 2 * !i + 2 in + if (left >= n') then raise Break; + let smaller = ref left in + if right < n' then + if A.get !arr left > A.get !arr right + then smaller := right; + if (last <= (A.get !arr !smaller)) then raise Break; + assert {last > (A.get !arr !smaller)}; + arr := A.set !arr !i (A.get !arr !smaller); + i := !smaller + done; + assert { model !this = add min (model (!arr,n')) } + with Break -> + assert { add (A.get !arr !i) (model !this) = + add last (add min (model (!arr, n'))) } + end; + if (!i < n') then + begin + arr := A.set !arr !i last; + assert { is_heap_array !arr 0 n' }; + assert { model !this = add min (model (!arr,n')) } + end; + this := (!arr, n'); + min +{ is_heap !this /\ + result = min_bag (model (old !this)) /\ + model (old !this) = add result (model !this) } + +end + +(* +Local Variables: +compile-command: "why3ide -I . vacid0_binary_heaps" +End: +*) diff --git a/examples/programs/vacid_0_binary_heaps/heap_model.why b/examples/programs/vacid_0_binary_heaps/heap_model.why new file mode 100644 index 0000000000..1b42e1003e --- /dev/null +++ b/examples/programs/vacid_0_binary_heaps/heap_model.why @@ -0,0 +1,35 @@ + +theory Model + +use import int.Int + +use import bag.Bag +use import elements.Elements +use import heap.Heap + +function model (h:logic_heap): (bag int) = + let (a,n) = h in elements a 0 n + +lemma Model_empty : + forall a: array int. model (a,0) = empty_bag + +lemma Model_singleton : forall a: array int. model (a,1) = singleton(A.get a 0) + +lemma Model_set : + forall a a': array int,v: int, i n : int. + 0 <= i < n -> + a' = A.set a i v -> + add (A.get a i) (model (a',n)) = + add v (model (a, n)) + +lemma Model_add_last: + forall a: array int, n : int. n >= 0 -> + model (a, n+1) = add (A.get a n) (model (a, n)) + +end + +(* +Local Variables: +compile-command: "why3ide -I . vacid0_model_theory" +End: +*) -- GitLab