I am trying to solve a SAT problem with 12000+ boolean variables using Z3.
I expect that most of the variables will evaluate to false in the solution.
Is there a way to guide or hint Z3 as SAT solver to try "polarity false" first?
I've tried it with cryptominisat 2 and got good results.
Z3 is a collection of solvers and preprocessors. We can provide hints for some of the solvers.
When the command (check-sat) is used, Z3 will select the solver automatically for us.
We should (check-sat-using <strategy>) if we want to select the solver ourselves.
For example, the following command will instruct Z3 to use a Boolean SAT solver.
(check-sat-using sat)
We can force it to always try "polarity false" first by using:
(check-sat-using (with sat :phase always-false))
We can also control the preprocessing steps. If we want to put the formula in CNF before invoking sat, we should use:
(check-sat-using (then tseitin-cnf (with sat :phase always-false)))
EDIT: if you are using the DIMACS input format and Z3 v4.3.1, then you can't set parameters for all available solvers using the command line. The next release will address this limitation. In the meantime, you can download the work-in-progress branch using:
git clone https://git01.codeplex.com/z3 -b unstable
and compile Z3. Then, to force polarity false, we use the command line option
sat.phase=always_false
The command z3 -pm:sat will display all available options for this module.
END EDIT
Here is a complete example in SMT 2.0 (also available online):
(declare-const p Bool)
(declare-const q Bool)
(declare-const r Bool)
(declare-const s Bool)
(assert (or (not p) (not q) (not r)))
(assert (or r s))
(assert (or r (not s)))
(assert (or r (and p q)))
(echo "With always false")
(check-sat-using (then tseitin-cnf (with sat :phase always-false)))
(get-model)
(echo "With always true")
(check-sat-using (then tseitin-cnf (with sat :phase always-true)))
(get-model)
Related
Using Z3 4.4.1 or master, the following input gives unknown:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (and (> x 0) (< x 10)))
(assert (and (> y 0) (< y 10)))
(assert (and (> z 0) (< z 10)))
(assert (= (* z z) (+ (* x x) (* y y))))
(check-sat-using (or-else qfnra-nlsat smt))
If I switch the order of the qfnra-nlsat and smt tactics, then Z3 will return sat, which is the correct solution. The way it works right now, I'm basically forced to use qfnra-nlsat at the very end of my strategy. However, this is not optimal for me.
Is the above behaviour a bug? It seems like qfnra-nlsat leaves some unwanted changes to the model, when I would expect the model to be unchanged if qfnra-nlsat fails.
Try instead
(check-sat-using (and-then qfnra-nlsat smt))
This is subtle:
The qfnra-nlsat tactic fails to establish whether the formula is satisfiable because the formula uses integers (and the model qfnra-nlsat finds a solution over the reals). It therefore acts as a no-op and produces the same subgoal it got. The first tactic in the or-else list that does not throw an exception becomes the tactic to decide the outcome. So qfnra-nlsat decides that the goal could not be reduced.
By using and-then instead you are basically reducing the goal using first qfnra-nlsat. If it succeeds, it produces either no sub-goals or a sub-goal with the formula "false". The smt tactic knows to handle these cases, where the sat and unsat cases are handled very efficiently.
There are other alternatives. In particular, if you want to use or-else as part of some larger set of alternatives, the approach is:
(check-sat-using (or-else (and-then qfnra-nlsat fail) (and-then smt fail)))
It causes a failure to be signaled if qfnra-nlsat creates non-true and non-false subgoals. Then upon failure, the smt tactic is applied.
I have a test.smt2 file:
(set-logic QF_IDL)
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (or (< a 2) (< b 2 )) )
(check-sat)
(get-model)
(exit)
Is there anyway to tell Z3 to only output a=1 (or b=1)? Because when a is 1, b's value does not matter any more.
I executed z3 smt.relevancy=2 -smt2 test.smt2
(following How do I get Z3 to return minimal model?, although smt.relevancy seems has default value 2), but it still outputs:
sat
(model
(define-fun b () Int
2)
(define-fun a () Int
1)
)
Thank you!
The example given in the answer to the question referred to is slightly out of date. A Solver() will pick a suitable tactic to solve the problem, and it appears that it picks a different one now. We can still get that behavior by using a SimpleSolver() (at a possibly significant performance loss). Here's an updated example:
from z3 import *
x, y = Bools('x y')
s = SimpleSolver()
s.set(auto_config=False,relevancy=2)
s.add(Or(x, y))
print s.check()
print s.model()
Note that the (check-sat) command will not execute the same tactic as the SimpleSolver(); to get the same behavior when solving SMT2 files, we need to use the smt tactic, i.e., use (check-sat-using smt). In many cases it will be beneficial to additionally run the simplifier on the problem first which we can achieve by constructing a custom tactic, e.g., (check-sat-using (then simplify smt))
The SMT2 standard states that calling get-value is only legal after a call to check-sat and only when check-sat returns "sat" or "unknown".
Here is a simple example of an unsat problem:
(set-option :produce-models true)
(set-logic QF_BV)
(set-info :smt-lib-version 2.0)
(declare-fun a ()(_ BitVec 4))
(declare-fun b ()(_ BitVec 4))
(declare-fun c ()(_ BitVec 4))
(declare-fun z ()(_ BitVec 4))
(assert (= #b1111 z))
(assert (= a b))
(assert (= (bvxor a z) c))
(assert (= b c))
(check-sat)
(get-value ( a ))
(get-value ( b ))
(get-value ( c ))
Since the problem is unsat, the get-value commands are illegal. Take out any one assert and it becomes sat and the get-value commands become legal. So my question is, how do you write a SMT2 script that checks the return value of check-sat and only calls get-value if it returned sat?
Illegally calling get-value is an issue for me as I am running different smt solvers in a flow and checking the program's return value and then parsing their output. CVC4 change's its return value to an error state if get-value is called illegally.
I don't think there's a good way, if what you want is to have one "SMT" file to rule the whole transaction.
This issue comes up often in interacting with SMT-solvers from other languages. The solution I adopted is that I keep an open pipe with the solver and feed it the lines of the script, read the responses, and decide on what to send next based on the responses I get. Essentially programmed interaction. (This is what the Haskell SBV library does, for instance.)
However, I do agree that this is a pain; and it would be nice if there was an SMT2-lib sanctioned way of handling such common interaction.
For CVC4 being run from the command line, add the flag
--dump-models output models after every SAT/INVALID/UNKNOWN
response [*]
This is not as specific as get-value. This option is non-standard and CVC4 currently does not support setting this flag from the SMT2 parser. (Let us know if you would like this to be supported.)
I tried to use bit vectors to get randomized results in model values like suggested by de Moura here but then with Z3Py instead of SMTLIB. I translated his example to:
from z3 import *
s = Solver()
x = BitVec('x', 16)
set_option('auto_config', False)
set_option('smt.phase_selection',5)
s.add(ULT(x,100))
s.check()
s.model()
s.check()
s.model()
However, the result seems to always be the same, i.e.
- repetitive checking with s.check() does not alter the result.
- even after a restart of the python interactive shell the result of the execution will be the same
Adding a change of the random seed did not alter the results: set_option('smt.random_seed', 123)
Does anyone have an idea why is not working as desired?
Thanks in advance!
Carsten
This case is simply too simple. It's essentially solved by the preprocessor and never gets to a point where it needs to select a phase, so random phase selection has no effect. Leo's answer to the cited post is now a little bit out of date and Z3 has changed, so it doesn't immediately replicate using the latest unstable version because Z3 chooses to use a different solver. We can still get the random behavior if we force it to use the incremental solver by adding a (push) command though; here's an updated example that is seed dependent:
(set-option :auto_config false)
(set-option :smt.phase_selection 5)
(set-option :smt.random_seed 456)
(declare-const x (_ BitVec 16))
(assert (bvult x (_ bv100 16)))
(push)
(check-sat)
(get-model)
;; try again to get a different model
(check-sat)
(get-model)
;; try again to get a different model
(check-sat)
(get-model)
I have some simple constraints involving multiplication of reals in z3 that are producing unknown. The problem seems to be that they are wrapped in a datatype, as the unwrapped version produces sat.
Here is a simplified case:
(declare-datatypes () ((T (NUM (n Real)))))
(declare-const a T)
(declare-const b T)
(declare-const c T)
(assert (is-NUM a))
(assert (is-NUM b))
(assert (is-NUM c))
(assert (= c (NUM (* (n a) (n b)))))
(check-sat)
;unknown
And without the datatype:
(declare-const a Real)
(declare-const b Real)
(declare-const c Real)
(assert (= c (* a b)))
(check-sat)
;sat
I'm using z3 3.2, but this also is reproducible in the web interface.
Yes, Z3 can return unknown in quantifier-free problems.
Here are the main reasons:
Run out of time or memory
The quantifier-free fragment is undecidable (e.g., nonlinear integer arithmetic)
The quantifier-free fragment is too expensive, and/or the procedure implemented in Z3 is incomplete.
Your problems are in a decidable fragment, and the unknown is due to the incomplete procedure for nonlinear arithmetic used in Z3. Z3 4.0 has a complete procedure for nonlinear real arithmetic, but it is still not integrated with the other theories. So, it will not help in the first problem.
The different in behavior in the first and second queries is due to different strategies used for each query. Z3 has a new framework for defining custom strategies. You can get sat for the first query by using the command
(check-sat-using (then simplify solve-eqs smt))
instead of
(check-sat)
The first command forces Z3 to eliminate variables by solving equalities (i.e., tactic solve-eqs). It will eliminate the equality (= c (NUM (* (n a) (n b)))). This tactic is automatically used in the second problem in Z3 3.x. Note that this tactic will not help if we replace the equality with (>= c (NUM (* (n a) (n b)))).
Moreover, the second problem contains only nonlinear arithmetic. So, in Z3 4.0, the new (and complete) solver for nonlinear real arithmetic will be automatically used.
You can learn about the new strategy framework at http://rise4fun.com/Z3/tutorial/strategies, http://rise4fun.com/Z3Py/tutorial/strategies
Your examples are in non-linear arithmetic. Z3 4.0 is able to solve problems with only non-linear arithmetic assertions, but not along with uninterpreted functions and other theories. That explains why it produces unknown in the first example. This limitation is likely to be addressed in Z3's future versions.