VerifyThis @ ETAPS 2015: solution to challenge 1

parent 66605993
(**
{1 VerifyThis @ ETAPS 2015 competition, Challenge 1: Relaxed Prefix}
{h
The following is the original description of the verification task,
reproduced verbatim from
<a href="http://etaps2015.verifythis.org/challenges">the competition web site</a>.
<pre>
RELAXED PREFIX (60 minutes)
===========================
Description
-----------
Verify a function isRelaxedPrefix determining if a list _pat_ (for
pattern) is a relaxed prefix of another list _a_.
The relaxed prefix property holds iff _pat_ is a prefix of _a_ after
removing at most one element from _pat_.
Examples
--------
pat = {1,3} is a relaxed prefix of a = {1,3,2,3} (standard prefix)
pat = {1,2,3} is a relaxed prefix of a = {1,3,2,3} (remove 2 from pat)
pat = {1,2,4} is not a relaxed prefix of a = {1,3,2,3}.
Implementation notes
--------------------
You can implement lists as arrays, e.g., of integers. A reference
implementation is given below. It may or may not contain errors.
public class Relaxed {
public static boolean isRelaxedPrefix(int[] pat, int[] a) {
int shift = 0;
for(int i=0; i<pat.length; i++) {
if (pat[i]!=a[i-shift])
if (shift==0) shift=1;
else return false;
}
return true;
}
public static void main(String[] argv) {
int[] pat = {1,2,3};
int[] a1 = {1,3,2,3};
System.out.println(isRelaxedPrefix(pat, a1));
}
}
Advanced verification task (if you get bored)
---------------------------------------------
Implement and verify a function relaxedContains(pat, a) returning
whether _a_ contains _pat_ in the above relaxed sense, i.e., whether
_pat_ is a relaxed prefix of any suffix of _a_.
</pre>}
The following is the solution by Jean-Christophe Filliâtre (CNRS)
and Guillaume Melquiond (Inria) who entered the competition as "team Why3".
*)
module RelaxedPrefix
use import int.Int
use import ref.Ref
use import array.Array
type char
(** [a1[ofs1..ofs1+len]] and [a2[ofs2..ofs2+len]] are valid sub-arrays
and they are equal *)
predicate eq_array (a1: array char) (ofs1: int)
(a2: array char) (ofs2: int) (len: int) =
0 <= len /\ 0 <= ofs1 /\ 0 <= ofs2 /\
ofs1 + len <= length a1 /\ ofs2 + len <= length a2 /\
forall i: int. 0 <= i < len -> a1[ofs1 + i] = a2[ofs2 + i]
(** The target property. Note that this definition imposes the
index of the character which is ignored (index [i] in the existential
quantifier). It simplifies our proof, but a looser definition would
be possible (see the comment at the end of this file). *)
predicate is_relaxed_prefix (pat a: array char) =
let n = length pat in
eq_array pat 0 a 0 n
\/ exists i: int. 0 <= i < n /\
eq_array pat 0 a 0 i /\
(i = length a \/ pat[i] <> a[i]) /\
eq_array pat (i+1) a i (n - i - 1)
(** This exception is used to exit the loop as soon as the target
property is no more possible. *)
exception NoPrefix
(** Note regarding the code: the suggested pseudo-code is buggy, as it
may access [a] out of bounds. We fix it by strengthening the
test in the conditional. *)
let is_relaxed_prefix (pat a: array char) : bool
ensures { result <-> is_relaxed_prefix pat a }
=
let n = length pat in
let m = length a in
try
let shift = ref 0 in
let ghost ignored = ref 0 in
for i = 0 to n - 1 do
invariant { 0 <= !shift <= 1 }
invariant { i = 0 -> !shift = 0 }
invariant { !shift = 1 -> 0 <= !ignored < i }
invariant { m + !shift >= i }
invariant {
if !shift = 0 then eq_array pat 0 a 0 i
else eq_array pat 0 a 0 !ignored /\
eq_array pat (!ignored + 1) a !ignored (i - !ignored - 1) /\
not (eq_array pat 0 a 0 i) /\
(!ignored < m -> pat[!ignored] <> a[!ignored]) }
if i - !shift >= m || pat[i] <> a[i - !shift] then begin
if !shift = 1 then raise NoPrefix;
ignored := i;
shift := 1;
end
done;
True
with NoPrefix ->
False
end
(** a simpler definition of [is_relaxed_prefix] would be the following: *)
predicate simple_is_relaxed_prefix (pat a: array char) =
let n = length pat in
eq_array pat 0 a 0 n
\/ exists i: int. 0 <= i < n /\
eq_array pat 0 a 0 i /\
eq_array pat (i+1) a i (n - i - 1)
(* TODO: prove the equivalence
lemma equivalence:
forall pat a: array char.
is_relaxed_prefix pat a <-> simple_is_relaxed_prefix pat a
*)
end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE why3session PUBLIC "-//Why3//proof session v5//EN"
"http://why3.lri.fr/why3session.dtd">
<why3session shape_version="4">
<prover id="0" name="Alt-Ergo" version="0.95.2" timelimit="6" memlimit="1000"/>
<prover id="1" name="CVC4" version="1.4" timelimit="6" memlimit="1000"/>
<prover id="2" name="Z3" version="4.3.1" timelimit="6" memlimit="1000"/>
<file name="../verifythis_2015_relaxed_prefix.mlw" expanded="true">
<theory name="RelaxedPrefix" sum="1aec45f1cb638f259a0aa093f19178a1" expanded="true">
<goal name="WP_parameter is_relaxed_prefix" expl="VC for is_relaxed_prefix" expanded="true">
<transf name="split_goal_wp" expanded="true">
<goal name="WP_parameter is_relaxed_prefix.1" expl="1. postcondition">
<proof prover="0"><result status="valid" time="0.01" steps="6"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.2" expl="2. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="3"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.3" expl="3. loop invariant init">
<proof prover="0"><result status="valid" time="0.02" steps="3"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.4" expl="4. loop invariant init">
<proof prover="0"><result status="valid" time="0.02" steps="3"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.5" expl="5. loop invariant init">
<proof prover="0"><result status="valid" time="0.02" steps="5"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.6" expl="6. postcondition">
<transf name="inline_goal">
<goal name="WP_parameter is_relaxed_prefix.6.1" expl="1. postcondition">
<transf name="split_goal_wp">
<goal name="WP_parameter is_relaxed_prefix.6.1.1" expl="1. postcondition">
<proof prover="0" timelimit="30"><result status="valid" time="0.02" steps="11"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.6.1.2" expl="2. postcondition">
<proof prover="0"><result status="valid" time="0.03" steps="14"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
<goal name="WP_parameter is_relaxed_prefix.7" expl="7. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="12"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.8" expl="8. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="12"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.9" expl="9. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="12"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.10" expl="10. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="12"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.11" expl="11. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.15" steps="43"/></proof>
<proof prover="1" obsolete="true"><result status="timeout" time="6.04"/></proof>
<proof prover="2" obsolete="true"><result status="timeout" time="5.98"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.12" expl="12. index in array bounds">
<proof prover="0"><result status="valid" time="0.02" steps="10"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.13" expl="13. index in array bounds">
<proof prover="0"><result status="valid" time="0.01" steps="11"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.14" expl="14. postcondition">
<transf name="inline_goal">
<goal name="WP_parameter is_relaxed_prefix.14.1" expl="1. postcondition">
<transf name="split_goal_wp">
<goal name="WP_parameter is_relaxed_prefix.14.1.1" expl="1. postcondition">
<proof prover="0" timelimit="30"><result status="valid" time="0.03" steps="34"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.14.1.2" expl="2. postcondition">
<proof prover="0"><result status="valid" time="0.31" steps="353"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
<goal name="WP_parameter is_relaxed_prefix.15" expl="15. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="15"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.16" expl="16. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.17" expl="17. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="15"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.18" expl="18. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.19" expl="19. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.10" steps="77"/></proof>
<proof prover="2"><result status="valid" time="0.01"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.20" expl="20. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="12"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.21" expl="21. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="12"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.22" expl="22. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="16"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.23" expl="23. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="12"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.24" expl="24. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.08" steps="157"/></proof>
</goal>
<goal name="WP_parameter is_relaxed_prefix.25" expl="25. postcondition">
<proof prover="0"><result status="valid" time="0.00" steps="38"/></proof>
</goal>
</transf>
</goal>
</theory>
</file>
</why3session>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment