This smt2 script gives unsat if I use
(check-sat-using (then simplify solve-eqs (repeat bit-blast) (! smt :bv.enable_int2bv true :arith.euclidean_solver true))), and gives sat if I remove :arith.euclidean_solver true. The expected result is sat.
Z3 version 4.4.0
Thank you in advance.
I opened a bug on github to track this.
The URL is: https://github.com/Z3Prover/z3/issues/100
Related
I have tried to implement Floor and Ceiling Function as defined in the following link
https://math.stackexchange.com/questions/3619044/floor-or-ceiling-function-encoding-in-first-order-logic/3619320#3619320
But Z3 query returning counterexample.
Floor Function
_X=Real('_X')
_Y=Int('_Y')
_W=Int('_W')
_n=Int('_n')
_Floor=Function('_Floor',RealSort(),IntSort())
..
_s.add(_X>=0)
_s.add(_Y>=0)
_s.add(Implies(_Floor(_X)==_Y,And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W ==_Y,_W<_Y))))))
_s.add(Implies(And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W==_Y,_W<_Y))),_Floor(_X)==_Y))
_s.add(Not(_Floor(0.5)==0))
Expected Result - Unsat
Actual Result - Sat
Ceiling Function
_X=Real('_X')
_Y=Int('_Y')
_W=Int('_W')
_Ceiling=Function('_Ceiling',RealSort(),IntSort())
..
..
_s.add(_X>=0)
_s.add(_Y>=0)
_s.add(Implies(_Ceiling(_X)==_Y,And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W ==_Y,_Y<_W))))))
_s.add(Implies(And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W==_Y,_Y<_W)))),_Ceiling(_X)==_Y))
_s.add(Not(_Ceilng(0.5)==1))
Expected Result - Unsat
Actual Result - Sat
[Your encoding doesn't load to z3, it gives a syntax error even after eliminating the '..', as your call to Implies needs an extra argument. But I'll ignore all that.]
The short answer is, you can't really do this sort of thing in an SMT-Solver. If you could, then you can solve arbitrary Diophantine equations. Simply cast it in terms of Reals, solve it (there is a decision procedure for Reals), and then add the extra constraint that the result is an integer by saying Floor(solution) = solution. So, by this argument, you can see that modeling such functions will be beyond the capabilities of an SMT solver.
See this answer for details: Get fractional part of real in QF_UFNRA
Having said that, this does not mean you cannot code this up in Z3. It just means that it will be more or less useless. Here's how I would go about it:
from z3 import *
s = Solver()
Floor = Function('Floor',RealSort(),IntSort())
r = Real('R')
f = Int('f')
s.add(ForAll([r, f], Implies(And(f <= r, r < f+1), Floor(r) == f)))
Now, if I do this:
s.add(Not(Floor(0.5) == 0))
print(s.check())
you'll get unsat, which is correct. If you do this instead:
s.add(Not(Floor(0.5) == 1))
print(s.check())
you'll see that z3 simply loops forever. To make this usefull, you'd want the following to work as well:
test = Real('test')
s.add(test == 2.4)
result = Int('result')
s.add(Floor(test) == result)
print(s.check())
but again, you'll see that z3 simply loops forever.
So, bottom line: Yes, you can model such constructs, and z3 will correctly answer the simplest of queries. But with anything interesting, it'll simply loop forever. (Essentially whenever you'd expect sat and most of the unsat scenarios unless they can be constant-folded away, I'd expect z3 to simply loop.) And there's a very good reason for that, as I mentioned: Such theories are just not decidable and fall well out of the range of what an SMT solver can do.
If you are interested in modeling such functions, your best bet is to use a more traditional theorem prover, like Isabelle, Coq, ACL2, HOL, HOL-Light, amongst others. They are much more suited for working on these sorts of problems. And also, give a read to Get fractional part of real in QF_UFNRA as it goes into some of the other details of how you can go about modeling such functions using non-linear real arithmetic.
Can I save the constraints I created for a z3 solver and later reload them to continue looking for more solutions?
I have learned there is the SMT-LIB2 format for such things and that z3 and z3py have an API for saving and loading in that format. Unfortunately I cannot make it work.
Here's my example program which pointlessly saves and reloads:
import z3
filename = 'z3test.smt'
# Make a solver with some arbitrary useless constraint
solver = z3.Solver()
solver.add(True)
# Save to file
smt2 = solver.sexpr()
with open(filename, mode='w', encoding='ascii') as f: # overwrite
f.write(smt2)
f.close()
# Load from file
solver.reset()
solver.from_file(filename)
It fails with:
Exception has occurred: ctypes.ArgumentError
argument 3: <class 'TypeError'>: wrong type
File "C:\Users\Marian Aldenhövel\Desktop\FridgeIQ\z3\z3-4.8.4.d6df51951f4c-x64-win\bin\python\z3\z3core.py", line 3449, in Z3_solver_from_file
_elems.f(a0, a1, _to_ascii(a2))
File "C:\Users\Marian Aldenhövel\Desktop\FridgeIQ\z3\z3-4.8.4.d6df51951f4c-x64-win\bin\python\z3\z3.py", line 6670, in from_file
_handle_parse_error(e, self.ctx)
File "C:\Users\Marian Aldenhövel\Desktop\FridgeIQ\src\z3test.py", line 17, in <module>
solver.from_file(filename)
Is this a problem with my understanding or my code? Can it be done like this? Are sexpr() and from_file() the right pair of API calls?
I am using z3 and z3py 4.8.4 from https://github.com/z3prover/z3/releases on Windows 10 64bit.
More detail if required:
I am playing with z3 in Python to find solutions for a large disection-puzzle.
To find all solutions I am calling solver.check(). When it returns a sat verdict I interpret the model as image of my puzzle solution. I then add a blocking clause ruling out that specific solution and call solver.check() again.
This works fine and I am delighted.
The runtime to find all solutions will be on the order of many days or until I get bored. I am concerned that my machine will not be running continuously for that long. It may crash, run out of power, or be rebooted for other reasons.
I can easily recreate the initial constraints which is the whole point of the program. But the blocking clauses are a runtime product and a function of how far we have gotten.
I thought I could save the state of the solver and if at runtime I find such a file restart by loading that with the blocking clauses intact and go on finding more solutions instead of having to start over.
Thank you for taking your time reading and thinking.
Marian
With z3 4.4.1 and z3 4.8.5, I would dump (and reload) the constraints in smt2 format as follows:
import z3
filename = "z3test.smt2"
x1 = z3.Real("x1")
x2 = z3.Real("x2")
solver = z3.Solver()
solver.add(x1 != x2)
#
# STORE
#
with open(filename, mode='w') as f:
f.write(solver.to_smt2())
#
# RELOAD
#
solver.reset()
constraints = z3.parse_smt2_file(filename, sorts={}, decls={})
solver.add(constraints)
print(solver)
output:
~$ python t.py
[And(x1 != x2, True)]
file z3test.smt2:
(set-info :status unknown)
(declare-fun x2 () Real)
(declare-fun x1 () Real)
(assert
(and (distinct x1 x2) true))
(check-sat)
I have no idea whether the API changed in the version you are using. Feedback is welcome.
Running Windows x64 builds of Z3 4.3.2 (official download) and Z3 4.4 0ab54b9e0c33 on this program (which is unfortunately quite long) yields an invalid rational value passed as an integer.
The problem does not appear to be a type checker problem, because the apparently offending formula (the last check-sat in the program) looks fine type-wise:
(declare-const i#99 Int)
(declare-const k#38 Int)
...
(assert (not (and (<= 0 i#99) (< i#99 (+ k#38 1)))))
(check-sat) ; ERROR
My guess is that the problem occurs during proof search because marginally changing the program makes the error disappear. I experimented with changing Z3's configuration options and observed that the error disappears if smt.arith.nl is set to false, respectively, if smt.qi.eager_threshold is set to a value lower than 10. Moreover, removing essentially any push-pop scope preceding the last check-sat also makes the error disappear (I didn't actually try to remove every single scope, though). Both observations make me believe that the error is raised during proof search and in an "area" of the search space that is only reached under specific circumstances.
The offending line as well as lines I experimented with are marked by [XXX].
Is this a bug or is something else going on here?
The issue can be followed on Z3's GitHub page: https://github.com/Z3Prover/z3/issues/32.
I have some code, which I want to check with help of some tactics. Since I have lot of if-then-else statements, I want to apply elim-term-ite tactic.
I have made use of following tactics
(check-sat-using (then (! simplify :arith-lhs true) elim-term-ite solve-eqs lia2pb pb2bv bit-blast sat))
However, if I an error with this as - "goal is in a fragment unsupported by lia2pb"
So then, if I try to remove the tactics lia2pb and the ones next to them, I get another error as unknown "incomplete".
I tried to remove all the tactics except for the simplify, however I would still get an incomplete error.
What is that I should try to help the sat solver solve the problem?
Should I try another tactics?
To use lia2pb (aka linear integer arithmetic to pseudo-boolean), all integer variables must be bounded. That is, they must have a lower and upper bound.
The tactic sat is only complete if the input goal does not contain theory atoms. That is, the goal contains only Boolean connectives and Boolean constants. If that is not the case, then it will return "unknown" if it cannot show the (Boolean abstraction of the input) goal to be unsatisfiable.
You can ask Z3 to display the input goal for lia2pb by using the following command:
(apply (then (! simplify :arith-lhs true) elim-term-ite solve-eqs)
If some of your formulas contain unbounded integer variables, you can build a strategy that reduces to SAT when possible, and invokes a general purpose solver otherwise. This can be accomplished using the or-else combinator. Here is an example:
(check-sat-using (then (! simplify :arith-lhs true) elim-term-ite solve-eqs
(or-else (then lia2pb pb2bv bit-blast sat)
smt)))
EDIT: The tactic lia2pb also assumes that the lower bound of every bounded integer variable is zero. This is not a big problem in practice, since we can use the tactic normalize-bounds before applying lia2pb. The tactic normalize-bounds will replace a bound variable x with y + l_x, where y is a fresh variable and l_x is the lower bound for x. For example, in a goal containing 3 <= x, x is replaced with y+3, where y is a new fresh variable.
The problem is pretty simple.
I assert following statement in Z3 using the C API interface.
(assert(>= (xA 1) (- (yB 0) period))))
Now Sometimes, I need to check what kind of assertions have been fed and the result in the SatSolver. I do this, by generating a text file by using ast_to_string() API. This API returns me above statement as -
(assert(>= (xA 1) (+ (yB 0) (* -1 period))))
When I feed this file to the Sat Solver it complains me with the error -
(error "ERROR: line 150 column 56: could not locate id -1.")
So then, I have to manually fix all -1 in the code and run the sat solver.
Is there any other way where I can avoid this?
Remember to set:
Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB2_COMPLIANT);
before using ast_to_string() in order that that output formulas comply with SMTLIB 2.0 format.