Z3_solver_check returning Z3_L_UNDEF - z3

I have a simple benchmark in Z3's C API as follows:
Z3_config cfg = Z3_mk_config();
Z3_context ctx = Z3_mk_context(cfg);
Z3_del_config(cfg);
Z3_solver theSolver = mk_solver(ctx);
Z3_sort domainSort = Z3_mk_bv_sort(ctx, 32);
Z3_sort rangeSort = Z3_mk_bv_sort(ctx, 8);
Z3_sort arr_sort = Z3_mk_array_sort(ctx, domainSort, rangeSort);
Z3_symbol arr_name = Z3_mk_string_symbol(ctx, "fqv");
Z3_ast fqv_arr = Z3_mk_const(ctx, arr_name, arr_sort);
Z3_ast idx = Z3_mk_concat(
ctx,
Z3_mk_select(ctx, fqv_arr, Z3_mk_int(ctx, 1, domainSort)),
Z3_mk_select(ctx, fqv_arr, Z3_mk_int(ctx, 0, domainSort))
);
idx = Z3_mk_concat(ctx, Z3_mk_select(ctx, fqv_arr, Z3_mk_int(ctx, 2, domainSort)), idx);
idx = Z3_mk_concat(ctx, Z3_mk_select(ctx, fqv_arr, Z3_mk_int(ctx, 3, domainSort)), idx);
arr_name = Z3_mk_string_symbol(ctx, "a");
Z3_ast a_arr = Z3_mk_const(ctx, arr_name, arr_sort);
arr_name = Z3_mk_string_symbol(ctx, "b");
Z3_ast b_arr = Z3_mk_const(ctx, arr_name, arr_sort);
Z3_ast body = Z3_mk_eq(ctx, Z3_mk_select(ctx, a_arr, idx), Z3_mk_select(ctx, b_arr, idx));
Z3_app bound_vars[] = {(Z3_app) fqv_arr};
int num_bound_vars = 1;
int weight = 0;
Z3_ast forall = Z3_mk_forall_const(ctx, weight, num_bound_vars, bound_vars, 0, 0, body);
Z3_ast a0 = Z3_mk_select(ctx, a_arr, Z3_mk_int(ctx, 0, domainSort));
Z3_ast b0 = Z3_mk_select(ctx, b_arr, Z3_mk_int(ctx, 0, domainSort));
Z3_solver_assert(ctx, theSolver, forall);
Z3_solver_assert(ctx, theSolver, Z3_mk_eq(ctx, Z3_mk_false(ctx), Z3_mk_eq(ctx, a0, b0)));
Basically, there are two constraints:
∀fqv: a[fqv] = b[fqv]
a[0] != b[0]
The corresponding Z3_ast's are:
(forall ((fqv (Array (_ BitVec 32) (_ BitVec 8))))
(! (= (select a
(concat (select fqv #x00000003)
(concat (select fqv #x00000002)
(concat (select fqv #x00000001)
(select fqv #x00000000)))))
(select b
(concat (select fqv #x00000003)
(concat (select fqv #x00000002)
(concat (select fqv #x00000001)
(select fqv #x00000000))))))
:weight 0))
and
(= false (= (select a #x00000000) (select b #x00000000)))
The result that I am getting out of Z3_solver_check(ctx, theSolver) is Z3_L_UNDEF. However, when I comment out the second constraint (a[0] != b[0]), it returns Z3_L_TRUE as expected.
Can someone please guide me on why am I getting Z3_L_UNDEF in this case? The result I am expecting to get out of this two constraints is Z3_L_FALSE. Because if arrays a and b are equal for all indices, they can't be not equal at index 0.
Here is also the output of Z3_solver_get_reason_unknown:
reason for last failure: smt tactic failed to show goal to be sat/unsat (incomplete (theory array))

Related

An efficient way to nest store operations

In Most efficient way to represent memory buffers in Z3 the question on how make nested store operations more efficient is answered that one can replace the (nested) store operations with selects as in: (assert (= (select A i1) v1)). However, I need the store operation because previous constraints have to be replaced with the new constraints.
For example: the following constraints simulate the following assembly program:
mov qword ptr [rax], rbx
mov rcx, qword ptr [rax]
I like to proof that rbx and rcx are equal, I assert (= RBX!2 RCX!2) and expect that the model can be satisfied. This works perfectly. I assert (not (= RBX!2 RCX!2)) and expect that the model cannot be satisfied. When I feed the following constraints to Z3 (eg here) it gives an almost instant answer: UNSAT. However, if I proof the same problem in a C# program (see below) it cannot deduce UNSAT (in reasonable time).
Question: What can I try to make the C# program as quick as the SMT2.0 program?
(declare-fun RAX!0 () (_ BitVec 64))
(declare-fun RAX!1 () (_ BitVec 64))
(declare-fun RAX!2 () (_ BitVec 64))
(declare-fun RBX!0 () (_ BitVec 64))
(declare-fun RBX!1 () (_ BitVec 64))
(declare-fun RBX!2 () (_ BitVec 64))
(declare-fun RCX!0 () (_ BitVec 64))
(declare-fun RCX!1 () (_ BitVec 64))
(declare-fun RCX!2 () (_ BitVec 64))
(declare-fun MEM!0 () (Array (_ BitVec 64) (_ BitVec 8)))
(declare-fun MEM!1 () (Array (_ BitVec 64) (_ BitVec 8)))
(declare-fun MEM!2 () (Array (_ BitVec 64) (_ BitVec 8)))
(assert (= RAX!1 RAX!0))
(assert (= RBX!1 RBX!0))
(assert (= RCX!1 RCX!0))
(assert (let ((a!1 (store (store (store MEM!0 RAX!0 ((_ extract 7 0) RBX!0))
(bvadd #x0000000000000001 RAX!0)
((_ extract 15 8) RBX!0))
(bvadd #x0000000000000002 RAX!0)
((_ extract 23 16) RBX!0))))
(let ((a!2 (store (store (store a!1
(bvadd #x0000000000000003 RAX!0)
((_ extract 31 24) RBX!0))
(bvadd #x0000000000000004 RAX!0)
((_ extract 39 32) RBX!0))
(bvadd #x0000000000000005 RAX!0)
((_ extract 47 40) RBX!0))))
(= MEM!1
(store (store a!2
(bvadd #x0000000000000006 RAX!0)
((_ extract 55 48) RBX!0))
(bvadd #x0000000000000007 RAX!0)
((_ extract 63 56) RBX!0))))))
(assert (= RAX!2 RAX!1))
(assert (= RBX!2 RBX!1))
(assert (= RCX!2
(concat (select MEM!1 (bvadd #x0000000000000007 RAX!1))
(select MEM!1 (bvadd #x0000000000000006 RAX!1))
(select MEM!1 (bvadd #x0000000000000005 RAX!1))
(select MEM!1 (bvadd #x0000000000000004 RAX!1))
(select MEM!1 (bvadd #x0000000000000003 RAX!1))
(select MEM!1 (bvadd #x0000000000000002 RAX!1))
(select MEM!1 (bvadd #x0000000000000001 RAX!1))
(select MEM!1 RAX!1))))
(assert (= MEM!2 MEM!1))
(assert (not (= RBX!2 RCX!2)))
C# code:
Dictionary<string, string> settings = new Dictionary<string, string>
{
{ "unsat-core", "false" }, // enable generation of unsat cores
{ "model", "false" }, // enable model generation
{ "proof", "false" }, // enable proof generation
{ "timeout", "60000" } // 60000=1min
};
Context ctx = new Context(settings);
Solver solver = ctx.MkSolver(ctx.MkTactic("qfbv"));
BitVecExpr rax0 = ctx.MkBVConst("RAX!0", 64);
BitVecExpr rax1 = ctx.MkBVConst("RAX!1", 64);
BitVecExpr rax2 = ctx.MkBVConst("RAX!2", 64);
BitVecExpr rbx0 = ctx.MkBVConst("RBX!0", 64);
BitVecExpr rbx1 = ctx.MkBVConst("RBX!1", 64);
BitVecExpr rbx2 = ctx.MkBVConst("RBX!2", 64);
BitVecExpr rcx0 = ctx.MkBVConst("RCX!0", 64);
BitVecExpr rcx1 = ctx.MkBVConst("RCX!1", 64);
BitVecExpr rcx2 = ctx.MkBVConst("RCX!2", 64);
ArrayExpr mem0 = ctx.MkArrayConst("MEM!0", ctx.MkBitVecSort(64), ctx.MkBitVecSort(8));
ArrayExpr mem1 = ctx.MkArrayConst("MEM!1", ctx.MkBitVecSort(64), ctx.MkBitVecSort(8));
ArrayExpr mem2 = ctx.MkArrayConst("MEM!2", ctx.MkBitVecSort(64), ctx.MkBitVecSort(8));
solver.Assert(ctx.MkEq(rax1, rax0));
solver.Assert(ctx.MkEq(rbx1, rbx0));
solver.Assert(ctx.MkEq(rcx1, rcx0));
ArrayExpr memX0 = ctx.MkStore(mem0, ctx.MkBVAdd(ctx.MkBV(0, 64), rax0), ctx.MkExtract((1 * 8) - 1, 0 * 8, rbx0));
ArrayExpr memX1 = ctx.MkStore(memX0, ctx.MkBVAdd(ctx.MkBV(1, 64), rax0), ctx.MkExtract((2 * 8) - 1, 1 * 8, rbx0));
ArrayExpr memX2 = ctx.MkStore(memX1, ctx.MkBVAdd(ctx.MkBV(2, 64), rax0), ctx.MkExtract((3 * 8) - 1, 2 * 8, rbx0));
ArrayExpr memX3 = ctx.MkStore(memX2, ctx.MkBVAdd(ctx.MkBV(3, 64), rax0), ctx.MkExtract((4 * 8) - 1, 3 * 8, rbx0));
ArrayExpr memX4 = ctx.MkStore(memX3, ctx.MkBVAdd(ctx.MkBV(4, 64), rax0), ctx.MkExtract((5 * 8) - 1, 4 * 8, rbx0));
ArrayExpr memX5 = ctx.MkStore(memX4, ctx.MkBVAdd(ctx.MkBV(5, 64), rax0), ctx.MkExtract((6 * 8) - 1, 5 * 8, rbx0));
ArrayExpr memX6 = ctx.MkStore(memX5, ctx.MkBVAdd(ctx.MkBV(6, 64), rax0), ctx.MkExtract((7 * 8) - 1, 6 * 8, rbx0));
memX7 = ctx.MkStore(memX6, ctx.MkBVAdd(ctx.MkBV(7, 64), rax0), ctx.MkExtract((8 * 8) - 1, 7 * 8, rbx0));
solver.Assert(ctx.MkEq(mem1, memX7).Simplify() as BoolExpr);
solver.Assert(ctx.MkEq(rax2, rax1));
solver.Assert(ctx.MkEq(rbx2, rbx1));
BitVecExpr y0 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(0, 64), rax1)) as BitVecExpr;
BitVecExpr y1 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(1, 64), rax1)) as BitVecExpr;
BitVecExpr y2 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(2, 64), rax1)) as BitVecExpr;
BitVecExpr y3 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(3, 64), rax1)) as BitVecExpr;
BitVecExpr y4 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(4, 64), rax1)) as BitVecExpr;
BitVecExpr y5 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(5, 64), rax1)) as BitVecExpr;
BitVecExpr y6 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(6, 64), rax1)) as BitVecExpr;
BitVecExpr y7 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(7, 64), rax1)) as BitVecExpr;
BitVecExpr y = ctx.MkConcat(y7, ctx.MkConcat(y6, ctx.MkConcat(y5, ctx.MkConcat(y4, ctx.MkConcat(y3, ctx.MkConcat(y2, ctx.MkConcat(y1, y0)))))));
solver.Assert(ctx.MkEq(rcx2, y).Simplify() as BoolExpr);
solver.Assert(ctx.MkEq(mem2, mem1));
Status status_Neg = solver.Check(ctx.MkNot(ctx.MkEq(rbx2, rcx2)));
Console.WriteLine("Status Neg = "+status_Neg); // Go on holiday...
I don't have a way to run the C# program to play with it, unfortunately. But I noticed that you had calls to Simplify:
solver.Assert(ctx.MkEq(mem1, memX7).Simplify() as BoolExpr);
I'm curious why you needed that call? Perhaps that's the culprit?
The other thing to try would be to use uninterpreted functions for representing memory, instead of Arrays. UF's are typically much easier to deal with, and they provide roughly the same abstraction in my personal experience.
It might be a good idea to look at what the C# interface generated as SMT-Lib, to see if the translation is significantly different than what you thought it would be. I guess you could do that using the following function: https://github.com/Z3Prover/z3/blob/master/src/api/dotnet/AST.cs#L195

Z3: Java API for quantified formulas

I am trying to use the JAVA API of Z3 to construct the following formula
(assert (forall ((x_0 fcn_sort_2) (x_1 fcn_sort_2))
(=> (and (= (domain x_0)
(domain x_1))
(forall ((y Int))
(= (alpha x_0 y)
(alpha x_1 y))))))
(= x_0 x_1)))))
by the following code
Sort[] types1 = new Sort[2]; // for x_0 and x_1
Expr[] xs1 = new Expr[2];
for (int j = 0; j < 2; j++) {
types1[j] = this.getZ3Sort("fcn_sort_2");
xs1[j] = ctx.mkConst(ctx.mkSymbol("x_" + Integer.toString(j)), types1[j]);
}
Sort[] types2 = new Sort[1]; // for y
Expr[] xs2 = new Expr[1];
types2[0] = ctx.mkIntSort();
xs2[0] = ctx.mkConst(ctx.mkSymbol("y"), types2[0]);
FuncDecl alpha_fcn = this.getFuncSymbol("alpha");
Expr[] arg0 = new Expr[] { xs1[0], xs2[0] };
Expr[] arg1 = new Expr[] { xs1[1], xs2[0] };
BoolExpr
// (= (alpha x_0 y) (alpha x_1 y))
body2 = ctx.mkEq(ctx.mkApp(alpha_fcn, arg0), ctx.mkApp(alpha_fcn, arg1)),
// forall ((y Int)) ...
bf2 = ctx.mkForall(xs2, body2, 1, null, null, null, null);
FuncDecl domain_fcn = this.getFuncSymbol("domain");
BoolExpr
// (= x_0 x_1)
eqX = ctx.mkEq(xs1[0], xs1[1]),
// (= (domain x_0) (domain x_1))
eqDo = ctx.mkEq(ctx.mkApp(domain_fcn, new Expr[] {xs1[0]}), ctx.mkApp(domain_fcn, new Expr[] {xs1[1]})),
// (and ...)
andNode = ctx.mkAnd(eqDo, bf2),
// (=> ...)
body1 = ctx.mkImplies(andNode, eqX),
// (forall ((x_0 ...) (x_1 ...))
bf1 = ctx.mkForall(xs1, body1, 1, null, null, null, null);
where getFuncSymbol is my own function to get a FuncDecl which is declared before.
Unfortunately, I have the wrong result with "let" and "a!1"
(assert (forall ((x_0 fcn_sort_2) (x_1 fcn_sort_2))
(let ((a!1 (and (= (domain_fcn_sort_2 x_0) (domain_fcn_sort_2 x_1))
(forall ((y Int))
(= (alpha_fcn_sort_2 x_0 y) (alpha_fcn_sort_2 x_1 y))))))
(=> a!1 (= x_0 x_1)))))
I found that something wrong, "let ((a!1", happens at the line
body1 = ctx.mkImplies(andNode, eqX)
Am I missing something? Thank you
let-expressions are introduced during pretty-printing in an attempt to make the output more concise. Here, it simply means that whenever the name a!1 occurs in the output, you can replace it with (and ...). Semantically, this doesn't make a difference.

z3py: How to improve the time efficiency of the following code

This is a simplified code using the similar implementation idea as the z3py code for another problem I am trying to solve which is more complex and takes about 1 minute to run.
The intuition of the following code is to translate the array of integers in the inputArray into the array of months defined as EnumSort, which is essentially to infer the model of monthArray.
from z3 import *
s = Solver()
Month,(Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)=EnumSort('Month',['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])
monthArray = Array('monthArray',IntSort(), Month)
inputArray = Array('inputArray',IntSort(),IntSort())
tempArray = Array('tempArray',IntSort(),IntSort())
intArray = [1,3,6,7,8,3,5,6,3,12,11,5,2,5,7,3,7,3,2,7,12,4,5,1,10,9]
for idx,num in enumerate(intArray):
tempArray = Store(tempArray,idx,num)
s.add(inputArray==tempArray)
length = Int('length')
s.add(length == len(intArray))
i = Int('i')
s.add(ForAll(i,Implies(And(i>=0,i<length),And(
Implies(inputArray[i]==1,monthArray[i]==Jan),
Implies(inputArray[i]==2,monthArray[i]==Feb),
Implies(inputArray[i]==3,monthArray[i]==Mar),
Implies(inputArray[i]==4,monthArray[i]==Apr),
Implies(inputArray[i]==5,monthArray[i]==May),
Implies(inputArray[i]==6,monthArray[i]==Jun),
Implies(inputArray[i]==7,monthArray[i]==Jul),
Implies(inputArray[i]==8,monthArray[i]==Aug),
Implies(inputArray[i]==9,monthArray[i]==Sep),
Implies(inputArray[i]==10,monthArray[i]==Oct),
Implies(inputArray[i]==11,monthArray[i]==Nov),
Implies(inputArray[i]==12,monthArray[i]==Dec)
))))
print s.check()
print s.model()
Could anyone give me some suggestions about the ways to improve the time efficiency using this code as an example? Thanks.
Edit:
SMT language output by calling Solver.to_smt2()
(set-info :status unknown)
(declare-datatypes () ((Month (Jan ) (Feb ) (Mar ) (Apr ) (May ) (Jun ) (Jul ) (Aug ) (Sep ) (Oct ) (Nov ) (Dec ))))
(declare-fun inputArray () (Array Int Int))
(declare-fun length () Int)
(declare-fun monthArray () (Array Int Month))
(assert
(= (select inputArray 0) 1))
(assert
(= (select inputArray 1) 3))
(assert
(= (select inputArray 2) 6))
(assert
(= (select inputArray 3) 7))
(assert
(= (select inputArray 4) 8))
(assert
(= (select inputArray 5) 3))
(assert
(= (select inputArray 6) 5))
(assert
(= (select inputArray 7) 6))
(assert
(= (select inputArray 8) 3))
(assert
(= (select inputArray 9) 12))
(assert
(= (select inputArray 10) 11))
(assert
(= (select inputArray 11) 5))
(assert
(= (select inputArray 12) 2))
(assert
(= (select inputArray 13) 5))
(assert
(= (select inputArray 14) 7))
(assert
(= (select inputArray 15) 3))
(assert
(= (select inputArray 16) 7))
(assert
(= (select inputArray 17) 3))
(assert
(= (select inputArray 18) 2))
(assert
(= (select inputArray 19) 7))
(assert
(= (select inputArray 20) 12))
(assert
(= (select inputArray 21) 4))
(assert
(= (select inputArray 22) 5))
(assert
(= (select inputArray 23) 1))
(assert
(= (select inputArray 24) 10))
(assert
(= (select inputArray 25) 9))
(assert
(= length 26))
(assert
(forall ((i Int) )(let (($x172 (=> (= (select inputArray i) 12) (= (select monthArray i) Dec))))
(let (($x175 (=> (= (select inputArray i) 11) (= (select monthArray i) Nov))))
(let (($x178 (=> (= (select inputArray i) 10) (= (select monthArray i) Oct))))
(let (($x181 (=> (= (select inputArray i) 9) (= (select monthArray i) Sep))))
(let (($x184 (=> (= (select inputArray i) 8) (= (select monthArray i) Aug))))
(let (($x187 (=> (= (select inputArray i) 7) (= (select monthArray i) Jul))))
(let (($x190 (=> (= (select inputArray i) 6) (= (select monthArray i) Jun))))
(let (($x193 (=> (= (select inputArray i) 5) (= (select monthArray i) May))))
(let (($x196 (=> (= (select inputArray i) 4) (= (select monthArray i) Apr))))
(let (($x199 (=> (= (select inputArray i) 3) (= (select monthArray i) Mar))))
(let (($x202 (=> (= (select inputArray i) 2) (= (select monthArray i) Feb))))
(let (($x205 (=> (= (select inputArray i) 1) (= (select monthArray i) Jan))))
(=> (and (>= i 0) (< i length)) (and $x205 $x202 $x199 $x196 $x193 $x190 $x187 $x184 $x181 $x178 $x175 $x172)))))))))))))))
)
(check-sat)
I find using 'qflia' (quantifier-free linear integer arithmetic) solver, instead of the general solver 'Solver()', improve the efficiency by about 3x in my case.

Get UNSAT Core using Z3 from .smt2 file

I need to get unsat core from z3. The contents of .smt2 file are:
(set-option :produce-unsat-cores true)
(set-logic QF_AUFBV )
(declare-fun a () (Array (_ BitVec 32) (_ BitVec 8) ) )
; Constraints
(! (assert (bvslt (concat (select a (_ bv3 32) ) (concat (select a (_ bv2 32) ) (concat (select a (_ bv1 32) ) (select a (_ bv0 32) ) ) ) ) (_ bv10 32) ) )
:named ?U0)
(! (assert (bvslt (_ bv10 32) (concat (select a (_ bv3 32) ) (concat (select a (_ bv2 32) ) (concat (select a (_ bv1 32) ) (select a (_ bv0 32) ) ) ) ) ) )
:named ?U1)
(check-sat)
(get-unsat-core)
(exit)
I am getting the following output when running z3:unsupported
; !
unsupported
; !
sat
(error "line 11 column 15: unsat core is not available")
I am new to z3, can't understand what is happening here (I am sure that the expression is unsat).
Thanks.
You use ! incorrectly. The exclamation point is used for naming formulae (not asserts). See section 3.9.8 from the Tutorial.
This should fix it: (assert (! (bvslt ...) :named ?U0)).

Z3 C api : multidimensional array type variable cause invalid result

here is the Z3 context:
(forall ((X (Array Int (Array Int Real))) (i Int) (j Int))
(let ((a!1 (* (- 1) (to_int (select (select X i) j)))))
(= (+ (testArr X i j) a!1) 0))))
this means:
forall X,i,j. testArr(X,i,j) == X[i][j]
now, i try to prove two similar assert:
1 (=> (= (select (select Z i1) j1) (select (select X i) j))
(= (select (select Z i1) j1) (testArr X i j)))
and
2 (=> (= v (select (select X i) j))
(= v (to_real (testArr X i j))))
the second assert Z3 return valid, but the 1st assert Z3 return invalid,and in other example Z3 sometimes return unknown.
why??

Resources