The theorem proving tool z3 is taking a lot of time to solve a formula, which I believe it should be able to handle easily. To understand this better and possibly optimize my input to z3, I wanted to see the internal constraints that z3 generates as part of its solving process.
How do I print the formula that z3 produces for its back-end solvers, when using z3 from the command line?
Z3 command line tool does not have such option. Moreover, Z3 contains several solvers and pre-processing steps. It is unclear which step would be useful for you. The Z3 source code is available at https://github.com/Z3Prover/z3. When Z3 is compiled in debug mode, it provides an extra command line option -tr:<tag>. This option can be used to selectively dump information. For example, the source file nlsat_solver.cpp contains the following instruction:
TRACE("nlsat", tout << "starting search...\n"; display(tout);
tout << "\nvar order:\n";
display_vars(tout););
The command line option -tr:nlsat will instruct Z3 to execute the instruction above. tout is the trace output stream. It will be stored in the file .z3-trace. The Z3 source is full of these TRACE commands. Since the code is available, we can also add our own trace commands in the code.
If you post your example, I can tell you which Z3 components are used to preprocess and solve it.
Then, we can select which "tags" we should enable for tracing.
EDIT (after the constraints were posted):
Your example is in the mixed integer & real nonlinear arithmetic.
The new nonlinear arithmetic solver (nlsat) in Z3 does not support to_int.
Thus, the Z3 general purpose solver is used to solve your problem.
Although this solver accepts almost everything, it is not even complete for nonlinear real arithmetic. The nonlinear support on this solver is based on: interval analysis and Grobner basis computations.
This solver is implemented in the folder src/smt (in the unstable branch).
The arithmetic module is implemented in the files theory_arith*.
A good tracing command line option is -tr:after_reduce. It will display the set of constraints after pre-processing.
The bottleneck is the arithmetic module (theory_arith*).
Additional Remarks:
The problem is in a undecidable fragment: mixed integer & real nonlinear arithmetic. That is, it is impossible to write a sound and complete solver for this fragment. Of course, we can write a solver that solves instances we find in practice. I believe it is possible to extend nlsat to handle the to_int.
If you avoid to_int, you will be able to use nlsat. The problem will be in the nonlinear real arithmetic fragment. I understand that this may be hard, since the to_int seems to be a key thing in your encoding.
The code in the "unstable" branch at z3.codeplex.com is much better organized than the official version in the "master" branch. I will merge it with the "master" branch soon. You can retrieve the "unstable" branch if you want to play with the source code.
The "unstable" branch uses a new build system. You can build the release version with tracing support. You just have to use the option -t when generating the Makefile.
python scripts/mk_make.py -t
When Z3 is compiled in debug mode, the option AUTO_CONFIG=false by default. Thus, to reproduce the behavior of "release" mode, you must provide the command line option AUTO_CONFIG=true.
Related
I'm trying to find the c++ file for Z3 where the algorithm backtraces if it can't find a solution on the current branch. I've been looking through all the files and tried debug mode on the python files, but no luck so far. I just want to add a print statement to the method, so I can tell when it is returning to a previous node and trying a new path.
Thanks!
It depends on which solver Z3 uses for your problem. It typically uses smt_context.cpp in src/smt. The relevant backjump can be traced in the context::pop_scope method. Other solvers exist too: the src/sat/sat_solver is used for bit-vector and Boolean problems. It has a similar pop method. Finally, nlsat is used for non-linear polynomial arithmetic over the reals.
I notice that the Z3 C++ (and C) API allows you to supply the logic to be used.
I have two questions about this that I couldn't answer by looking online:
Are these supposed to be the standard SMT-LIB logics i.e. QF_LRA
When are these worth supplying i.e. when will Z3 actually use this information
My context is mainly QF no BV but everything else possible, I am using the SMT solver incrementally and I can always work out what logic I will be in at the start.
Z3 will also try to figure out what the logic is (when run with default options), but it doesn't have custom tactics for all combinations of theories (see default_tactic.cpp and smt_strategic_solver.cpp). When you are not sure what Z3 will decide to do, then it's best to set the tactic right up front, so that you will get errors if you try to use things that are not in that logic. It will also use that information to set up the smt kernel, e.g., enabling various preprocessors, various solver features, and chosing heuristics (see e.g., smt_setup.cpp).
Try it out and see!
Usually it does make a big difference. Setting the logic means the solver will use a specialized tactic to solve the formula, instead of going through the generic loop. Z3 will also try to guess the logic, but it's usually better to just provide it upfront.
I just downloaded the benchmarks for seq and regexp sorts (using z3-4.3.2). What could be the problem when I get unknown as result after running "membership_1.smt2"?
I did not specify any further command line options. According to the benchmark it should result in sat, but unknown is printed without any model.
Thank you
edit:
I noticed further, that "re-begin" is not recognized. Has this to do with the version of z3 or did u just forgot a command line option?
Firstly, I don't know where the OP or commenter found the "membership_1.smt2" example input. I checked the SMT-LIB benchmarks, and the source of Z3, S3, and Z3-str, and couldn't find it.
In any case, the problem was that the OP was testing a benchmark written either for S3 or Z3-str and running it against an unmodified version of Z3. S3 and Z3-str require a modified version of Z3 to handle these extensions. This is described on the S3 website [S3: A Symbolic String Solver for Web Security Analysis, http://www.comp.nus.edu.sg/~trinhmt/S3/, accessed Aug. 4, 2016]:
Modified Version of Z3 Solver
The source code of the modified Z3 is available here.
We modify Z3 to have the interaction between String theory and Arithmetic theory.
These newly-added API methods allows us to query the length of a string variable, and relationship between the length of different
string variables, as shown in our CCS'14 paper.
Our modified version of Z3 is also used by Z3-str GROUP for integer/string theory integration.
Grepping the (unmodified) Z3 source shows no matches for "re-begin" or "re-concat". Grepping the modified version shows that these tokes are defined in lib/seq_decl_plugin.cpp of z3-source-060115.zip.
I have precise and validated descriptions of the behaviors of many X86 instructions in terms amenable to encoding in QF_ABV and solving directly with the standard solver (using no special solving strategies). I wrote an SMT-LIB script whose interface matches my ultimate goal perfectly:
X86State, a record sort describing x86 machine state (registers and flags as bitvectors, and memory as an array).
X86Instr, a record sort describing x86 instructions (enumerated mnemonics, operands as an ML-like discriminated union describing registers, memory expressions, etc.)
A function x86-translate taking an X86State and an X86Instr, and returning a new X86State. It decodes the X86Instr and produces a new X86State in terms of the symbolic effects of the given X86Instr on the input X86State.
It's great for prototyping: the user can write x86 easily and directly. After simplifying a formula built using the library, all functions and extraneous data types are eliminated, leaving a QF_ABV expression. I hoped that users could simply (set-logic QF_ABV) and #include my script (alas, neither the SMT-LIB standard nor Z3 support #include).
Unfortunately, by defining functions and types, the script requires theories such as uninterpreted functions, thus requiring a logic other than QF_ABV (or even QF_AUFBV due to the types). My experience with SMT solvers dictates that the lowest acceptable logic should be specified for best solving time. Also, it is unclear whether I can reuse my SMT-LIB script in a programmatic context (e.g. OCaml, Python, C) as I desire. Finally, the script is a bit verbose given the lack of higher-order functions, and my lack of access to par leading to code duplication.
Thus, despite having accomplished my technical goals, I think that SMT-LIB might be the wrong approach. Is there a more natural avenue for interacting with Z3 to implement my x86 instruction description / QF_ABV translation scheme? Is the SMT-LIB script re-usable at all in these avenues? For example, you can build "custom OCaml top-levels", i.e. interpreters with scripts "burned into them". Something like that could be nice. Or do I have to re-implement the functionality in another language, in a program that interacts with Z3 via a theory extension (C DLL)? What's the best option here?
Well, I don't think that people write .smt2 files by hand. These are usually generated automatically by some program.
I find the Z3 Python interface quite nice, so I guess you could give it a try. But you can always write a simple .smt2 dumper from any language.
BTW, do you plan releasing the specification you wrote for X86? I would be really interested!
I am running Z3 on UFBV queries. Currently the query contains 2 calls check-sat.
If I put push 1 just after check-sat, Z3 solves the query in 30sec. If I don't put any push 1 at all, thus have two calls check-sat without any push 1 between them, then Z3 solves it in 200sec.
Interesting. Any specific reasons or just a coincidence?
Z3 3.x has a "strategy specification language" based on tactics and tacticals. I'm not "advertising" that yet because it is working in progress.
The basic idea is described in this slide deck.
We have a different built-in strategy for each logic. The strategies usually do not support incremental solving, because they may apply transformations that use a "closed-world" assumption. Example, we have transformations that map 0-1 linear integer arithmetic into SAT. Whenever Z3 detects that the user "wants" incremental solving (e.g., multiple check-sat commands, push&pop commands), it switches to a general purpose solver. In future versions, we will provide more features for controlling Z3 behavior.
BTW, if you have two consecutive (check-sat) (check-sat) commands, Z3 not necessarily enters in incremental mode. It will enter only if there is an assert or push command between the two calls.
Now, suppose your query is of the form: (check-sat) <assertions> (check-sat), and your second query is of the form (check-sat) <assertions> (push) (check-sat). In both cases, Z3 will be in incremental mode in the second (check-sat). However, the behavior is still not the same. The incremental solver "compiles" the asserted formulas to an internal format, and its behavior is affected if a push command has been executed. For example, it will use a more efficient encoding of binary clauses only if there is no user scope. By user scope, I mean, the number of push commands - number of pop commands. It does that because the data-structure used in the more efficient encoding does not have an efficient undo/inverse operation.