1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
(** {1 Priority queues} *)
(** {2 Polymorphic mutable priority queues} *)
module Pqueue
(** {3 Types} *)
type elt
(** the abstract type of elements *)
predicate le elt elt
(** `elt` is equipped with a total pre order `le` *)
clone export relations.TotalPreOrder
with type t = elt, predicate rel = le, axiom .
use int.Int
use seq.Seq
use seq.Occ
(** the priority queue is modeled as a sorted sequence of elements *)
type t = abstract { mutable elts: seq elt }
invariant { forall i1 i2.
0 <= i1 <= i2 < length elts -> le elts[i1] elts[i2] }
meta coercion function elts
(** {3 Operations} *)
val create () : t ensures { result = empty }
(** create a fresh, empty queue *)
val push (x: elt) (q: t) : unit
writes { q }
ensures { length q = 1 + length (old q) }
ensures { occ_all x q = 1 + occ_all x (old q) }
ensures { forall y. y <> x -> occ_all y q = occ_all y (old q) }
(** push an element in a queue *)
exception Empty
(** exception raised by `pop` and `peek` to signal an empty queue *)
val pop (q: t) : elt
writes {q}
ensures { length (old q) > 0 }
ensures { result = (old q)[0] }
ensures { q = (old q)[1..] }
raises { Empty -> q = old q = empty }
(** remove and return the minimal element *)
val safe_pop (q: t) : elt
requires { length q > 0 }
writes { q }
ensures { result = (old q)[0] }
ensures { q = (old q)[1..] }
(** remove and return the minimal element *)
val peek (q: t) : elt
ensures { length q > 0 }
ensures { result = q[0] }
raises { Empty -> q = empty }
(** return the minimal element, without modifying the queue *)
val safe_peek (q: t) : elt
requires { length q > 0 }
ensures { result = q[0] }
(** return the minimal element, without modifying the queue *)
val clear (q: t) : unit
writes { q }
ensures { q = empty }
(** empty the queue *)
val copy (q: t) : t
ensures { result == q }
(** return a fresh copy of the queue *)
val is_empty (q: t) : bool
ensures { result <-> q = empty }
(** check whether the queue is empty *)
val length (q: t) : int
ensures { result = length q }
(** return the number of elements in the queue *)
end
(** Test the interface above using an external heapsort *)
module Harness
use int.Int
use array.Array
use array.IntArraySorted
use array.ArrayPermut
use map.Occ as MO
use seq.Seq
use seq.FreeMonoid
use seq.Occ as SO
clone Pqueue as PQ with type elt = int, predicate le = (<=)
let heapsort (a: array int) : unit
ensures { sorted a }
ensures { permut_all (old a) a }
= let n = length a in
let pq = PQ.create () in
for i = 0 to n - 1 do
invariant { length pq = i }
invariant { forall x. MO.occ x a.elts 0 n =
MO.occ x a.elts i n + SO.occ_all x pq }
PQ.push (Array.([]) a i) pq
done;
for i = 0 to n - 1 do
invariant { length pq = n - i }
invariant { sorted_sub a 0 i }
invariant { forall j k. 0 <= j < i -> 0 <= k < length pq ->
Array.([]) a j <= pq[k] }
invariant { forall x. MO.occ x (old a.elts) 0 n =
MO.occ x a.elts 0 i + SO.occ_all x pq }
a[i] <- PQ.safe_pop pq
done
end
(** {2 Simpler interface}
when duplicate elements are not allowed
*)
module PqueueNoDup
(** {3 Types} *)
type elt
(** the abstract type of elements *)
predicate le elt elt
(** `elt` is equipped with a total pre order `le` *)
clone export relations.TotalPreOrder
with type t = elt, predicate rel = le, axiom .
use set.Fset
type t = abstract { mutable elts: fset elt }
(** the priority queue is modeled as a finite set of elements *)
meta coercion function elts
(** {3 Operations} *)
val create () : t
ensures { result = empty }
(** create a fresh, empty queue *)
val push (x: elt) (q: t) : unit
writes { q }
ensures { q = add x (old q) }
(** push an element in a queue *)
exception Empty
(** exception raised by `pop` and `peek` to signal an empty queue *)
predicate minimal_elt (x: elt) (s: fset elt) =
mem x s /\ forall e: elt. mem e s -> le x e
(** property of the element returned by `pop` and `peek` *)
val pop (q: t) : elt
writes { q }
ensures { q = remove result (old q) }
ensures { minimal_elt result (old q) }
raises { Empty -> q = old q = empty }
(** remove and returns the minimal element *)
val safe_pop (q: t) : elt
writes { q }
requires { not q = empty }
ensures { q = remove result (old q) }
ensures { minimal_elt result (old q) }
(** remove and returns the minimal element *)
val peek (q: t) : elt
ensures { minimal_elt result q }
raises { Empty -> q = empty }
(** return the minimal element, without modifying the queue *)
val safe_peek (q: t) : elt
requires { not q = empty }
ensures { minimal_elt result q }
(** return the minimal element, without modifying the queue *)
val clear (q: t) : unit
writes { q }
ensures { q = empty }
(** empty the queue *)
val copy (q: t) : t
ensures { result = q }
(** return a fresh copy of the queue *)
val is_empty (q: t) : bool
ensures { result <-> q = empty }
(** check whether the queue is empty *)
val length (q: t) : int
ensures { result = cardinal q }
(** return the number of elements in the queue *)
end
|