Generates loop invariants for program verification
A data-driven tool that generates provably sufficient loop invariants for program verification.
[ LoopInvGen extends our old (now deactivated) project, PIE -- the Precondition Inference Engine. ]
Installation | Invariant Inference · Batch Verification | Use as a Library | Citing LoopInvGen · License (MIT)
docker
(recommended)Note: The docker image may consume ~ 3 GB of disk space.
We recommend running LoopInvGen within a docker container, since they have negligible performance overhead. (See this report)
docker
for your OS.docker pull padhi/loopinvgen
.docker run -it padhi/loopinvgen
.bash
shell within LoopInvGen directory.# Alternatively, you could also build the Docker image locally:
docker build -t padhi/loopinvgen github.com/SaswatPadhi/LoopInvGen
Docker containers are isolated from the host system. Therefore, to run LoopInvGen on SyGuS files residing on the host system, you must first bind mount them while running the container:
docker run -v /host/dir:/home/opam/LoopInvGen/shared -it padhi/loopinvgen
The /host/dir
on the host system would then be accessible within the container at ~/LoopInvGen/shared
(with read+write permissions).
# Create a LoopInvGen container with 4GB memory, no swap and 1 CPU
$ docker run -it --memory=4g --memory-swap=4g --cpus=1 padhi/loopinvgen
See the official Docker guide for more details on applying resource constraints.
Please see the Dockerfile
for the complete list of required packages
for building LoopInvGen and its dependencies.
Most of these packages are already installed on standard installations of most *nix distributions,
except, may be, these: aspcud libgmp-dev libomp-dev m4
.
opam
package manager for OCaml.See https://opam.ocaml.org/doc/Install.html for detailed instructions.
ocaml
>= 4.08.0.We recommend using an OCaml compiler with flambda
optimizations enabled.
For example, with opam 2.0+, you could run opam switch create 4.10.0+flambda
.
opam install
the dependencies.$ opam install alcotest.1.1.0 core.v0.13.0 dune.2.5.1
We have tested LoopInvGen with the latest stable version of Z3 (4.8.7). You could either:
git checkout https://github.com/Z3Prover/z3.git
for the bleeding-edge version, orwget https://github.com/Z3Prover/z3/archive/z3-4.8.7.zip && unzip z3-4.8.7.zip
for the stable versiongit clone
this project, and build everything.$ ./scripts/build_all.sh -z /PATH/TO/z3_dir
The build_all.sh
script would build Z3, copy it to _dep/
, and then build LoopInvGen.
Alternatively, you can copy a precompiled version of Z3 to a _dep
directory at the root of the repository,
and simply run ./scripts/build_all.sh
.
For debug builds, use the -D
or --debug
switch when invoking build_all.sh
.
For future builds after any changes to the source code, you only need to run dune build
.
You can configure the build profile to either debug
or optimize
(default),
using: dune build --profile <profile>
.
Infer invariants for SyGuS-INV benchmarks by invoking LoopInvGen as:
$ ./loopinvgen.sh benchmarks/LIA/2016.SyGuS-Comp/array.sl
(define-fun inv-f ((x Int) (y Int) (z Int)) Bool (not (and (>= x 5) (not (<= y z)))))
Note: LoopInvGen processes benchmarks in multiple stages.
We trap CTRL+C (SIGINT
signal) to break out of the current stage,
and CTRL+\ (SIGQUIT
signal) to kill LoopInvGen and with its child processes.
You may use the -t
flag to run LoopInvGen with a maximum limit
on the number of seconds (wall-clock time) for which the inference algorithm may run.
$ ./loopinvgen.sh -t 8 benchmarks/LIA/2016.SyGuS-Comp/array.sl
For timeout based on CPU time, you may use ulimit
.
You may use the -F
flag to preseed LoopInvGen's inference engine
with custom features (written in SMTLib format).
$ ./loopinvgen.sh -F benchmarks/NIA/2018.CHI_InvGame/~features/s10.some.smt2.input benchmarks/NIA/2018.CHI_InvGame/s10.desugared.sl
The -v
switch makes LoopInvGen verify the benchmark with the generated invariant:
$ ./loopinvgen.sh -v benchmarks/LIA/2016.SyGuS-Comp/array.sl
PASS
It gives one of the following verdicts:
PASS : The generated invariant successfully verifies the benchmark.
PASS (NO SOLUTION) : The benchmark is invalid (no invariant can verify it),
and no invariant was generated.
FAIL {<vc1>;...} : The generated invariant fails to verify the VCs: vc1, vc2 etc.
where each VC is one of {pre, post, trans}.
FAIL (NO SOLUTION) : The benchmark is invalid (no invariant can verify it),
but an invariant (that is not empty/false) was generated.
[TIMEOUT] <verdict> : Invariant inference timed out.
With an empty (false) invariant, <verdict> is one of the verdicts above.
Try ./loopinvgen.sh -h
for other options that allow more control over the inference process.
Execute ./scripts/test_all.sh -b benchmarks/LIA
to run LoopInvGen on all benchmarks in benchmarks/LIA.
The test_all.sh
script invokes LoopInvGen for invariant inference,
and then verifies that the generated invariant is sufficient to prove correctness of the SyGuS benchmark.
Note: Within test_all.sh
,
we trap CTRL+C (SIGINT
signal) to kill the currently running benchmark,
and CTRL+\ (SIGQUIT
signal) to kill the test_all.sh
script with its child processes.
For each benchmark, the test_all.sh
script generates one of the verdicts mentioned above, or:
[SKIPPED] <verdict> : Invariant inference was skipped for an already passing benchmark.
<verdict> is one of the PASS verdicts above.
The test_all.sh
script creates a new log directory and tests all benchmarks each time it is run.
However, one may want to rerun only the previously failed benchmarks, for example with a different timeout,
from a previously failing run.
This can be achieved by forcing test_all.sh
to use a previous log directory, using -l <old_log_dir>
.
test_all.sh
is a generic benchmarking script that may run any invariant inference tool
which accepts the SyGuS format. This makes it easier for us to compare various tools easily.
To use an invariant inference tool other than LoopInvGen, invoke it as:
$ ./scripts/test_all.sh -b <path/to/benchmarks> -T <path/to/tool> [-- [-tool] [-specific] [-options]]
Just like loopinvgen.sh
, the test_all.sh
script allows users to limit the
execution time for the invariant inference tools using the -t
flag.
$ ./scripts/test_all.sh -b benchmarks/LIA -t 10
Try ./scripts/test_all.sh -h
for more options.
@inproceedings{pldi/2016/PadhiSM,
author = {Saswat Padhi and Rahul Sharma and Todd D. Millstein},
title = {Data-Driven Precondition Inference with Learned Features},
booktitle = {Proceedings of the 37th {ACM} {SIGPLAN} Conference on Programming
Language Design and Implementation, {PLDI} 2016, Santa Barbara, CA,
USA, June 13-17, 2016},
pages = {42--56},
year = {2016},
url = {http://doi.acm.org/10.1145/2908080.2908099},
doi = {10.1145/2908080.2908099}
}