Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
why3
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
120
Issues
120
List
Boards
Labels
Service Desk
Milestones
Merge Requests
17
Merge Requests
17
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Why3
why3
Commits
715be130
Commit
715be130
authored
Jun 04, 2018
by
Jean-Christophe Filliâtre
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
new example mex.MexArrayInPlace
parent
22f12ce4
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
232 additions
and
2 deletions
+232
-2
examples/mex.mlw
examples/mex.mlw
+87
-2
examples/mex/why3session.xml
examples/mex/why3session.xml
+145
-0
examples/mex/why3shapes.gz
examples/mex/why3shapes.gz
+0
-0
No files found.
examples/mex.mlw
View file @
715be130
(* {1 Minimum excludant, aka mex}
(** {1 Minimum excludant, aka mex}
Author: Jean-Christophe Filliâtre (CNRS)
Given a finite set of integers, find the smallest nonnegative integer
that does not belong to this set.
In the following, the set is given as an array A.
If N is the size of this array, it is clear that we have 0 <= mex <= N
for we cannot have the N+1 first natural numbers in the N cells of
array A (pigeon hole principle).
*)
(**
A simple algorithm is thus to mark values that belong to [0..N[ in
some external Boolean array of length N, ignoring any value that is
negative or greater or equal than N. Then a second loop scans the
marks until we find some unused value. If don't find any, then it means
that A contains exactly the integers 0,...,N-1 and the answer is N.
The very last step in this reasoning requires to invoke the pigeon hole
principle (imported from the standard library).
Time O(N) and space O(N).
*)
module MexArray
use import int.Int
...
...
@@ -22,7 +41,7 @@ module MexArray
ensures { forall x. 0 <= x < result -> mem x a }
= let n = length a in
let used = make n false in
let ghost idx = ref (fun i -> i) in
let ghost idx = ref (fun i -> i) in
(* the position of each marked value *)
for i = 0 to n - 1 do
invariant { forall x. 0 <= x < n -> used[x] ->
mem x a && 0 <= !idx x < n && a[!idx x] = x }
...
...
@@ -42,8 +61,74 @@ module MexArray
if a[!r] = n then posn := !r;
incr r
done;
(* we cannot have !r=n (all values marked) and !posn>=0 at the same time *)
if !r = n && !posn >= 0 then pigeonhole (n+1) n (set !idx n !posn);
!r
end
(**
In this second implementation, we assume we are free to mutate array A.
The idea is then to scan the array from left to right, while
swapping elements to put any value in 0..N-1 at its place in the
array. When we are done, a second loop looks for the mex, advancing
as long as a[i]=i holds.
Since we perform only swaps, it is obvious that the mex of the final
array is equal to the mex of the original array.
Time O(N) and space O(1). The argument for a linear time complexity is as
follows: whenever we do not advance, we swap the element to its place,
which is further and did not contain that element; so we can do this only
N times.
Surprinsingly, proving that N is the answer whenever array A contains a
permutation of 0..N-1 is now easy (no need for a pigeon hole
principle or any kind of proof by induction).
*)
module MexArrayInPlace
use import int.Int
use import int.NumOf
use import array.Array
use import array.ArraySwap
use import ref.Refint
predicate mem (x: int) (a: array int) =
exists i. 0 <= i < length a && a[i] = x
function placed (a: array int) : int -> bool =
fun i -> a[i] = i
let mex (a: array int) : int
ensures { 0 <= result <= length a }
ensures { not (mem result (old a)) }
ensures { forall x. 0 <= x < result -> mem x (old a) }
= let n = length a in
let i = ref 0 in
while !i < n do
invariant { 0 <= !i <= n }
invariant { forall x. mem x a <-> mem x (old a) }
invariant { forall j. 0 <= j < !i -> 0 <= a[j] < n -> a[a[j]] = a[j] }
variant { n - !i, n - numof (placed a) 0 n }
let x = a[!i] in
if x < 0 || x >= n then
incr i
else if x < !i then begin
swap a !i x; incr i
end else if a[x] = x then
incr i
else
swap a !i x
done;
assert { forall j. 0 <= j < n -> let x = (old a)[j] in
0 <= x < n -> a[x] = x };
for i = 0 to n - 1 do
invariant { forall j. 0 <= j < i -> a[j] = j }
if a[i] <> i then return i
done;
n
end
examples/mex/why3session.xml
View file @
715be130
...
...
@@ -2,6 +2,7 @@
<!DOCTYPE why3session PUBLIC "-//Why3//proof session v5//EN"
"http://why3.lri.fr/why3session.dtd">
<why3session
shape_version=
"4"
>
<prover
id=
"0"
name=
"Z3"
version=
"4.4.0"
timelimit=
"1"
steplimit=
"0"
memlimit=
"1000"
/>
<prover
id=
"1"
name=
"CVC4"
version=
"1.5"
timelimit=
"1"
steplimit=
"0"
memlimit=
"1000"
/>
<prover
id=
"2"
name=
"Alt-Ergo"
version=
"2.0.0"
timelimit=
"1"
steplimit=
"0"
memlimit=
"1000"
/>
<file
name=
"../mex.mlw"
proved=
"true"
>
...
...
@@ -95,5 +96,149 @@
</transf>
</goal>
</theory>
<theory
name=
"MexArrayInPlace"
proved=
"true"
>
<goal
name=
"VC mex"
expl=
"VC for mex"
proved=
"true"
>
<transf
name=
"split_vc"
proved=
"true"
>
<goal
name=
"VC mex.0"
expl=
"loop invariant init"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.1"
expl=
"loop invariant init"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.01"
/></proof>
</goal>
<goal
name=
"VC mex.2"
expl=
"loop invariant init"
proved=
"true"
>
<transf
name=
"split_all_full"
proved=
"true"
>
<goal
name=
"VC mex.2.0"
expl=
"loop invariant init"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.01"
/></proof>
</goal>
</transf>
</goal>
<goal
name=
"VC mex.3"
expl=
"index in array bounds"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
<goal
name=
"VC mex.4"
expl=
"loop variant decrease"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.5"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.04"
/></proof>
</goal>
<goal
name=
"VC mex.6"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.7"
expl=
"loop invariant preservation"
proved=
"true"
>
<transf
name=
"split_all_full"
proved=
"true"
>
<goal
name=
"VC mex.7.0"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.04"
/></proof>
</goal>
</transf>
</goal>
<goal
name=
"VC mex.8"
expl=
"precondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.9"
expl=
"loop variant decrease"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
<goal
name=
"VC mex.10"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
<goal
name=
"VC mex.11"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.22"
/></proof>
</goal>
<goal
name=
"VC mex.12"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"0"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.13"
expl=
"index in array bounds"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
<goal
name=
"VC mex.14"
expl=
"loop variant decrease"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
<goal
name=
"VC mex.15"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.04"
/></proof>
</goal>
<goal
name=
"VC mex.16"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.17"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.04"
/></proof>
</goal>
<goal
name=
"VC mex.18"
expl=
"precondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.19"
expl=
"loop variant decrease"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.30"
/></proof>
</goal>
<goal
name=
"VC mex.20"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.21"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.24"
/></proof>
</goal>
<goal
name=
"VC mex.22"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.09"
/></proof>
</goal>
<goal
name=
"VC mex.23"
expl=
"VC for mex"
proved=
"true"
>
<proof
prover=
"0"
><result
status=
"valid"
time=
"0.32"
/></proof>
</goal>
<goal
name=
"VC mex.24"
expl=
"loop invariant init"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.00"
/></proof>
</goal>
<goal
name=
"VC mex.25"
expl=
"index in array bounds"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.01"
/></proof>
</goal>
<goal
name=
"VC mex.26"
expl=
"postcondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.01"
/></proof>
</goal>
<goal
name=
"VC mex.27"
expl=
"postcondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.28"
expl=
"postcondition"
proved=
"true"
>
<transf
name=
"assert"
proved=
"true"
arg1=
"(mem x a)"
>
<goal
name=
"VC mex.28.0"
proved=
"true"
>
<transf
name=
"assert"
proved=
"true"
arg1=
"(a[x] = x)"
>
<goal
name=
"VC mex.28.0.0"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.28.0.1"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
</transf>
</goal>
<goal
name=
"VC mex.28.1"
expl=
"postcondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
</transf>
</goal>
<goal
name=
"VC mex.29"
expl=
"loop invariant preservation"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.30"
expl=
"postcondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.31"
expl=
"postcondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.03"
/></proof>
</goal>
<goal
name=
"VC mex.32"
expl=
"postcondition"
proved=
"true"
>
<transf
name=
"assert"
proved=
"true"
arg1=
"(mem x a)"
>
<goal
name=
"VC mex.32.0"
proved=
"true"
>
<transf
name=
"assert"
proved=
"true"
arg1=
"(a[x] = x)"
>
<goal
name=
"VC mex.32.0.0"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
<goal
name=
"VC mex.32.0.1"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
</transf>
</goal>
<goal
name=
"VC mex.32.1"
expl=
"postcondition"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
</transf>
</goal>
<goal
name=
"VC mex.33"
expl=
"out of loop bounds"
proved=
"true"
>
<proof
prover=
"1"
><result
status=
"valid"
time=
"0.02"
/></proof>
</goal>
</transf>
</goal>
</theory>
</file>
</why3session>
examples/mex/why3shapes.gz
View file @
715be130
No preview for this file type
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment