Longest Increasing Subsequence
Verification of a simple backtracking algorithm to find out the length of a longest increasing subsequence, inspired by Jeff Erickson's Algorithms, section 2.7.
Authors: Jean-Christophe Filliâtre
Topics: Words / Algorithms
Tools: Why3
see also the index (by topic, by tool, by reference, by year)
Longest Increasing Subsequence
A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. The longest increasing subsequence problem aims to find a subsequence of a given sequence in which the subsequence's elements are sorted in an ascending order and in which the subsequence is as long as possible. (Wikipedia)
In the following, we verify a simple backtracking algorithm to find out the length of a longest increasing subsequence, inspired by Jeff Erickson's Algorithms, section 2.7. See here.
Note: There are more efficient algorithms to solve this problem. See Wikipedia.
Author: Jean-Christophe Filliâtre (CNRS)
module Spec use int.Int use seq.Seq type elt val predicate lt elt elt clone relations.TotalStrictOrder with type t = elt, predicate rel = lt, axiom . type word = seq elt predicate iss (s: seq int) (w: word) = (* s maps 0..|s| to w's characters *) (forall i. 0 <= i < length s -> 0 <= s[i] < length w) && (* in a strictly increasing way *) (forall i j. 0 <= i < j < length s -> s[i] < s[j] && lt w[s[i]] w[s[j]])
[s] describes an increasing subsequence of [w]
predicate liss (s: seq int) (w: word) = iss s w && forall s'. iss s' w -> length s' <= length s
[s] is a longest increasing subsequence of [w]
end module Backtracking use int.Int use seq.Seq use seq.FreeMonoid use Spec let liss (w: word) : (len: int, ghost s: seq int) ensures { len = length s } ensures { liss s w } = let rec liss_from (i: int) : (len: int, ghost s: seq int) requires { 0 <= i < length w } variant { length w - i } ensures { len = length s > 0 } ensures { s[0] = i } ensures { iss s w } ensures { forall s'. iss s' w -> length s' >= 1 -> s'[0] = i -> length s' <= length s } = let ref len = 1 in let ghost ref s = singleton i in for j = i + 1 to length w - 1 do invariant { len = length s > 0 } invariant { s[0] = i } invariant { iss s w } invariant { forall s' k. iss s' w -> length s' >= 2 -> s'[0] = i < s'[1] = k < j -> length s' <= length s } if lt w[i] w[j] then let lenj, sj = liss_from j in if 1 + lenj > len then len, s <- 1 + lenj, cons i sj done; (len, s) in let ref len = 0 in let ghost ref s = empty in for i = 0 to length w - 1 do invariant { len = length s } invariant { iss s w } invariant { forall s' j. iss s' w -> length s' >= 1 -> s'[0] = j < i -> length s' <= length s } let leni, si = liss_from i in if leni > len then len, s <- leni, si done; (len, s) end
download ZIP archive
Why3 Proof Results for Project "longest_increasing_subsequence"
Theory "longest_increasing_subsequence.Backtracking": fully verified
| Obligations | Alt-Ergo 2.4.0 | CVC5 1.0.5 | Z3 4.8.10 | ||||||||
| VC for liss | --- | --- | --- | ||||||||
| split_vc | |||||||||||
| loop invariant init | --- | --- | 0.02 | ||||||||
| loop invariant init | --- | --- | 0.02 | ||||||||
| loop invariant init | --- | 0.13 | --- | ||||||||
| loop invariant init | --- | --- | 0.07 | ||||||||
| variant decrease | --- | 0.13 | --- | ||||||||
| precondition | --- | --- | 0.05 | ||||||||
| loop invariant preservation | --- | 0.13 | --- | ||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| unfold iss in Ensures4 | |||||||||||
| loop invariant preservation | 0.02 | --- | --- | ||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| unfold iss in Ensures4 | |||||||||||
| loop invariant preservation | 0.41 | --- | --- | ||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| unfold iss in Ensures4 | |||||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| split_vc | |||||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| unfold iss in H5 | |||||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| split_vc | |||||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| case (k < j) | |||||||||||
| true case (loop invariant preservation) | --- | 0.14 | --- | ||||||||
| false case (loop invariant preservation) | --- | --- | --- | ||||||||
| assert (length s'[1..] <= length s[1..]) | |||||||||||
| asserted formula | --- | --- | --- | ||||||||
| assert (s'[1..][0] = j) | |||||||||||
| asserted formula | 0.06 | --- | --- | ||||||||
| asserted formula | 0.91 | --- | --- | ||||||||
| false case (loop invariant preservation) | --- | --- | 0.08 | ||||||||
| loop invariant preservation | --- | --- | 0.03 | ||||||||
| loop invariant preservation | --- | --- | 0.03 | ||||||||
| loop invariant preservation | --- | --- | 0.03 | ||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| unfold iss in Ensures1 | |||||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| unfold iss in H5 | |||||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| split_vc | |||||||||||
| loop invariant preservation | --- | --- | --- | ||||||||
| case (k < j) | |||||||||||
| true case (loop invariant preservation) | 0.05 | --- | --- | ||||||||
| false case (loop invariant preservation) | --- | --- | --- | ||||||||
| assert (length s'[1..] <= length s[1..]) | |||||||||||
| asserted formula | --- | --- | --- | ||||||||
| assert (s'[1..][0] = j) | |||||||||||
| asserted formula | --- | 0.10 | --- | ||||||||
| asserted formula | 0.09 | --- | --- | ||||||||
| false case (loop invariant preservation) | --- | --- | 0.07 | ||||||||
| loop invariant preservation | --- | --- | 0.02 | ||||||||
| loop invariant preservation | --- | --- | 0.03 | ||||||||
| loop invariant preservation | --- | --- | 0.03 | ||||||||
| loop invariant preservation | --- | 0.09 | --- | ||||||||
| postcondition | --- | --- | 0.03 | ||||||||
| postcondition | --- | --- | 0.02 | ||||||||
| postcondition | --- | --- | 0.05 | ||||||||
| postcondition | --- | --- | --- | ||||||||
| case (length s' = 1) | |||||||||||
| true case (postcondition) | --- | --- | 0.04 | ||||||||
| false case (postcondition) | --- | --- | --- | ||||||||
| assert (i < s'[1] < length w) | |||||||||||
| asserted formula | --- | --- | --- | ||||||||
| unfold iss in H2 | |||||||||||
| asserted formula | 0.03 | --- | --- | ||||||||
| false case (postcondition) | --- | 0.14 | --- | ||||||||
| out of loop bounds | --- | --- | 0.03 | ||||||||
| loop invariant init | --- | --- | 0.03 | ||||||||
| loop invariant init | --- | --- | 0.02 | ||||||||
| loop invariant init | --- | 0.16 | --- | ||||||||
| precondition | --- | --- | 0.03 | ||||||||
| loop invariant preservation | --- | --- | 0.05 | ||||||||
| loop invariant preservation | --- | 0.16 | --- | ||||||||
| loop invariant preservation | --- | 0.17 | --- | ||||||||
| loop invariant preservation | --- | 0.06 | --- | ||||||||
| loop invariant preservation | --- | --- | 0.07 | ||||||||
| loop invariant preservation | --- | 0.15 | --- | ||||||||
| postcondition | --- | --- | 0.02 | ||||||||
| postcondition | --- | 0.08 | --- | ||||||||
| out of loop bounds | --- | --- | 0.05 | ||||||||