Commit 60ffb6d6 by Jean-Christophe Filliâtre

### documentation: solution for VSTTE'10 problem 2

parent b50d24d9
 ... ... @@ -49,6 +49,8 @@ See Chapter~\ref{chap:manpages} for more details regarding command lines. \medskip As an introduction to \whyml, we use the five problems from the VSTTE 2010 verification competition~\cite{vstte10comp}. The source code for all these examples is contained in \why's distribution, in dub-directory \texttt{examples/programs/}. \subsection{Problem 1: Sum and Maximum} ... ... @@ -192,9 +194,98 @@ Coq, and thus completes the verification. \subsection{Problem 2: Inverting an Injection} The second problem is stated as follows: \begin{quote} Invert an injective array $A$ on $N$ elements in the subrange from $0$ to $N - 1$, i.e., the output array $B$ must be such that $B[A[i]] = i$ for $0 \le i < N$. \end{quote} We may assume that $A$ is surjective and we have to prove that the resulting array is also injective. The code is immediate, since it is as simple as \begin{verbatim} for i = 0 to n - 1 do b[a[i]] <- i done \end{verbatim} so it is more a matter of specification and of getting the proof done with as much automation as possible. In a new file, we start a new module and we import arithmetic and arrays: \begin{verbatim} module InvertingAnInjection use import int.Int use import module array.Array \end{verbatim} It is convenient to introduce predicate definitions for the properties of being injective and surjective. These are purely logical declarations: \begin{verbatim} logic injective (a: array int) (n: int) = forall i j: int. 0 <= i < n -> 0 <= j < n -> i <> j -> a[i] <> a[j] logic surjective (a: array int) (n: int) = forall i: int. 0 <= i < n -> exists j: int. (0 <= j < n and a[j] = i) \end{verbatim} It is also convenient to introduce the predicate being in the subrange from 0 to $n-1$'': \begin{verbatim} logic range (a: array int) (n: int) = forall i: int. 0 <= i < n -> 0 <= a[i] < n \end{verbatim} Using these predicates, we can formulate the assumption that any injective array of size $n$ within the range $0..n-1$ is also surjective: \begin{verbatim} lemma injective_surjective: forall a: array int, n: int. injective a n -> range a n -> surjective a n \end{verbatim} We declare it as a lemma rather than as an axiom, since it is actually provable. It requires induction and can be proved using the Coq proof assistant for instance. Finally we can give the code a specification, with a loop invariant which simply expresses the values assigned to array \texttt{b} so far: \begin{verbatim} let inverting (a: array int) (b: array int) (n: int) = { 0 <= n = length a = length b and injective a n and range a n } for i = 0 to n - 1 do invariant { forall j: int. 0 <= j < i -> b[a[j]] = j } b[a[i]] <- i done { injective b n } \end{verbatim} Here we chose to have array \texttt{b} as argument; returning a freshly allocated array would be equally simple. The whole module is given Figure~\ref{fig:Inverting}. The verification conditions for function \texttt{inverting} are easily discharged automatically, thanks to the lemma. \begin{figure} \centering \begin{verbatim} module InvertingAnInjection use import int.Int use import module array.Array logic injective (a: array int) (n: int) = forall i j: int. 0 <= i < n -> 0 <= j < n -> i <> j -> a[i] <> a[j] logic surjective (a: array int) (n: int) = forall i: int. 0 <= i < n -> exists j: int. (0 <= j < n and a[j] = i) logic range (a: array int) (n: int) = forall i: int. 0 <= i < n -> 0 <= a[i] < n lemma injective_surjective: forall a: array int, n: int. injective a n -> range a n -> surjective a n let inverting (a: array int) (b: array int) (n: int) = { 0 <= n = length a = length b and injective a n and range a n } for i = 0 to n - 1 do invariant { forall j: int. 0 <= j < i -> b[a[j]] = j } b[a[i]] <- i done { injective b n } end \end{verbatim} \hrulefill \caption{Solution for VSTTE'10 competition problem 2.} ... ... @@ -237,7 +328,10 @@ Coq, and thus completes the verification. % other examples: same fringe ? %%% Local Variables: %%% compile-command: "make -C .. doc" %%% mode: latex %%% TeX-PDF-mode: t %%% TeX-master: "manual" %%% End: % LocalWords: surjective
 (* VSTTE'10 competition http://www.macs.hw.ac.uk/vstte10/Competition.html Problem 2: inverting an injection *) module M module InvertingAnInjection use import int.Int use import module array.Array ... ... @@ -10,25 +10,81 @@ module M forall i j: int. 0 <= i < n -> 0 <= j < n -> i <> j -> a[i] <> a[j] logic surjective (a: array int) (n: int) = forall i: int [i]. 0 <= i < n -> exists j: int. (0 <= j < n and a[j] = i) forall i: int. 0 <= i < n -> exists j: int. (0 <= j < n and a[j] = i) logic range (a: array int) (n: int) = forall i: int. 0 <= i < n -> 0 <= a[i] < n lemma Injective_surjective: lemma injective_surjective: forall a: array int, n: int. injective a n -> range a n -> surjective a n let inverting (a: array int) (b: array int) n = { n >= 0 and length a = n and length b = n and injective a n and range a n } for i = 0 to n-1 do invariant { length b = n and forall j: int. 0 <= j < i -> b[a[j]] = j } b[a[i]] <- i let inverting (a: array int) (b: array int) (n: int) = { 0 <= n = length a = length b and injective a n and range a n } for i = 0 to n - 1 do invariant { forall j: int. 0 <= j < i -> b[a[j]] = j } b[a[i]] <- i done { injective b n } (* variant where array b is returned and with additional post *) let inverting2 (a: array int) (n: int) = { 0 <= n = length a and injective a n and range a n } let b = make n 0 in for i = 0 to n - 1 do invariant { forall j: int. 0 <= j < i -> b[a[j]] = j } b[a[i]] <- i done; b { length result = n and injective result n and forall i: int. 0 <= i < n -> result[a[i]] = i } end module Test use import module array.Array use import module InvertingAnInjection let test () = let a = make 10 0 in a[0] <- 9; a[1] <- 3; a[2] <- 8; a[3] <- 2; a[4] <- 7; a[5] <- 4; a[6] <- 0; a[7] <- 1; a[8] <- 5; a[9] <- 6; assert { a[0] = 9 && a[1] = 3 && a[2] = 8 && a[3] = 2 && a[4] = 7 && a[5] = 4 && a[6] = 0 && a[7] = 1 && a[8] = 5 && a[9] = 6 }; let b = inverting2 a 10 in assert { b[0] = 6 && b[1] = 7 && b[2] = 3 && b[3] = 1 && b[4] = 5 && b[5] = 8 && b[6] = 9 && b[7] = 4 && b[8] = 2 && b[9] = 0 } end (* ... ...

Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!