I am trying to solve a constraint problem with the following features:
4 variables representing real numbers
a few inequalities by rational fractions which involve polynomials of small-ish degree (4), with an annoying OR.
I copy below the said constraints (note that OR).
I expect "UNSAT" (for N = 4 that's actually a theorem, but I'd like to go beyond 4!)
Unfortunately, z3 cannot solve this first problem. Any ideas or suggestions about tactics or other tools would be very appreciated!
[S_0 >= S_1,
S_1 >= S_2,
S_2 >= S_3,
S_3 >= 0,
Or((S_0/(S_0 + S_1))*(S_0/(S_0 + S_3))*(S_1/(S_1 + S_2)) +
(S_0/(S_0 + S_2))*(S_0/(S_0 + S_3))*(S_2/(S_2 + S_1)) <
(S_0/(S_0 + S_3))*(S_1/(S_1 + S_0))*(S_1/(S_1 + S_2)) +
(S_1/(S_1 + S_2))*(S_1/(S_1 + S_3))*(S_3/(S_3 + S_0)),
(S_0/(S_0 + S_3))*(S_1/(S_1 + S_0))*(S_1/(S_1 + S_2)) +
(S_1/(S_1 + S_2))*(S_1/(S_1 + S_3))*(S_3/(S_3 + S_0)) <
(S_0/(S_0 + S_3))*(S_2/(S_2 + S_0))*(S_2/(S_2 + S_1)) +
(S_2/(S_2 + S_1))*(S_2/(S_2 + S_3))*(S_3/(S_3 + S_0)),
(S_0/(S_0 + S_3))*(S_2/(S_2 + S_0))*(S_2/(S_2 + S_1)) +
(S_2/(S_2 + S_1))*(S_2/(S_2 + S_3))*(S_3/(S_3 + S_0)) <
(S_1/(S_1 + S_2))*(S_3/(S_3 + S_0))*(S_3/(S_3 + S_1)) +
(S_2/(S_2 + S_1))*(S_3/(S_3 + S_0))*(S_3/(S_3 + S_2)))]
Looks like z3 is choking on this problem, but both mathsat and cvc4 are doing just fine. Here's the problem coded in SMTLib:
$ cat a.smt2
(set-logic QF_NRA)
(set-option :produce-models true)
(declare-fun S_1 () Real)
(declare-fun S_0 () Real)
(declare-fun S_2 () Real)
(declare-fun S_3 () Real)
(assert (>= S_0 S_1))
(assert (>= S_1 S_2))
(assert (>= S_2 S_3))
(assert (>= S_3 0.0))
(assert (let ((a!1 (+ (* (/ S_0 (+ S_0 S_1)) (/ S_0 (+ S_0 S_3)) (/ S_1 (+ S_1 S_2)))
(* (/ S_0 (+ S_0 S_2)) (/ S_0 (+ S_0 S_3)) (/ S_2 (+ S_2 S_1)))))
(a!2 (+ (* (/ S_0 (+ S_0 S_3)) (/ S_1 (+ S_1 S_0)) (/ S_1 (+ S_1 S_2)))
(* (/ S_1 (+ S_1 S_2)) (/ S_1 (+ S_1 S_3)) (/ S_3 (+ S_3 S_0)))))
(a!3 (+ (* (/ S_0 (+ S_0 S_3)) (/ S_2 (+ S_2 S_0)) (/ S_2 (+ S_2 S_1)))
(* (/ S_2 (+ S_2 S_1)) (/ S_2 (+ S_2 S_3)) (/ S_3 (+ S_3 S_0)))))
(a!4 (+ (* (/ S_1 (+ S_1 S_2)) (/ S_3 (+ S_3 S_0)) (/ S_3 (+ S_3 S_1)))
(* (/ S_2 (+ S_2 S_1)) (/ S_3 (+ S_3 S_0)) (/ S_3 (+ S_3 S_2))))))
(or (< a!1 a!2) (< a!2 a!3) (< a!3 a!4))))
(check-sat)
(get-model)
Mathsat:
$ mathsat a.smt2
sat
( (S_1 0)
(S_0 (/ 3 2))
(S_2 0)
(S_3 0) )
CVC4:
$ cvc4 a.smt2
sat
(model
(define-fun S_1 () Real 0.0)
(define-fun S_0 () Real 1.0)
(define-fun S_2 () Real 0.0)
(define-fun S_3 () Real 0.0)
)
Both of these results are instantaneous. z3 seems to loop forever indeed.
I didn't check the models to be correct, so would be good to make sure they are OK and I got the SMTLib translation done right as well. You said you were expecting unsat, but obviously mathsat and cvc4 both disagree, assuming the translation I got is ok.
If you find that cvc4 and mathsat are indeed correct, you might want to file this as a z3 issue as this is something they should be able to handle.
Related
We're trying to build a solver for a weighted mean function. The code is written in SMT2Lib, and ran by CVC5 or Z3.
However, after adding an assert that indicates the non-negativity of the denominator, the code does not terminate. ("(assert (> tau0_max 0))")
Are there any alternatives to the parameters or the way we can declare the functions differently in order to approach this problem?
(Ints are not suitable to our problem. We'd like to use Rationals, but instead use Reals as they're offered by SMT2Lib).
(set-option :produce-assignments true)
(set-option :produce-models true)
(set-option :produce-proofs true)
(set-logic ALL)
;define data points x_0 x_1 x_2
(declare-fun x (Int) Real)
(declare-fun n () Int)
(define-fun sqr ((x Real)) Real (* x x))
(define-fun max ((x Real) (y Real)) Real (ite (> x y) x y))
;(define-fun c0 ((i Int)) Real 1.0)
(define-fun miu () Real (/ (+ (x 0) (+ (x 1) (+ (x 2) (+ (x 3) (+ (x 4) (+ (x 5) (+ (x 6) (+ (x 7) (+ (x 8) (+ (x 9) (x 10))))))))))) 11.0))
(define-fun miu_c0 () Real (/ (+ (x 0) (+ (x 1) (+ (x 2) (+ (x 3) (+ (x 4) (+ (x 5) (+ (x 6) (+ (x 7) (+ (x 8) (+ (x 9) (+ (x 10) (x 11)))))))))))) 12.0))
(define-fun tau0 ((i Int)) Real (sqr (- (x i) miu_c0)))
(define-fun tau0_max () Real (max (tau0 0) (max (tau0 1) (max (tau0 2) (max (tau0 3) (max (tau0 4) (max (tau0 5) (max (tau0 6) (max (tau0 7) (max (tau0 8) (max (tau0 9) (max (tau0 10) (tau0 11)))))))))))))
**(assert (> tau0_max 0))**
(define-fun c1 ((i Int)) Real (- 1.0 (/ (tau0 i) tau0_max)))
(define-fun miu_c1 () Real (/ (+ (* (c1 0) (x 0)) (+ (* (c1 1) (x 1)) (+ (* (c1 2) (x 2)) (+ (* (c1 3) (x 3)) (+ (* (c1 4) (x 4)) (+ (* (c1 5) (x 5)) (+ (* (c1 6) (x 6)) (+ (* (c1 7) (x 7)) (+ (* (c1 8) (x 8)) (+ (* (c1 9) (x 9)) (+ (* (c1 10) (x 10)) (* (c1 11) (x 11))))))))))))) 12.0))
(define-fun tau1 ((i Int)) Real (sqr (- (x i) miu_c1)))
(define-fun tau1_max () Real (max (tau1 0) (max (tau1 1) (max (tau1 2) (max (tau1 3) (max (tau1 4) (max (tau1 5) (max (tau1 6) (max (tau1 7) (max (tau1 8) (max (tau1 9) (max (tau1 10) (tau1 11)))))))))))))
(define-fun c2 ((i Int)) Real (* (c1 i) (- 1.0 (/ (tau1 i) tau1_max))))
(assert (= (c2 0) 1.0))
(check-sat)
(get-model)
I want to use z3 to find the result of the following expression after quantifier elimination. What is the correct syntax?
(declare-fun n () Int)
(declare-fun X () Int)
(declare-fun X_1_ () Int)
(declare-fun X_0_ () Int)
(assert (exists ((R__0 Int) (R__1 Int)(R_0_0 Int) (R_1_0 Int)) (and (>= n 3)
(= X n)
(=(+ X_0_ X_1_) X)
(>= X_0_ 0)
(<= R_0_0 X_0_)
(>= R_0_0 0)
(<= R_0_0 R__0)
(>= X_1_ 0)
(<= R_1_0 X_1_)
(>= R_1_0 0)
(<= R_1_0 R__0)
(<= R__0 X)
(<= R__1 X)
(= (+ R_1_0 R_0_0) R__0)
(> (* 3 R__0) (* 2 n))
(>= R_0_0 R_1_0)
(<= (* 3 R_0_0) (* 2 n))
(<= (* 3 R__1) (* 2 n)))))
(apply (using-params qe :qe-nonlinear true))
Use the qe_rec tactic. Changing your last line to:
(apply qe_rec)
produces:
(goals
(goal
(>= X_1_ 0)
(>= X_0_ 0)
(= (+ X_0_ X_1_) X)
(= X n)
(>= n 3)
(<= (+ (* (- 2) n) (* 3 X_1_)) 0)
(>= (* 9 X_1_) 7)
(<= (+ (* 2 n) (* (- 6) X_0_)) (- 1))
:precision precise :depth 1)
)
We look for a number of the form efghiihgfe which is the product of two numbers of the form 999ab and 99qcd.
We use the following code
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Int)
(declare-const e Int)
(declare-const f Int)
(declare-const g Int)
(declare-const h Int)
(declare-const i Int)
(declare-const p Int)
(declare-const q Int)
(assert (and (>= a 0) (<= a 9)))
(assert (and (>= b 0) (<= b 9)))
(assert (and (>= c 0) (<= c 9)))
(assert (and (>= d 0) (<= d 9)))
(assert (and (>= e 0) (<= e 9)))
(assert (and (>= f 0) (<= f 9)))
(assert (and (>= g 0) (<= g 9)))
(assert (and (>= h 0) (<= h 9)))
(assert (and (>= i 0) (<= i 9)))
(assert (and (>= p 0) (<= p 9)))
(assert (and (>= q 0) (<= q 9)))
(assert (= (* (+ 99900 (* 10 a) b ) (+ 99000 (* 100 q) (* 10 c) d ))
(+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e) ) )
(check-sat)
(get-model)
(eval (+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e))
and the output is
(model
(define-fun q () Int
6)
(define-fun p () Int
0)
(define-fun i () Int
0)
(define-fun h () Int
6)
(define-fun g () Int
6)
(define-fun f () Int
9)
(define-fun e () Int
9)
(define-fun d () Int
1)
(define-fun c () Int
8)
(define-fun b () Int
9)
(define-fun a () Int
7)
)
9966006699
To verify that 9966006699 is the maxim we run the code
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Int)
(declare-const e Int)
(declare-const f Int)
(declare-const g Int)
(declare-const h Int)
(declare-const i Int)
(declare-const p Int)
(declare-const q Int)
(assert (and (>= a 0) (<= a 9)))
(assert (and (>= b 0) (<= b 9)))
(assert (and (>= c 0) (<= c 9)))
(assert (and (>= d 0) (<= d 9)))
(assert (and (>= e 0) (<= e 9)))
(assert (and (>= f 0) (<= f 9)))
(assert (and (>= g 0) (<= g 9)))
(assert (and (>= h 0) (<= h 9)))
(assert (and (>= i 0) (<= i 9)))
(assert (and (>= p 0) (<= p 9)))
(assert (and (>= q 0) (<= q 9)))
(assert (= (* (+ 99900 (* 10 a) b ) (+ 99000 (* 100 q) (* 10 c) d ))
(+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e) ) )
(assert (> (+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e) 9966006699 ))
(check-sat)
and the output is
unsat
Please let me know if there is a more efficient program with Z3 to solve the problem.
Thank you, maybe use bit-vectors to force using finite domains instead of ILP.
I am trying to use Z3 through its Python interface to infer the satisfiability of simple linear formulae. It seems to be quite slow even on simple formulae such as the following (composed of 10 clauses with 10 terms each) which I write down in the smt2 format:
(declare-fun x0 () 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)
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 84 x0)) (* 48 x1)) (* 55 x2)) (* -46 x3)) (* -8 x4)) (* -12 x5)) (* 34 x6)) (* 35 x7)) (* -36 x8)) (* 99 x9)) 77))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -66 x0)) (* -13 x1)) (* -81 x2)) (* -88 x3)) (* -42 x4)) (* 57 x5)) (* 46 x6)) (* -9 x7)) (* -39 x8)) (* 18 x9)) 4))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -18 x0)) (* 93 x1)) (* 23 x2)) (* 25 x3)) (* 63 x4)) (* 47 x5)) (* -68 x6)) (* -25 x7)) (* 49 x8)) (* 14 x9)) 78))
(assert (<= (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -44 x0)) (* -89 x1)) (* -48 x2)) (* -25 x3)) (* 40 x4)) (* 84 x5)) (* 40 x6)) (* 52 x7)) (* -8 x8)) (* 66 x9)) 5))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 30 x0)) (* 29 x1)) (* 64 x2)) (* 18 x3)) (* 63 x4)) (* -94 x5)) (* 20 x6)) (* -30 x7)) (* 60 x8)) (* -35 x9)) 72))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 97 x0)) (* -90 x1)) (* 74 x2)) (* -51 x3)) (* 70 x4)) (* 41 x5)) (* 31 x6)) (* 99 x7)) (* -34 x8)) (* 36 x9)) 60))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 38 x0)) (* -11 x1)) (* -82 x2)) (* -59 x3)) (* 93 x4)) (* 2 x5)) (* 69 x6)) (* 86 x7)) (* -83 x8)) (* 49 x9)) 14))
(assert (<= (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -55 x0)) (* 50 x1)) (* -48 x2)) (* -27 x3)) (* -7 x4)) (* 86 x5)) (* -15 x6)) (* 96 x7)) (* -46 x8)) (* 11 x9)) 56))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 50 x0)) (* -51 x1)) (* -32 x2)) (* -23 x3)) (* -75 x4)) (* 24 x5)) (* 39 x6)) (* -89 x7)) (* 8 x8)) (* 23 x9)) 36))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -50 x0)) (* 98 x1)) (* 62 x2)) (* -39 x3)) (* -90 x4)) (* 19 x5)) (* -10 x6)) (* 32 x7)) (* -51 x8)) (* 52 x9)) 24))
(check-sat)
I am generating these formulae dynamically using the following block of code:
(Notice: a formula is a list of clauses; a clause is a list of terms, a comparison sign and a free coefficient; a term is a pair variable-identifier (integer), coefficient of the variable (integer)).
import z3
from pyCloSE.formula import LE, SAT, UNSAT, UNKNOWN
context = z3.Context()
solver = z3.SolverFor("QF_LIA", context)
# Define all variables as integers.
definitions = dict()
for variable in formula.getVariables():
definitions[variable] = z3.Int("x{}".format(variable), context)
# Create assertions.
constraints = []
for clause in formula.getClauses():
terms = [term.getCoefficient() * definitions[term.getIndex()] for term in clause.getTerms()]
sumOfTerms = reduce(lambda a,b: a+b, terms)
if clause.getComparison() == LE:
constraints.append(sumOfTerms <= clause.getFreeCoefficient())
else:
constraints.append(sumOfTerms != clause.getFreeCoefficient())
solver.add(*constraints)
result = solver.check()
return result
The problem I am having is that Z3 is stuck on such a formula. It seems to be stuck too when I save it to a file named formula.smt2 and try to solve it through the bash Z3 command.
The version of the solver I am using is: Z3 version 4.3.2
Is the format I am using inconvenient or is it due to Z3? Is there any trick I could use to speed up the solving process?
As Juan Ospina suggested I tried to figure out which part of the formula was the difficult one for the solver. It seems it is the following:
(declare-fun x0 () 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)
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -18 x0)) (* 93 x1)) (* 23 x2)) (* 25 x3)) (* 63 x4)) (* 47 x5)) (* -68 x6)) (* -25 x7)) (* 49 x8)) (* 14 x9)) 78))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 30 x0)) (* 29 x1)) (* 64 x2)) (* 18 x3)) (* 63 x4)) (* -94 x5)) (* 20 x6)) (* -30 x7)) (* 60 x8)) (* -35 x9)) 72))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 97 x0)) (* -90 x1)) (* 74 x2)) (* -51 x3)) (* 70 x4)) (* 41 x5)) (* 31 x6)) (* 99 x7)) (* -34 x8)) (* 36 x9)) 60))
(assert (<= (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -55 x0)) (* 50 x1)) (* -48 x2)) (* -27 x3)) (* -7 x4)) (* 86 x5)) (* -15 x6)) (* 96 x7)) (* -46 x8)) (* 11 x9)) 56))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* 50 x0)) (* -51 x1)) (* -32 x2)) (* -23 x3)) (* -75 x4)) (* 24 x5)) (* 39 x6)) (* -89 x7)) (* 8 x8)) (* 23 x9)) 36))
(assert (distinct (+ (+ (+ (+ (+ (+ (+ (+ (+ (+ 0 (* -50 x0)) (* 98 x1)) (* 62 x2)) (* -39 x3)) (* -90 x4)) (* 19 x5)) (* -10 x6)) (* 32 x7)) (* -51 x8)) (* 52 x9)) 24))
In fact if you remove any clause from this formula the solver is able to answer in less than a second while if you feed it with the entire formula it runs out of time.
Why does this happen? Is it normal that Z3 finds this formula so difficult to solve?
Best,
Andrea
I have such an expression
z3::expr expr = (exists ((flag Bool))
(exists ((w Int))
(exists ((i Int))
(exists ((counter Int))
(and (= i (+ x y z))
flag
(not (= i 0))
(= i counter)
(not (= w counter))
(>= i 1)
(= w 0)))))))
I use C++ API to do quantifier elimination and simplification.
z3::goal g(ctx);
g.add(expr);
z3::apply_result result = (qe & simplify & propagate_ineqs)(g);
I have defined the tactics.
I want to get such result:
(or (>= (+ x y z) 1 )
(<= (+ x y z) -1 ))
but I get this output which is appropriate for my application:
(let ((a!1 (or (<= (+ (* (- 1) x)
(* (- 1) y)
(* (- 1) z))
(- 1))
(<= (+ x y z) (- 1)))))
(and (or (<= (+ x y z) (- 1))
(>= (+ x y z) 1))
a!1
(>= (+ x y z) 1)))
what tactics should I use to make it work as I want?
I solved the issue by setting these options in the context, before defining the goal:
ctx.set(":pp-min-alias-size", 1000000);
ctx.set(":pp-max-depth", 1000000);
it didn't simplify as I wanted, but removed the "let"s and that's better than nothing!