domain T {}
adt Ordering {
Less()
Equal()
Greater()
}
domain PartialCmp[DomT] {
function compare(self: DomT, other: DomT): Ordering
axiom { forall a: DomT, b: DomT :: {compare(a, b)} (compare(a, b) == Equal()) == (a == b) }
axiom { forall a: DomT, b: DomT, c: DomT :: {compare(a, b), compare(b, c)} compare(a, b).isLess && compare(b, c).isLess ==> compare(a, c).isLess }
}
method binary_search(data: Seq[T], key: T)
returns (found: Bool)
requires forall a: Int, b: Int :: {data[a], data[b]} 0 <= a < b < |data| ==> !compare(data[a], data[b]).isGreater
ensures found == (key in data)
//decreases
{
var lo: Int := 0
var hi: Int := |data|
found := false
while (!found && lo < hi)
invariant 0 <= lo <= hi <= |data|
invariant !found ==> !(key in data[..lo]) && !(key in data[hi..])
invariant found ==> (key in data)
//decreases hi - lo
{
var mid: Int := lo + (hi - lo) / 2
if (compare(data[mid], key).isLess) {
lo := mid + 1
} elseif (compare(data[mid], key).isEqual) {
found := true
} else {
hi := mid
}
}
}
The following snippet verifies, but does not prove termination:
generic_search.vprWhen the loop variant
decreases hi - lois added, the IDE reports errors with no positions, i.e., the status bar says "4 errors due to imported files":Why is it failing this way? The termination measure is just an integer -- does the termination plugin try to use the "generic" type in constructing the proof here?
Note that the monomorphic/integer version verifies fine, including the termination measures (as expected).
monomorphic_search.vpr