1 (** {1 Priority queues} *)
3 (** {2 Polymorphic mutable priority queues} *)
10 (** the abstract type of elements *)
13 (** `elt` is equipped with a total pre order `le` *)
15 clone export relations.TotalPreOrder
16 with type t = elt, predicate rel = le, axiom .
22 (** the priority queue is modeled as a sorted sequence of elements *)
23 type t = abstract { mutable elts: seq elt }
24 invariant { forall i1 i2.
25 0 <= i1 <= i2 < length elts -> le elts[i1] elts[i2] }
26 meta coercion function elts
30 val create () : t ensures { result = empty }
31 (** create a fresh, empty queue *)
33 val push (x: elt) (q: t) : unit
35 ensures { length q = 1 + length (old q) }
36 ensures { occ_all x q = 1 + occ_all x (old q) }
37 ensures { forall y. y <> x -> occ_all y q = occ_all y (old q) }
38 (** push an element in a queue *)
41 (** exception raised by `pop` and `peek` to signal an empty queue *)
45 ensures { length (old q) > 0 }
46 ensures { result = (old q)[0] }
47 ensures { q = (old q)[1..] }
48 raises { Empty -> q = old q = empty }
49 (** remove and return the minimal element *)
51 val safe_pop (q: t) : elt
52 requires { length q > 0 }
54 ensures { result = (old q)[0] }
55 ensures { q = (old q)[1..] }
56 (** remove and return the minimal element *)
59 ensures { length q > 0 }
60 ensures { result = q[0] }
61 raises { Empty -> q = empty }
62 (** return the minimal element, without modifying the queue *)
64 val safe_peek (q: t) : elt
65 requires { length q > 0 }
66 ensures { result = q[0] }
67 (** return the minimal element, without modifying the queue *)
69 val clear (q: t) : unit
72 (** empty the queue *)
75 ensures { result == q }
76 (** return a fresh copy of the queue *)
78 val is_empty (q: t) : bool
79 ensures { result <-> q = empty }
80 (** check whether the queue is empty *)
82 val length (q: t) : int
83 ensures { result = length q }
84 (** return the number of elements in the queue *)
88 (** Test the interface above using an external heapsort *)
93 use array.IntArraySorted
100 clone Pqueue as PQ with type elt = int, predicate le = (<=)
102 let heapsort (a: array int) : unit
104 ensures { permut_all (old a) a }
105 = let n = length a in
106 let pq = PQ.create () in
107 for i = 0 to n - 1 do
108 invariant { length pq = i }
109 invariant { forall x. MO.occ x a.elts 0 n =
110 MO.occ x a.elts i n + SO.occ_all x pq }
111 PQ.push (Array.([]) a i) pq
113 for i = 0 to n - 1 do
114 invariant { length pq = n - i }
115 invariant { sorted_sub a 0 i }
116 invariant { forall j k. 0 <= j < i -> 0 <= k < length pq ->
117 Array.([]) a j <= pq[k] }
118 invariant { forall x. MO.occ x (old a.elts) 0 n =
119 MO.occ x a.elts 0 i + SO.occ_all x pq }
120 a[i] <- PQ.safe_pop pq
125 (** {2 Simpler interface}
127 when duplicate elements are not allowed
136 (** the abstract type of elements *)
139 (** `elt` is equipped with a total pre order `le` *)
141 clone export relations.TotalPreOrder
142 with type t = elt, predicate rel = le, axiom .
146 type t = abstract { mutable elts: fset elt }
147 (** the priority queue is modeled as a finite set of elements *)
148 meta coercion function elts
150 (** {3 Operations} *)
153 ensures { result = empty }
154 (** create a fresh, empty queue *)
156 val push (x: elt) (q: t) : unit
158 ensures { q = add x (old q) }
159 (** push an element in a queue *)
162 (** exception raised by `pop` and `peek` to signal an empty queue *)
164 predicate minimal_elt (x: elt) (s: fset elt) =
165 mem x s /\ forall e: elt. mem e s -> le x e
166 (** property of the element returned by `pop` and `peek` *)
170 ensures { q = remove result (old q) }
171 ensures { minimal_elt result (old q) }
172 raises { Empty -> q = old q = empty }
173 (** remove and returns the minimal element *)
175 val safe_pop (q: t) : elt
177 requires { not q = empty }
178 ensures { q = remove result (old q) }
179 ensures { minimal_elt result (old q) }
180 (** remove and returns the minimal element *)
182 val peek (q: t) : elt
183 ensures { minimal_elt result q }
184 raises { Empty -> q = empty }
185 (** return the minimal element, without modifying the queue *)
187 val safe_peek (q: t) : elt
188 requires { not q = empty }
189 ensures { minimal_elt result q }
190 (** return the minimal element, without modifying the queue *)
192 val clear (q: t) : unit
194 ensures { q = empty }
195 (** empty the queue *)
198 ensures { result = q }
199 (** return a fresh copy of the queue *)
201 val is_empty (q: t) : bool
202 ensures { result <-> q = empty }
203 (** check whether the queue is empty *)
205 val length (q: t) : int
206 ensures { result = cardinal q }
207 (** return the number of elements in the queue *)