Why3 Standard Library index
module Pqueue
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 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
the priority queue is modeled as a sorted sequence of elements
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 module Harness
Test the interface above using an external heapsort
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
when duplicate elements are not allowed
module PqueueNoDup
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
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
Generated by why3doc 1.8.0