如何改进Z3py中基于二进制搜索的优化

如何改进Z3py中基于二进制搜索的优化,z3,z3py,sat-solvers,Z3,Z3py,Sat Solvers,我试图用Z3py优化基于最小化的集合覆盖问题(SCP41)的一个实例 结果如下: 使用 (1) 我知道Z3支持优化()。很多时候,我在SCP41和其他实例中都达到了最佳状态,但有少数情况下没有达到 (2) 我明白,如果我在没有优化模块的情况下使用z3pyapi,我将不得不执行@leonardodemoura()中描述的典型顺序搜索。它从不给我结果 我的方法 (3) 我尝试通过实现一个二进制搜索来改进顺序搜索方法,类似于它在()中解释@Philippe的方式,当我运行算法时,它会等待,但没有得到任

我试图用Z3py优化基于最小化的集合覆盖问题(SCP41)的一个实例

结果如下:

使用

(1) 我知道Z3支持优化()。很多时候,我在SCP41和其他实例中都达到了最佳状态,但有少数情况下没有达到

(2) 我明白,如果我在没有优化模块的情况下使用z3pyapi,我将不得不执行@leonardodemoura()中描述的典型顺序搜索。它从不给我结果

我的方法

(3) 我尝试通过实现一个二进制搜索来改进顺序搜索方法,类似于它在()中解释@Philippe的方式,当我运行算法时,它会等待,但没有得到任何结果

我知道二进制搜索应该更快,并且在这种情况下有效?我还知道实例SCP41是一个很大的东西,产生了许多限制,它变得非常组合,这是我的完整代码(),这是我的二进制搜索它:

def min(F, Z, M, LB, UB, C):    
    i = 0
    s = Solver()

    s.add(F[0])
    s.add(F[1])
    s.add(F[2])
    s.add(F[3])
    s.add(F[4])
    s.add(F[5])

    r = s.check()

    if r == sat:
        UB = s.model()[Z]

        while int(str(LB)) <= int(str(UB)):

            C = int(( int(str(LB)) + int(str(UB)) / 2))

            s.push()
            s.add( Z > LB, Z <= C)

            r = s.check()

            if r==sat:
                UB = Z
                return s.model()
            elif r==unsat:
                LB = C
                s.pop()

            i = i + 1
            if (i > M):
                raise Z3Exception("maximum not found, maximum number of iterations was reached")
    return unsat
def最小值(F、Z、M、LB、UB、C):
i=0
s=解算器()
s、 添加(F[0])
s、 添加(F[1])
s、 加(F[2])
s、 加(F[3])
s、 加上(F[4])
s、 加(F[5])
r=s.检查()
如果r==sat:
UB=s.model()[Z]
而int(str(LB))LB,zm:
raise Z3Exception(“未找到最大值,已达到最大迭代次数”)
未售出的退货
这是我在初始测试中使用的另一个实例(),它在任何情况下都运行良好

什么是不正确的二进制搜索或Z3的某些概念没有正确应用

问候,,
亚历克斯

我不认为你的问题与最小化本身有关。如果在程序中的
r=s.check()
之后放置一个
print r
,您会看到z3很难返回结果。所以你的循环甚至不会执行一次

因为你的程序太大了,所以不可能通读它!但我看到了很多这样的东西:

 Or(X250 == 0, X500 == 1)
这表明变量
X250
X500
等(有很多)实际上是布尔值,而不是整数。如果这确实是真的,你应该绝对坚持使用布尔语。求解整数约束比求解纯布尔约束要困难得多,当您使用整数来像这样对布尔进行建模时,底层解算器只会探索无法到达的搜索空间

如果确实如此,即如果您使用
Int
值来建模布尔值,我强烈建议您对问题进行建模,以摆脱
Int
值,只使用布尔值。如果您提出问题的“小”实例,我们可以帮助您进行建模


如果您确实需要
Int
值(很可能是这样),那么我会说您的问题对于SMT解算器来说太难了,无法有效处理。您最好使用其他针对此类优化问题进行优化的系统。

我知道,将Ints值更改为Bools值,消除了模型的大部分约束,并使Z3更容易求解,这是相当可观的。为了更好地理解,我在初始问题的末尾添加了一个带有小实例的代码;所以你应该让他们变成布尔人。看起来你有伪布尔约束;i、 例如,“这N个布尔值中最多有K个是真的”;可通过
Pb
约束直接建模。看看这个答案:一旦你完全摆脱了整数,我认为z3将很好地解决这个问题。您甚至可能不需要“二进制搜索”;但这是需要明确检查的。