1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
|
;; Copyright (C) 2015, University of British Columbia
;; Written by Yan Peng (June 26th 2017)
;;
;; License: A 3-clause BSD license.
;; See the LICENSE file distributed with ACL2
;;
(in-package "SMT")
(include-book "centaur/sv/tutorial/support" :dir :system)
;; (include-book "examples/examples")
;; (include-book "examples/ringosc")
;; ------------------------------------------------------- ;;
;; Documentation
(include-book "xdoc/save" :dir :system) ;; load xdoc::save
(defxdoc Smtlink
:parents (ACL2::projects)
:short "Tutorial and documentation for the ACL2 book, Smtlink."
:long "<h3>Introduction</h3>
<p>A framework for integrating external SMT solvers into ACL2 based on the
@(see ACL2::clause-processor) and the @(tsee ACL2::computed-hints)
mechanism.</p>
<h4>Overview</h4>
<p>@('Smtlink') is a framework for representing suitable ACL2 theorems as a SMT
(Satisfiability Modulo Theories) formula, and calling SMT solvers from within
ACL2.</p>
<p>SMT solvers combine domain-specific techniques together into a SAT
(Satisfiability) Solver and solves domain-specific satisfiability problems.
Typical domain specific procedures include procedures in integer and real,
linear and non-linear arithmetic, array theory, and uninterpreted function
theory. Modern SMT solvers benefit from the development of both the SAT
solvers and the domain-specific techniques and have become very fast at solving
some relatively large problems.</p>
<p>In the 2018 Workshop version, we call it @('smtlink 2.0'), we make major
improvements over the initial version with respect to soundness, extensibility,
ease-of-use, and the range of types and associated theory-solvers supported.
Most theorems that one would want to prove using an SMT solver must first be
translated to use only the primitive operations supported by the SMT solver --
this translation includes function expansion and type inference. @('Smtlink
2.0') performs this translation using sequence of steps performed by verified
clause processors and computed hints. These steps are ensured to be sound.
The final transliteration from ACL2 to Z3's Python interface requires a trusted
clause processor. This is a great improvement in soundness and extensibility
over the the original @('Smtlink') which was implemented as a single,
monolithic, trusted clause processor. @('Smtlink 2.0') provides support for
@(tsee acl2::FTY), @(tsee fty::defprod), @(tsee fty::deflist), @(tsee
fty::defalist), and @(tsee fty::defoption) types by using Z3's arrays and user
defined data types.</p>
<p>@('Smtlink') can be used both in ACL2 and ACL2(r). The macro @(see
Real/rationalp) should make one's proof portable between ACL2 and ACL2(r). It
is also compatible with both Python 2 and Python 3.</p>
<p>@('Smtlink') currently only supports <a
href='https://github.com/Z3Prover/z3/wiki'>Z3</a>. We hope to add an interface
to include the <a href='http://smtlib.cs.uiowa.edu/'>SMT-LIB</a> in near
future.</p>
<h3>Using Smtlink</h3>
<h4>Requirements</h4>
<ul>
<li>Python 2/3 is properly installed.</li>
<li>Z3 is properly installed.
<p>One needs to build Z3 on one's own instead of using the binary release.
Also, since we are using the Python interface, please follow the \"python\"
section in the \"z3 bindings\" section in <a
href='https://github.com/Z3Prover/z3/'>README</a> of Z3.</p>
<p>I've also wrote a small piece of @(see z3-installation) document about how
to install Z3 and its Python API.</p>
<p>To check if Z3 is properly installed, run Python, which will put you in an
interactive loop. Then run:</p>
@({
from z3 import *
x = Real('x')
y = Real('y')
s = Solver()
s.add(x + y > 5, x > 1, y > 1)
print(s.check())
print(s.model())
quit()
})
<p>One should expect some results like:</p>
@({
>>> print(s.check())
sat
>>> print(s.model())
[y = 4, x = 2]
})
</li>
<li>ACL2 and the system books are properly installed.</li>
<li>@('Smtlink') uses Unix commands.</li>
</ul>
<h4>Build Smtlink</h4>
<ul>
<li>Setup smtlink configuration in file smtlink-config in either a user
specified directory @('$SMT_HOME') or in directory @('$HOME'). When both
environment variables are set, @('$SMT_HOME') is used. The configuration takes
below format:
@({
smt-cmd=...
})
<box>
<p>
<b><color rgb='#FF0000'>NOTE:</color></b>
It used to be four options, we simplified it into just one @('smt-cmd').
</p>
</box>
<p>@('smt-cmd') is the command for running Z3, which is the Python command
since we are using the Python interface. The Z3 library is imported into Python
in the scripts written out by Smtlink like is shown in the example script in
\"Requirements\".</p></li>
<li>Certify the book top.lisp in the Smtlink directory, to bake setup into
certified books.
<p>This took about 8 mins on my 4-core mac with hyperthreading @('-j 2').</p>
<box>
<p>
<b><color rgb='#FF0000'>NOTE:</color></b>
A complete recertification of Smtlink is required if one changes the
configuration in smtlink-config.
</p>
</box>
</li>
</ul>
<h4>Load and Setup Smtlink</h4>
<p>To use @('Smtlink'), one needs to include book:</p>
@({
(include-book \"projects/smtlink/top\" :dir :system)
})
<p>Then one needs to enable @(tsee acl2::tshell) by doing:</p>
@({
(value-triple (tshell-ensure))
})
<p>@(tsee value-triple) makes sure the form @('(tshell-ensure)') can be
submitted in an event context and therefore is certifiable.</p>
<p>In order to install the computed-hint, one needs to
@(see add-default-hints).</p>
@({
(add-default-hints '((SMT::SMT-computed-hint clause)))
})
<box>
<p>
<b><color rgb='#FF0000'>NOTE:</color></b>
The computed-hint used to be called @('SMT::SMT-process-hint'), we find this name
doesn't represent what it does. We changed the name to
@('SMT::SMT-computed-hint').
</p>
</box>
<p>For a detail description of how to setup and get started using @('Smtlink'),
see @(tsee tutorial) and @(tsee SMT-hint).</p>
<h3>Reference</h3>
<p>@('Smtlink') has experienced a great interface and infrastructure change
since its first publication at ACL2 workshop 2015. But you may still find below
paper useful in understanding basics of @('Smtlink'):</p>
<p>Yan Peng and Mark R. Greenstreet. <a
href='https://arxiv.org/abs/1509.06082'>Extending ACL2 with SMT Solvers</a>In
ACL2 Workshop 2015. October 2015. EPTCS 192. Pages 61-77.</p>")
(defxdoc z3-py
:parents (Trusted)
:short "The Z3 python interface related books."
:long "<h3>Introduction</h3>")
(defxdoc Trusted
:parents (Developer)
:short "Trusted part of Smtlink."
:long "<h3>Introduction</h3>")
(defxdoc Verified
:parents (Developer)
:short "Verified part of Smtlink"
:long "<h3>Introduction</h3>")
(defxdoc Developer
:parents (Smtlink)
:short "The developer's reference to Smtlink."
:long "<h3>Introduction</h3>")
(sv::deftutorial Tutorial
:parents (Smtlink)
:short "A tutorial to walk you through how to use Smtlink to prove ACL2 theorems."
:long "<h3>Prerequisites</h3>
<p>Following instructions in :doc @(see Smtlink), one should have setup the
configuration in file smtlink-config and have certified the Smtlink book
afterwards to bake in the configurations.</p>
<p>Then the header of the ACL2 script should look like:</p>
@({
(in-package \"ACL2\")
(include-book \"projects/smtlink/top\" :dir :system)
(tshell-ensure)
})
<p>Smtlink uses a sequence of computed hints and clause processors to perform
different stages. In order to install the computed-hint, one needs to
@(see add-default-hints).</p>
@({
(add-default-hints '((SMT::SMT-computed-hint clause)))
})
<box>
<p>
<b><color rgb='#FF0000'>NOTE:</color></b>
The computed-hint used to be called @('SMT::SMT-process-hint'), we find this name
doesn't represent what it does. We changed the name to
@('SMT::SMT-computed-hint').
</p>
</box>
<p>The rest of this document contains four pieces of arithmetic examples to
show what one can do with @('Smtlink') and how. The first one shows a regular
example, the second one is proved using the extended version called
smtlink-custom, the third one is a theorem that does not pass Smtlink, and the
fourth is a list of examples for @('FTY') types.</p>"
)
(defxdoc SMT-hint
:parents (Smtlink SMT-hint-interface)
:short "Describes the hints interface for Smtlink."
:long "
@({Examples:
:smtlink(-custom)
(:functions ((my-expt :formals ((r rationalp)
(i rationalp))
:returns ((ex rationalp :hints (:in-theory (enable my-expt))))
:level 0)
...)
:hypotheses (((< (my-expt z n) (my-expt z m))
:hints (:use ((:instance hypo1-hint (x x)))))
((< 0 (expt z m)))
((< 0 (expt z n)))
...)
:fty (acl2::integer-list)
:main-hint (:use ((:instance main-hint (n n) (x x))))
:int-to-rat t
:smt-fname \"my-smt-problem.lisp\"
:smt-dir \"/home/tmp\"
:rm-file t)
})
<p>@(':smtlink') is a customized argument option to @(see acl2::hints).
@('smtlink-custom') is used when one wants to use the customized version of
Smtlink. The next argument to @(':smtlink') we call @(see smt-hint). These
are the hints one wants to provide to Smtlink so that it can figure out the
proof easily. Let's take a look at each one of them:</p>
<dl>
<dt>@(':functions')</dt><p/>
<dd><p>@('functions') are for dealing with recursive functions. Smtlink
translate a basic set of ACL2 functions (See @(see smt-basics)) into SMT
functions. Non-recursive functions defined with the basic functions are
automatically expanded in the verified clause processor. Recursive functions
can be specified to expand to a given level. The innermost function call is
translated into an uninterpreted function. When level equals 0, no expansion
is done.</p>
<p>The argument to @(':functions') is a list of functions. For each of the
function, for example,</p>
@({
(my-expt :formals ((r rationalp)
(i rationalp))
:returns ((ex rationalp :hints (:in-theory (enable my-expt))))
:level 0)
})
<p>@('my-expt') is function that has already been defined. It has two formals,
named as @('r') with type @('rationalp') and @('i') with type @('rationalp').
It returns an argument called @('ex') with type @('rationalp'). Return types
of functions are proved as one of the clauses returned by the verified clause
processor. One can give hints to the proof. The hints uses a similar form as
in @(see acl2::hints). The only difference is that the hints will only go to a
specific subgoal, therefore no goal specifier is needed. @('level') is the
expansion level.</p>
</dd>
<dt>@(':hypotheses')</dt><p/>
<dd><p>@(':hypotheses') are \"facts\" that the user believes to be true and
should help with the proof. The facts will be returned as auxiliary clauses
to be proved from the verified clause processor. One can provide hints for
proving any of the hypotheses. It follows the format of the @(see acl2::hints),
except that no goal specifier is needed.</p></dd>
<dt>@(':fty')</dt><p/>
<dd><p>@(':fty') specifies a list of FTY types to be used in this
theorem</p></dd>
<dt>@(':main-hint')</dt><p/>
<dd><p>@(':main-hint') provides a hint to the main returned auxiliary theorem.
This theorem proves the expanded clause implies the original clause. The
format of the hint follows that of the @(see acl2::hints), except that no goal
specifier is needed.</p></dd>
<dt>@(':int-to-rat')</dt><p/>
<dd><p>Z3 has a limited solver for mixed Integer and Real number theories, but
have a better solver for solving pure Real number problems. Sometimes one
might want to try raising all Integers to Reals to prove a theorem.</p></dd>
<dt>@(':smt-fname')</dt><p/>
<dd><p>@(':smt-fname') provides a user specified file name for the generated
Z3 problem, instead of the default one.</p></dd>
<dt>@(':smt-dir')</dt><p/>
<dd><p>@(':smt-dir') provides a user specified directory for the generated Z3
file, instead of the default one in /tmp.</p></dd>
<dt>@(':rm-file')</dt><p/>
<dd><p>@(':rm-file') specified whether one wants the generated Z3 file to be
preserved, in default case, it is removed.</p></dd>
</dl>
")
(defxdoc Status
:parents (Smtlink)
:short "A discussion of what theories are supported in Smtlink and what we
intend to support in the future."
:long "<h3>SMT solvers</h3>
<p>Currently only Z3 is supported.</p>
<h3>Theories</h3>
<p>Currently @('Smtlink') supports:</p>
<ul>
<li><b>Basic types:</b> @(tsee booleanp), @(tsee integerp), @(tsee real),
@(tsee rationalp), @(tsee real/rationalp) and @(tsee symbolp)</li>
<li><b>FTY types generated using:</b> @(tsee defprod), @(tsee deflist),
@(tsee defalist) and @(tsee defoption)</li>
<li><b>Basic functions:</b> @(tsee binary-+), @(tsee binary-*), @(tsee
unary-/), @(tsee unary--), @(tsee equal), @(tsee <), @(tsee implies), @(tsee
if), @(tsee not), and @(tsee lambda)</li>
<li><b>Functions associated with FTY types:</b>
<ul>
<li><b>defprod:</b> recognizer, fixer, constructor, and field accessors.</li>
<li><b>deflist:</b> recognizer, fixer, @(tsee cons), @(tsee car), @(tsee cdr)
and @(tsee consp).</li>
<li><b>defalist:</b> recognizer, fixer, @(tsee acons), and @(tsee
assoc-equal)</li>
<li><b>defoption:</b> recognizer, fixer, constructor, and field-accessor.</li>
</ul>
</li>
</ul>
<h3>Wishlist</h3>
<ul>
<li>Using @(tsee acl2::meta-extract) capability introduced in year 2017 Workshop for
fully verifying several of the verified clause-processors in the architecture.
This will improve performance.</li>
<li>Develop type inference engine to remove the burden on the user for
providing type information.</li>
<li>Generate ACL2 evaluatable counter-examples.</li>
<li>Adding support for SMT-LIB.</li>
<li>Build a computed hint for Smtlink so that it's automatically fired on goals
that seems likely to be solved by Smtlink, possibly recognizing induction
steps.</li>
<li>Do proof reconstruction for the trusted clause-processor so that ACL2
doesn't have to trust an external procedure.</li>
</ul>"
)
(defxdoc Z3-installation
:parents (Smtlink)
:short "How to install Z3"
:long "<h3>How I installed Z3</h3>
<p>In case you find the Z3 README page confusing, here's how I installed Z3.
One can adjust the process to one's own needs. The version of Z3 I used is
@('Z3 version 4.5.0 - 64 bit'), and the version of Python I used is @('Python
2.7.15').</p>
<ul>
<li>Download the current stable release from Z3 <a
href='https://github.com/Z3Prover/z3/releases'>releases</a>
<p>We want to download the source code and compile it by ourselves. It might be
doable to use the binary releases by setting up @('PYTHONPATH') and
@('DYLD_LIBRARY_PATH') (on macos), but I haven't tried it and there's no
instruction in Z3 telling us if that's the way to use it.</p>
</li>
<li>Assume we are in the release directory, do:
@({
python scripts/mk_make.py --prefix=$HOME/usr --python --pypkgdir=$HOME/usr/lib/python-2.7/site-packages
})
<p>I want to install it in my @('$HOME/usr') directory prefix, but you can
replace that part of the path with your conventional path. Note that Z3
restricts @('--prefix') to be the prefix of @('--pypkgdir'). Also,
@('$HOME/usr') does not need to exist in order to follow these steps; that
directory and subdirectories will be created as necessary.</p>
</li>
<li>Now make the C/C++ libraries, do:
@({
cd build; make
})
</li>
<li>Now do the installation in places specified in @('--prefix'):
@({
make install
})
<p>Now if one takes a look at @('$HOME/usr'), one will see in @('$HOME/usr/bin'),
we have the @('z3') executable, in @('$HOME/usr/include') we have all the z3
C++ header files, in @('$HOME/usr/lib') we have @('libz3.dylib') and in
@('$HOME/usr/lib/python-2.7/site-packages') we have all the z3 Python API
files.</p>
<p>Because we are using a user specified prefix, the command line produces the
message:</p>
@({
Z3Py was installed at /.../usr/lib/python-2.7/site-packages, make sure
this directory is in your PYTHONPATH environment variable. @echo Z3 was
successfully installed.
})
</li>
<li>So the last step is to add this path to PYTHONPATH. Adding this path to
existing PYTHONPATH:
@({
export PYTHONPATH=$HOME/usr/lib/python-2.7/site-packages:$PYTHONPATH
})
If PYTHONPATH is undefined, do:
@({
export PYTHONPATH=$HOME/usr/lib/python-2.7/site-packages
@})
</li>
<li>Now one should be able to import z3 into Python.
Run Python, which will put you in an interactive loop.
@({
from z3 import *
x = Real('x')
y = Real('y')
s = Solver()
s.add(x + y > 5, x > 1, y > 1)
print(s.check())
print(s.model())
quit()
})
<p>One should expect some results like:</p>
@({
>>> print(s.check())
sat
>>> print(s.model())
[y = 4, x = 2]
})
<p>This example asks for a satisfying assignment to the problem:
@($x + y > 5$), @($x > 1$) and @($y > 1$). It should be easy to check the
result.</p>
</li>
</ul>
<h3>Additional Notes</h3>
<p>
The instructions above explain how to install Z3 in the user's home directory.
</p>
<p>
Another option is to install Z3 in a machine-wide location.
The following instructions worked on at least two Mac machines:
</p>
<ol>
<li>
Download the latest stable release of Z3 as explained in the instructions above.
Unzip it: let @('<dir>') be the name of the resulting directory.
</li>
<li>
Move the directory to a machine-wide location, e.g.:
@({
sudo mv <dir> /usr/local/
})
The @('sudo') is needed because @('/usr/local') is typically owned by @('root'),
and it is not good practice to change the ownership of @('/usr/local')
to a non-@('root') user.
There is no need to change the ownership of @('/usr/local/<dir>') to @('root').
</li>
<li>
Prepare to build Z3 with the Python bindings:
@({
cd /usr/local/<dir>
python scripts/mk_make.py --python
})
Note that no @('--prefix') or @('--pypkgdir') options are used here,
unlike the instructions given above.
This may give a warning related to Z3's restriction,
mentioned in the instructions above,
that @('--prefix') must be a prefix of @('--pypkgdir');
despite this warning, things worked on at least two Mac machines.
On Mac, ensuring that this restriction is satisfied is tricky because
Python packages are normally installed in places like
@('/Library/Frameworks/Python.framework/Versions/3.6/...') or
@('/System/Library/Frameworks/Python.framework/Versions/2.7/...'),
but prefixes of these locations normally do not hold
the @('bin'), @('lib'), and @('include') directories
that the Z3 installation creates (see below).
</li>
<li>
Build Z3:
@({
cd build
make
})
This may take a while to complete.
</li>
<li>
Install Z3:
@({
sudo make install
})
The @('sudo') is needed because this will write into
@('/usr/local/bin'), @('/usr/local/lib'), and @('/usr/local/include'),
which are typically owned by @('root') (see comments above about this).
</li>
<li>
Run the Z3 example in Python described in the instructions above,
to confirm that the installation was successful.
</li>
</ol>
<h3>Allow the Build System to Find Z3</h3>
<p>To make sure ACL2's build system can find Z3, Z3 should be installed in
one's path. There are two ways to achieve this:</p>
<ul>
<li>
Add the path to where Z3 is installed into one's path. For example,
@({
export PATH=/path to z3 executable/:$PATH
})
</li>
<li>
Another way of achieving this purpose is to create the following bash script
called ``z3'' and put it in one's path:
@({
#!/bin/bash
/path to z3 executable/z3 \"$@\"
})
In some systems, after creating that script, one needs to run ``rehash'' in the
shell.
</li>
</ul>
")
;; (xdoc::save "./manual" :redef-okp t) ;; write the manual
|