Longest Common Prefix (Quantified Permissions)

Challenge from the VerifyThis Verification Competition 2012: finding the longest common prefix in an array.

/* First task of the longest common prefix problem from * VerifyThis@FM2012: http://fm2012.verifythis.org/challenges */ define access(a) forall k: Int :: 0 <= k && k < len(a) ==> acc(loc(a, k).val) define untouched(a) forall k: Int :: 0 <= k && k < len(a) ==> loc(a, k).val == old(loc(a, k).val) /* Task A */ // used to write matching trigger terms below function offset(k:Int, x:Int, y:Int) : Int { y + k - x } method lcp(a: IArray, x: Int, y: Int) returns (n: Int) requires access(a) requires 0 <= x && 0 <= y && x < len(a) && y < len(a) ensures access(a) ensures 0 <= n && x + n <= len(a) && y + n <= len(a) ensures forall k: Int :: {loc(a, offset(k,x,y))} // instantiation trigger term x <= k && k < x + n ==> loc(a, k).val == loc(a, offset(k,x,y)).val /* The following postcondition is logically equivalent to the previous one, and a bit * easier to understand. However, it can currently not be used because it contains * no possible triggers (due to the arithmetic operations inside the loc-expressions). */ // ensures forall k: Int :: 0 <= k && k < n ==> loc(a, x + k).val == loc(a, y + k).val ensures x + n < len(a) && y + n < len(a) ==> loc(a, x + n).val != loc(a, y + n).val { n := 0 while (x + n < len(a) && y + n < len(a) && loc(a, x + n).val == loc(a, y + n).val) invariant n >= 0 invariant access(a) invariant x + n <= len(a) && y + n <= len(a) invariant forall k: Int :: {loc(a, offset(k,x,y))} // instantiation trigger term x <= k && k < x + n ==> loc(a, k).val == loc(a, offset(k,x,y)).val { n := n + 1 } } /* Encoding of arrays */ field val: Int domain IArray { function loc(a: IArray, i: Int): Ref function len(a: IArray): Int function first(r: Ref): IArray function second(r: Ref): Int axiom all_diff { forall a: IArray, i: Int :: {loc(a, i)} first(loc(a, i)) == a && second(loc(a, i)) == i } axiom length_nonneg { forall a: IArray :: len(a) >= 0 } }