it seems, there is no good support for integer-subranges in Z3. One would have to restrict all 'constants' and results with
`(assert (and (<= 0 x) (<= x nMax )))`.
Wouldn't it be useful to have something like a 'modular integer' type, with values between 0 and n? I could go for bitvectors, but not all of my n are powers of two.
How can i express something like x must be one of [ 2, 4, 5, 6, 8, 13] ? Some kind of set-membership? list-operation ? Only bitvectors ??
I'm not aware of any solver that supports modular arithmetic natively.
You can use bit-vectors + <= constraints.
Related
I'm trying to learn Z3 and the following example baffles me:
from z3 import *
a = Int("a")
b = Int("b")
print(solve(2**a <= b))
print(solve(a > 0, b > 0, 2**a <= b))
I would expect it returns "[a = 1, b = 2]" but it instead returns "failed to solve".
Why cannot it be solved?
Is it possible to compute with powers and logarithms in Z3 at all? How do I find, say, the length of binary string representation of a number (log base 2)?
Long story short, z3 (or SMT solvers in general) cannot deal with non-linear constraints like this. Exponentiation/Logs etc are difficult to deal with, and there are no decision procedures for them over the integers. Even over reals they are difficult to handle. That is, the solver will apply some heuristics, which may or may not work. But for these sorts of constraints, SMT solvers are just not the right tool.
For an earlier answer on non-linear arithmetic in z3, see this answer: https://stackoverflow.com/a/13898524/936310
Here're some more details if you are interested. First, there is no power-operator for integers in SMTLib or z3. If you look at the generated program, you'll see that it's actually over real values:
from z3 import *
a = Int("a")
b = Int("b")
s = Solver()
s.add(2**a <= b)
print(s.sexpr())
print(s.check())
This prints:
(declare-fun b () Int)
(declare-fun a () Int)
(assert (<= (^ 2 a) (to_real b)))
unknown
Note the conversion to to_real. The ^ operator automatically creates a real. The way this would be solved is if the solver can come up with a solution over reals, and then checks to see if the result is an integer. Let's see what happens if we try with Reals:
from z3 import *
a = Real("a")
b = Real("b")
s = Solver()
s.add(2**a <= b)
print(s.check())
print(s.model())
This prints:
sat
[b = 1, a = 0]
Great! But you also wanted a > 0, b > 0; so let's add that:
from z3 import *
a = Real("a")
b = Real("b")
s = Solver()
s.add(2**a <= b)
s.add(a > 0)
s.add(b > 0)
print(s.check())
This prints:
unknown
So, the solver can't handle this case either. You can play around with tactics (qfnra-nlsat), but it's unlikely to handle problems of this sort in general. Again, refer to https://stackoverflow.com/a/13898524/936310 for details.
I have tried to solve 2^x=4 with Z3, by putting the following on the Z3 website: https://rise4fun.com/z3/tutorial.
(declare-const x Real)
(declare-const y Real)
(declare-const z Real)
(assert (=(^ 2 x) 4))
(check-sat)
(get-model)
Z3 produced
unknown
(model
)
Am I misusing Z3?
Problems involving exponentials are typically beyond the reach of z3, or general-purpose SMT solvers. This doesn't mean that they cannot solve them: Theory of reals is decidable. But they may not have the right "heuristics" to kick in to answer every query involving exponentials as sat/unsat. You can search stack-overflow for keywords like nnf, non-linear, etc., to see a plethora of questions regarding queries that involve such difficult terms.
Having said that, there's a separate line of research called delta-satisfiability that can help with these sorts of problems to a great extent. Note that delta-satisfiability is different than regular satisfiability. It means either the formula is satisfiable, or a delta-perturbation of it is. The most prominent such solver is dReal, and you can read all about it here: http://dreal.github.io/
For your query, dReal says:
[urfa]~/qq>dreal a.smt2
delta-sat with delta = 0.001
(model
(define-fun x () Real [2, 2])
(define-fun y () Real [-0.0005, 0.0005])
(define-fun z () Real [-0.0005, 0.0005])
)
(You didn't actually use y and z in your query, so you can ignore those outputs.)
As you can see dReal determines x must be in the range [2, 2], i.e., it must be 2. But it also says delta-sat with delta = 0.001: This means it has ensured the correctness within that factor. (You can tweak the factor yourself, making it arbitrarily small, but not zero.) When you have problems that arise from physical systems, delta-sat is the right choice in modeling them in the SMT-world.
This is the code that I wrote for a method that returns the maximum of two integers:
predicate greater(x: int, a: int, b: int){
(x >= a) && (x >= b)
}
method Max(a: int, b: int) returns (max: int)
ensures max >= a
ensures max >= b
ensures forall x /*{:trigger greater(x,a,b)}*/ :: (greater(x,a,b)) ==> x >= max
{
if (a > b){
max := a;
}else{
max := b;
}
// assert greater(max, a, b); - trivial assertion
}
method Main(){
var res:= Max(4, 5);
assert res == 5;
}
As you can see, I have tried both the two techniques metnioned in the Wiki page (manual trigger assignment and also adding a trivial non-useful assertion in the method body. However, I still get an assertion error.
I am not sure what else to do. I have read other answers like this, this and this, but none have helped me so far.
PS: I know there is a simpler way to write the postconditions for this particular method, however, I really wish to model the postconditions in terms of the forall quantifier only.
Let's forget greater for a while and just take a look at what you're trying to achieve. After the call to Max in Main, you know the following (from the postcondition of Max):
res >= 4
res >= 5
forall x :: x >= 4 && x >= 5 ==> x >= res
You're trying to prove res == 5 from this. The second of these three things immediately gives you half of that equality, so all you need to do is obtain 5 >= res. If you instantiate the quantifier with 5 for x, you will get
5 >= 4 && 5 >= 4 ==> 5 >= res
which simplifies to 5 >= res, which is what you need, so that's the end of your proof.
In summary, the proof comes down to instantiating the quantifier with 5 for x. Next, you need to know a little about how the Dafny verifier instantiates quantifiers. Essentially, it does this by looking at the "shape" of the quantifier and looking for similar things in the context of what you're trying to prove. By "shape", I mean things like "the functions and predicates it uses". Usually, this technique works well, but in your case, the quantifier is so plain that it doesn't have any "shape" to speak of. Consequently, the verifier fails to come up with the needed instantiation.
It would be nice if we could just say "hey, try instantiating that quantifier with 5 for x". Well, we can, if we give the quantifier some "shape" that we can refer to. That's what those wiki and other guidelines are trying to say. This is where it's useful to introduce the predicate greater. (Don't try to manually write trigger annotations.)
Alright, after introducing greater, your specification says
ensures greater(max, a, b)
ensures forall x :: greater(x, a, b) ==> x >= max
This says "max satisfies greater(max, a, b)" and "among all values x that satisfy greater(x, a, b), max is the smallest". After the call to Max in Main, we then have:
greater(res, 4, 5)
forall x :: greater(x, 4, 5) ==> x >= res
Recall, I said the verifier tries to figure out quantifier instantiations by looking at the quantifier and looking at the context around your assertion, and you're trying to instantiate the quantifier with 5 for x. So, if you can add something to the context just before the assertion that tempts the verifier to do that instantiation, then you're done.
Here's the answer: you want to introduce the term greater(5, 4, 5). This has a shape much like the greater(x, 4, 5) in the quantifier. Because of this similarity, the verifier will instantiate x with 5, which gives
greater(5, 4, 5) ==> 5 >= res
And since greater(5, 4, 5) is easily proved to be true, the needed fact 5 >= res follows.
So, change the body of Main to
var res := Max(4, 5);
assert greater(5, 4, 5);
assert res == 5;
and you're done. The verifier will prove the both assertions. The first is trivial, and after proving it, the verifier gets to use the term greater(5, 4, 5) in the proof of the second assertion. That term is what triggers the quantifier, which produces the fact 5 >= res, which proves the second assertion.
I want to point out that most quantifiers we try to prove do have some shape already. In your case, the predicate greater was introduced in order to give some shape to the quantifier. The technique of adding the extra assertion (here, assert greater(5, 4, 5)) is the same whether or not greater was already defined or was introduced as a trivial predicate that provides shape.
I have the following questions:
A. If I have a variable x which I declare it (case 1) to be Bool (case 2) to be Int and assert x=0 or x=1 (case 3) to be Int and assert 0<=x<=1. What happens in Z3, or more generally in SMT, in each of the cases? Is, (case 1) desired since things happen at SAT and not SMT level? Do you have some reference paper here?
B. I have the following statement in Python (for using Z3 Python API)
tmp.append(sum([self.a[i * self.nrVM + k] * componentsRequirements[i][1] for i
in range(self.nrComp)]) <= self.MemProv[k])
where a is declared as a Z3 Int variable (0 or 1), componentsRequirements is a Python variable which is to be considered float, self.MemProv is declared as a Z3 Real variable.
The strange thing is that for float values for componentsRequirements, e.g 0.5, the constraint built by the solver considers it 0 and not 0.5. For example in:
(assert (<= (to_real (+ 0 (* 0 C1_VM2)
(* 0 C2_VM2)
(* 2 C3_VM2)
(* 2 C4_VM2)
(* 3 C5_VM2)
(* 1 C6_VM2)
(* 0 C7_VM2)
(* 2 C8_VM2)
(* 1 C9_VM2)
(* 2 C10_VM2)))
StorageProv2))
the 0 above should be actually 0.5. When changing a to a Real value then floats are considered, but this is admitted by us because of the semantics of a. I tried to use commutativity between a and componentsRequirements but with no success.
C. If I'd like to use x as type Bool and multiply it by an Int, I get, of course, an error (Bool*Real/Int not allowed), in Z3. Is there a way to overcome this problem but keeping the types of both multipliers? An example in this sense is the above (a - Bool, componentsRequirements - Real/Int):
a[i * self.nrVM + k] * componentsRequirements[i][1]
Thanks
Regarding A
Patrick gave a nice explanation for this one. In practice, you really have to try and see what happens. Different problems might exhibit different behavior due to when/how heuristics kick in. I don't think there's a general rule of thumb here. My personal preference would be to keep booleans as booleans and convert as necessary, but that's mostly from a programming/maintenance perspective, not an efficiency one.
Regarding B
Your "division" getting truncated problem is most likely the same as this: Retrieve a value in Z3Py yields unexpected result
You can either be explicit and write 1.0/2.0 etc.; or use:
from __future__ import division
at the top of your program.
Regarding C
SMTLib is a strongly typed language; you cannot multiply by a bool. You have to convert it to a number first. Something like (* (ite b 1 0) x), where b is your boolean. Or you can write a custom function that does this for you and call that instead; something like:
(define-fun mul_bool_int ((b Bool) (i Int)) Int (ite b i 0))
(assert (= 0 (mul_bool_int false 5)))
(assert (= 5 (mul_bool_int true 5)))
I honestly can't answer for z3 specifically, but I want to state my opinion on point A).
In general, the constraint x=0 v x=1 is abstracted into t1 v t2, where t1 is x=0 and t2 is x=1, at the SAT engine level.
Thus, the SAT engine might try to assign both t1 and t2 to true during the construction of a satisfiable truth assignment for the input formula. It is important to note that this is a contradiction in the theory of LAR, but the SAT engine is not capable of such reasoning. Therefore, the SAT engine might continue its search for a while after taking this decision.
When the LAR Solver is finally invoked, it will detect the LAR-unsatisfiability of the given (possibly partial) truth assignment. As a consequence, it (should) hand the clause not t1 or not t2 to the SAT engine as learning clause so as to block the bad assignment of values to be generated again.
If there are many of such bad assignments, it might require multiple calls to the LAR Solver so as to generate all blocking clauses that are needed to rectify the SAT truth assignment, possibly up to one for each of those bad combinations.
Upon receiving the conflict clause, the SAT engine will have to backjump to the place where it made the bad assignment and do the right decision. Obviously, not all the work done by the SAT engine since it made the bad assignment of values gets wasted: any useful clause that was learned in the meanwhile will certainly be re-used. However, this can still result in a noticeable performance hit on some formulas.
Compare all of this back-and-forth computation being wasted with simply declaring x as a Bool: now the SAT engine knows that it can only assign one of two values to it, and won't ever assign x and not x contemporarily.
In this specific situation, one might mitigate this problem by providing the necessary blocking clauses right into the input formula. However, it is not trivial to conclude that this is always the best practice: explicitly listing all known blocking clauses might result in an explosion of the formula size in some situations, and into an even worse degradation of performance in practice. The best advice is to try different approaches and perform an experimental evaluation before settling for any particular encoding of a problem.
Disclaimer: it is possible that some SMT solvers are smarter than others, and automatically generate appropriate blocking clauses for 0/1 variables upon parsing the formula or avoid this situation altogether through other means (i.e. afaik, Model-Based SMT solvers shouldn't incur in the same problem)
Is there any function in which z3 calculate directly the logarithm to Bitvectors?
Otherwise how can I implement the logarithm efficiently?
I think your best bet is to code it up as an if-then-else chain as essentially a look-up table. Assuming base-2, you'd have something like (assuming lg 0 = 0):
(ite (< x 2) 0
(ite (< x 4) 1
(ite (< x 8) 2
.... etc ...
Since logarithm grows slowly, you'd only need 32 branches for 32-bit vectors, etc. Other bases would be similar. You can easily generate this code automatically.