len package:sbv
Coding list-length recursively. Again, we map directly to an SMTLib
function.
Length of a list.
>>> sat $ \(l :: SList Word16) -> length l .== 2
Satisfiable. Model:
s0 = [0,0] :: [Word16]
>>> sat $ \(l :: SList Word16) -> length l .< 0
Unsatisfiable
>>> prove $ \(l1 :: SList Word16) (l2 :: SList Word16) -> length l1 + length l2 .== length (l1 ++ l2)
Q.E.D.
Length of a string.
>>> sat $ \s -> length s .== 2
Satisfiable. Model:
s0 = "BA" :: String
>>> sat $ \s -> length s .< 0
Unsatisfiable
>>> prove $ \s1 s2 -> length s1 + length s2 .== length (s1 ++ s2)
Q.E.D.
length (xs ++ ys) == length xs + length ys
We have:
>>> lenAppend
Lemma: lenAppend Q.E.D.
[Proven] lenAppend
length xs == length ys -> length (xs ++ ys) == 2 * length xs
We have:
>>> lenAppend2
Lemma: lenAppend2 Q.E.D.
[Proven] lenAppend2
length (x : xs) = 1 + length xs
We have:
>>> lengthTail
Lemma: lengthTail Q.E.D.
[Proven] lengthTail
n >= 0 ==> length (drop n xs) = (length xs - n) `max` 0
>>> length_drop
Lemma: length_drop Q.E.D.
[Proven] length_drop
n >= 0 ==> length (take n xs) = length xs `min` n
>>> length_take
Lemma: length_take Q.E.D.
[Proven] length_take
Calculate the length of a list, using recursive functions.
We have:
>>> lenExample
Satisfiable. Model:
s0 = [1,2,3] :: [Integer]
s1 = 3 :: Integer
Proof of correctness of an imperative list-length algorithm, using
weakest preconditions. Illustrates the use of SBV's symbolic lists
together with the WP algorithm.
The state of the length program, paramaterized over the element type
a
Unique length used for firstified names.
Line length for KD proofs
It is instructive to see what kind of counter-example we get if a
lemma fails to prove. Below, we do a variant of the 'lengthTail, but
with a bad implementation over integers, and see the counter-example.
Our implementation returns an incorrect answer if the given list is
longer than 5 elements and have 42 in it. We have:
>>> badLengthProof `catch` (\(_ :: SomeException) -> pure ())
Lemma: badLengthProof
*** Failed to prove badLengthProof.
Falsifiable. Counter-example:
xs = [15,11,13,16,27,42] :: [Integer]
imp = 42 :: Integer
spec = 6 :: Integer
An example where we attempt to prove a non-theorem. Notice the
counter-example generated for:
length xs = ite (length xs .== 3) 5 (length xs)
We have:
>>> badRevLen `catch` (\(_ :: SomeException) -> pure ())
Lemma: badRevLen
*** Failed to prove badRevLen.
Falsifiable. Counter-example:
xs = [A_1,A_2,A_1] :: [A]
length xs == length (reverse xs)
We have:
>>> revLen
Inductive lemma: revLen
Step: Base Q.E.D.
Step: 1 Q.E.D.
Step: 2 Q.E.D.
Step: 3 Q.E.D.
Step: 4 Q.E.D.
Result: Q.E.D.
[Proven] revLen
Prove that interleave preserves total length.
The induction here is on the total length of the lists, and hence we
use the generalized induction principle. We have:
>>> interleaveLen
Inductive lemma (strong): interleaveLen
Step: Measure is non-negative Q.E.D.
Step: 1 (2 way full case split)
Step: 1.1 Q.E.D.
Step: 1.2.1 Q.E.D.
Step: 1.2.2 Q.E.D.
Step: 1.2.3 Q.E.D.
Result: Q.E.D.
[Proven] interleaveLen
A program is the algorithm, together with its pre- and
post-conditions.