Defining Rules for Bit Vectors in SMT2 - z3

I have switched from using Int to Bit Vectors in SMT. However, the logic QF_BV does not allow the use of any quantifiers in your script, and I need to define FOL rules.
I know how to eliminate existential quantifiers, but universal quantifiers? How to do that?
Imagine a code like that:
(set-logic QF_AUFBV)
(define-sort Index () (_ BitVec 3))
(declare-fun P (Index) Bool)
(assert (forall ((i Index)) (= (P (bvadd i #b001)) (not (P i)) ) ) )

Strictly speaking, you're out-of-luck. According to http://smtlib.cs.uiowa.edu/logics.shtml, there's no logic that contains quantifiers and bit-vectors at the same time.
Having said that, most solvers will allow non-standard combinations. Simply leave out the set-logic command, and you might get lucky. For instance, Z3 takes your query just fine without the set-logic part; I just tried..

Related

Confused about a simple SAT matching problem using Z3

I am trying to solve a simple matching problem using Z3 which it claims is unsat. I have set this up the following way:
p_{x}_{y} to match up offer x with request y.
sum_{x} {p_x_y} <= 1 meaning y can only be matched once (using PbLe)
sum_{y} {p_x_y} <= 1 meaning x can only be matched once (using PbLe)
whether p_x_y is a valid match comes from an external computation that returns a Bool, so for this I have p_x_y => computation_result (i.e. if paired, then computation_result).
finally, I want to maximize the number of matchings. So I have:
maximize sum_{x} ( sum_{y} p_x_y ) (I do this with p_x_y.ite(Int(1), Int(0))).
I was able to whip this up quite quickly using z3-rs in Rust (not sure if that makes a difference). And this is the solver state before I run check on it:
Solver: (declare-fun p_0_0 () Bool)
(declare-fun p_1_0 () Bool)
(declare-fun k!0 () Int)
(declare-fun k!1 () Int)
(assert (=> p_0_0 true))
(assert (=> p_1_0 true))
(assert ((_ at-most 1) p_0_0))
(assert ((_ at-most 1) p_1_0))
(assert ((_ at-most 1) p_0_0 p_1_0))
(maximize (+ (ite p_1_0 k!1 k!0) (ite p_0_0 k!1 k!0)))
(check-sat)
Z3 claims this is Unsat and I am quite stumped. I don't see why p_0_0 = T, p_1_0 = F doesn't satisfy this formula.
Thank you very much for the help.
I can't replicate this. When I run your program, z3 prints: (after adding (get-model) at the end)
sat
(
(define-fun p_0_0 () Bool
true)
(define-fun p_1_0 () Bool
false)
(define-fun k!1 () Int
0)
(define-fun k!0 () Int
(- 1))
)
which matches your expectations.
Couple of things to make sure:
Is your z3 version "new" enough? 4.11.3 is the latest master I think
You mentioned you use it from Rust. Perhaps you didn't use the rust-API correctly? Or, maybe Rust interface has a bug.
I'd start by running it manually on your machine using the SMTLib script you've given. If you get SAT (which you should!), perhaps ask at the Rust forum as the bug is likely either in your Rust program or the Rust bindings itself. If you get UNSAT, try upgrading your z3 installation and possibly recompile the Rust bindings if that's relevant. (I'm not familiar with the Rust bindings to say if it needs a recompile or not if you upgrade your z3. It could be either way.)
A guess
Without seeing the details, it's hard to opine further. However, notice that you've posed this as an optimization problem; and asked z3 to maximize the addition of two uninterpreted integers. So, it's possible the Rust bindings are adding a call of the form:
(get-objectives)
at the end, to which z3 will respond:
sat
(objectives
((+ (ite p_1_0 k!1 k!0) (ite p_0_0 k!1 k!0)) oo)
)
That is, the objective you're maximizing is unbounded. This means there's no value for k!0 and k!1 the solver can present to you: The goal gets arbitrarily large as these get larger. It's possible the Rust interface is internally treating this as "unsat" since it cannot find the values for these constants. But that's just my guess without knowing the specifics of how the Rust bindings work.

Get fractional part of real in QF_UFNRA

Using smtlib I would like to make something like modulo using QF_UFNRA. This disables me from using mod, to_int, to_real an such things.
In the end I want to get the fractional part of z in the following code:
(set-logic QF_UFNRA)
(declare-fun z () Real)
(declare-fun z1 () Real)
(define-fun zval_1 ((x Real)) Real
x
)
(declare-fun zval (Real) Real)
(assert (= z 1.5));
(assert (=> (and (<= 0.0 z) (< z 1.0)) (= (zval z) (zval_1 z))))
(assert (=> (>= z 1.0) (= (zval z) (zval (- z 1.0)))))
(assert (= z1 (zval z)))
Of course, as I am asking this question here, implies, that it didn't work out.
Has anybody got an idea how to get the fractional part of z into z1 using logic QF_UFNRA?
This is a great question. Unfortunately, what you want to do is not possible in general if you restrict yourself to QF_UFNRA.
If you could encode such functionality, then you can decide arbitrary Diophantine equations. You would simply cast a given Diophantine equation over reals, compute the "fraction" of the real solution with this alleged method, and assert that the fraction is 0. Since reals are decidable, this would give you a decision procedure for Diophantine equations, accomplishing the impossible. (This is known as Hilbert's 10th problem.)
So, as innocent as the task looks, it is actually not doable. But that doesn't mean you cannot encode this with some extensions, and possibly have the solver successfully decide instances of it.
If you allow quantifiers and recursive functions
If you allow yourself quantifiers and recursive-functions, then you can write:
(set-logic UFNRA)
(define-fun-rec frac ((x Real)) Real (ite (< x 1) x (frac (- x 1))))
(declare-fun res () Real)
(assert (= (frac 1.5) res))
(check-sat)
(get-value (res))
To which z3 responds:
sat
((res (/ 1.0 2.0)))
Note that we used the UFNRA logic allowing quantification, which is required here implicitly due to the use of the define-fun-rec construct. (See the SMTLib manual for details.) This is essentially what you tried to encode in your question, but instead using the recursive-function-definition facilities instead of implicit encoding. There are several caveats in using recursive functions in SMTLib however: In particular, you can write functions that render your system inconsistent rather easily. See Section 4.2.3 of http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.5-draft.pdf for details.
If you can use QF_UFNIRA
If you move to QF_UFNIRA, i.e., allow mixing reals and integers, the encoding is easy:
(set-logic QF_UFNIRA)
(declare-fun z () Real)
(declare-fun zF () Real)
(declare-fun zI () Int)
(assert (= z (+ zF zI)))
(assert (<= 0 zF))
(assert (< zF 1))
(assert (= z 1.5))
(check-sat)
(get-value (zF zI))
z3 responds:
sat
((zF (/ 1.0 2.0))
(zI 1))
(You might have to be careful about the computation of zI when z < 0, but the idea is the same.)
Note that just because the encoding is easy doesn't mean z3 will always be able to answer the query successfully. Due to mixing of Real's and Integer's, the problem remains undecidable as discussed before. If you have other constraints on z, z3 might very well respond unknown to this encoding. In this particular case, it happens to be simple enough so z3 is able to find a model.
If you have sin and pi:
This is more of a thought experiment than a real alternative. If SMTLib allowed for sin and pi, then you can check whether sin (zI * pi) is 0, for a suitably constrained zI. Any satisfying model to this query would ensure that zI is integer. You can then use this value to extract the fractional part by subtracting zI from z.
But this is futile as SMTLib neither allows for sin nor pi. And for good reason: Decidability would be lost. Having said that, maybe some brave soul can design a logic that supported sin, pi, etc., and successfully answered your query correctly, while returning unknown when the problem becomes too hard for the solver. This is already the case for nonlinear arithmetic and the QF_UFNIRA fragment: The solver may give up in general, but the heuristics it employs might solve problems of practical interest.
Restriction to Rationals
As a theoretical aside, it turns out that if you restrict yourself to rationals only (instead of actual reals) then you can indeed write a first-order formula to recognize integers. The encoding is not for the faint of heart, however: http://math.mit.edu/~poonen/papers/ae.pdf. Furthermore, since the encoding involves quantifiers, it's probably quite unlikely that SMT solvers will do well with a formulation based on this idea.
[Incidentally, I should extend thanks to my work colleagues; this question made for a great lunch-time conversation!]

Tactic to use soft constraints/assumptions only after a time-out?

Assume that I have a Z3 preamble that includes several function declarations and definitional axioms (with explicit patterns), e.g., my own sequence axioms:
(declare-sort $Seq)
(declare-fun $Seq.nil () $Seq)
(declare-fun $Seq.len ($Seq) Int)
(declare-fun $Seq.con (Int $Seq) $Seq)
(declare-fun $Seq.at ($Seq Int) Int)
(declare-fun $Seq.in ($Seq Int) Bool)
...
(assert (forall ((xs $Seq)) (! ... )
(assert (forall ((xs $Seq) (x Int)) (! ... )
...
After this preamble has been emitted a lot of assertions are pushed to Z3, interspersed with calls to check-set to see whether certain negated formulas can be shown unsat (FYI: my context is software verification using symbolic execution).
Most of these assertions are simple and don't refuting them doesn't require the sequence axioms. However, from a few simple tests I get the impression that their presence nevertheless slows Z3 down.
I thus guarded the definitional axioms by an implication with a dummy boolean constant as the left-hand side of the implication (as suggested by this answer), e.g.,
(declare-const $useSeq Bool)
(assert (=> ($useSeq (forall ((xs $Seq)) (! ... )
and changed every check-sat that needs to reason about sequences into one that assumes $useSeq, i.e.,
(check-sat $useSeq)
Question: Is there a tactic/way to make Z3 use certain assertions only after a time-out? E.g.,
(check-sat-using (or-else (try-for smt 500) (smt $useSeq)))
I could of course manually emit a time-bounded check-sat first, followed by a check-sat useSeq $useSeq if needed, but it would be nice if it could be done with some kind of tactics.
Unfortunately, this cannot be done with the current set of tactics available in Z3.

mapping user-defined functions in z3

I'm curious what the limitations on z3's map operator are. According to the z3 tutorial (http://rise4fun.com/z3/tutorial), "Z3 provides a parametrized map function on arrays. It allows applying arbitrary functions to the range of arrays."
Map appears to work when I'm mapping built-in functions or functions declared with (declare-fun ...) syntax. When I attempt to use map with function (really macros) defined with (define-fun ...) syntax, I receive the error invalid function declaration reference, named expressions (aka macros) cannot be referenced.
Is there a standard way to map user-defined functions over arrays?
Here is some code that illustrates my confusion:
;simple function, equivalent to or
(define-fun my-or ((x Bool) (y Bool)) Bool (or x y))
(assert (forall ((x Bool) (y Bool)) (= (my-or x y) (or x y))))
(check-sat)
;mapping or with map works just fine
(define-sort Set () (Array Int Bool))
(declare-const a Set)
(assert ( = a ((_ map or) a a) ))
(check-sat)
;but this fails with error
(assert ( = a ((_ map my-or) a a) ))
I'm currently hacking around the problem like this:
(define-fun my-or-impl ((x Bool) (y Bool)) Bool (or x y))
(declare-fun my-or (Bool Bool) Bool)
(assert (forall ((x Bool) (y Bool)) (= (my-or x y) (my-or-impl x y))))
(check-sat)
But I'm hoping that there's a way to solve this which doesn't involve universal quantifiers.
Unfortunately, define-fun is just a macro definition in Z3. They are implemented in the Z3 SMT 2.0 parser. They are not part of the Z3 kernel. That is, Z3 solvers do not even "see" these definitions.
The approach using declare-fun and quantifiers works, but as you said we should avoid quantifiers since they create performance problems, and it is really easy to create problems with quantifiers that Z3 can't solve.
The best option is to use (_ map or).
The best option is to use (_ map or).
Unless one wants to map a non-built-in function over an array... I guess declare-fun plus assert is the only way to go?

Does not 'check-sat' support Boolean function as assumption?

In the following example, I tried to use uninterpreted Boolean function like "(declare-const p (Int) Bool)" rather than single Boolean constant for each assumption. But it does not work (it gives compilation error).
(set-option :produce-unsat-cores true)
(set-option :produce-models true)
(declare-fun p (Int) Bool)
;(declare-const p1 Bool)
;(declare-const p2 Bool)
; (declare-const p3 Bool)
;; We assert (=> p C) to track C using p
(declare-const x Int)
(declare-const y Int)
(assert (=> (p 1) (> x 10)))
;; An Boolean constant may track more than one formula
(assert (=> (p 1) (> y x)))
(assert (=> (p 2) (< y 5)))
(assert (=> (p 3) (> y 0)))
(check-sat (p 1) (p 2) (p 3))
(get-unsat-core)
Output
Z3(18, 16): ERROR: invalid check-sat command, 'not' expected, assumptions must be Boolean literals
Z3(19, 19): ERROR: unsat core is not available
I understand that it is not possible (unsupported) to use Boolean function. Is there any reason behind that? Is there different way to do that?
We have this restriction because Z3 applies many simplifications before it solves a problem. Some of them will rewrite formulas and terms. The problem that is actually solved by Z3 is very often quite different from the input problem. We would have trace back the simplified assumptions to the original assumptions, or introduce auxiliary variables. Restricting to Boolean literals avoids this issue, and makes the interface very clean. Note that this restriction does not limit the expressiveness. If you think it is too annoying to declare many Boolean variables to track different assertions. I suggest you take a look at the new Python front-end for Z3 called Z3Py. It is much more convenient to use than SMT 2.0. Here is your example in Z3Py: http://rise4fun.com/Z3Py/cL
In this example, instead of creating an uninterpreted predicate p, a "vector" (actually, it is a Python list) o Boolean constants is created.
The Z3Py online tutorial contains many examples.
It is also possible to implement in Z3Py the approach that creates auxiliary variables.
Here is the script that does the trick. I defined a function check_ext that does all the plumbing. http://rise4fun.com/Z3Py/B4

Resources