I'm using Z3 to solve a system that consists of Boolean constraints on variables Vi as well as a constraint of the following form:
L < If(V0, T0, F0) + If(V1, T1, F1) + ... + If(Vn, Tn, Fn) <= H
where L, H, and the Ti and Fi are integer constants.
Although all the variables are Boolean, I found that the QF_LIA solver was somewhat faster than the generic one, so I'm using the former. My assumption was that Z3 was handling the constraint above by introducing new variables and clauses to implement adders in the obvious way. However, doing that conversion myself (using MiniSat+) and passing the result to a SAT solver takes an order of magnitude longer than Z3 does. Thus, I'm wondering what strategy Z3 uses to solve systems of the type described above - is it something other than the conversion using adders?
Z3 uses a reduction to SAT to solve this kind of problem. If you are using the shell, you can provide the option -v:10 (verbosity messages). Z3 will display several messages describing what it is doing. For the kind of problem you described, Z3 will probably display verbose messages of the form:
(lia2pb :num-exprs 9 :num-asts 185 ...)
(pb2bv :num-exprs 9 :num-asts 185 ...)
lia2pb means that Z3 is converting a linear integer arithmetic problem into a pseudo boolean constraint problem. And pb2bv means that it is reducing the problem to bit-vector arithmetic.
The lia2pb transformation is implemented in the file:
http://z3.codeplex.com/SourceControl/latest#src/tactic/arith/lia2pb_tactic.cpp
and pb2bv transformation is implemented in the file:
http://z3.codeplex.com/SourceControl/latest#src/tactic/arith/pb2bv_tactic.cpp
Related
I've come up with an SMT formula in Z3 which outputs one solution to a constraint solving problem using only BitVectors and IntVectors of fixed length. The logic I use for the IntVectors is only simple Presburger arithmetic (of the form (x[i] - x[i + 1] <=/>= z) for some x and z). I also take the sum of all of the bits in the bitvector (NOT the binary value), and set that value to be within a range of [a, b].
This works perfectly. The only problem is that, as z3 works by always taking the easiest path towards determining satisfiability, I always get the same answer back, whereas in my domain I'd like to find a variety of substantially different solutions (I know for a fact that multiple, very different solutions exist). I'd like to use this nifty tool I found https://bitbucket.org/kuldeepmeel/weightgen, which lets you uniformly sample a constrained space of possibilities using SAT. To use this though, I need to convert my SMT formula into a SAT formula.
Do you know of any resources that would help me learn how to perform Presburger arithmetic and adding the bits of a bitvector as a SAT instance? Alternatively, do you know of any SMT solver which as an intermediate step outputs a readable description of the problem as a SAT instance?
Many thanks!
[Edited to reflect the fact that I really do need the uniform sampling feature.]
I understand that Z3 has some supports for nonlinear arith but wondering to what extends ? Is it possible to specify what classes of nonlinear arithmetics are supported and are not (or likely to give time out) ? Know these in advances will help me abort my task early.
Seems like power related stuff is not supported as shown below
def pow2(x):
k=Int('k')
return Exists(k, And(k>=0,2**k==x))
prove(pow2(7))
failed to prove
Z3 supports nonlinear polynomial Real arithmetic. So, there is no support for transcendental functions (e.g., sine and cosine), and exponential (e.g., 2^x). Actually, for the exponential, Z3 can handle exponents that can be simplified to numerals. Here is an example,
x = Real('x')
y = Real('y')
solve(y == 3, x**y == 2)
In this example, the y in x**y is rewritten to 3 during a preprocessing step. After preprocessing, the nlsat solver for nonlinear polynomial real arithmetic is invoked.
Regarding nonlinear integer arithmetic, see this related post.
I am trying to encode formulas with functions in Z3 and I have an encoding problem. Consider the following example:
f(x) = x + 42
g(x1, x2) = f(x1) / f(x2)
h(x1, x2) = g(x1, x2) % g(x2, x1)
k(x1, x2, x3) = h(x1, x2) - h(x2, x3)
sat( k(y1, y2, y3) == 42 && k(y3, y2, y1) == 42 * 2 && ... )
I would like my encoding to be both efficient (no expression duplication) and allow Z3 to re-use lemmas about functions across subproblems. Here is what I have tried so far:
Inline the functions for every free variable instantiation y1, y2, etc. This introduces duplication and performance is not as good as I hoped for.
Assert the function declarations with universal quantifiers. This works for very specific examples - from the solving times it seems that Z3 can (?) re-use results from previous queries that involve the same functions. However, solving times vary greatly and in many cases (1) turns out to be faster.
Use function definitions (i.e., quantifiers + the MACRO_FINDER option). If my understanding of the documentation is correct, this should expand the functions and thus should be close to (1). However, in terms of performance the results were a bit surprising (">" means faster):
For problems where (1) > (2) I get: (1) > (3) > (2)
For problems where (2) > (1) I get: (2) > (1) = (3)
I have also tried tweaking the MBQI option (and others) with most of the above. However, it is not clear what is the best combination. I am using Z3 4.0.
The question is: What is the "right" way to encode the problem? Note that I only have interpreted functions (I do not really need UF). Could I use this fact for a more efficient encoding and avoid function expansion?
Thanks
I think there's no clear answer to this question. Some techniques work better for one type of benchmarks and other techniques work better for others. For the QBVF benchmarks we've looked at so far, we found macros give us the best combination of small benchmark size and small solving times, but this may not apply in this case.
Your understanding of the documentation is correct, the macro finder will identify quantifiers that look like function definitions and replace all other calls to that function with its definition. It's possible that not all of your macros are picked up or that you are using quasi-macros which aren't detected correctly, either of which could go towards explaining why the performance is sometimes worse than your (1). How much is the difference in the case that (1) > (3)? A little overhead is to be expected, but vast variations in runtime are probably due to some macros being malformed or not being detected.
In general, the is no "right" way to encode these problems. Function expansion can not always be avoided. The trade-off is essentially between expanding eagerly (1, 3), or doing it lazily (2). It may be that there is a correlation of the type SAT (1, 3 faster) and UNSAT (2 faster), but this is also not guaranteed to be the case.
I am trying to optimize z3 python input that is generated from my models. I am able to run it on models up 15k constraints (200 states) and then z3 stops finishing in reasonable time (<10 minutes). Is there a way to optimize the constraints that are generated from my models ?
Model for 3 states:
http://pastebin.com/EHZ1P20C
The performance of the script http://pastebin.com/F5iuhN42 can be improved by using a custom strategy. Z3 allows users to define custom strategies/solvers. This tutorial shows how to define strategies/tactics using the Z3 Python API. In the script http://pastebin.com/F5iuhN42, if we replace the line
s = Solver()
with
s = Then('simplify', 'elim-term-ite', 'solve-eqs', 'smt').solver()
the runtime will decrease from 30 secs to 1 sec (on my machine).
The procedure Then is creating a strategy/tactic composed of 4 steps:
Simplifier (i.e., a rewriter that applies rules such as x + 1 - x + y ==> 1 + y
Elimination of expressions of the form If(a, b, c) where b and c are not Boolean. The script makes extensive use this kind of expression. The tactic elim-term-ite will apply transformations that eliminate this kind of expression.
Equational solver. It applies transformations such as x = a And F[x] ==> F[a]. In the script above, this tactic can eliminate more than 1000 variables.
The tactic smt invokes a general purpose SMT solver in Z3.
The method .solver() converts a Z3 tactic/strategy into a solver object that provides the add and check methods. The tutorial that I included in the beginning of the message has more details.
Many thanks Josh and Leonardo for answering the previous question.
I have few more questions.
<1> Consider another example.
(exists k) i * k > = 4 and k > 1.
This has a simple solution i > 0. (both for Int and Real case)
However, when I tried following,
(declare-const i Int)
(assert (exists ((k Int)) (and (>= (* i k) 4) (> k 1))))
(apply (using-params qe :qe-nonlinear true))
Z3 Could not eliminate quantifier here.
However, it could eliminate for a Real case. (when i and k are both reals)
Is Quantifier Elimination more difficult for integers?
<2> I am using Z3 C API in my system. I am adding some non-linear constraints on Integers with quantifiers in my system.
Z3 currently checks for satisfiability and gives me a correct model when the system is satisfiable.
I know that after quantifier elimination, these constraints get reduced to linear constraints.
I thought that z3 does quantifier elimination automatically before checking satisfiability. But since, it couldn't do that in case 1 above, I now think, that it usually finds a model without Quantifier Elimination. Am I correct?
Currently z3 can solve the constraints in my system. But it may fail on complex systems.
In such case, is it a good idea to do quantifier elimination by some other method without z3 and add constraints to z3 later?
<3> I can think of adding Real non-linear constraints instead of Integer non-linear constraints in my system. In that case, how can I enforce z3 to do Quantifier Elimination using C-API ?
<4> Finally, is this a good idea to enforce z3 to do Quantifier Elimination? Or it usually finds a model more intelligently without doing Quantifier Elimination?
Thanks.
<1> The theory of nonlinear integer arithmetic does not admit quantifier elimination (qe).
Moreover, the decision problem for nonlinear integer arithmetic is undecidable.
Recall that, Z3 has limited support for quantifier elimination of nonlinear real arithmetic formulas. The current procedure is based on virtual term substitution. Future versions, may have full support for nonlinear real arithmetic.
<2> Quantifier elimination is not enabled by default. The user must request it.
Z3 may find models for satisfiable formulas even when quantifier elimination is not enabled.
It uses a technique called model-based quantifier instantiation (MBQI). The Z3 online tutorial has several examples describing capabilities and limitations of this technique.
<3> You have to enable it when you create the Z3_context object.
Any option that is set in the command line, can be provided during Z3_context object creation. Here is an example, that enables model construction and quantifier elimination:
Z3_config cfg = Z3_mk_config();
Z3_context ctx;
Z3_set_param_value(cfg, "MODEL", "true");
Z3_set_param_value(cfg, "ELIM_QUANTIFIERS", "true");
Z3_set_param_value(cfg, "ELIM_NLARITH_QUANTIFIERS", "true");
ctx = mk_context_custom(cfg, throw_z3_error);
Z3_del_config(cfg);
After that, ctx is pointing to a Z3 context object that supports model construction and quantifier elimination.
<4> The MBQI module is not complete even for the linear arithmetic fragment.
The Z3 online tutorial describes the fragments it is complete. MBQI module is a good option for problems that contain uninterpreted functions. If your problems only use arithmetic, then quantifier elimination is usually better and more efficient. That being said, several problems can be quickly solved using MBQI.