Is it possible to treat int constants as uninterpreted in z3? For example, treat tuple(project(t, 0), project(t, 1)) = t as tuple(project(t, left), project(t, right)) = t. Context: my equations are essentially in QF_UF, but because they contain int constants I'm forced to use a logic with integer arithmetic which leads to nontermination sometimes.
You can declare Int to be an uninterpreted sort, so long as you set the logic to be something that doesn't define it already:
(set-logic QF_UF)
(declare-sort Int 0)
(declare-fun f ((Int)) Int)
(declare-fun i () Int)
(assert (distinct (f i) (f i)))
(check-sat)
z3 says:
unsat
If you add:
(assert (= (f 2) 2))
then you get:
(error "line 8 column 15: Sort mismatch at argument #1 for function (declare-fun f (Int) Int) supplied sort is Int")
which avoids confusions. (Though the error message is rather confusing to read!)
If you set your logic to be:
(set-logic QF_LIA)
then z3 says:
(error "line 3 column 18: sort already defined Int")
so, that works out as well. See Section 4.2.3 of the SMTLib specification for details.
Hope that helps!
Related
In z3, one can declare a fully-uninterpreted const like so:
(declare-const x Int)
Similarly, one can define a fully-interpreted one like this:
(define-fun y () Int 3)
; y == 3
Given an algebraic datatype, one can have a fully interpreted tuple like the following:
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(define-fun z () Item (mk-item 3 4))
; z == Item(size=3, weight=4)
... Or a non-interpreted one like below:
(declare-const i1 (Item Int Int))
Now is it possible to have a partially-interpreted data type, so that, based on the previous example, weight would be fixed for each item and size could vary?
; (bad syntax, but I hope you get the idea)
; in this case the size is varying, but weight is fixed to 5
(declare-const i2 (Item Int 5))
You should simply declare it with declare-fun and assert an equality for the portions that you know:
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(declare-fun x () Item)
(assert (= (weight x) 5))
(check-sat)
(get-model)
This produces:
sat
(model
(define-fun x () Item
(mk-item 0 5))
)
I know that both bv2int and int2bv are handled as uninterpreted functions in Z3. Still, I am looking for a best practice in solving the following problem: given a "small" (< 10 bits) bitvector index,
how to efficiently cast it to Int, and use in queries like this one:
(declare-const s String)
(declare-const someInt Int)
(declare-const someBitVec10 (_ BitVec 10))
(assert (= s "74g\x00!!#2#$$"))
;(assert (str.in.re (str.at s someBitVec10) (re.range "a" "z")))
( assert (str.in.re (str.at s someInt ) (re.range "1" "3")))
(check-sat)
(get-value (s someInt))
Output:
sat
((s "74g\x00!!#2#$$")
(someInt 7))
Thanks!
I am using z3 with the C++ API for the example:
context c;
sort I = c.int_sort();
sort B = c.bool_sort();
expr x = c.int_const("x");
expr x1 = c.int_const("x1");
func_decl p1 = function("p1", I, B);
func_decl p2 = function("p2", I, B);
solver s(c);
s.add(forall(x, (implies(p1(x), ((p2(x)))))));
s.add(p1(x1));
The generated model is:
sat
(define-fun x1 () Int
0)
(define-fun p1 ((x!1 Int)) Bool
true)
(define-fun p2 ((x!1 Int)) Bool
true)
The imagined to have the model p1(x1) and p2(x1). I tried also with the options:
p.set("mbqi", true);
p.set("smt.mbqi.max_iterations", "10000000");
p.set("auto-config", true);
But, I have the same result. Am I missing something?
Thank you.
Z3 produces a correct model, so I'm not exactly sure what the problem is. I can only imagine that there is some confusion about the argument names of the functions.
Per declaration, p1 is a function that takes an int and returns a Boolean. When Z3 builds an interpretation for this function, it names the first argument x!1 which has nothing to do with the constant function x1 (no bang). The model returned states
(define-fun x1 () Int
0)
(define-fun p1 ((x!1 Int)) Bool
true)
which means x1 is a constant function that always returns zero, i.e., x1() := 0. Additionally, p1 is a function with one argument (called x!1) and which returns true regardless of the input, i.e., for all x!1, p1(x!1) := true.
I'm trying to influence the randomness of results for model values generated by Z3. As far as I understand, the options for this are very limited: in case of linear arithmetic, the simplex solver does not allow for random results that still satisfy the given constraints. However, there is an option smt.arith.random_initial_value ("use random initial values in the simplex-based procedure for linear arithmetic (default: false)") which I don't seem to get working:
from z3 import *
set_option('smt.arith.random_initial_value',True)
x = Int('x')
y = Int('y')
s = Solver()
s.add( x+y > 0)
s.check()
s.model()
This seems to always produce [y = 0, x = 1] as a result. Even model completion for variables unused in the given constraints seems to produce deterministic results all the time.
Any ideas or hints about how this option works?
Thanks for catching that! There was indeed a bug that caused the random seed not to be passed through to the arithmetic theory. This is now fixed in the unstable branch (fix here).
This example:
(set-option :smt.arith.random_initial_value true)
(declare-const x Int)
(declare-const y Int)
(assert (> (+ x y) 0))
(check-sat-using (using-params qflra :random_seed 1))
(get-model)
(check-sat-using (using-params qflra :random_seed 2))
(get-model)
(check-sat-using (using-params qflra :random_seed 3))
(get-model)
Now produces three different models:
sat
model
(define-fun y () Int
4294966763)
(define-fun x () Int
4294966337)
)
sat
(model
(define-fun y () Int
216)
(define-fun x () Int
4294966341)
)
sat
(model
(define-fun y () Int
196)
(define-fun x () Int
4294966344)
)
It looks like there may be another place where this option isn't passed through correctly (e.g., when using set-logic instead of calling the qflra tactic directly), we're still looking into that.
I'm having some trouble using sorts in the SMTlib2 format. For example, I define an Interval as:
(declare-sort Pair 2)
(define-sort Interval () (Pair Int Int))
Now how can I return a new Interval from a function? e.g.:
(define-fun getInterval ((a Int) (b Int)) Interval
(Interval a b))
This doesn't work.
My question is: how can I construct and instantiate objects of a given sort, and how can I access their fields?
Right now I'm using 2 UFs that I created as field getters, but I still don't know how to have a constructor:
(declare-fun L (Interval) Int)
(declare-fun H (Interval) Int)
Thanks,
Nuno
You should look into Record subsection, Datatypes section in Z3 SMT guide. Basically, you can create a record type with a constructor mk-pair and two selectors first and second for accessing its fields.
Here is an examplerise4fun link:
(set-option :macro-finder true)
(declare-datatypes (T1 T2) ((Pair (mk-pair (first T1) (second T2)))))
(define-sort Interval () (Pair Int Int))
(define-fun getInterval ((a Int) (b Int)) Interval
(mk-pair a b))
(declare-const p1 Interval)
(declare-const p2 Interval)
;construct objects of a give sort
(assert (= p1 (getInterval 2 2)))
;accessing their fields
(assert (= (first p1) (second p2)))
(check-sat)
(get-model)