Commit 1a5d1a23 by Jean-Christophe Filliatre

### inverse_in_place completed (with the help of Martin)

parent 03786119
This source diff could not be displayed because it is too large. You can view the blob instead.
 ... ... @@ -9,6 +9,10 @@ proceeds as follows: a negative value -x-1 is simply changed into x; a nonnegative value is the topmost element of a new orbit, which is inversed by the inner loop. Authors: Martin Clochard (École Normale Supérieure) Jean-Christophe Filliâtre (CNRS) Andrei Paskevich (Université Paris Sud) *) module InverseInPlace ... ... @@ -39,39 +43,14 @@ module InverseInPlace (forall i: int. 0 <= i < length b -> a[b[i]] = i) -> is_permutation b (*** predicate is_permutation_neg (a: array int) = forall i: int. 0 <= i < length a -> - (length a) <= a[i] < length a /\ forall j: int. 0 <= j < length a -> i <> j -> a[i] <> a[j] /\ a[i] <> lnot a[j] lemma is_permutation_neg_is_permutation: forall a: array int. is_permutation_neg a -> (forall i: int. 0 <= i < length a -> 0 <= a[i]) -> is_permutation a ***) (* predicate nodup (a: M.map int int) (m: int) = forall i j: int. 0 <= i < j < m -> (M.get a i <> M.get a j /\ M.get a i <> ~ (M.get a j)) \/ (M.get a i = ~ (M.get a j) = m) \/ (~ (M.get a i) = M.get a j = m) *) inductive orbit (array int) int int int = | orbitO: forall a: array int, x: int. orbit a x x 0 | orbitS: forall a: array int, x y s: int. orbit a x y s -> orbit a x a[y] (s+1) (** [orbit a x y s] means y=a^s(x) *) lemma orbit1: forall a: array int, x: int. orbit a x a[x] 1 lemma orbit_permutation_1: forall a: array int. is_permutation a -> forall x y s: int. 0 <= x < length a -> orbit a x y s -> 0 <= y < length a predicate loopinvariant (old a: array int) (m m' n: int) = (forall e: int. 0 <= e < n -> -n <= a[e] < n) /\ (forall e: int. m < e < n -> 0 <= a[e]) /\ (forall e: int. m < e < n -> old[a[e]] = e) /\ (forall e: int. 0 <= e <= m' -> a[e] >= 0 -> old[e] = a[e]) /\ (forall e: int. 0 <= e <= m -> a[e] <= m) /\ (forall e: int. 0 <= e <= m' -> a[e] < 0 -> old[~ a[e]] = e /\ (~a[e] <= m -> a[~a[e]] < 0)) let inverse_in_place (a: array int) requires { is_permutation a } ... ... @@ -80,38 +59,19 @@ module InverseInPlace = 'L:let n = length a in for m = n-1 downto 0 do invariant { forall e: int. 0 <= e < n -> -n <= a[e] < n } invariant { forall e: int. m < e < n -> 0 <= a[e] } invariant { forall e: int. m < e < n -> (at a 'L)[a[e]] = e } invariant { forall e: int. 0 <= e <= m -> a[e] < 0 -> (at a 'L)[~ a[e]] = e } invariant { forall e: int. 0 <= e <= m -> a[e] >= 0 -> (at a 'L)[e] = a[e] } invariant { forall e: int. 0 <= e <= m -> a[e] >= 0 -> forall y s: int. orbit (at a 'L) a[e] y s -> 0 <= y <= m } invariant { loopinvariant (at a 'L) a m m n } let i = ref a[m] in if !i >= 0 then begin (* unrolled loop once *) assert { orbit (at a 'L) m !i 1 }; a[m] <- -1; let j = ref (~m) in let k = ref !i in i := a[!i]; assert { orbit (at a 'L) m !k 1 }; assert { 0 <= !i -> orbit (at a 'L) m !i 2 }; (* TODO: a ghost reference to count number of steps *) while !i >= 0 do invariant { a[!k] = !i <= m /\ 0 <= !k <= m /\ -n <= !j < 0 /\ (at a 'L)[~ !j] = !k /\ a[m] < 0 } invariant { forall e: int. 0 <= e < n -> -n <= a[e] < n } invariant { forall e: int. m < e < n -> 0 <= a[e] } invariant { forall e: int. m < e < n -> (at a 'L)[a[e]] = e } invariant { forall e: int. 0 <= e < m -> a[e] < 0 -> (at a 'L)[~ a[e]] = e } invariant { forall e: int. 0 <= e < m -> a[e] >= 0 -> (at a 'L)[e] = a[e] } invariant { forall e: int. 0 <= e < m -> a[e] >= 0 -> forall y s: int. orbit (at a 'L) a[e] y s -> 0 <= y <= m } invariant { a[!k] = !i <= m /\ 0 <= !k <= m /\ ~m <= !j < 0 /\ (at a 'L)[~ !j] = !k /\ a[~ !j] < 0 /\ a[m] < 0 } invariant { forall e: int. 0 <= e < m -> a[e] < 0 -> a[e] <> !j } invariant { loopinvariant (at a 'L) a m (m-1) n } variant { num_of a.elts 0 n } a[!k] <- !j; j := ~ !k; ... ...
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!