I am working with the Z3 Java API and trying to define a function f(x) = x + 1 via using recursive API. However, instead of directly defining the function as y = x + 1, I want to use constraints to represent this relationship. Below is the code I have written:
@Test
public void test1() {
Context ctx = new Context();
FuncDecl f = ctx.mkRecFuncDecl(ctx.mkSymbol("f"),
new Sort[]{ctx.mkIntSort()},
ctx.mkIntSort());
Expr x = ctx.mkFreshConst("x", ctx.mkIntSort());
Expr y = ctx.mkFreshConst("y", ctx.mkIntSort());
Expr cons = ctx.mkEq(ctx.mkAdd(x, ctx.mkInt(1)), y);
ctx.AddRecDef(f, new Expr[]{x}, y);
Solver solver = ctx.mkSolver();
solver.add(cons);
solver.add(ctx.mkNot(ctx.mkEq(ctx.mkInt(2), ctx.mkApp(f, ctx.mkInt(1)))));
assert solver.check() == Status.UNSATISFIABLE; //Fail
}
the function does not behave as expected. The constraint f(1) != 2 should be unsatisfiable, but it seems like the constraints are not correctly applied.
How can I correctly define function f(x) = x + 1 using constraints in the Z3 Java API?
In general, when you're defining a function, simply return the defining expression. (i.e., do not return a "free" variable with constraints on it; simply build the expression itself.)
So, you should write:
import com.microsoft.z3.*;
class Test {
public static void main(String[] args) {
Context ctx = new Context();
FuncDecl f = ctx.mkRecFuncDecl(ctx.mkSymbol("f"),
new Sort[]{ctx.mkIntSort()},
ctx.mkIntSort());
Expr x = ctx.mkFreshConst("x", ctx.mkIntSort());
ctx.AddRecDef(f, new Expr[]{x}, ctx.mkAdd(x, ctx.mkInt(1)));
Solver solver = ctx.mkSolver();
solver.add(ctx.mkNot(ctx.mkEq(ctx.mkInt(2), ctx.mkApp(f, ctx.mkInt(1)))));
System.out.println(solver.check());
}
}
When I run this, I get:
Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
UNSATISFIABLE
So, you do get UNSATISFIABLE
as you'd expect. I didn't inspect the source of unchecked-unsafe
operations here, which is probably a good idea to look at for additional safety.