整数变量的最小值和最大值

时间:2012-08-13 12:46:57

标签: z3

让我们假设一个非常简单的约束:solve(x > 0 && x < 5)

可以Z3(或任何其他SMT求解器,或任何其他自动技术) 计算满足给定约束条件的(整数)变量x的最小值和最大值?

在我们的例子中,最小值为1,最大值为4。

3 个答案:

答案 0 :(得分:9)

Z3不支持优化(最大化/最小化)目标函数或变量。 我们计划增加这种能力,但今年不会发生这种情况。 在当前版本中,我们可以通过解决几个问题来“优化”目标函数,其中在每次迭代中我们添加额外的约束。我们知道,当问题变得不可满足时,我们找到了最佳方案。这是一个小的Python脚本,说明了这个想法。该脚本最大化变量X的值。为了最小化,我们只需将s.add(X > last_model[X])替换为s.add(X < last_model[X])。这个脚本非常天真,它执行“线性搜索”。它可以在很多方面得到改进,但它展示了基本的想法。

您也可以在以下网址尝试使用该脚本:http://rise4fun.com/Z3Py/KI1

请参阅以下相关问题: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)

答案 1 :(得分:6)

正如莱昂纳多指出的那样,在此之前对此进行了详细讨论:Determine upper/lower bound for variables in an arbitrary propositional formula。另请参阅:How to optimize a piece of code in Z3? (PI_NON_NESTED_ARITH_WEIGHT related)

总而言之,可以使用量化公式,也可以反复进行。不幸的是,这些技术不等同于

  • 量化方法不需要迭代,并且可以在对求解器的单次调用中找到全局最小值/最大值;至少在理论上。然而,它确实会产生更难的公式。因此,后端解算器可能会超时,或者只是返回“未知”。

  • 迭代方法为后端解算器创建简单的公式来处理,但如果没有最优值,它可以永远循环;最简单的例子是尝试找到最大的Int值。量化版本可以通过快速告诉您没有这样的值来很好地解决这个问题,而迭代版本将无限期地继续。如果您事先不知道约束确实有最佳解决方案,则可能会出现问题。 (不用说,“足够的”迭代计数通常难以猜测,并且可能取决于随机因素,例如解算器使用的种子。)

另外请记住,如果手头有问题域的自定义优化算法,通用SMT求解器不太可能胜过它。

答案 2 :(得分:0)

z3 现在支持优化。

from z3 import *

o = Optimize()
x = Int( 'x' )
o.add(And(x > 0, x < 5))
o.maximize(x)
print(o.check())  # prints sat
print(o.model())  # prints [x = 4]

这个特殊问题是一个 integer program