Add z3 repl

Julien LepillerThu Jan 23 21:51:25+0100 2020

c2c8c87

guile-z3
namelast commitdate
.gitignoreInitial commitThu Jan 16 02:53:35+0100 2020
COPYINGInitial commitThu Jan 16 02:53:35+0100 2020
COPYING.LESSERInitial commitThu Jan 16 02:53:35+0100 2020
Makefile.amInitial commitThu Jan 16 02:53:35+0100 2020
README.mdAdd z3 replThu Jan 23 21:51:25+0100 2020
build-aux/Add z3 replThu Jan 23 21:51:25+0100 2020
configure.acInitial commitThu Jan 16 02:53:35+0100 2020
env.inInitial commitThu Jan 16 02:53:35+0100 2020
tests/Initial commitThu Jan 16 02:53:35+0100 2020
z3.scm.inAdd z3 replThu Jan 23 21:51:25+0100 2020

README.md

Guile Z3 Bindings

This project aims to give GNU Guile users a very simple library to use Z3, the theorem prover. Z3 itself is able to read files formated in SMT-LIB2, which is a s-expression format. Instead of writting files and calling Z3, this library offers you all the benefits of using guile to produce your expressions in software.

How to Build Guile Z3

Guile Z3 needs Z3 and guile of course, as well as the usual suspects:

From this repo, run the following:

autoreconf -fiv
./configure Z3_LIBDIR=/usr/lib
make

To install run:

make install

To run the tests, run:

make check

How to Use Guile Z3

As a very simple example, we can try to find solutions for the following equation system:

/
| x + 2y = 20
| x - y = 2
\

This can be done with guile-z3:

(use-modules (z3))

(run-with-z3
  (lambda (context)
    (z3-eval context
      '((set-option :produce-models true)
        (set-logic QF_LIA)
        (declare-fun x () Int)
        (declare-fun y () Int)
        (assert (= (+ x (* 2 y)) 20))
        (assert (= (- x y) 2))
        (check-sat)))))

And Z3 tells us there is a solution! But what is it? We can get the solution with:

(use-modules (z3))

(run-with-z3
  (lambda (context)
    ;; First, we check that we can find a solution.  Z3 will build an example
    ;; after check-sat.
    (let ((sat? (equal?
                  (z3-eval context
                    '((set-option :produce-models true)
                      (set-logic QF_LIA)
                      (declare-fun x () Int)
                      (declare-fun y () Int)
                      (assert (= (+ x (* 2 y)) 20))
                      (assert (= (- x y) 2))
                      (check-sat)))
                  'sat)))
      ;; Then, outside of Z3, we can do something with the result.  Here, we
      ;; check that a solution can be found.
      (if sat?
        ;; If we find one, we ask one to Z3 and we get a nice association list
        ;; as a result.
        (let ((solution (z3-eval context '((get-value (x y))))))
          (format #t "A solution is x=~a and y=~a~%"
                  (assoc-ref solution 'x) (assoc-ref solution 'y)))
        ;; Otherwise, we tell the user the equation is not satisfiable.
        (format #t "unsat~%")))))

Of course, we pass Z3 actual s-expressions, so we can use all the quote-unquote magick we are used to!

Interactive Z3 Session

To start an interactive Z3 session through the Guile REPL, use this command:

,use (z3) ; use guile-z3
,z3 ; start a Z3 repl!

Quick Reference

Procedure (run-with-z3 thunk)

Runs a one-argument procedure in a new Z3 context. The only argument to that procedure is the newly-created Z3 context.

Procedure (z3-eval context query)

Runs a query as an SMT-LIB2 s-expression in the Z3 context. See the Z3 manual for more information on the expected format.