Can I use a SMT program's result in another SMT expression? - z3
I would like to use a model's output (in my case sat and unsat only) in another model. Here, a model is a satisfying assignment to constants involved in a set of logical formulas (Z3 expressions in this case). My objective can be briefly explained as follows.
My problem can be described in detail as follows: I have a formalized a problem P, a set logical formulas (expressions) corresponding to a number of constraints (C). Among the expressions, one (e.g., Ai > 0) is my objective. Executing the model/formalization P returns sat, if all the constraints are satisfiable. Note that, Ai = 0 is always possible.
Now, I want to find the set of assignments to a particular set of variables corresponds to the constraints (C) that ensure that Ai > 0 (for any i) is not possible.
Currently, I am solving the problem by writing a program (in C#) that develop a DFS-based searching algorithm of the constraints (i.e., constraint values) and execute P to see if the result is false with the help of "push/pop". Though I have tried to make the search better, it does not help me a lot. It is very inefficient for a large problem size. It would be great if I could create another SMT program (model) utilizing P for searching such a satisfiable set.
The current formalization of problem P (a short SMT LIB 2 version of the original problem) is as follows:
(declare-fun th1 () Real)
(declare-fun th2 () Real)
(declare-fun th3 () Real)
(declare-fun th4 () Real)
(declare-fun th5 () Real)
(declare-fun l1 () Real)
(declare-fun l2 () Real)
(declare-fun l3 () Real)
(declare-fun l4 () Real)
(declare-fun l5 () Real)
(declare-fun l6 () Real)
(declare-fun l7 () Real)
(declare-fun p1 () Real)
(declare-fun p2 () Real)
(declare-fun p3 () Real)
(declare-fun p4 () Real)
(declare-fun p5 () Real)
(declare-fun sl1 () Int)
(declare-fun sl2 () Int)
(declare-fun sl3 () Int)
(declare-fun sl4 () Int)
(declare-fun sl5 () Int)
(declare-fun sl6 () Int)
(declare-fun sl7 () Int)
(declare-fun sp1 () Int)
(declare-fun sp2 () Int)
(declare-fun sp3 () Int)
(declare-fun sp4 () Int)
(declare-fun sp5 () Int)
(declare-fun a1 () Int)
(declare-fun a2 () Int)
(declare-fun a3 () Int)
(declare-fun a4 () Int)
(declare-fun a5 () Int)
(declare-fun na () Int)
(declare-fun ns () Int)
(declare-fun attack () Bool)
;;;; System
(assert (and (= l1 (* (- th2 th1) 17.0))
(= l2 (* (- th5 th1) 4.5))
(= l3 (* (- th3 th2) 5.05))
(= l4 (* (- th4 th2) 5.65))
(= l5 (* (- th5 th2) 5.75))
(= l6 (* (- th4 th3) 5.85))
(= l7 (* (- th5 th4) 23.75))
(= p1 (+ l1 l2))
(= p2 (+ l1 l3 l4 l5))
(= p3 (+ l3 l6))
(= p4 (+ l4 l6 l7))
(= p5 (+ l2 l5 l7))
)
)
;;;; Secured measurements
(assert (and (or (= sl1 0) (= sl1 1))
(or (= sl2 0) (= sl2 1))
(or (= sl3 0) (= sl3 1))
(or (= sl4 0) (= sl4 1))
(or (= sl5 0) (= sl5 1))
(or (= sl6 0) (= sl6 1))
(or (= sl7 0) (= sl7 1))
(or (= sp1 0) (= sp1 1))
(or (= sp2 0) (= sp2 1))
(or (= sp3 0) (= sp3 1))
(or (= sp4 0) (= sp4 1))
(or (= sp5 0) (= sp5 1))
)
)
(assert (and (=> (not (= l1 0.0)) (= sl1 0))
(=> (not (= l2 0.0)) (= sl2 0))
(=> (not (= l3 0.0)) (= sl3 0))
(=> (not (= l4 0.0)) (= sl4 0))
(=> (not (= l5 0.0)) (= sl5 0))
(=> (not (= l6 0.0)) (= sl6 0))
(=> (not (= l7 0.0)) (= sl7 0))
(=> (not (= p1 0.0)) (= sp1 0))
(=> (not (= p2 0.0)) (= sp2 0))
(=> (not (= p3 0.0)) (= sp3 0))
(=> (not (= p4 0.0)) (= sp4 0))
(=> (not (= p5 0.0)) (= sp5 0))
)
)
(assert (and (= sl1 1) (= sl2 1)))
;;;; Attacks
(assert (and (or (= a1 0) (= a1 1))
(or (= a2 0) (= a2 1))
(or (= a3 0) (= a3 1))
(or (= a4 0) (= a4 1))
(or (= a5 0) (= a5 1))
)
)
(assert (and
(= (not (= th1 0.0)) (= a1 1))
(= (not (= th2 0.0)) (= a2 1))
(= (not (= th3 0.0)) (= a3 1))
(= (not (= th4 0.0)) (= a4 1))
(= (not (= th5 0.0)) (= a5 1))
)
)
(assert (= th1 0.0)) // Base condition
(assert (= na (+ a1 a2 a3 a4 a5)))
(assert (=> attack (> na 1)))
;;;; Check for satisfiable model
(assert attack)
(check-sat)
(get-model)
(exit)
I want synthesize the security measurements (i.e., find the assignments of 'sl' and 'sp' terms) so that there would be no attack (i.e., na will be 0) given the constraints, e.g., as follows:
(assert (= ns (+ sl1 sl2 sl3 sl4 sl5 sl6 sl7 sp1 sp2 sp3 sp4 sp5)))
(assert (<= ns 4))
In this case, the assertion (i.e., '(assert (and (= sl1 1) (= sl2 1)))' ) will be commented. Currently, I have developed a C# program that take an assignment of 'sl' and 'sp', assert them like (assert (and (= sl1 1) (= sl2 1) ...))', and execute the given program to see if there is any attack possible. I am done when the program returns unsat (i.e., na > 1 is not possible). Is there any way to solve the problem using SMT (Z3) only?
Thanks for clearing up the question. If I've understood things, you can perform the search for sli and spj values using Z3, but you cannot do this using SMT-LIB only, you need to use an API. The idea is to use the models (satisfying assignments) from one sat check as constraints in future checks, as explained in detail in these answers:
Z3: finding all satisfying models
Z3: Check if model is unique
(Z3Py) checking all solutions for equation
Here's your example encoded in the Python API (z3py link: http://rise4fun.com/Z3Py/KHzm):
s = Solver()
th1, th2, th3, th4, th5 = Reals('th1 th2 th3 th4 th5')
th = { 'th1' : th1, 'th2' : th2, 'th3' : th3, 'th4' : th4, 'th5' : th5}
l1, l2, l3, l4, l5, l6, l7 = Reals('l1 l2 l3 l4 l5 l6 l7')
l = { 'l1' : l1, 'l2' : l2, 'l3' : l3, 'l4' : l4, 'l5' : l5, 'l6' : l6, 'l7' : l7 }
p1, p2, p3, p4, p5 = Reals('p1 p2 p3 p4 p5')
p = { 'p1' : p1, 'p2' : p2, 'p3' : p3, 'p4' : p4, 'p5' : p5 }
sl1, sl2, sl3, sl4, sl5, sl6, sl7 = Ints('sl1 sl2 sl3 sl4 sl5 sl6 sl7')
sl = { 'sl1' : sl1, 'sl2' : sl2, 'sl3' : sl3, 'sl4' : sl4, 'sl5' : sl5, 'sl6' : sl6, 'sl7' : sl7 }
sp1, sp2, sp3, sp4, sp5 = Ints('sp1 sp2 sp3 sp4 sp5')
sp = { 'sp1' : sp1, 'sp2' : sp2, 'sp3' : sp3, 'sp4' : sp4, 'sp5' : sp5 }
a1, a2, a3, a4, a5 = Ints('a1 a2 a3 a4 a5')
a = { 'a1' : a1, 'a2' : a2, 'a3' : a3, 'a4' : a4, 'a5' : a5 }
na, ns = Ints('na ns')
attack = Bool('attack')
n = { 'na' : na, 'ns' : ns, 'attack' : attack}
dict_decl = dict(th.items() + l.items() + p.items() + sl.items() + sp.items() + a.items() + n.items() )
assertions = []
assertions.append(parse_smt2_string('(assert (and (= l1 (* (- th2 th1) 17.0)) (= l2 (* (- th5 th1) 4.5)) (= l3 (* (- th3 th2) 5.05)) (= l4 (* (- th4 th2) 5.65)) (= l5 (* (- th5 th2) 5.75)) (= l6 (* (- th4 th3) 5.85)) (= l7 (* (- th5 th4) 23.75)) (= p1 (+ l1 l2)) (= p2 (+ l1 l3 l4 l5)) (= p3 (+ l3 l6)) (= p4 (+ l4 l6 l7)) (= p5 (+ l2 l5 l7))))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (and (or (= sl1 0) (= sl1 1)) (or (= sl2 0) (= sl2 1)) (or (= sl3 0) (= sl3 1)) (or (= sl4 0) (= sl4 1)) (or (= sl5 0) (= sl5 1)) (or (= sl6 0) (= sl6 1)) (or (= sl7 0) (= sl7 1)) (or (= sp1 0) (= sp1 1)) (or (= sp2 0) (= sp2 1)) (or (= sp3 0) (= sp3 1)) (or (= sp4 0) (= sp4 1)) (or (= sp5 0) (= sp5 1)) ))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (and (=> (not (= l1 0.0)) (= sl1 0)) (=> (not (= l2 0.0)) (= sl2 0)) (=> (not (= l3 0.0)) (= sl3 0)) (=> (not (= l4 0.0)) (= sl4 0)) (=> (not (= l5 0.0)) (= sl5 0)) (=> (not (= l6 0.0)) (= sl6 0)) (=> (not (= l7 0.0)) (= sl7 0)) (=> (not (= p1 0.0)) (= sp1 0)) (=> (not (= p2 0.0)) (= sp2 0)) (=> (not (= p3 0.0)) (= sp3 0)) (=> (not (= p4 0.0)) (= sp4 0)) (=> (not (= p5 0.0)) (= sp5 0)) ))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (and (= sl1 1) (= sl2 1)))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (and (or (= a1 0) (= a1 1))(or (= a2 0) (= a2 1))(or (= a3 0) (= a3 1))(or (= a4 0) (= a4 1))(or (= a5 0) (= a5 1)) ))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (and (= (not (= th1 0.0)) (= a1 1))(= (not (= th2 0.0)) (= a2 1))(= (not (= th3 0.0)) (= a3 1))(= (not (= th4 0.0)) (= a4 1))(= (not (= th5 0.0)) (= a5 1)) ))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (= ns (+ sl1 sl2 sl3 sl4 sl5 sl6 sl7 sp1 sp2 sp3 sp4 sp5)))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (<= ns 4))', decls=dict_decl))
#assertions.append(parse_smt2_string('(assert (and (= sl1 1) (= sl2 1)))', decls=dict_decl)) # commented as suggested
assertions.append(parse_smt2_string('(assert (= th1 0.0))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (= na (+ a1 a2 a3 a4 a5)))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert (=> attack (> na 1)))', decls=dict_decl))
assertions.append(parse_smt2_string('(assert attack)', decls=dict_decl))
print assertions
s.add(assertions)
synthesized = []
iters = 0
while s.check() == sat:
print "Iteration " + str(iters)
print s.model()
avoid = []
# key step: add constraint to prevent any values assigned (if possible) to constants from being equal to their satisfying assignments (models) in this sat iteration
for sli in sl.values():
avoid.append(sli != s.model()[sli])
for spi in sp.values():
avoid.append(spi != s.model()[spi])
s.add(Or(avoid))
# end key step
synthesized.append(avoid)
print avoid
iters = iters + 1
# unless you know how to guarantee termination (e.g., there is a constraint ensuring the slis and spis take values in finite sets)
if iters >= 1000:
break
print "Done"
print synthesized # all the constraints
Apologies for all the constants and numbers, I just used the quickest translation of your SMT-LIB script, but it ended up being rather cumbersome, I would use iterators everywhere. This generated the following constraints over the sli and spj constants:
[[sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 1, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 1, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 1, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 1, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 1, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 1, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 1, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 1, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 1, sp2 ≠ 0, sp3 ≠ 1, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 1, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 1, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 1, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 1, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 1, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 1, sl6 ≠ 1, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 1, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 1, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 1, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 0, sp3 ≠ 0, sp4 ≠ 1, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 0, sp2 ≠ 1, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0], [sl4 ≠ 0, sl5 ≠ 0, sl6 ≠ 0, sl7 ≠ 0, sl1 ≠ 1, sl2 ≠ 1, sl3 ≠ 0, sp1 ≠ 1, sp2 ≠ 1, sp3 ≠ 0, sp4 ≠ 0, sp5 ≠ 0]]
If I understand this correctly, then you are precisely looking for (universal) quantification. Excuse my pseudo-notation, but are you not looking for a satisfying assignment to the free variables (config_params) in the following?
config_constraints(config_params) -> forall attack_params: not attack_constraints(attack_params, config_params)
where the () notation merely indicates which variable (sets) the constraints depend upon. I'm pretty sure that quantifiers are supported in the .Net API, as they are in the Java API.
Related
solving equation and quantifier elimination
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) )
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))))
Z3 Fixedpoints: What is the meaning of formula false in model?
I'm trying to check a simple Timed Automata for reachability using Z3's fixed-point engine. The TA I'm modeling is: -->(x = 0 & 0 <= c <= 5) --[c > 2]-->(x = 1) I want to verify that the state x = 1 & c = 3 is reachable. To do that I input the following into Z3: (declare-rel T (Int Real Int Real)) (declare-rel REACH (Int Real)) (declare-var x Int) (declare-var c Real) (declare-var nx Int) (declare-var nc Real) (declare-var delay Real) (rule (! (=> (and (= x 0) (> c 2.0)) (T x c 1 c)) :named stepint)) (rule (! (=> (and (REACH x c) (T x c nx nc)) (REACH nx nc)) :named tstep)) (rule (! (=> (and (= c 0.0) (= x 0)) (REACH x c)) :named initialstates)) (rule (! (let ((a!1 (and (>= delay 0.0) (= nc (+ c delay)) (or (not (= x 0)) (< nc 5.0))))) (=> a!1 (T x c x nc))) :named TICK)) (query (and (REACH x c) (= x 1) (= c 3.0)) :print-certificate true) When I run the above in Z3 on rise4fun I get back: formula false in model: (= REACH_1_0 3.0) formula false in model: (= REACH_0_0 1) formula false in model: (= query!0_0_n 1) formula false in model: (= query!0_1_n 3.0) sat (REACH 1 3.0) Which indicates that x= 1 & c = 3 is reachable. What does "formula false in model mean"? Is this simply informational or is Z3 warning me about potentially poorly formed input?
The bugs appear fixed in the "opt" branch. I have not ported the fixes to the unstable branch yet. It will happen, but if impatient, use the "opt" branch. Sorry.
z3 times out in case of a formula with quantifiers
I am getting timeout on the following example. http://rise4fun.com/Z3/zbOcW Is there any trick to make this work (eg.by reformulating the problem or using triggers)?
For this example, the macro finder will be useful (I think often with forall quantifiers with implications), you can enable it with: (set-option :macro-finder true) Here's your updated example that gets sat quickly (rise4fun link: http://rise4fun.com/Z3/Ux7gN ): (set-option :macro-finder true) (declare-const a (Array Int Bool)) (declare-const sz Int) (declare-const n Int) (declare-const d Int) (declare-const r Bool) (declare-const x Int) (declare-const y Int) ;;ttff (declare-fun ttff (Int Int Int) Bool) (assert (forall ((x1 Int) (y1 Int) (n1 Int)) (= (ttff x1 y1 n1) (and (forall ((i Int)) (=> (and (<= x1 i) (< i y1)) (= (select a i) true))) (forall ((i Int)) (=> (and (<= y1 i) (< i n1)) (= (select a i) false))))))) ;; A1 (assert (and (<= 0 n) (<= n sz))) ;; A2 (assert (< 0 d)) ;; A3 (assert (and (and (<= 0 x) (<= x y)) (<= y n))) ;; A4 (assert (ttff x y n)) ;; A6 (assert (=> (< 0 y) (= (select a (- y 1)) true))) ;; A7 (assert (=> (< 0 x) (= (select a (- x 1)) false))) ;;G (assert (not (iff (and (<= (* 2 d) (+ n 1)) (ttff (- (+ n 1) (* 2 d)) (- (+ n 1) d) (+ n 1))) (and (= (- (+ n 1) y) d) (<= d (- y x)))))) (check-sat) (get-model)
How can I write a long smt-lib expression with an existential quantifier?
I have the following expression (declare-fun x00 () Real) (declare-fun x01 () Real) (declare-fun x10 () Real) (declare-fun x11 () Real) (declare-fun t0init () Real) (declare-fun z0init0 () Real) (declare-fun z0init1 () Real) (assert (>= t0init 0)) (assert (= (+ x00 z0init0) x10)) (assert (= (+ x01 z0init1) x11)) (assert (< (+ (* 1 x00)(* 0 x01)) 0.0)) (assert (= (+ (* 0 x00)(* 1 x01)) 0.0)) (assert (< (+ (* 1 x10)(* 0 x11)) 0.0)) (assert (= (+ (* 0 x10)(* 1 x11)) 0.0)) ... (assert (< (+ (* 1 x40)(* 0 x41)) 0.0)) (assert (= (+ (* 0 x40)(* 1 x41)) 0.0)) (assert (= (+ (* 1 z4end0)(* 0 z4end1)) (* t4end 1))) (assert (= (+ (* 0 z4end0)(* 1 z4end1)) (* t4end -2))) and I would like to express as a simple formula in order to express the following: (assert exists (x00 x01) ("the above expression")) and then perform a quantifier elimination. Is there anyone who knows how to proceed? I know how to do it with z3py but I need some faster solution. Thank you very much for any hint.
One possible solution is as follows (declare-fun x00 () Real) (declare-fun x01 () Real) (declare-fun x10 () Real) (declare-fun x11 () Real) (declare-fun t0init () Real) (declare-fun z0init0 () Real) (declare-fun z0init1 () Real) (define-fun conjecture () Bool (and (>= t0init 0) (= (+ x00 z0init0) x10) (= (+ x01 z0init1) x11))) (assert (exists ((x00 Real) (x01 Real)) conjecture)) (check-sat) and the corresponding output is sat I am not sure if the quantifier elimination that you need will work with Z3. Maybe for your problem "Redlog" of "Reduce" is the better option. All the best.