Commit 9bcb4076 authored by Jean-Christophe Filliâtre's avatar Jean-Christophe Filliâtre
Browse files

added solutions for VerifyThis 2017

parent af08d5c4
(* VerifyThis 2017 challenge 2 (**
Maximum-sum submatrix (2D version of Kadane's algorithm) {1 VerifyThis @ ETAPS 2017 competition
Challenge 2: Maximum-sum submatrix}
See https://formal.iti.kit.edu/ulbrich/verifythis2017/
Author: Jean-Christophe Filliâtre (CNRS)
*) *)
(* note: this is a 2D-version of maximum-sum subarray, for which several
verified implementations can be found in maximum_subarray.mlw,
including Kadane's linear algorithm *)
module Kadane2D module Kadane2D
use import int.Int use import int.Int
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<prover id="0" name="Alt-Ergo" version="1.30" timelimit="5" steplimit="0" memlimit="1000"/> <prover id="0" name="Alt-Ergo" version="1.30" timelimit="5" steplimit="0" memlimit="1000"/>
<prover id="1" name="CVC4" version="1.4" timelimit="5" steplimit="0" memlimit="1000"/> <prover id="1" name="CVC4" version="1.4" timelimit="5" steplimit="0" memlimit="1000"/>
<prover id="2" name="Z3" version="4.4.0" timelimit="5" steplimit="0" memlimit="1000"/> <prover id="2" name="Z3" version="4.4.0" timelimit="5" steplimit="0" memlimit="1000"/>
<file name="../kadane_2d.mlw"> <file name="../verifythis_2017_maximum_sum_submatrix.mlw">
<theory name="Kadane2D" sum="09fbb7ac5139de301e5efc628ae0287e"> <theory name="Kadane2D" sum="09fbb7ac5139de301e5efc628ae0287e">
<goal name="VC maximum_submatrix" expl="VC for maximum_submatrix"> <goal name="VC maximum_submatrix" expl="VC for maximum_submatrix">
<transf name="split_goal_wp"> <transf name="split_goal_wp">
......
(**
{1 VerifyThis @ ETAPS 2017 competition
Challenge 3: Odd-Even Transposition Sort}
See https://formal.iti.kit.edu/ulbrich/verifythis2017/
Author: Jean-Christophe Filliâtre (CNRS)
*)
(* note: this is only a solution for the sequential (single processor) version
of the challenge *)
module Challenge3
use import int.Int
use import int.Sum
use import int.NumOf
use import int.ComputerDivision
use import ref.Refint
use import array.Array
use import array.IntArraySorted
use import array.ArraySwap
use import array.ArrayPermut
(* odd-sorted up to n exclusive *)
predicate odd_sorted (a: array int) (n: int) =
forall i. 0 <= i -> 2*i + 2 < n -> a[2*i+1] <= a[2*i+2]
(* even-sorted up to n exclusive *)
predicate even_sorted (a: array int) (n: int) =
forall i. 0 <= i -> 2*i + 1 < n -> a[2*i] <= a[2*i+1]
let lemma odd_even_sorted (a: array int) (n: int)
requires { 0 <= n <= length a }
requires { odd_sorted a n }
requires { even_sorted a n }
ensures { sorted_sub a 0 n }
= if n > 0 && length a > 0 then
for i = 1 to n - 1 do
invariant { sorted_sub a 0 i }
assert { forall j. 0 <= j < i -> a[j] <= a[i]
by a[i-1] <= a[i]
by i-1 = 2 * div (i-1) 2 \/
i-1 = 2 * div (i-1) 2 + 1 }
done
(* to prove termination, we count the total number of inversions *)
predicate inversion (a: array int) (i j: int) =
a[i] > a[j]
function inversions_for (a: array int) (i: int) : int =
numof (inversion a i) i (length a)
function inversions (a: array int) : int =
sum (inversions_for a) 0 (length a)
(* the key lemma to prove termination: whenever we swap two consecutive
values that are ill-sorted, the total number of inversions decreases *)
let lemma exchange_inversion (a1 a2: array int) (i0: int)
requires { 0 <= i0 < length a1 - 1 }
requires { a1[i0] > a1[i0 + 1] }
requires { exchange a1 a2 i0 (i0 + 1) }
ensures { inversions a2 < inversions a1 }
= assert { inversion a1 i0 (i0+1) };
assert { not (inversion a2 i0 (i0+1)) };
assert { forall i. 0 <= i < i0 ->
inversions_for a2 i = inversions_for a1 i
by numof (inversion a2 i) i (length a2)
= numof (inversion a2 i) i i0
+ numof (inversion a2 i) i0 (i0+1)
+ numof (inversion a2 i) (i0+1) (i0+2)
+ numof (inversion a2 i) (i0+2) (length a2)
/\ numof (inversion a1 i) i (length a1)
= numof (inversion a1 i) i i0
+ numof (inversion a1 i) i0 (i0+1)
+ numof (inversion a1 i) (i0+1) (i0+2)
+ numof (inversion a1 i) (i0+2) (length a1)
/\ numof (inversion a2 i) i0 (i0+1)
= numof (inversion a1 i) (i0+1) (i0+2)
/\ numof (inversion a2 i) (i0+1) (i0+2)
= numof (inversion a1 i) i0 (i0+1)
/\ numof (inversion a2 i) i i0 = numof (inversion a1 i) i i0
/\ numof (inversion a2 i) (i0+2) (length a2)
= numof (inversion a1 i) (i0+2) (length a1)
};
assert { forall i. i0 + 1 < i < length a1 ->
inversions_for a2 i = inversions_for a1 i };
assert { inversions_for a2 i0 = inversions_for a1 (i0+1)
by numof (inversion a1 (i0+1)) (i0+2) (length a1)
= numof (inversion a2 i0 ) (i0+2) (length a1) };
assert { 1 + inversions_for a2 (i0+1) = inversions_for a1 i0
by numof (inversion a1 i0) i0 (length a1)
= numof (inversion a1 i0) (i0+1) (length a1)
= 1 + numof (inversion a1 i0) (i0+2) (length a1) };
let sum_decomp (a: array int) (i j k: int)
requires { 0 <= i <= j <= k <= length a = length a1 }
ensures { sum (inversions_for a) i k =
sum (inversions_for a) i j + sum (inversions_for a) j k }
= () in
let decomp (a: array int)
requires { length a = length a1 }
ensures { inversions a = sum (inversions_for a) 0 i0
+ inversions_for a i0
+ inversions_for a (i0+1)
+ sum (inversions_for a) (i0+2) (length a) }
= sum_decomp a 0 i0 (length a);
sum_decomp a i0 (i0+1) (length a);
sum_decomp a (i0+1) (i0+2) (length a);
in
decomp a1; decomp a2;
()
(* note: program variable "sorted" renamed into "is_sorted"
(clash with library predicate "sorted" on arrays) *)
let odd_even_transposition_sort (a: array int)
ensures { sorted a }
ensures { permut_all (old a) a }
= let is_sorted = ref false in
while not !is_sorted do
invariant { permut_all (old a) a }
invariant { !is_sorted -> sorted a }
variant { if !is_sorted then 0 else 1, inversions a }
is_sorted := true;
let i = ref 1 in
let ghost half_i = ref 0 in
label L in
while !i < length a - 1 do
invariant { 0 <= !half_i /\ 0 <= !i = 2 * !half_i + 1 }
invariant { permut_all (old a) a }
invariant { odd_sorted a !i }
invariant { if !is_sorted then inversions a = inversions (a at L)
else inversions a < inversions (a at L) }
variant { length a - !i }
if a[!i] > a[!i+1] then begin
swap a !i (!i+1);
is_sorted := false;
end;
i := !i + 2;
ghost half_i := !half_i + 1
done;
assert { odd_sorted a (length a) };
i := 0;
ghost half_i := 0;
while !i < length a - 1 do
invariant { 0 <= !half_i /\ 0 <= !i = 2 * !half_i }
invariant { 0 <= !i }
invariant { permut_all (old a) a }
invariant { !is_sorted -> odd_sorted a (length a) }
invariant { even_sorted a !i }
invariant { if !is_sorted then inversions a = inversions (a at L)
else inversions a < inversions (a at L) }
invariant { !is_sorted \/ inversions a < inversions (a at L) }
variant { length a - !i }
if a[!i] > a[!i+1] then begin
swap a !i (!i+1);
is_sorted := false;
end;
i := !i + 2;
ghost half_i := !half_i + 1
done;
assert { !is_sorted -> even_sorted a (length a) }
done
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="1.30" timelimit="5" steplimit="0" memlimit="1000"/>
<prover id="1" name="CVC4" version="1.4" timelimit="5" steplimit="0" memlimit="1000"/>
<prover id="2" name="Z3" version="4.4.0" timelimit="5" steplimit="0" memlimit="1000"/>
<file name="../verifythis_2017_odd_even_transposition_sort.mlw">
<theory name="Challenge3" sum="8cc63513fbd356eee4e515b0627da335">
<goal name="VC odd_even_sorted" expl="VC for odd_even_sorted">
<transf name="split_goal_wp">
<goal name="VC odd_even_sorted.1" expl="1. loop bounds">
<proof prover="0"><result status="valid" time="0.01" steps="7"/></proof>
</goal>
<goal name="VC odd_even_sorted.2" expl="2. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="9"/></proof>
</goal>
<goal name="VC odd_even_sorted.3" expl="3. assertion">
<transf name="split_goal_wp">
<goal name="VC odd_even_sorted.3.1" expl="1. assertion">
<proof prover="0"><result status="valid" time="0.02" steps="18"/></proof>
</goal>
<goal name="VC odd_even_sorted.3.2" expl="2. VC for odd_even_sorted">
<proof prover="0"><result status="valid" time="0.02" steps="27"/></proof>
</goal>
<goal name="VC odd_even_sorted.3.3" expl="3. VC for odd_even_sorted">
<proof prover="0"><result status="valid" time="0.01" steps="19"/></proof>
</goal>
</transf>
</goal>
<goal name="VC odd_even_sorted.4" expl="4. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="21"/></proof>
</goal>
<goal name="VC odd_even_sorted.5" expl="5. postcondition">
<proof prover="0"><result status="valid" time="0.01" steps="13"/></proof>
</goal>
</transf>
</goal>
<goal name="VC exchange_inversion" expl="VC for exchange_inversion">
<transf name="split_goal_wp">
<goal name="VC exchange_inversion.1" expl="1. assertion">
<proof prover="0"><result status="valid" time="0.01" steps="6"/></proof>
</goal>
<goal name="VC exchange_inversion.2" expl="2. assertion">
<proof prover="0"><result status="valid" time="0.01" steps="18"/></proof>
</goal>
<goal name="VC exchange_inversion.3" expl="3. assertion">
<transf name="split_goal_wp">
<goal name="VC exchange_inversion.3.1" expl="1. assertion">
<proof prover="1"><result status="valid" time="1.33"/></proof>
<proof prover="2"><result status="valid" time="0.05"/></proof>
</goal>
<goal name="VC exchange_inversion.3.2" expl="2. assertion">
<proof prover="2"><result status="valid" time="0.05"/></proof>
</goal>
<goal name="VC exchange_inversion.3.3" expl="3. assertion">
<proof prover="0"><result status="valid" time="1.32" steps="1133"/></proof>
</goal>
<goal name="VC exchange_inversion.3.4" expl="4. assertion">
<proof prover="0"><result status="valid" time="0.63" steps="636"/></proof>
</goal>
<goal name="VC exchange_inversion.3.5" expl="5. assertion">
<proof prover="2" timelimit="35"><result status="valid" time="3.30"/></proof>
</goal>
<goal name="VC exchange_inversion.3.6" expl="6. assertion">
<proof prover="2"><result status="valid" time="0.34"/></proof>
</goal>
<goal name="VC exchange_inversion.3.7" expl="7. VC for exchange_inversion">
<transf name="introduce_premises">
<goal name="VC exchange_inversion.3.7.1" expl="1. VC for exchange_inversion">
<transf name="inline_goal">
<goal name="VC exchange_inversion.3.7.1.1" expl="1. VC for exchange_inversion">
<proof prover="2"><result status="valid" time="0.05"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
</transf>
</goal>
<goal name="VC exchange_inversion.4" expl="4. assertion">
<proof prover="2"><result status="valid" time="0.97"/></proof>
</goal>
<goal name="VC exchange_inversion.5" expl="5. assertion">
<transf name="split_goal_wp">
<goal name="VC exchange_inversion.5.1" expl="1. VC for exchange_inversion">
<proof prover="2"><result status="valid" time="0.38"/></proof>
</goal>
<goal name="VC exchange_inversion.5.2" expl="2. VC for exchange_inversion">
<proof prover="0"><result status="valid" time="1.77" steps="852"/></proof>
</goal>
</transf>
</goal>
<goal name="VC exchange_inversion.6" expl="6. assertion">
<transf name="split_goal_wp">
<goal name="VC exchange_inversion.6.1" expl="1. VC for exchange_inversion">
<proof prover="0"><result status="valid" time="0.08" steps="156"/></proof>
</goal>
<goal name="VC exchange_inversion.6.2" expl="2. VC for exchange_inversion">
<proof prover="0"><result status="valid" time="0.02" steps="45"/></proof>
</goal>
<goal name="VC exchange_inversion.6.3" expl="3. VC for exchange_inversion">
<proof prover="2"><result status="valid" time="0.21"/></proof>
</goal>
</transf>
</goal>
<goal name="VC exchange_inversion.7" expl="7. postcondition">
<proof prover="0"><result status="valid" time="0.02" steps="18"/></proof>
</goal>
<goal name="VC exchange_inversion.8" expl="8. precondition">
<proof prover="0"><result status="valid" time="0.02" steps="10"/></proof>
</goal>
<goal name="VC exchange_inversion.9" expl="9. precondition">
<proof prover="0"><result status="valid" time="0.01" steps="11"/></proof>
</goal>
<goal name="VC exchange_inversion.10" expl="10. precondition">
<proof prover="0"><result status="valid" time="0.01" steps="12"/></proof>
</goal>
<goal name="VC exchange_inversion.11" expl="11. postcondition">
<proof prover="0"><result status="valid" time="0.13" steps="44"/></proof>
</goal>
<goal name="VC exchange_inversion.12" expl="12. precondition">
<proof prover="0"><result status="valid" time="0.01" steps="1"/></proof>
</goal>
<goal name="VC exchange_inversion.13" expl="13. precondition">
<proof prover="0"><result status="valid" time="0.01" steps="11"/></proof>
</goal>
<goal name="VC exchange_inversion.14" expl="14. postcondition">
<proof prover="2"><result status="valid" time="1.21"/></proof>
</goal>
</transf>
</goal>
<goal name="VC odd_even_transposition_sort" expl="VC for odd_even_transposition_sort">
<transf name="split_goal_wp">
<goal name="VC odd_even_transposition_sort.1" expl="1. loop invariant init">
<proof prover="0"><result status="valid" time="0.00" steps="4"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.2" expl="2. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="1"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.3" expl="3. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="5"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.4" expl="4. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="5"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.5" expl="5. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="6"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.6" expl="6. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="5"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.7" expl="7. index in array bounds">
<proof prover="0"><result status="valid" time="0.01" steps="12"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.8" expl="8. index in array bounds">
<proof prover="0"><result status="valid" time="0.01" steps="12"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.9" expl="9. precondition">
<proof prover="0"><result status="valid" time="0.02" steps="16"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.10" expl="10. loop variant decrease">
<proof prover="0"><result status="valid" time="0.01" steps="18"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.11" expl="11. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="18"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.12" expl="12. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.12" steps="168"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.13" expl="13. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.08" steps="134"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.14" expl="14. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="109"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.15" expl="15. loop variant decrease">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.16" expl="16. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.17" expl="17. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.18" expl="18. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="24"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.19" expl="19. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="24"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.20" expl="20. assertion">
<proof prover="0"><result status="valid" time="0.01" steps="21"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.21" expl="21. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.22" expl="22. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.23" expl="23. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="15"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.24" expl="24. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="16"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.25" expl="25. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="16"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.26" expl="26. loop invariant init">
<proof prover="0"><result status="valid" time="0.02" steps="24"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.27" expl="27. loop invariant init">
<proof prover="0"><result status="valid" time="0.01" steps="22"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.28" expl="28. index in array bounds">
<proof prover="0"><result status="valid" time="0.01" steps="22"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.29" expl="29. index in array bounds">
<proof prover="0"><result status="valid" time="0.01" steps="22"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.30" expl="30. precondition">
<proof prover="0"><result status="valid" time="0.01" steps="28"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.31" expl="31. loop variant decrease">
<proof prover="0"><result status="valid" time="0.01" steps="28"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.32" expl="32. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="28"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.33" expl="33. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="28"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.34" expl="34. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.13" steps="223"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.35" expl="35. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="28"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.36" expl="36. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.35" steps="231"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.37" expl="37. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.04" steps="219"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.38" expl="38. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.08" steps="175"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.39" expl="39. loop variant decrease">
<proof prover="0"><result status="valid" time="0.01" steps="25"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.40" expl="40. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="25"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.41" expl="41. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="25"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.42" expl="42. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.07" steps="25"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.43" expl="43. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="27"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.44" expl="44. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="36"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.45" expl="45. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01" steps="37"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.46" expl="46. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02" steps="25"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.47" expl="47. assertion">
<proof prover="0"><result status="valid" time="0.02" steps="35"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.48" expl="48. loop variant decrease">
<proof prover="2"><result status="valid" time="0.09"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.49" expl="49. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.07" steps="22"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.50" expl="50. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.03" steps="59"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.51" expl="51. postcondition">
<proof prover="0"><result status="valid" time="0.01" steps="5"/></proof>
</goal>
<goal name="VC odd_even_transposition_sort.52" expl="52. postcondition">
<proof prover="0"><result status="valid" time="0.01" steps="5"/></proof>
</goal>
</transf>
</goal>
</theory>
</file>
</why3session>
(**
{1 VerifyThis @ ETAPS 2017 competition
Challenge 1: Pair Insertion Sort}
See https://formal.iti.kit.edu/ulbrich/verifythis2017/
Author: Jean-Christophe Filliâtre (CNRS)
*)
module Challenge1
use import int.Int
use import ref.Refint
use import array.Array
use import array.ArrayPermut
let pair_insertion_sort (a: array int)
ensures { forall k l. 0 <= k <= l < length a -> a[k] <= a[l] }
ensures { permut_all (old a) a }
= let i = ref 0 in (* i is running index (inc by 2 every iteration)*)
while !i < length a - 1 do
invariant { 0 <= !i <= length a }
invariant { forall k l. 0 <= k <= l < !i -> a[k] <= a[l] }
invariant { permut_all (old a) a }
variant { length a - !i }
let x = ref a[!i] in (* let x and y hold the next to elements in A *)
let y = ref a[!i + 1] in
if !x < !y then (* ensure that x is not smaller than y *)
begin let tmp = !x in x := !y; y := tmp end (* swap x and y *)
else begin
label L in
assert { exchange (a at L) a[(!i-1)+1 <- !y][(!i-1)+2 <- !x]
((!i-1)+1) ((!i-1)+2) }
end;
let j = ref (!i - 1) in
(* j is the index used to find the insertion point *)
while !j >= 0 && a[!j] > !x do (* find the insertion point for x *)
invariant { -1 <= !j < !i }
invariant { forall k l.
0 <= k <= l <= !j -> a[k] <= a[l] }
invariant { forall k l.
0 <= k <= !j -> !j+2 < l < !i+2 -> a[k] <= a[l] }
invariant { forall k l.
!j+2 < k <= l < !i+2 -> a[k] <= a[l] }
invariant { forall l.
!j+2 < l < !i+2 -> !x < a[l] }
invariant { permut_all (old a) a[!j+1 <- !y][!j+2 <- !x] }
variant { !j }
label L in
a[!j + 2] <- a[!j]; (* shift existing content by 2 *)
assert { exchange (a at L)[!j+2 <- !x] a[!j <- !x] !j (!j + 2) };
assert { exchange (a at L)[!j+1 <- !y][!j+2 <- !x]
a[!j+1 <- !y][!j <- !x] !j (!j + 2) };
assert { exchange (a at L)[!j+1 <- !y][!j+2 <- a[!j]][!j <- !x]
a[!j <- !y][!j+1 <- !x][!j+2 <- a[!j]] !j (!j + 1) };
j := !j - 1
done;
a[!j + 2] <- !x; (* store x at its insertion place *)
(* A[j+1] is an available space now *)
while !j >= 0 && a[!j] > !y do (* #ind the insertion point for y *)
invariant { -1 <= !j < !i }
invariant { forall k l.
0 <= k <= l <= !j -> a[k] <= a[l] }
invariant { forall k l.
0 <= k <= !j -> !j+1 < l < !i+2 -> a[k] <= a[l] }
invariant { forall k l.
!j+1 < k <= l < !i+2 -> a[k] <= a[l] }
invariant { forall l.
!j+1 < l < !i+2 -> !y <= a[l] }
invariant { permut_all (old a) a[!j+1 <- !y] }
variant { !j }
label L in
a[!j + 1] <- a[!j]; (* shift existing content by 1 *)
assert { exchange (a at L)[!j+1 <- !y] a[!j <- !y] !j (!j + 1) };
j := !j - 1
done;
a[!j + 1] <- !y; (* store y at its insertion place *)
i := !i + 2
done;
if !i = length a - 1 then begin (* if length(A) is odd, an extra *)
let y = a[!i] in (* single insertion is needed for *)
let j = ref (!i - 1) in (* the last element *)
while !j >= 0 && a[!j] > y do
invariant { -1 <= !j < !i }
invariant { forall k l.
0 <= k <= l <= !j -> a[k] <= a[l] }