Files
why3/stdlib/pqueue.mlw

210 lines
5.3 KiB
Plaintext
Raw Permalink Normal View History

2012-05-07 15:12:08 +02:00
(** {1 Priority queues} *)
(** {2 Polymorphic mutable priority queues} *)
2011-09-15 13:02:44 +02:00
module Pqueue
2012-05-07 15:12:08 +02:00
(** {3 Types} *)
2011-09-15 13:02:44 +02:00
type elt
(** the abstract type of elements *)
2011-09-15 13:02:44 +02:00
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
2012-05-07 15:12:08 +02:00
(** {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
2018-06-14 08:10:07 +02:00
(** 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
2012-05-07 15:12:08 +02:00
(** {2 Simpler interface}
2012-10-13 00:23:29 +02:00
when duplicate elements are not allowed
2012-05-07 15:12:08 +02:00
*)
module PqueueNoDup
2012-05-07 15:12:08 +02:00
(** {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
2011-09-15 13:02:44 +02:00
2019-03-07 11:09:04 +01:00
type t = abstract { mutable elts: fset elt }
(** the priority queue is modeled as a finite set of elements *)
meta coercion function elts
2011-09-15 13:02:44 +02:00
2012-05-07 15:12:08 +02:00
(** {3 Operations} *)
val create () : t
ensures { result = empty }
(** create a fresh, empty queue *)
2011-09-15 13:02:44 +02:00
val push (x: elt) (q: t) : unit
writes { q }
ensures { q = add x (old q) }
(** push an element in a queue *)
2011-09-15 13:02:44 +02:00
exception Empty
2018-06-14 08:10:07 +02:00
(** exception raised by `pop` and `peek` to signal an empty queue *)
2011-09-15 13:02:44 +02:00
2019-03-07 11:09:04 +01:00
predicate minimal_elt (x: elt) (s: fset elt) =
mem x s /\ forall e: elt. mem e s -> le x e
2018-06-14 08:10:07 +02:00
(** 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 *)
2011-09-15 13:02:44 +02:00
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 *)
2011-09-15 13:02:44 +02:00
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 *)
2011-09-15 13:02:44 +02:00
val copy (q: t) : t
ensures { result = q }
(** return a fresh copy of the queue *)
2011-09-15 13:02:44 +02:00
val is_empty (q: t) : bool
ensures { result <-> q = empty }
(** check whether the queue is empty *)
2011-09-15 13:02:44 +02:00
val length (q: t) : int
ensures { result = cardinal q }
(** return the number of elements in the queue *)
2011-09-15 13:02:44 +02:00
end