Set Bit at Index i in Z3 - z3

I am trying to set set a bit at a particular index in a bit vector in z3.
Currently, I use bit-wise or to accomplish this. I am working with large bit vectors (over a 1000 bits) and believe this is a causing the solver to take a significant amount of time. I was hoping their was a way that was faster than this to set an arbitrary bit in a bit-vector (similar to the store used by Arrays).
Is there a better way to do this, or am I stuck just using the bit-wise or?

I'm not sure if it would be faster, but you can always do an assert like this:
(assert (= ((_ extract i i) bv) #b1))
to tell the solver that the ith bit of bv is high. Whether this is usable in your particular application depends on how those new expressions are passed around, of course. If this trick doesn't work for you, I think you are stuck with the bitwise-or.

In addition, for bit-vectors one can use a combination of extract and concatenation to form new bit-vectors from old ones. For example
(concat ((_ extract n-1 k+1) x) y ((_ extract k-1 0) x))
where y is a bit-vector of length 1, should have the effect of forming a bit-vector that is equal to x except for the position k, where it is defined by y.

Related

Creating a variable width mask constraint in Z3

I would like to create a constraint on a Bitvector (X) that masks another Bitvector to its n least significant bits. I would like this to be as efficient as possible. What I have tried so far is to represent the second bitvector as: 1<<n - 1, where n is another Bitvector. This gives me two problems:
First, it slows down the solver massively
Second, and possibly related to the first, I cannot set the width of n to be smaller than the width of X. If I do, it fails with a type error on n.
Any ideas for a more efficient way of approaching this, or solving the width issue?
It's not quite clear what you're trying to do, posting actual code is always more helpful. But, from your description, you can simply shift left first and then shift right again. This'll push 0's from the bottom, and then drop them off; making sure the bit-vector has the least-most n bits left. The amount you shift should equal to bitsize - n where bitsize is the length of your bit-vectors and n is how many least-significant bits you want to preserve. Assuming you're dealing with 64-bit vectors, it'd look something like:
(declare-const n (_ BitVec 64))
(declare-const x (_ BitVec 64))
(define-fun amnt () (_ BitVec 64) (bvsub #x0000000000000040 n))
(define-fun maskedX () (_ BitVec 64) (bvlshr (bvshl x amnt) amnt))
(The constant #x0000000000000040 is how you write 64 in SMT-lib as a 64-bit bit-vector constant.) Note that this implicitly assumes n is at most 64: If that's not true, then subtraction will wrap-around and you'll get a different constraint. I'm assuming there already is a constraint in your system that says nis at most the bit-vector size you're dealing with.
Regarding efficiency: There's really no obvious way to make bit-vector constraints like this fast or slow: It really depends on what other constraints you have around. So, impossible to opine whether this is the best way to achieve what you want without knowing anything else about your problem. It is usually not helpful to think about "speed" in SMTLib when symbolic values are present, there are so many factors that go into solver efficiency.
Regarding types: SMTLib is based on a very simple first-order type system. So, yes: Almost all bit-vector operations have to have the exact same sizes as arguments. This is by design: Variable-length bit-vectors are simply not available in the logic, as it would render it useless since the satisfiablity of formulas would depend on actual bit-sizes you instantiate them to.
If this doesn't help, I'd recommend posting an actual code snippet of what you're trying to do and the problem you're running into. The more concrete the example is, the better.

Complexity of finding a solution to SMT system with quantifier

I need to find a solution to a problem by generating by using z3py. The formulas are generated depending on input of the user. During the generation of the formulas temporary SMT variables are created that can take on only a limited amount of values, eg is its an integer only even values are allowed. For this case let the temporary variables be a and b and their relation with global variables x and y are defined by the predicate P(a,b,x,y).
An example generated using SMT-LIB like syntax:
(set-info :status unknown)
(declare-fun y () Int)
(declare-fun x () Int)
(assert
(forall (
(a Int) (b Int) (z Int) )
(let
(($x22 (exists ((z Int))(and (< x z) (> z y)))))
(=>
P(a, b, x, y)
$x22))))
(check-sat)
where
z is a variable of which all possible values must be considered
a and b represent variables who's allowed values are restricted by the predicate P
the variable 'x' and 'y' need to be computed for which the formula is satisfied.
Questions:
Does the predicate P reduce the time needed by z3 to find a solution?
Alternatively: viewing that z3 perform search over all possible values for z and a will the predicate P reduce the size of the search space?
Note: The question was updated after remarks from Levent Erkok.
The SMTLib example you gave (generated or hand-written) doesn't make much sense to me. You have universal quantification over x and z, and inside of that you existentially quantify z again, and the whole formula seems meaningless. But perhaps that's not your point and this is just a toy. So, I'll simply ignore that.
Typically, "redundant equations" (as you put it), should not impact performance. (By redundant, I assume you mean things that are derivable from other facts you presented?) Aside: a=z in your above formula is not redundant at all.
This should be true as long as you remain in the decidable subset of the logics; which typically means linear and quantifier-free.
The issue here is that you have quantifier and in particular you have nested quantifiers. SMT-solvers do not deal well with them. (Search stack-overflow for many questions regarding quantifiers and z3.) So, if you have performance issues, the best strategy is to see if you really need them. Just by looking at the example you posted, it is impossible to tell as it doesn't seem to be stating a legitimate fact. So, see if you can express your property without quantifiers.
If you have to have quantifiers, then you are at the mercy of the e-matcher and the heuristics, and all bets are off. I've seen wild performance characteristics in that case. And if reasoning with quantifiers is your goal, then I'd argue that SMT solvers are just not the right tool for you, and you should instead use theorem provers like HOL/Isabelle/Coq etc., that have built-in support for quantifiers and higher-order logic.
If you were to post an actual example of what you're trying to have z3 prove for you, we might be able to see if there's another way to formulate it that might make it easier for z3 to handle. Without a specific goal and an example, it's impossible to opine any further on performance.

z3py: What is the most efficient way of constraining a bit in BitVec?

I have a number of constraints asserting for bits in BitVec and I wonder what is the most efficient way of asserting constraints for a specific bit in a BitVec?
Assume I want to assert that the 5th bit in a BitVec is 1, is there any way that is more efficient (lower check time) than this?
bitvec = BitVec('bitvec',10)
s.add(Extract(5,5,bitvec)==1)
From what I understand about the internals of Z3 (from experimenting and looking at the source) this is the most efficient way possible.
As I understand it extracts and concats have no solver runtime cost. They just split the bits into parts.
The only alternative would be to apply an and operation to extract the bit. But that should turn into an extract after simplification (which indeed you can test by running the simplify tactic. It's a fun rewrite to observe).

Can we limit the value of a z3 real term by its numerator/denominator representation?

In z3, a real term's value is represented by the division of two integer numbers: numerator and denominator. I very often find real values (as solutions to my z3 problems) with very large numerators and denominators like as follows:
29176049827299110215982818410792217459/804618286561124267999713087296957062500
-556895298158182412321541102649719164259083/4272120792496289300944476637003193523343750
There are often other assignments of those real variables in the case of alternative solutions (to the same problem) with smaller numerators and denominators. I am just wondering whether I can limit the numerator and denominator (e.g., with respect to the number of digits). Actually, I am looking for a z3 feature for this purpose. Thank you in advance for your answer.
It's not true in general that a real number in Z3 is represented as a ratio of a numerator and a denominator. This would restrict Z3 to rationals. For an example where Z3 returns an irrational number, try:
(declare-const x Real)
(assert (= (* x x) 2.0))
(check-sat)
(get-model)
That being said, for many specific problems, Z3 will indeed respond with a rational representation of a real number. I think this often happens when it's possible for your problem to be re-normalized and solved in the integers. In these situations, you could try to force your problem to be solved in the rationals using techniques similar to the answer in this question. Then, you can assert that your number has a numerator p < p_max for some constant p_max.

Z3 patterns and injectivity

In the Z3 tutorial, section 13.2.3, there is a nice example on how to reduce the number of patterns that have to be instantiated when dealing with the axiomatisation of injectivity. In the example, the function f that has to be stated injective, takes an object of type A as input and return an object of type B. As far as I understand the sorts A and B are disjunct.
I have an SMT problem (FOL+EUF) on which Z3 seems not to terminate, and I am trying to isolate the cause. I have a function f:A->A that I assert being injective. Could the problem be that the domain and codomain of f coincide?
Thanks in advance for any suggestion.
Z3 does not terminate because it keeps trying to build an interpretation for the problem.
Satisfiable problems containing injectivity axiom are usually hard for Z3.
They usually fall in a class of problems that can't be decided by Z3
The Z3 guide describes most of the classes that can be decided by Z3.
Moreover, Z3 can produce models for infinite domains such as integers and reals. However, in most cases, the functions produced by Z3 have finite ranges. For example, the quantifier forall x, y: x <= y implies f(x) <= f(y) can be satisfied by assigning f to a function that has a finite range. More information can be found in this article. Unfortunately, injectivity usually requires a range that is as "big" as the domain. Moreover, it is very easy to write axioms that can only be satisfied by an infinite universe. For example, the formula
(assert
(forall ((d1 Value)(d2 Value)(d3 Value)(d4 Value))
(! (=>
(and (= (ENC d1 d2) (ENC d3 d4)))
(and (= d1 d3) (= d2 d4))
)
:pattern ((ENC d1 d2) (ENC d3 d4)))
)
)
can only be satisfied if the universe of Value has one element or is infinite.
Another problem is combining the injectivity axiom for a function f with axioms of the form forall x: f(x) != a. If f is a function from A to A, then the formula can only be satisfied if A has an infinite universe.
That being said, we can prevent the non-termination by reducing the amount of "resources" used by the Z3 model finder for quantified formulas. The options
(set-option :auto-config false)
(set-option :mbqi-max-iterations 10)
If we use these options, Z3 will terminate in your example, but will return unknown. It also returns a "candidate" model. It is not really a model since it does not satisfy all universal quantifiers in the problem. The option
(set-option :mbqi-trace true)
will instruct Z3 to display which quantifiers were not satisfied.
Regarding the example in section 13.2.3, the function may use the same input and return types. Using the trick described in this section will only help unsatisfiable instances. Z3 will also not terminate (for satisfiable formulas) if you re-encode the injectivity axioms using this trick.
Note that the tutorial you cited is very old, and contains outdated information.

Resources