I have the following query (written using the SMT-LIB v1.0 standard):
(benchmark gametime
:status unknown
:logic QF_AUFBV
:extrafuns ((x BitVec[32]))
:extrafuns ((a Array[32:32]))
:extrapreds ((constraint1 ))
:extrapreds ((constraint0 ))
:formula
(flet ($x37 (and (iff constraint0 (= (select a bv0[32]) bv0[32])) (iff constraint1 (= x bv1[32]))))
(and $x37 (and constraint0 constraint1)))
)
(The query is a bit redundant, but it's automatically generated.)
Running this through Z3, and asking for a model, I receive the following:
a -> as-array[k!0]
constraint1 -> true
x -> bv1[32]
constraint0 -> true
k!0 -> {
bv0[32] -> bv0[32]
else -> bv0[32]
}
This is great, because I have values for "a" and "x", as needed. However, another query is similar, except for one small change:
(benchmark gametime
:status unknown
:logic QF_AUFBV
:extrafuns ((x BitVec[32]))
:extrafuns ((a Array[32:32]))
:extrapreds ((constraint1 ))
:extrapreds ((constraint0 ))
:formula
(flet ($x37 (and (iff constraint0 (**bvuge** (select a bv0[32]) bv0[32])) (iff constraint1 (= x bv1[32]))))
(and $x37 (and constraint0 constraint1)))
)
The change is highlighted: what was an equality is now a "bvuge" check. I receive the following model from Z3:
constraint1 -> true
x -> bv1[32]
constraint0 -> true
I do not have an assignment for "a" anymore. Was this intentional? Are there "default" values for variables that I should assume, if they are not present in the model? (For example, here the default value would be that the array "a" is zero everywhere.)
For what it's worth, this problem only shows up if the operation is "bvuge". Others ("bvsge", "bvugt", "bvsgt", "bvult", "bvslt", "bvule", "bvsle") seem to work.
I do not have an assignment for "a" anymore. Was this intentional?
Yes this is intentional. Any value of the array will satisfy the formula.
This is because the constraint0:
(bvuge (select a bv0[32]) bv0[32]))
is equivalent to true. Any bit-vector value is greater or equal to 0 under unsigned comparison.
So the value of 'a' is a don't care.
Related
So I'm trying to check whether all values in an array is unique with the following Z3 code.
(declare-const A (Array Int Int))
(declare-const n Int)
(assert (forall ((i Int) (j Int)) (and (and (and (>= i 0) (< i n)) (and (>= j 0) (< j n)))
(implies (= (select A i) (select A j)) (= i j)))))
(check-sat)
I'm quite new to Z3 so I don't quite understand the grammar and stuff, but can anyone tell me whether this code is right, and if not, where's the problem?
The problem as you wrote is unsat, because it says whenever 0 <= i < n and 0 <= j < n, if A[i] = A[j], then i = j. There is no array and a particular n you can pick to satisfy this constraint.
What you really want to write is the following instead:
(declare-const A (Array Int Int))
(declare-const n Int)
(assert (forall ((i Int) (j Int)) (implies (and (>= i 0) (< i n)
(>= j 0) (< j n)
(= (select A i) (select A j)))
(= i j))))
(check-sat)
(get-model)
The above says If it's the case that i and j are within bounds, and array elements are the same, then i must equal j. And this variant would be satisifiable for any n; and indeed here's what z3 reports:
sat
(
(define-fun n () Int
0)
(define-fun A () (Array Int Int)
((as const (Array Int Int)) 0))
)
But note that z3 simply picked n = 0, which made it easy to satisfy the formula. Let's make sure we get a more interesting model, by adding:
(assert (> n 2))
Now we get:
sat
(
(define-fun n () Int
3)
(define-fun A () (Array Int Int)
(lambda ((x!1 Int))
(let ((a!1 (ite (and (<= 1 x!1) (not (<= 2 x!1))) 7 8)))
(ite (<= 1 x!1) (ite (and (<= 1 x!1) (<= 2 x!1)) 6 a!1) 5))))
)
and we see that z3 picked the array to have 3 elements with distinct values at positions we care about.
Note that this sort of reasoning with quantifiers is a soft-spot for SMT solvers; while z3 is able to find models for these cases, if you keep adding quantified axioms you'll likely get unknown as the answer, or z3 (or any other SMT solver for that matter) will take longer and longer time to respond.
I am trying to figure out how to get the unsat core using the Java API for Z3. Our scenario is as follows (code is underneath, which works in rise4fun):
We create the SMT2 input programtically
The input contains function definitions, datatype declarations, and assertions
We parse this using the parseSMTLIB2String API
We ensure that the context and the solver have unsat_core -> true
Z3 returns UNSAT for the provided input, which is correct
The UNSAT core is always empty though.
The same input produces an UNSAT core correctly on rise4fun (x1 x3)
I am guessing I am misusing the API somehow... but not quite sure how/why.
I have noticed that I cannot set the unsat core option in the SMT string that I pass to parseSMTLIB2String, because that is not allowed. I am guessing that is expected.
Can someone point me in the right direction please?
Thanks!!
(set-option :smt.macro-finder true)
;; The following is only for rise4fun, i cannot get it
;; to work with the parse SMT Java API
(set-option :produce-unsat-cores true)
(define-sort Ref () Int)
(declare-datatypes (T1 T2) ((Tuple2 (mk-Tuple2 (_1 T1)(_2 T2)))))
(declare-datatypes (T1 T2 T3) ((Tuple3 (mk-Tuple3 (_1 T1)(_2 T2)(_3 T3)))))
(define-sort Set (T) (Array T Bool))
(define-sort Bag (T) (Array T Int))
(declare-const emptySetOf_Int (Set Int))
(assert (!(forall ((x Int)) (= (select emptySetOf_Int x) false)) :named AXIOM1))
(declare-sort TopLevelDeclarations) (declare-const mk-TopLevelDeclarations TopLevelDeclarations)
(declare-datatypes () ((A (mk-A (x Int)(y Int)))))
(declare-datatypes () ((Any
(lift-TopLevelDeclarations (sel-TopLevelDeclarations TopLevelDeclarations))
(lift-A (sel-A A))
null))
)
(declare-const heap (Array Ref Any))
(define-fun deref ((ref Ref)) Any
(select heap ref)
)
(define-fun deref-is-TopLevelDeclarations ((this Ref)) Bool
(is-lift-TopLevelDeclarations (deref this))
)
(define-fun deref-TopLevelDeclarations ((this Ref)) TopLevelDeclarations
(sel-TopLevelDeclarations (deref this))
)
(define-fun deref-is-A ((this Ref)) Bool
(is-lift-A (deref this))
)
(define-fun deref-A ((this Ref)) A
(sel-A (deref this))
)
(define-fun deref-isa-TopLevelDeclarations ((this Ref)) Bool
(deref-is-TopLevelDeclarations this)
)
(define-fun deref-isa-A ((this Ref)) Bool
(deref-is-A this)
)
(define-fun A!x ((this Ref)) Int
(x (deref-A this))
)
(define-fun A!y ((this Ref)) Int
(y (deref-A this))
)
(define-fun TopLevelDeclarations.inv ((this Ref)) Bool
true
)
(assert (! (forall ((this Ref))
(=> (deref-is-TopLevelDeclarations this) (TopLevelDeclarations.inv this))
) :named x0))
(define-fun A.inv ((this Ref)) Bool
(and
(> (A!x this) 0)
(> (A!y this) 0)
(< (A!x this) 0)
)
)
(assert (! (forall ((this Ref))
(=> (deref-is-A this) (A.inv this))
) :named x1))
(assert (!(deref-is-TopLevelDeclarations 0) :named TOP))
(assert (!(exists ((instanceOfA Ref)) (deref-is-A instanceOfA)) :named x3))
(check-sat)
(get-unsat-core)
You're not using the Java API, except for the call to parseSMTLIB2String. This function does not execute any SMT commands and there is no function that would do that for you. parseSMTLIB2String exists exclusively to parse assertions, it will ignore everything else. For this particular problem, I recommend to simply pass the problem file to z3.exe either as a command line argument or via stdin (use -in option). This produces
unsat
(x1 x3)
If the intent is to use the Java API for other things at a later point, see the Java API unsat core example.
I just had the same problem and found that it depends on how you pass the parsed input to the solver.
While the following approach produces an empty unsat-core...:
BoolExpr[] program = context.parseSMTLIB2File(input_file, null, null, null, null);
solver.add(program);
solver.check();
solver.getUnsatCore();
... the unsat-core is produced correctly if you give the parsed input file to the solver as follows:
BoolExpr[] program = context.parseSMTLIB2File(input_file, null, null, null, null);
solver.check(program);
solver.getUnsatCore();
I therefore assume that everything that is passed via solver.add() belongs to the assumptions and therefore presumably does not belong to the unsat-core according to Z3.
I have an enumeration type BoolT that contains Bool and Bot
(declare-datatypes () ((BoolT Bool Bot)))
and I want to define an equality function eq that given two BoolT returns Bot if one of the arguments is Bot, otherwise the equality between the two Bool arguments. However, I am not able to define the actual comparison between the boolean values. Until now I get the function
(define-fun eq ((x1 BoolT) (x2 BoolT)) BoolT
(ite (or (= x1 Bot) (= x2 Bot)) Bot Bool))
while I need something like
(define-fun eq ((x1 BoolT) (x2 BoolT)) BoolT
(ite (or (= x1 Bot) (= x2 Bot)) Bot
(or (and (= x1 true)(= x2 true)) (and (= x1 false)(= x2 false)))
)
or at least a correct definition of the following predicate
(define-fun is-True ((x1 BoolT)) Bool
(ite (= x1 true) true false)
)
Is there a way to model the eq function or the previous predicate on BoolT?
You will need tagged unions in Z3, similar to ML data-types. You can't just take the union of an existing type and included it in a datatype declaration.
So you will need to write something like:
(declare-datatypes () ((BoolT True False Bot)))
or
(declare-datatypes () ((BoolT (mkB (tf B)) Bot) (B True False)))
Then you can write:
(define-fun is-True1 ((x BoolT)) Bool
(= (mkB True) x))
or
(define-fun is-True2 ((x BoolT)) Bool
(and (is-mkB x) (= True (tf x))))
and assert
(declare-const a BoolT)
(assert (is-True2 a))
Declaring (B True False)
automatically declares predicates is-True and is-False
(declare-const b B)
(assert (is-True b))
I want to transform the bitvector theory into int theory in Z3, and when encounter the "bvnot" operation, I relpace it with "not", here is a simple example:
(assert (= (bvnot (ite (bvsle t0 #x0a) #b1 #b0)) #b1))
and after transformation :
(assert (= (not (ite (< t0 10) 1 0)) 1))
However, Z3 reported error with this assertion:
invalid function application for not, sort mismatch on argument at position 1, expected Bool but given Int
How can I convert int sort to boolean sort?
Tanhks!
Jin
You already have everything in place, but the constants 1 and 0 are not Boolean values; the corresponding values are true and false, i.e., this should work:
(assert (= (not (ite (< t0 10) true false)) true))
If I want to check if a set has elements of another set is also possible?
For example (contains Set1 Set2):
contains [1,2] [3,5] -> is false
contains [1] [2,3, 1] -> is true
The sets are finite. And the maximum value of the sets is five and the minimum is 0, the sets may not have values greater than 5 neither smaller than 0.
For example:
[1,5,3] -> valid set
[1,8,2] -> invalid set
If it were only for a set and check whether a value exist in the set was easy. It was in the following way:
( declare-sort Set 0 )
( declare-fun contains (Set Int) bool )
( declare-const set Set )
( declare-const A Int )
( assert ( contains set A ))
( assert ( not (contains set 0 )))
( check-sat )
But for two sets I do not see how it's done.
Thank you for your attention.
The operation (contains S1 S2) that you describe in your message is the subset relation. If we encode sets of integers as functions from Int to Boolean (like in: max value in set z3), then S1 and S2 are declared as:
(declare-fun S1 (Int) Bool)
(declare-fun S2 (Int) Bool)
Then, we can say that S1 is a subset of S2 by asserting
(assert (forall ((x Int)) (=> (S1 x) (S2 x))))
We just saying that any element in S1 is also an element of S2.
EDIT
We can use the expression (exists ((x Int)) (and (S1 x) (S2 x))) to check whether the sets S1 and S2 have an element in common or not
END EDIT
The minimal element of a set can be encoded as we did in max value in set z3.
For example, suppose the minimal element of S1 is min_S1.
; Now, let min_S1 be the min value in S1
(declare-const min_S1 Int)
; Then, we now that min_S1 is an element of S1, that is
(assert (S1 min_S1))
; All elements in S1 are bigger than or equal to min_S1
(assert (forall ((x Int)) (=> (S1 x) (not (<= x (- min_S1 1))))))
If the minimal values of the sets you are encoding are known at "encoding time" (and are small). We can use yet another encoding based on Bit-vectors.
In this encoding, a set is a Bit-vector. If the sets only contain values between 0 and 5, then we can use a Bit-vector of size 6. The idea is: if bit i is true iff i is an element of the set.
Here is an example with the main operation:
(declare-const S1 (_ BitVec 6))
(declare-const S2 (_ BitVec 6))
(declare-const S3 (_ BitVec 6))
; set equality is just bit-vector equality
(assert (= S1 S2))
; set intersection, union, and complement are encoded using bit-wise operations
; S3 is S1 union S2
(assert (= S3 (bvor S1 S2)))
; S3 is S1 intersection of S2
(assert (= S3 (bvand S1 S2)))
; S3 is the complement of S1
(assert (= S3 (bvnot S1)))
; S1 is a subset of S2 if S1 = (S1 intersection S2), that is
(assert (= S1 (bvand S1 S2)))
; S1 is the empty set if it is the 0 bit-vector
(assert (= S1 #b000000))
; To build a set that contains only i we can use the left shift
; Here, we assume that i is also a bit-vector
(declare-const i (_ BitVec 6))
; S1 is the set that contains only i
; We are also assuming that i is a value in [0, 5]
(assert (= S1 (bvshl #b000001 i)))