2 (** Purely applicative heaps implemented with Braun trees.
4 Braun trees are binary trees where, for each node, the left subtree
5 has the same size of the right subtree or is one element larger
8 Consequently, a Braun tree has logarithmic height (lemma [inv_height]).
9 The nice thing with Braun trees is that we do not need extra information
10 to ensure logarithmic height.
12 We also prove an algorithm from Okasaki to compute the size of a braun
13 tree in time O(log^2(n)) (function [fast_size]).
15 Author: Jean-Christophe Filliâtre (CNRS)
22 use export bintree.Size
23 use export bintree.Occ
27 val predicate le elt elt
29 clone relations.TotalPreOrder with type t = elt, predicate rel = le, axiom .
31 (* [e] is no greater than the root of [t], if any *)
32 let predicate le_root (e: elt) (t: tree elt) = match t with
34 | Node _ x _ -> le e x
37 predicate heap (t: tree elt) = match t with
39 | Node l x r -> le_root x l && heap l && le_root x r && heap r
42 function minimum (tree elt) : elt
43 axiom minimum_def: forall l x r. minimum (Node l x r) = x
45 predicate is_minimum (x: elt) (t: tree elt) =
46 mem x t && forall e. mem e t -> le x e
48 (* the root is the smallest element *)
49 let rec lemma root_is_min (t: tree elt) : unit
50 requires { heap t && 0 < size t }
51 ensures { is_minimum (minimum t) t }
53 = let Node l _ r = t in
54 if not is_empty l then root_is_min l;
55 if not is_empty r then root_is_min r
57 predicate inv (t: tree elt) = match t with
59 | Node l _ r -> (size l = size r || size l = size r + 1) && inv l && inv r
62 let constant empty : tree elt = Empty
63 ensures { heap result }
64 ensures { inv result }
65 ensures { size result = 0 }
66 ensures { forall e. not (mem e result) }
68 let get_min (t: tree elt) : elt
69 requires { heap t && 0 < size t }
70 ensures { result = minimum t }
77 let rec add (x: elt) (t: tree elt) : tree elt
81 ensures { heap result }
82 ensures { inv result }
83 ensures { occ x result = occ x t + 1 }
84 ensures { forall e. e <> x -> occ e result = occ e t }
85 ensures { size result = size t + 1 }
97 let rec extract (t: tree elt) : (elt, tree elt)
100 requires { 0 < size t }
102 ensures { let e, t' = result in
103 heap t' && inv t' && size t' = size t - 1 &&
104 occ e t' = occ e t - 1 &&
105 forall x. x <> e -> occ x t' = occ x t }
111 assert { r = Empty };
114 let x, l = extract l in
118 let rec replace_min (x: elt) (t: tree elt) : tree elt
121 requires { 0 < size t }
123 ensures { heap result }
124 ensures { inv result }
125 ensures { if x = minimum t then occ x result = occ x t
126 else occ x result = occ x t + 1 &&
127 occ (minimum t) result = occ (minimum t) t - 1 }
128 ensures { forall e. e <> x -> e <> minimum t -> occ e result = occ e t }
129 ensures { size result = size t }
133 if le_root x l && le_root x r then
136 let lx = get_min l in
138 (* lx <= x, rx necessarily *)
139 Node (replace_min x l) lx r
141 (* rx <= x, lx necessarily *)
142 Node l (get_min r) (replace_min x r)
147 let rec merge (l r: tree elt) : tree elt
148 requires { heap l && heap r }
149 requires { inv l && inv r }
150 requires { size r <= size l <= size r + 1 }
151 ensures { heap result }
152 ensures { inv result }
153 ensures { forall e. occ e result = occ e l + occ e r }
154 ensures { size result = size l + size r }
155 variant { size l + size r }
160 | Node ll lx lr, Node _ ly _ ->
162 Node r lx (merge ll lr)
164 let x, l = extract l in
165 Node (replace_min x r) ly l
170 let remove_min (t: tree elt) : tree elt
173 requires { 0 < size t }
174 ensures { heap result }
175 ensures { inv result }
176 ensures { occ (minimum t) result = occ (minimum t) t - 1 }
177 ensures { forall e. e <> minimum t -> occ e result = occ e t }
178 ensures { size result = size t - 1 }
182 | Node l _ r -> merge l r
185 (** The size of a Braun tree can be computed in time O(log^2(n))
188 Three Algorithms on Braun Trees (Functional Pearl)
190 J. Functional Programming 7 (6) 661–666, November 1997 *)
192 use int.ComputerDivision
194 let rec diff (m: int) (t: tree elt) : int
196 requires { 0 <= m <= size t <= m + 1 }
198 ensures { size t = m + result }
205 else if mod m 2 = 1 then
210 diff (div (m - 1) 2) r
213 let rec fast_size (t: tree elt) : int
216 ensures { result = size t }
220 | Node l _ r -> let m = fast_size r in 1 + 2 * m + diff m l
223 (** A Braun tree has a logarithmic height *)
228 let rec lemma size_height (t1 t2: tree elt)
229 requires { inv t1 && inv t2 }
230 variant { size t1 + size t2 }
231 ensures { size t1 >= size t2 -> height t1 >= height t2 }
233 | Node l1 _ r1, Node l2 _ r2 ->
240 let rec lemma inv_height (t: tree elt)
243 ensures { size t > 0 ->
244 let h = height t in power 2 (h-1) <= size t < power 2 h }
246 | Empty | Node Empty _ _ ->
250 assert { height l = h-1 };