tortoise and hare example totally revamped

this is much closer now to TAOCP, vol 2, exercise 6 page 7
parent 626ca4d8
...@@ -3,88 +3,162 @@ ...@@ -3,88 +3,162 @@
See The Art of Computer Programming, vol 2, exercise 6 page 7. *) See The Art of Computer Programming, vol 2, exercise 6 page 7. *)
module TortoiseAndHare module TortoiseAndHareAlgorithm
use import int.Int use import int.Int
use int.Iter use import int.EuclideanDivision
use import int.Iter
use import seq.Seq
use import seq.Distinct
use import ref.Refint
use import pigeon.Pigeonhole
type t val function f int : int
val predicate eq (x y : t)
ensures { result <-> x = y }
(* let f be a function from t to t *) (* f maps 0..m-1 to 0..m-1 *)
val function f t : t constant m: int
axiom m_positive: m > 0
axiom f_range: forall x. 0 <= x < m -> 0 <= f x < m
(* given some initial value x0 *) (* given some initial value x0 *)
val constant x0: t val constant x0: int
ensures { 0 <= result < m }
(* we can build the infinite sequence defined by x{i+1} = f(xi) *) (* we can build the infinite sequence defined by x{i+1} = f(xi) *)
function x (i: int): t = Iter.iter f i x0 function x (i: int): int = iter f i x0
(* let use assume now that the sequence (x_i) has finitely many distinct let rec lemma x_in_range (n: int)
values (e.g. f is an integer function with values in 0..m) requires { 0 <= n } ensures { 0 <= x n < m }
variant { n }
it means that there exists values lambda and mu such that = if n > 0 then x_in_range (n - 1)
(1) x0, x1, ... x{mu+lambda-1} are all distinct,
and (* First, we prove the existence of mu and lambda, with a ghost program.
(2) x{n+lambda} = x_n when n >= mu. *) Starting with x0, we repeteadly apply f, storing the elements in
a sequence, until we find a repetition. *)
(* lambda and mu are skomlemized *) let ghost periodicity () : (int, int)
constant mu : int returns { mu, lambda ->
constant lambda : int 0 <= mu < m /\ 1 <= lambda <= m /\ mu + lambda <= m /\
x (mu + lambda) = x mu /\
(* they are axiomatized as follows *) forall i j. 0 <= i < j < mu + lambda -> x i <> x j
axiom mu_range: 0 <= mu }
= let s = ref (singleton x0) in
axiom lambda_range: 1 <= lambda let cur = ref x0 in
for k = 1 to m do
axiom distinct: invariant { 1 <= length !s = k <= m /\ !cur = !s[length !s - 1] }
forall i j: int. 0 <= i < mu+lambda -> 0 <= j < mu+lambda -> invariant { forall i. 0 <= i < length !s -> !s[i] = x i }
i <> j -> x i <> x j invariant { distinct !s }
cur := f !cur;
axiom cycle: forall n: int. mu <= n -> x (n + lambda) = x n (* look for a repetition *)
for mu = 0 to length !s - 1 do
lemma cycle_induction: invariant { forall i. 0 <= i < mu -> !s[i] <> !cur }
forall n: int. mu <= n -> forall k: int. 0 <= k -> x (n + lambda * k) = x n if !cur = !s[mu] then return (mu, length !s - mu)
done;
(* Now comes the code. s := snoc !s !cur;
Two references, tortoise and hare, traverses the sequence (xi) if k = m then pigeonhole (m+1) m (pure { fun i -> !s[i] })
at speed 1 and 2 respectively. We stop whenever they are equal. done;
absurd
The challenge is to prove termination.
Actually, we even prove that the code runs in time O(lambda + mu). *) (* Then we can state the condition for two elements to be equal. *)
let lemma equality (mu lambda: int)
use import ref.Ref requires { 0 <= mu < m /\ 1 <= lambda <= m /\ mu + lambda <= m /\
use import relations.WellFounded x (mu + lambda) = x mu }
requires { forall i j. 0 <= i < j < mu + lambda -> x i <> x j }
(* the minimal distance between x i and x j *) ensures { forall r n. r > n >= 0 ->
function dist int int : int x r = x n <-> n >= mu /\ exists k. k >= 1 /\ r-n = k*lambda }
= let rec lemma plus_lambda (n: int) variant { n }
(* it is defined as soon as i,j >= mu *) requires { mu <= n }
axiom dist_def: forall i j: int. mu <= i -> mu <= j -> ensures { x (n + lambda) = x n } =
dist i j >= 0 /\ if n > mu then plus_lambda (n - 1) in
x (i + dist i j) = x j /\ let rec lemma plus_lambdas (n k: int) variant { k }
forall k: int. 0 <= k -> x (i + k) = x j -> dist i j <= k requires { mu <= n } requires { 0 <= k }
ensures { x (n + k * lambda) = x n } =
predicate rel (t2 t1: t) = if k > 0 then begin
exists i: int. t1 = x i /\ t2 = x (i+1) /\ 1 <= i <= mu + lambda /\ plus_lambdas n (k - 1); plus_lambda (n + (k - 1) * lambda) end in
(i >= mu -> dist (2*i+2) (i+1) < dist (2*i) i) let decomp (i: int) : (int, int)
requires { i >= mu }
axiom wfrel: well_founded rel returns { qi,mi -> i = mu + qi * lambda + mi && qi >= 0 &&
0 <= mi < lambda && x i = x (mu + mi) } =
let tortoise_hare () = let qi = div (i - mu) lambda in
let mi = mod (i - mu) lambda in
plus_lambdas (mu + mi) qi;
qi, mi in
let lemma equ (r n: int)
requires { r > n >= 0 } requires { x r = x n }
ensures { n >= mu /\ exists k. k >= 1 /\ r-n = k*lambda } =
if n < mu then (if r >= mu then let _ = decomp r in absurd)
else begin
let qr,mr = decomp r in let qn, mn = decomp n in
assert { mr = mn };
assert { r-n = (qr-qn) * lambda }
end in
()
(* Finally, we implement the tortoise and hare algorithm that computes
the values of mu and lambda in linear time and constant space *)
let tortoise_and_hare () : (int, int)
returns { mu, lambda ->
0 <= mu < m /\ 1 <= lambda <= m /\ mu + lambda <= m /\
x (mu + lambda) = x mu /\
forall i j. 0 <= i < j < mu + lambda -> x i <> x j
}
= let mu, lambda = periodicity () in
equality mu lambda;
(* the first loop implements the tortoise and hare,
and finds the smallest n >= 1 such that x n = x (2n) *)
let tortoise = ref (f x0) in let tortoise = ref (f x0) in
let hare = ref (f (f x0)) in let hare = ref (f (f x0)) in
while not (eq !tortoise !hare) do let n = ref 1 in
while !tortoise <> !hare do
invariant { invariant {
exists t: int. 1 <= !n <= mu+lambda /\ !tortoise = x !n /\ !hare = x (2 * !n) /\
1 <= t <= mu+lambda /\ !tortoise = x t /\ !hare = x (2 * t) /\ forall i. 1 <= i < !n -> x i <> x (2*i) }
forall i: int. 1 <= i < t -> x i <> x (2*i) } variant { mu + lambda - !n }
variant { !tortoise with rel }
tortoise := f !tortoise; tortoise := f !tortoise;
hare := f (f !hare) hare := f (f !hare);
done incr n;
if !n > mu + lambda then begin
(* TODO: code to find out lambda and mu. See wikipedia. *) let m = lambda - mod mu lambda in
let i = mu + m in
assert { 2*i - i = (div mu lambda + 1) * lambda };
absurd
end
done;
let n = !n in
assert { n >= mu };
assert { exists k. k >= 1 /\ n = k * lambda >= 1 };
assert { forall j. j >= mu -> x j = x (j + n) };
let xn = !tortoise in
(* a first loop to find mu *)
let i = ref 0 in
let xi = ref x0 in (* = x i *)
let xni = ref xn in (* = x (n+i) *)
while !xi <> !xni do
invariant { 0 <= !i <= mu }
invariant { !xi = x !i /\ !xni = x (n + !i) }
invariant { forall j. 0 <= j < !i -> x j <> x (n + j) }
variant { mu - !i }
xi := f !xi;
xni := f !xni;
incr i;
done;
let m = !i in
assert { m = mu };
(* and a second loop to find lambda
(this is slightly less efficient than the argument in TAOCP,
but since the first loop is already O(mu+lambda), using two loops
respectively O(mu) and O(lambda) is not a problem). *)
i := 1;
xni := f xn;
while !xni <> xn do
invariant { !xni = x (n + !i) }
invariant { forall j. 1 <= j < !i -> x (n + j) <> x n }
invariant { 1 <= !i <= lambda }
variant { lambda - !i }
xni := f !xni;
incr i
done;
assert { !i = lambda };
m, !i
end end
...@@ -2,30 +2,370 @@ ...@@ -2,30 +2,370 @@
<!DOCTYPE why3session PUBLIC "-//Why3//proof session v5//EN" <!DOCTYPE why3session PUBLIC "-//Why3//proof session v5//EN"
"http://why3.lri.fr/why3session.dtd"> "http://why3.lri.fr/why3session.dtd">
<why3session shape_version="4"> <why3session shape_version="4">
<prover id="0" name="Coq" version="8.7.1" timelimit="5" steplimit="0" memlimit="1000"/> <prover id="2" name="Alt-Ergo" version="2.0.0" timelimit="1" steplimit="0" memlimit="1000"/>
<prover id="1" name="Coq" version="8.7.2" timelimit="5" steplimit="0" memlimit="0"/> <prover id="5" name="Z3" version="4.4.0" timelimit="1" steplimit="0" memlimit="1000"/>
<prover id="3" name="Alt-Ergo" version="1.30" timelimit="5" steplimit="0" memlimit="1000"/> <prover id="6" name="CVC4" version="1.5" timelimit="1" steplimit="0" memlimit="1000"/>
<prover id="4" name="Z3" version="4.5.0" timelimit="5" steplimit="0" memlimit="1000"/> <prover id="7" name="Eprover" version="1.8-001" timelimit="16" steplimit="0" memlimit="1000"/>
<file name="../tortoise_and_hare.mlw" proved="true"> <file name="../tortoise_and_hare.mlw" proved="true">
<theory name="TortoiseAndHare" proved="true"> <theory name="TortoiseAndHareAlgorithm" proved="true">
<goal name="VC x0" expl="VC for x0" proved="true"> <goal name="VC x0" expl="VC for x0" proved="true">
<transf name="split_goal_right" proved="true" > <proof prover="6"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="VC x_in_range" expl="VC for x_in_range" proved="true">
<proof prover="2"><result status="valid" time="0.36" steps="311"/></proof>
</goal>
<goal name="VC periodicity" expl="VC for periodicity" proved="true">
<transf name="split_vc" proved="true" >
<goal name="VC periodicity.0" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="VC periodicity.1" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.18"/></proof>
</goal>
<goal name="VC periodicity.2" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.06"/></proof>
</goal>
<goal name="VC periodicity.3" expl="loop invariant init" proved="true">
<proof prover="2"><result status="valid" time="0.01" steps="16"/></proof>
</goal>
<goal name="VC periodicity.4" expl="VC for periodicity" proved="true">
<proof prover="6"><result status="valid" time="0.19"/></proof>
</goal>
<goal name="VC periodicity.5" expl="loop invariant preservation" proved="true">
<proof prover="6"><result status="valid" time="0.07"/></proof>
</goal>
<goal name="VC periodicity.6" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC periodicity.7" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.19"/></proof>
</goal>
<goal name="VC periodicity.8" expl="loop invariant preservation" proved="true">
<proof prover="6"><result status="valid" time="1.24"/></proof>
</goal>
<goal name="VC periodicity.9" expl="loop invariant preservation" proved="true">
<proof prover="2"><result status="valid" time="0.92" steps="823"/></proof>
</goal>
<goal name="VC periodicity.10" expl="loop invariant preservation" proved="true">
<proof prover="6"><result status="valid" time="0.16"/></proof>
</goal>
<goal name="VC periodicity.11" expl="VC for periodicity" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
<goal name="VC periodicity.12" expl="unreachable point" proved="true">
<proof prover="6"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="VC periodicity.13" expl="unreachable point" proved="true">
<proof prover="6"><result status="valid" time="0.06"/></proof>
</goal>
</transf> </transf>
</goal> </goal>
<goal name="cycle_induction" proved="true"> <goal name="VC equality" expl="VC for equality" proved="true">
<proof prover="0" edited="tortoise_and_hare_WP_TortoiseAndHare_cycle_induction_1.v"><result status="valid" time="0.36"/></proof> <transf name="split_vc" proved="true" >
<goal name="VC equality.0" expl="variant decrease" proved="true">
<proof prover="6"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="VC equality.1" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC equality.2" expl="postcondition" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC equality.3" expl="variant decrease" proved="true">
<proof prover="6"><result status="valid" time="0.07"/></proof>
</goal>
<goal name="VC equality.4" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
<goal name="VC equality.5" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
<goal name="VC equality.6" expl="precondition" proved="true">
<transf name="assert" proved="true" arg1="((k-1)*lambda &gt;= 0)">
<goal name="VC equality.6.0" proved="true">
<proof prover="7"><result status="valid" time="2.45"/></proof>
</goal>
<goal name="VC equality.6.1" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
</transf>
</goal>
<goal name="VC equality.7" expl="postcondition" proved="true">
<proof prover="6"><result status="valid" time="0.06"/></proof>
</goal>
<goal name="VC equality.8" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="VC equality.9" expl="precondition" proved="true">
<transf name="split_all_full" proved="true" >
<goal name="VC equality.9.0" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.09"/></proof>
</goal>
</transf>
</goal>
<goal name="VC equality.10" expl="precondition" proved="true">
<transf name="split_vc" proved="true" >
<goal name="VC equality.10.0" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
</transf>
</goal>
<goal name="VC equality.11" expl="precondition" proved="true">
<proof prover="5"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="VC equality.12" expl="postcondition" proved="true">
<proof prover="5"><result status="valid" time="0.18"/></proof>
</goal>
<goal name="VC equality.13" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="VC equality.14" expl="unreachable point" proved="true">
<transf name="split_all_full" proved="true" >
<goal name="VC equality.14.0" expl="unreachable point" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
</transf>
</goal>
<goal name="VC equality.15" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC equality.16" expl="precondition" proved="true">
<transf name="split_vc" proved="true" >
<goal name="VC equality.16.0" expl="precondition" proved="true">
<proof prover="7"><result status="valid" time="0.03"/></proof>
</goal>
</transf>
</goal>
<goal name="VC equality.17" expl="assertion" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC equality.18" expl="assertion" proved="true">
<proof prover="5"><result status="valid" time="0.21"/></proof>
</goal>
<goal name="VC equality.19" expl="postcondition" proved="true">
<proof prover="2"><result status="valid" time="0.03" steps="73"/></proof>
</goal>
<goal name="VC equality.20" expl="postcondition" proved="true">
<transf name="split_vc" proved="true" >
<goal name="VC equality.20.0" expl="VC for equality" proved="true">
<proof prover="6"><result status="valid" time="0.08"/></proof>
</goal>
<goal name="VC equality.20.1" expl="VC for equality" proved="true">
<proof prover="2"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="VC equality.20.2" expl="VC for equality" proved="true">
<transf name="assert" proved="true" arg1="((k-1) * lambda &gt;= 0)">
<goal name="VC equality.20.2.0" proved="true">
<proof prover="7"><result status="valid" time="5.90"/></proof>
</goal>
<goal name="VC equality.20.2.1" expl="VC for equality" proved="true">
<proof prover="7"><result status="valid" time="0.22"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
</transf>
</goal> </goal>
<goal name="VC tortoise_hare" expl="VC for tortoise_hare" proved="true"> <goal name="VC tortoise_and_hare" expl="VC for tortoise_and_hare" proved="true">
<transf name="split_goal_right" proved="true" > <transf name="split_vc" proved="true" >
<goal name="VC tortoise_hare.0" expl="loop invariant init" proved="true"> <goal name="VC tortoise_and_hare.0" expl="precondition" proved="true">
<proof prover="3"><result status="valid" time="0.02" steps="77"/></proof> <proof prover="6"><result status="valid" time="0.02"/></proof>
<proof prover="4" obsolete="true"><result status="valid" time="0.02"/></proof> </goal>
<goal name="VC tortoise_and_hare.1" expl="precondition" proved="true">
<transf name="split_vc" proved="true" >
<goal name="VC tortoise_and_hare.1.0" expl="precondition" proved="true">
<transf name="split_all_full" proved="true" >
<goal name="VC tortoise_and_hare.1.0.0" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.2" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.07"/></proof>
</goal>
<goal name="VC tortoise_and_hare.3" expl="precondition" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="VC tortoise_and_hare.4" expl="assertion" proved="true">
<proof prover="2"><result status="valid" time="0.02" steps="20"/></proof>
</goal>
<goal name="VC tortoise_and_hare.5" expl="unreachable point" proved="true">
<proof prover="2"><result status="valid" time="0.63" steps="396"/></proof>
</goal>
<goal name="VC tortoise_and_hare.6" expl="loop variant decrease" proved="true">
<proof prover="6"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="VC tortoise_and_hare.7" expl="loop invariant preservation" proved="true">
<transf name="split_vc" proved="true" >
<goal name="VC tortoise_and_hare.7.0" expl="VC for tortoise_and_hare" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="VC tortoise_and_hare.7.1" expl="VC for tortoise_and_hare" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC tortoise_and_hare.7.2" expl="VC for tortoise_and_hare" proved="true">
<proof prover="6"><result status="valid" time="0.29"/></proof>
</goal>
<goal name="VC tortoise_and_hare.7.3" expl="VC for tortoise_and_hare" proved="true">
<proof prover="6"><result status="valid" time="0.12"/></proof>
</goal>
<goal name="VC tortoise_and_hare.7.4" expl="VC for tortoise_and_hare" proved="true">
<proof prover="6"><result status="valid" time="0.10"/></proof>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.8" expl="assertion" proved="true">
<proof prover="5"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="VC tortoise_and_hare.9" expl="assertion" proved="true">
<transf name="instantiate" proved="true" arg1="H7" arg2="(n+n),n">
<goal name="VC tortoise_and_hare.9.0" expl="assertion" proved="true">
<proof prover="2"><result status="valid" time="0.01" steps="33"/></proof>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.10" expl="assertion" proved="true">
<transf name="destruct" proved="true" arg1="H1">
<goal name="VC tortoise_and_hare.10.0" expl="assertion" proved="true">
<transf name="replace" proved="true" arg1="n" arg2="(k*lambda)">
<goal name="VC tortoise_and_hare.10.0.0" expl="assertion" proved="true">
<transf name="instantiate" proved="true" arg1="H10" arg2="(j+n),j">
<goal name="VC tortoise_and_hare.10.0.0.0" expl="assertion" proved="true">
<proof prover="6"><result status="valid" time="0.12"/></proof>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.10.0.1" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.11" expl="loop invariant init" proved="true">
<transf name="split_all_full" proved="true" >
<goal name="VC tortoise_and_hare.11.0" expl="VC for tortoise_and_hare" proved="true">
<proof prover="2"><result status="valid" time="0.01" steps="19"/></proof>
</goal>
<goal name="VC tortoise_and_hare.11.1" expl="VC for tortoise_and_hare" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.12" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.25"/></proof>
</goal>
<goal name="VC tortoise_and_hare.13" expl="loop invariant init" proved="true">
<proof prover="5"><result status="valid" time="0.01"/></proof>
</goal>
<goal name="VC tortoise_and_hare.14" expl="loop variant decrease" proved="true">
<transf name="case" proved="true" arg1="(i = mu+1)">
<goal name="VC tortoise_and_hare.14.0" expl="true case (loop variant decrease)" proved="true">
<transf name="assert" proved="true" arg1="(x mu = x (mu + n))">
<goal name="VC tortoise_and_hare.14.0.0" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
<goal name="VC tortoise_and_hare.14.0.1" expl="true case (loop variant decrease)" proved="true">
<proof prover="6"><result status="valid" time="0.12"/></proof>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.14.1" expl="false case (loop variant decrease)" proved="true">
<proof prover="5"><result status="valid" time="0.03"/></proof>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.15" expl="loop invariant preservation" proved="true">
<transf name="replace" proved="true" arg1="n" arg2="(2*n - n)">
<goal name="VC tortoise_and_hare.15.0" expl="loop invariant preservation" proved="true">
<proof prover="2"><result status="valid" time="0.01" steps="36"/></proof>
</goal>
<goal name="VC tortoise_and_hare.15.1" proved="true">
<proof prover="6"><result status="valid" time="0.02"/></proof>
</goal>
</transf>
</goal>
<goal name="VC tortoise_and_hare.16" expl="loop invariant preservation" proved="true">
<proof prover="6"><result status="valid" time="0.27"/></proof>
</goal>
<goal name="VC tortoise_and_hare.17" expl="loop invariant preservation" proved="true">
<proof prover="6"><result status="valid" time="0.07"/></proof>
</goal>
<goal name="VC tortoise_and_hare.18" expl="assertion" proved="true">
<proof prover="6"><result status="valid" time="0.60"/></proof>
</goal>
<goal name="VC tortoise_and_hare.19" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.09"/></proof>
</goal>
<goal name="VC tortoise_and_hare.20" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC tortoise_and_hare.21" expl="loop invariant init" proved="true">
<proof prover="6"><result status="valid" time="0.05"/></proof>
</goal>
<goal name="VC tortoise_and_hare.22" expl="loop variant decrease" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="VC tortoise_and_hare.23" expl="loop invariant preservation" proved="true">
<proof prover="6"><result status="valid" time="0.06"/></proof>
</goal>
<goal name="VC tortoise_and_hare.24" expl="loop invariant preservation" proved="true">
<proof prover="2"><result status="valid" time="0.02" steps="41"/></proof>
</goal>
<goal name="VC tortoise_and_hare.25" expl="loop invariant preservation" proved="true">
<transf name="split_vc" proved="true" >
<goal name="VC tortoise_and_hare.25.0" expl="VC for tortoise_and_hare" proved="true">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="VC tortoise_and_hare.25.1" expl="VC for tortoise_and_hare" proved="true">
<transf name="assert" proved="true" arg1="(x (n+lambda) = x n)">
<goal name="VC tortoise_and_hare.25.1.0" proved="true">
<proof prover="6"><result status="valid" time="0.39"/></proof>
</goal>
<goal name="VC tortoise_and_hare.25.1.1" expl="VC for tortoise_and_hare" proved="true">
<proof prover="5"><result status="valid" time="0.02"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal> </goal>
<goal name="VC tortoise_hare.1" expl="loop variant decrease" proved="true"> <goal name="VC tortoise_and_hare.26" expl="assertion" proved="true">
<proof prover="1" memlimit="1000" edited="tortoise_and_hare_WP_TortoiseAndHare_WP_parameter_tortoise_hare_1.v"><result status="valid" time="0.43"/></proof> <transf name="instantiate" proved="true" arg1="H23" arg2="(n+i),n">
<goal name="VC tortoise_and_hare.26.0" expl="assertion" proved="true">
<transf name="assert" proved="true" arg1="(exists k. k &gt;= 1 /\ i = k * lambda)">
<goal name="VC tortoise_and_hare.26.0.0" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="VC tortoise_and_hare.26.0.1" expl="assertion" proved="true">
<transf name="destruct" proved="true" arg1="h">
<goal name="VC tortoise_and_hare.26.0.1.0" expl="assertion" proved="true">
<transf name="case" proved="true" arg1="(k=1)">
<goal name="VC tortoise_and_hare.26.0.1.0.0" expl="true case (assertion)" proved="true">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="VC tortoise_and_hare.26.0.1.0.1" expl="false case (assertion)" proved="true">
<transf name="assert" proved="true" arg1="(x (n + (k-1) * lambda) = x n)">
<goal name="VC tortoise_and_hare.26.0.1.0.1.0" proved="true">
<proof prover="6"><result status="valid" time="0.52"/></proof>
</goal>
<goal name="VC tortoise_and_hare.26.0.1.0.1.1" expl="false case (assertion)" proved="true">
<proof prover="6"><result status="valid" time="0.60"/></proof>
</goal>
</transf>
</goal>