Is this a bug in z3 int.to.str? - z3

I'm posting this z3 issue here too in case any z3 users have somehow encountered it. We are experimenting a little with the semantics of int.to.str, and we found this weird behavior that looks like a bug. Here is the first query that works OK:
(declare-const s String)
(declare-const i Int)
(assert (< i -2))
(assert (= s (int.to.str i)))
(assert (< 0 (str.len s )))
(check-sat)
(get-value (s i))
And the result:
sat
((s "-11")
(i (- 11)))
When I change the '<' sign to '=' I get an unsat response:
(declare-const s String)
(declare-const i Int)
(assert (= i -2))
(assert (= s (int.to.str i)))
(assert (< 0 (str.len s )))
(check-sat)
(get-value (s i))
Here is the result I get:
unsat
(error "line 10 column 16: model is not available")
Am I missing something here? Thanks!

This is indeed a bug, as described here.

Related

Quantifier patterns in Z3

I am having trouble attempting to prove this fairly simple Z3 query.
(set-option :smt.auto-config false) ; disable automatic self configuration
(set-option :smt.mbqi false) ; disable model-based quantifier instantiation
(declare-fun sum (Int) Int)
(declare-fun list () (Array Int Int))
(declare-fun i0 () Int)
(declare-fun s0 () Int)
(declare-fun i1 () Int)
(declare-fun s1 () Int)
(assert (forall ((n Int))
(! (or (not (<= n 0)) (= (sum n) 0))
:pattern ((sum n)))))
(assert (forall ((n Int))
(! (let ((a1 (= (sum n)
(+ (select list (- n 1))
(sum (- n 1))))))
(or (<= n 0) a1))
:pattern ((sum n)))))
(assert (>= i0 0))
(assert (= s0 (sum i0)))
(assert (= i1 (+ 1 i0)))
(assert (= s1 (+ 1 s0 (select list i0))))
(assert (not (= s1 (sum i1))))
(check-sat)
Seems to me that the final assertion should instantiate the second quantified statement for i1 while the assert involving s0 should instantiate the quantifiers for i0. These two should should easily lead to UNSAT.
However, Z3 returns unknown. What am I missing?
Never mind, there was an silly error in my query.
This code:
(assert (= s1 (+ 1 s0 (select list i0))))
should have been:
(assert (= s1 (+ s0 (select list i0))))

Why does the following expression in z3 take a long time?

What is wrong with this z3 expression?
(declare-const arg_1 Int)
(assert
(and
(not (= 0 (mod arg_1 10)))
(= 0 (mod (+ 1 arg_1) 10))))
(check-sat)
(get-model)
Trying to evaluate it with z3 hangs for ever. On the other hand, if I try either of the below, it returns immediately.
Using the first expression only
(declare-const arg_1 Int)
(assert (not (= 0 (mod arg_1 10))))
(check-sat)
(get-model)
=> sat
(model
(define-fun arg_1 () Int
1)
)
Using the second expression only
(declare-const arg_1 Int)
(assert (= 0 (mod (+ 1 arg_1) 10)))
(check-sat)
(get-model)
=> sat
(model
(define-fun arg_1 () Int
9)
)
Asserting them together in the same file also returns immediately.
(declare-const arg_1 Int)
(declare-const arg_2 Int)
(assert (= 0 (mod (+ 1 arg_1) 10)))
(assert (not (= 0 (mod arg_2 10))))
;(assert (= arg_1 arg_2))
(check-sat)
(get-model)
=> sat
(model
(define-fun arg_2 () Int
1)
(define-fun arg_1 () Int
9)
)
However, if I uncomment the arg_1 = arg_2 assertion, it will hang.
This is most likely a z3 bug. If you run the original with z3 -v:3, you get:
$ z3 -v:3 a.smt2
(smt.searching)
(smt.simplifying-clause-set :num-deleted-clauses 1)
final-check OPTIMAL
final-check OPTIMAL
...
and it keeps printing that. I tried with cvc4, yices, and mathsat; and they all solve it immediately. You should report this at https://github.com/Z3Prover/z3/issues so they can take a look at it.

Z3 returns model not available

If possible I'd like a second opinion on my code.
The constraints of the problem are:
a,b,c,d,e,f are non-zero integers
s1 = [a,b,c] and s2 = [d,e,f] are sets
The sum s1_i + s2_j for i,j = 0..2 has to be a perfect square
I don't understand why but my code returns model not available. Moreover, when commenting out the following lines:
(assert (and (> sqrtx4 1) (= x4 (* sqrtx4 sqrtx4))))
(assert (and (> sqrtx5 1) (= x5 (* sqrtx5 sqrtx5))))
(assert (and (> sqrtx6 1) (= x6 (* sqrtx6 sqrtx6))))
(assert (and (> sqrtx7 1) (= x7 (* sqrtx7 sqrtx7))))
(assert (and (> sqrtx8 1) (= x8 (* sqrtx8 sqrtx8))))
(assert (and (> sqrtx9 1) (= x9 (* sqrtx9 sqrtx9))))
The values for d, e, f are negative. There is no constraint that requires them to do so. I'm wondering if perhaps there are some hidden constraints that sneaked in and mess up the model.
A valid expected solution would be:
a = 3
b = 168
c = 483
d = 1
e = 193
f = 673
Edit: inserting (assert (= a 3)) and (assert (= b 168)) results in the solver finding the correct values. This only puzzles me further.
Full code:
(declare-fun sqrtx1 () Int)
(declare-fun sqrtx2 () Int)
(declare-fun sqrtx3 () Int)
(declare-fun sqrtx4 () Int)
(declare-fun sqrtx5 () Int)
(declare-fun sqrtx6 () Int)
(declare-fun sqrtx7 () Int)
(declare-fun sqrtx8 () Int)
(declare-fun sqrtx9 () Int)
(declare-fun a () Int)
(declare-fun b () Int)
(declare-fun c () Int)
(declare-fun d () Int)
(declare-fun e () Int)
(declare-fun f () Int)
(declare-fun x1 () Int)
(declare-fun x2 () Int)
(declare-fun x3 () Int)
(declare-fun x4 () Int)
(declare-fun x5 () Int)
(declare-fun x6 () Int)
(declare-fun x7 () Int)
(declare-fun x8 () Int)
(declare-fun x9 () Int)
;all numbers are non-zero integers
(assert (not (= a 0)))
(assert (not (= b 0)))
(assert (not (= c 0)))
(assert (not (= d 0)))
(assert (not (= e 0)))
(assert (not (= f 0)))
;both arrays need to be sets
(assert (not (= a b)))
(assert (not (= a c)))
(assert (not (= b c)))
(assert (not (= d e)))
(assert (not (= d f)))
(assert (not (= e f)))
(assert (and (> sqrtx1 1) (= x1 (* sqrtx1 sqrtx1))))
(assert (and (> sqrtx2 1) (= x2 (* sqrtx2 sqrtx2))))
(assert (and (> sqrtx3 1) (= x3 (* sqrtx3 sqrtx3))))
(assert (and (> sqrtx4 1) (= x4 (* sqrtx4 sqrtx4))))
(assert (and (> sqrtx5 1) (= x5 (* sqrtx5 sqrtx5))))
(assert (and (> sqrtx6 1) (= x6 (* sqrtx6 sqrtx6))))
(assert (and (> sqrtx7 1) (= x7 (* sqrtx7 sqrtx7))))
(assert (and (> sqrtx8 1) (= x8 (* sqrtx8 sqrtx8))))
(assert (and (> sqrtx9 1) (= x9 (* sqrtx9 sqrtx9))))
;all combinations of sums need to be squared
(assert (= (+ a d) x1))
(assert (= (+ a e) x2))
(assert (= (+ a f) x3))
(assert (= (+ b d) x4))
(assert (= (+ b e) x5))
(assert (= (+ b f) x6))
(assert (= (+ c d) x7))
(assert (= (+ c e) x8))
(assert (= (+ c f) x9))
(check-sat-using (then simplify solve-eqs smt))
(get-model)
(get-value (a))
(get-value (b))
(get-value (c))
(get-value (d))
(get-value (e))
(get-value (f))
Nonlinear integer arithmetic is undecidable. This means that there is no decision procedure that can decide arbitrary non-linear integer constraints to be satisfiable. This is what z3 is telling you when it says "unknown" as the answer your query.
This, of course, does not mean that individual cases cannot be answered. Z3 has certain tactics it applies to solve such formulas, but it is inherently limited in what it can handle. Your problem falls into that category: One that Z3 is just not capable of solving.
Z3 has a dedicated NRA (non-linear real arithmetic) tactic that you can utilize. It essentially treats all variables as reals, solves the problem (nonlinear real arithmetic is decidable and z3 can find all algebraic real solutions), and then checks if the results are actually integer. If not, it tries another solution over the reals. Sometimes this tactic can handle non-linear integer problems, if you happen to hit the right solution. You can trigger it using:
(check-sat-using qfnra)
Unfortunately it doesn't solve your particular problem in the time I allowed it to run. (More than 10 minutes.) It's unlikely it'll ever hit the right solution.
You really don't have many options here. SMT solvers are just not a good fit for nonlinear integer problems. In fact, as I alluded to above, there is no tool that can handle arbitrary nonlinear integer problems due to undecidability; but some tools fare better than others depending on the algorithms they use.
When you tell z3 what a and b are, you are essentially taking away much of the non-linearity, and the rest becomes easy to handle. It is possible that you can find a sequence of tactics to apply that solves your original, but such tricks are very brittle in practice and not easily discovered; as you are essentially introducing heuristics into the search and you don't have much control over how that behaves.
Side note: Your script can be improved slightly. To express that a bunch of numbers are all different, use the distinct predicate:
(assert (distinct (a b c)))
(assert (distinct (d e f)))

str.suffix in z3 API is unknown

I'm trying to use suffix API function in Z3 in the following script,
but Z3 complains it does not know str.suffix. Since I see it in the API
here I guess it exists but only called different (?)
Thanks!
(declare-const s String)
(declare-const s00 String)
(declare-const s1 String)
(declare-const s2 String)
(declare-const i Int)
(assert (= s "X2a2##aDD\x00444ppa800"))
(assert (= s00 (str.substr s 0 (str.indexof s "\x00" 0))))
(assert (str.suffixof s1 s00))
(assert (str.suffixof s2 s1))
(assert (= (str.len s1) (+ (str.len s2) 1)))
(assert (or (and (str.contains s00 "a")
(str.contains s1 "a"))
(not (str.contains s00 "a"))))
(assert (not (str.contains s2 "a")))
(assert (= i (ite (not (str.contains s00 "a")) -1
(- (str.len s00) (str.len s1)))))
(check-sat)
(get-value (s s00 s1 s2 i))
EDIT:
The script was fixed according to the answer. Here is the output from z3:
sat
((s "X2a2##aDD\x00444ppa800")
(s00 "X2a2##aDD")
(s1 "aDD")
(s2 "DD")
(i 6))
The correct call is: str.suffixof
(PS. Your file still doesn't load even with that fix since it has other issues; but that's besides the point of this question.)

Guiding z3's proof search

I'm trying to get z3 to work (most of the time) for very simple non-linear integer arithmetic problems. Unfortunately, I've hit a bit of a wall with exponentiation. I want to be able handle problems like x^{a+b+2} = (x * x * x^{a} * x{b}). I only need to handle non-negative exponents.
I tried redefining exponentiation as a recursive function (so that it's just allowed to return 1 for any non-positive exponent) and using a pattern to facilitate z3 inferring that x^{a+b} = x^{a} * x^{b}, but it doesn't seem to work - I'm still timing out.
(define-fun-rec pow ((x!1 Int) (x!2 Int)) Int
(if (<= x!2 0) 1 (* x!1 (pow x!1 (- x!2 1)))))
; split +
(assert (forall ((a Int) (b Int) (c Int))
(! (=>
(and (>= b 0) (>= c 0))
(= (pow a (+ b c)) (* (pow a c) (pow a b))))
:pattern ((pow a (+ b c))))))
; small cases
(assert (forall ((a Int)) (= 1 (pow a 0))))
(assert (forall ((a Int)) (= a (pow a 1))))
(assert (forall ((a Int)) (= (* a a) (pow a 2))))
(assert (forall ((a Int)) (= (* a a a) (pow a 3))))
; Our problem
(declare-const x Int)
(declare-const i Int)
(assert (>= i 0))
; This should be provably unsat, by splitting and the small case for 2
(assert (not (= (* (* x x) (pow x i)) (pow x (+ i 2)))))
(check-sat) ;times out
Am I using patterns incorrectly, is there a way to give stronger hints to the proof search, or an easier way to do achieve what I want?
Pattern (also called triggers) may only contain uninterpreted functions. Since + is an interpreted function, you essentially provide an invalid pattern, in which case virtually anything can happen.
As a first step, I disabled Z3's auto-configuration feature and also MBQI-based quantifier instantiation:
(set-option :auto_config false)
(set-option :smt.mbqi false)
Next, I introduced an uninterpreted plus function and replaced each application of + by plus. That sufficed to make your assertion verify (i.e. yield unsat). You can of course also axiomatise plus in terms of +, i.e.
(declare-fun plus (Int Int) Int)
(assert (forall ((a Int) (b Int))
(! (= (plus a b) (+ a b))
:pattern ((plus a b)))))
but your assertion already verifies without the definitional axioms for plus.

Resources