Minimum and maximum values of integer variable

2019-02-13 04:55发布

Let's assume a very simple constraint: solve(x > 0 && x < 5).

Can Z3 (or any other SMT solver, or any other automatic technique) compute the minimum and maximum values of (integer) variable x that satisfies the given constraints?

In our case, the minimum is 1 and the maximum is 4.

标签: z3
2条回答
我欲成王,谁敢阻挡
2楼-- · 2019-02-13 05:33

Z3 has not support for optimizing (maximizing/minimizing) objective functions or variables. We plan to add this kind of capability, but it will not happen this year. In the current version, we can "optimize" an objective function by solving several problems where in each iteration we add additional constraints. We know we found the optimal when the problem becomes unsatisfiable. Here is a small Python script that illustrates the idea. The script maximizes the value of a variable X. For minimization, we just have to replace s.add(X > last_model[X]) with s.add(X < last_model[X]). This script is very naive, it performs a "linear search". It can be improved in many ways, but it demonstrates the basic idea.

You can also try the script online at: http://rise4fun.com/Z3Py/KI1

See the following related question: Determine upper/lower bound for variables in an arbitrary propositional formula

from z3 import *

# Given formula F, find the model the maximizes the value of X 
# using at-most M iterations.
def max(F, X, M):
    s = Solver()
    s.add(F)
    last_model  = None
    i = 0
    while True:
        r = s.check()
        if r == unsat:
            if last_model != None:
                return last_model
            else:
                return unsat
        if r == unknown:
            raise Z3Exception("failed")
        last_model = s.model()
        s.add(X > last_model[X])
        i = i + 1
        if (i > M):
            raise Z3Exception("maximum not found, maximum number of iterations was reached")

x, y = Ints('x y')
F = [x > 0, x < 10, x == 2*y]
print max(F, x, 10000)
查看更多
淡お忘
3楼-- · 2019-02-13 05:56

As Leonardo pointed out, this was discussed in detail before: Determine upper/lower bound for variables in an arbitrary propositional formula. Also see: How to optimize a piece of code in Z3? (PI_NON_NESTED_ARITH_WEIGHT related).

To summarize, one can either use a quantified formula, or go iteratively. Unfortunately, these techniques are not equivalent:

  • Quantified approach needs no iteration, and can find global min/max in a single call to the solver; at least in theory. However, it does give rise to harder formulas. So, the backend solver can time-out, or simply return "unknown".

  • Iterative approach creates simple formulas for the backend solver to deal with, but it can loop forever if there's no optimal value; simplest example being trying to find the largest Int value. Quantified version can solve this problem nicely by quickly telling you that there is no such value, while the iterative version would go on indefinitely. This can be a problem if you don't know ahead of time that your constraints do have an optimal solution. (Needless to say, the "sufficient" iteration count is typically hard to guess, and might depend on random factors, like the seed used by the solver.)

Also keep in mind that if there is a custom optimization algorithm for the problem domain at hand, it's unlikely that a general purpose SMT solver can outperform it.

查看更多
登录 后发表回答