z3 context reset API - z3

I want to reset the context in z3, similarly to what I do in yices: void yices_reset (yices_context ctx)
Is there an equivalent command for z3? Currently I use Z3_del_context(ctx); but I am not sure it is the most efficient way. Should I use the push/pop context commands, or is there another method?

Z3_del_context(ctx) is an option. However, in your question, you mention push/pop. So, it seems you actually want to reset just the set of assertions. If that is the case, I suggest you start using Z3_solver objects. We can create many different Z3_solver objects in a Z3_context object. The main advantage is they may share declarations, formulas, expressions, etc. BTW, Z3 comes with a C++ wrapper (z3++.h) that is much easier to use them the C API. Here is a C++ example using multiple solver objects. BTW, you can use multiple solver objects at the same time.
context c;
expr x = c.int_const("x");
expr y = c.int_const("y");
{
solver s(c);
s.add(x >= 1);
s.add(y < x + 3);
std::cout << s.check() << "\n";
model m = s.get_model();
std::cout << m << "\n";
// solver object c will be destroyed at this point
}
{
// creating a new solver object
solver s2(c);
s2.add(x > y + 1);
std::cout << s2.check() << "\n";
}
EDIT: Solver objects also have a reset method. It erases all assertions asserted in a given solver.

Related

How do I evaluate a quantification expression within a Z3 model evaluation?

Consider the following, which creates a simple model where a string is equal to a specific value:
from z3 import *
s = Solver()
x = String('x')
s.add(x == StringVal('foo'))
s.check()
I then want to ask whether there exists a string that is equal to x's model value:
y = String('y')
expr = Exists(y, y == x)
print(s.model().evaluate(expr))
I would expect this to return a boolean value, but instead the output is itself an expression:
Exists(y, y == "foo")
How do I get this expression to be actually evaluated within the evaluate method, instead of coughed back up? I'm assuming evaluate doesn't like the fact that I introduced a new unbound variable, but surely putting that variable within an Exists (or for that matter, a ForAll) is sufficient for the expression to be evaluated? Is there a way to write quantification methods without introducing a new unbound variable?
Turns out quantification is slightly beyond what Z3 supports in the evaluate method (which makes sense). The workaround is to re-run s.check() if evaluate returns a QuantifierRef:
result = s.model().evaluate(expr)
print(result)
if isinstance(result, QuantifierRef):
s.push()
s.add(result)
print(s.check())
s.pop()
Of course, you can also ask why you're even bothering with an evaluate call instead of just putting expr as an additional constraint before the call to check.

Is there way to give input as normal expression to Z3 Solver?

The Z3 input format is an extension of the one defined by SMT-LIB 2.0 standard. The input expressions need to write in prefix form. As for example rise4fun,
x + (y * 2) = 20 needs to be given input in the form of " (= (+ x (* 2 y)) 20)) ".
Z3 supports JAVA API. As for example, let us consider the below code which evaluates and checks satisfiability expressions: x+y = 500 and x + (y * 2) = 20.
final Context ctx = new Context();
final Solver solver = ctx.mkSimpleSolver();
IntExpr x = ctx.mkIntConst("x");
IntExpr y = ctx.mkIntConst("y");
IntExpr th = ctx.mkInt(500);
IntExpr th1 = ctx.mkInt(2);
IntExpr th2 = ctx.mkInt(20);
BoolExpr t1 = ctx.mkEq(ctx.mkAdd(x,y), th);
BoolExpr t2 = ctx.mkEq(ctx.mkAdd(x,ctx.mkMul(th1, y)), th2);
solver.add(t1);
solver.add(t2);
solver.check()
The problem is if an external user wants to give input to the solver, he cannot give it in the form of the general formula as " x+y = 500, x + (y * 2) = 20 ".
The input needs to be parsed and then should be written manually using JAVA API in prefix form (Note BoolExpr t2 in above code) to give the final expressions to Solver.
Is there any parser/library/API (Preferably JAVA or in any other language) which parses the general expressions with arithmetic operators(+, -, <, >, =), propositional logic connectors (And, OR), Quantifiers(ForAll, Exists) and then gives input to the Z3 Solvers ?
Please suggest and help.
This is precisely why people build high-level interfaces to SMT solvers. There are many choices here for z3:
Official Python interface to z3: https://ericpony.github.io/z3py-tutorial/guide-examples.htm This is supported by Microsoft directly, and is probably the easiest to use.
PySMT, which aims to cover as many SMT solvers as they can: https://github.com/pysmt/pysmt
Scala bindings: https://github.com/epfl-lara/ScalaZ3
Haskell SBV: http://hackage.haskell.org/package/sbv
Many others at various maturity levels for Racket, Go, Lisp.. You name it. You can find many of them on github.
The goal of these "wrappers" is to precisely save the end-user from all the details of intricate bindings, and provide something much easier and less-error prone to use. On the flip side, they require you to learn yet another library. In my experience, if the host language of your choice has such an implementation, it'd pay off nicely to use it. If not, you should build one!

Does z3 distinguish variables by their names?

Suppose we have the following code:
context c;
solver s(c);
expr x=c.bool_const("a");
expr y=c.bool_const("a");
expr z=c.bool_const("b");
s.add(x&&!y);
std::cout<<s.check();
s.reset();
s.add(x&&!z);
std::cout<<s.check();
The executing result of above code is 'unsat sat';
The result shows that z3 regards x and y as the same variable.
Does z3 distinguish variables by their names?
And if I use the same variable in different places, can I write the code as following:
context c;
solver(s);
function test1(){
s.add(c.bool_const("a"));
}
function test2(){
s.add(!c.bool_const("a"));
}
Dose the function 'test1' and 'test2" manipulate the same variable?
You seem to confuse the programming variables x and y that exist in the host language C++ with logical variables a and b that Z3 reasons about. x and y both represent the logical variable a, and by adding x && !y to the constraints you give Z3 the fact a && !a, which makes your constraints unsatisfiable.

UNKNOWN when using def's

This simple example generates UNKNOWN for me, I suppose there is something that I don't understand about def's.
from z3 import *
s = Solver()
def Min(b, r):
return If(b, r, 1)
a = Real('a')
b = Bool('b')
s.add(a==0.9)
s.add(a<=Min(b,0.9))
s.check()
print "Presenting result "
m = s.model()
print "traversing model..."
for d in m.decls():
print "%s = %s" % (d.name(), m[d])
You did not make any mistake. This is a problem in one of Z3 solvers. Your problem is in a fragment of arithmetic called "difference-logic". A problem in in this fragment, if the arithmetic atoms can be written as x - y <= k, where k is a numeral. When a problem is in this fragment, Z3 will use a specialized solver for it. However, this solver may fail (returns unknown) when the input problem also contains if-then-else terms (the If in your Min).
The bug has been fixed, and will be available in the next release. In the meantime, you can try one of the following workarounds:
Force Z3 to eliminate if-then-else terms before invoking the solver. You just have to replace s = Solver() with s = Then('elim-term-ite', 'smt').solver(). Here is the modified script at rise4fun.
We can add a redundant assertion that is not in the different logic fragment. Example: z + w > 2. Here is the modified script at rise4fun.

How to read smtlib2 strings using Z3 C++ api?

I want to create an expr object from a given SMTLIB2 file. I can see a Z3_parse_smtlib_string function in the C examples. Is there a wrapper for that in the expr class?
The Z3 C++ API does not explicitly provide this functionality as part of the expr class. However, the C++ API can be used alongside the C API, i.e., the function Z3_parse_smtlib_string (or ..._file) can be used to achieve this. Note that this function returns a Z3_ast, which must be converted to an expr object to get back to the C++ "world".
A simple example:
#include <z3++.h>
...
context ctx;
Z3_ast a = Z3_parse_smtlib2_file(ctx, "test.smt2", 0, 0, 0, 0, 0, 0);
expr e(ctx, a);
std::cout << "Result = " << e << std::endl;
Since the Z3_parse_smtlib2_* functions do not perform error checking, no exception will be thrown upon errors. This can be achieved by calls to context::check_error().

Resources