Closed lahiri-phdworks closed 4 years ago
Actually we would be running z3
on a more advanced cases as shown below.
Can this issue be related to using NRA with quantification and uninterpreted functions?
# -*- coding: utf-8 -*-
from z3 import *
HYPOTENUSE = 150
BOUND_X = 400
BOUND_Y = 400
LT1_x1, LT1_y1 = Reals('LT1_x1 LT1_y1')
LT1_x2, LT1_y2 = Reals('LT1_x2 LT1_y2')
LT1_u, LT1_v, LT1_m = Reals('LT1_u LT1_v LT1_m')
LT1_a1, LT1_b1, LT1_c1 = Reals('LT1_a1 LT1_b1 LT1_c1')
LT1_a2, LT1_b2, LT1_c2 = Reals('LT1_a2 LT1_b2 LT1_c2')
LT1_a3, LT1_b3, LT1_c3 = Reals('LT1_a3 LT1_b3 LT1_c3')
S = SolverFor("NRA")
S.add((LT1_u - LT1_x1) ** 2 + (LT1_v - LT1_y1) ** 2 == (HYPOTENUSE ** 2)/2)
S.add((LT1_u - LT1_x2) ** 2 + (LT1_v - LT1_y2) ** 2 == (HYPOTENUSE ** 2)/2)
S.add((LT1_x2 - LT1_x1) ** 2 + (LT1_y2 - LT1_y1) ** 2 == HYPOTENUSE ** 2)
S.add(LT1_a1 * LT1_a2 + LT1_b1 * LT1_b2 == 0)
S.add(LT1_a3 + LT1_m * LT1_b3 == 0)
S.add(LT1_a1 * LT1_u + LT1_b1 * LT1_v + LT1_c1 == 0)
S.add(LT1_a2 * LT1_u + LT1_b2 * LT1_v + LT1_c2 == 0)
S.add(LT1_u >= 0, LT1_v >= 0)
S.add(LT1_u <= BOUND_X, LT1_v <= BOUND_Y)
S.add(LT1_x1 >= 0, LT1_x2 >= 0)
S.add(LT1_y1 >= 0, LT1_y2 >= 0)
S.add(LT1_b1 != 0)
S.add(LT1_b2 != 0)
S.add(LT1_b3 != 0)
doodle = Function("doodle_function", RealSort(), RealSort(), BoolSort())
covered_by = Function("covers", RealSort(), RealSort(), RealSort())
lt1_area_piece = Function("lt1_area_piece", RealSort(), RealSort(), BoolSort())
x = Int('tx')
y = Int('ty')
S.add(x >= 0, y >= 0, x <= BOUND_X, y <= BOUND_Y)
S.add(ForAll([x, y], lt1_area_piece(x, y) == And(
(LT1_a1 * x + LT1_b1 * y + LT1_c1)/LT1_b1 > 0,
(LT1_a2 * x + LT1_b2 * y + LT1_c2)/LT1_b2 > 0,
(LT1_a3 * x + LT1_b3 * y + LT1_c3)/LT1_b3 < 0
)
))
S.add(ForAll([x, y], Implies(lt1_area_piece(x, y), covered_by(x, y) == 3)))
print(S.check())
print(S.sexpr())
This the trial it is taking on the models
(model-del k!0)
(model-add z () Real (ite k!0 50.0 (+ 50.0 1.0)))
(model-del k!1)
(model-add l () Real (- k!1 (+ (* m x) (* n y))))
(model-del k!2)
(model-add x () Real (ite k!2 0.0 (+ 0.0 (- 1.0))))
(model-del k!3)
(model-add y () Real (ite k!3 30.0 (+ 30.0 (- 1.0))))
(model-del k!4)
(model-add m () Real (ite k!4 5.0 (+ 5.0 (- 1.0))))
(model-del k!5)
(model-add n () Real (ite k!5 5.0 (+ 5.0 (- 1.0))))
(model-del k!6)
(model-add k!1 () Real (ite k!6 300.0 (+ 300.0 1.0)))
(model-del k!7)
(model-add k!6 () Bool (not k!7))
(model-add k!2 () Bool true)
(model-add k!3 () Bool true)
(model-add k!0 () Bool true)
(model-add k!4 () Bool true)
(model-add k!5 () Bool true)
(model-add k!7 () Bool true)
There isn't any model to give you. The trail you see are instructions that lets z3 transform a model found for a simplified formula into a model of the original formula. It doesn't imply that z3 is able to find a model for the formula. You are using quantifiers and division and non-linear functions. This cocktail isn't playing well with the main solvers that handle NRA. Remove the division whenever possible. For example, if LT1_b1 is never 0, you can just use multiplication for the same checks, e.g. X * Y > 0 instead of X / Y > 0, and even better you can spell out the cases:
X / Y > 0 becomes (X > 0 and Y > 0) or (X < 0 and Y < 0)
Thanks for telling me.
Will this statement also cause issues ?
S.add((LT1_u - LT1_x1) ** 2 + (LT1_v - LT1_y1) ** 2 == (HYPOTENUSE ** 2)/2)
.
There are hooks to handle powers and convert them to multiplication for the solvers that only understand multiplication. But it is not comprehensively tested so I had to fix bugs in these scenarios a number of times before based on either fuzz or users.
NRA + functions work well with Z3 actually. It is wonderful. What is failing in my case is the universal quantification over NRA with uninterpreted functions.
Intention :
Z3 solver interface exposes a
check()
function which sometimes returns "unknown" status when invoked on constraints involving quantified expressions. Whenmodel()
function is called on z3.status withunknown
it raisesmodel not available exception
. Want to get a partial model out from z3.Issue :
Using the
sexpr()
function and adding in theset-options
properly, z3 can be used to get a model even for unknown result. I have attached an example below.Can z3's python API be used to retrieve such a model (bypassing the exception) ?
Python Code & SMT LIB Code
below is the stack trace for the run when I call
print(S.model())
afterprint(S.check())
Equivalent SMT File.
I now pass it to z3 on the cmd-line
Partial Model Output :
Any suggestions or code examples regarding the same can be very helpful.