当公式应该令人满意时,Z3求解器返回不饱和

时间:2015-05-15 15:46:28

标签: python z3 z3py sat-solvers

我得到了一个'简单'的公式,Z3求解器(python接口)似乎无法处理。虽然我可以在一分钟内手工找到令人满意的作业,但它已经运行了相当长的一段时间(30分钟),然后又回来了。这是公式:

[Or(<uc 1.0> == 0, <uc 1.0> == 1),
 Or(<uc 1.1> == 0, <uc 1.1> == 1),
 Or(<uc 1.2> == 0, <uc 1.2> == 1),
 <uc 1.0> + <uc 1.1> + <uc 1.2> == 1,
 Or(<uc 0.0> == 0, <uc 0.0> == 1),
 Or(<uc 0.1> == 0, <uc 0.1> == 1),
 Or(<uc 0.2> == 0, <uc 0.2> == 1),
 <uc 0.0> + <uc 0.1> + <uc 0.2> == 1,
 Or(<uc 2.0> == 0, <uc 2.0> == 1),
 Or(<uc 2.1> == 0, <uc 2.1> == 1),
 Or(<uc 2.2> == 0, <uc 2.2> == 1),
 <uc 2.0> + <uc 2.1> + <uc 2.2> == 1,
 ForAll(c,
        Or(c > 1000,
           Or(c < -1000,
              ForAll(b,
                     Or(b > 1000,
                        Or(b < -1000,
                           ForAll(a,
                                  Or(a > 1000,
                                     Or(a < -1000,
                                        And(And(And(True,
                                        a ==
                                        <uc 0.0>*b +
                                        <uc 0.1>*c +
                                        <uc 0.2>*a),
                                        b ==
                                        <uc 1.0>*b +
                                        <uc 1.1>*c +
                                        <uc 1.2>*a),
                                        c ==
                                        <uc 2.0>*b +
                                        <uc 2.1>*c +
                                        <uc 2.2>*a))))))))))]

看起来有点可怕,但让我引导你完成它。 &LT; uc i.j&gt;都是整数变量。我先说明一下 应该是0或1然后我引入约束 其中只有一个应该是1和其他人 需要为0(使用总和)。

在第二部分中,您可以忽略所有或者基本上将每个变量的搜索空间限制为[-1000,1000]。然后,我有最内在的约束,这应该意味着:&lt; uc 0.2&gt; = 1&lt; uc 1.0&gt; = 1&lt; uc 2.1&gt; = 1,所有其他= 0.这就是全部。我很确定解算器 应该能够解决这个问题,但没有运气。我可以改变总和 限制为类似Or(&lt; uc 1.0&gt;,&lt; uc 1.1&gt;,&lt; uc 1.2&gt;)的那些,搞笑 足够,在这种情况下解决我的问题(解算器 以秒为单位返回正确的赋值)但一般来说,这是 显然,不等于我想要的东西。

问题:

  • 是否有类似的东西,我可以使用而不是整数?
  • 一些推荐的方式来表达恰好一个参数是1的事实?
  • 使这个可解决的没有更改公式的第二部分的其他方法。

非常感谢!

//编辑:在玩了几个选项之后,我通过在ForAll条件之后放置边条件(只是交换两行代码)来“解决”它。这根本不应该有所作为,但现在他在0.5秒内找到了正确的任务 - 什么?我也用4个变量(a,b,c,d)代替(a,b,c)尝试了这个例子但是它再次运行了几个小时...任何帮助?同时用长度和/或不起作用来处理总和。

2 个答案:

答案 0 :(得分:1)

我尝试使用布尔值而不是0-1变量的整数。但是,这并没有太大帮助。按照目前的情况,可以改进量化实例化机制来处理这些实例。

答案 1 :(得分:1)

所以我无法在没有重构整个方法的情况下摆脱乘法,所以我所做的就是在forAll块下面移动具有所有条件(uc = 1或uc = 1和sum = 1)的块。这在大多数情况下都有效,但仍有一些测试可能会持续数小时而没有结果。最后我做的是将forAll语句组合在一起而不是将它们分开。所以而不是:

ForAll(c,
        Or(c > 1000,
           Or(c < -1000,
              ForAll(b,
                     Or(b > 1000,
                        Or(b < -1000...

我会得到类似的东西

ForAll(c,
   ForAll(b,
        Or(c > 1000,
           Or(c < -1000,
              Or(b > 1000,
                 Or(b < -1000...

这最终解决了问题,解算器现在能够处理所有测试用例。我有点失望,它花了这么多的尝试和错误来纠正它,但至少我现在可以解决我的公式。 谢谢!