Z3 求解器在公式可满足时返回 unsat
Z3 solver returning unsat when formula should be satisfiable
我得到了 Z3 求解器(python 接口)似乎无法处理的 'simple' 公式。它是 运行 相当长的一段时间(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))))))))))]
它可能看起来有点吓人,但让我带您一探究竟。
都是整型变量。我首先指定他们
应该是 0 或 1 然后我引入约束
其中一个应该是 1 而其他的
需要为 0(使用总和)。
在第二部分中,您可以忽略所有 Or,这基本上只是将我对每个变量的搜索 space 限制为 [-1000, 1000]。然后我有最内在的约束,这应该意味着:< uc 0.2> = 1 < uc 1.0> = 1 < uc 2.1> = 1 和所有其他 = 0。就是这样。我很确定求解器
应该能够解决这个问题,但没有运气。我可以改变总和
对类似 Or(< uc 1.0>,< uc 1.1>,< uc 1.2>) 的约束,这很有趣
足够了,在这种情况下解决了我的问题(求解器
returns 以秒为单位的正确分配)但总的来说,这是
显然,不等于我想要的。
问题:
- 有没有类似的东西,我可以用它来代替整数?
- 一些推荐的方式来表达恰好一个参数是 1 的事实?
- 无需 更改公式的第二部分即可解决此问题的其他方法。
非常感谢!
// 编辑:在尝试了几个选项后,我 'solved' 通过将辅助条件放在 ForAll 条件之后(只需交换两行代码)。这根本不应该有什么不同,但现在他在 0.5 秒内找到了正确的分配 - 什么?我还尝试了使用 4 个变量 (a、b、c、d) 而不是 (a、b、c) 的示例,但它又运行了几个小时……有什么帮助吗?同样用长度 And/Or 更改总和也不起作用。
我使用布尔值而不是 0-1 变量的整数尝试了您的示例。但是,这并没有太大帮助。按照目前的情况,可以改进量词实例化机制以处理此类实例。
所以我无法在不重构整个方法的情况下摆脱乘法,所以我所做的是将所有条件(uc=1 或 uc=1 和 sum = 1)的块移动到 forAll 块下方.这在大多数情况下都有效,但仍有一些测试会 运行 几个小时而没有结果。最终为我做的是将 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...
这终于解决了问题,求解器现在能够处理所有测试用例。我有点失望,因为我花了那么多尝试和错误才把它弄好,但至少我现在可以解决我的公式了。
谢谢!
我得到了 Z3 求解器(python 接口)似乎无法处理的 'simple' 公式。它是 运行 相当长的一段时间(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))))))))))]
它可能看起来有点吓人,但让我带您一探究竟。
在第二部分中,您可以忽略所有 Or,这基本上只是将我对每个变量的搜索 space 限制为 [-1000, 1000]。然后我有最内在的约束,这应该意味着:< uc 0.2> = 1 < uc 1.0> = 1 < uc 2.1> = 1 和所有其他 = 0。就是这样。我很确定求解器 应该能够解决这个问题,但没有运气。我可以改变总和 对类似 Or(< uc 1.0>,< uc 1.1>,< uc 1.2>) 的约束,这很有趣 足够了,在这种情况下解决了我的问题(求解器 returns 以秒为单位的正确分配)但总的来说,这是 显然,不等于我想要的。
问题:
- 有没有类似的东西,我可以用它来代替整数?
- 一些推荐的方式来表达恰好一个参数是 1 的事实?
- 无需 更改公式的第二部分即可解决此问题的其他方法。
非常感谢!
// 编辑:在尝试了几个选项后,我 'solved' 通过将辅助条件放在 ForAll 条件之后(只需交换两行代码)。这根本不应该有什么不同,但现在他在 0.5 秒内找到了正确的分配 - 什么?我还尝试了使用 4 个变量 (a、b、c、d) 而不是 (a、b、c) 的示例,但它又运行了几个小时……有什么帮助吗?同样用长度 And/Or 更改总和也不起作用。
我使用布尔值而不是 0-1 变量的整数尝试了您的示例。但是,这并没有太大帮助。按照目前的情况,可以改进量词实例化机制以处理此类实例。
所以我无法在不重构整个方法的情况下摆脱乘法,所以我所做的是将所有条件(uc=1 或 uc=1 和 sum = 1)的块移动到 forAll 块下方.这在大多数情况下都有效,但仍有一些测试会 运行 几个小时而没有结果。最终为我做的是将 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...
这终于解决了问题,求解器现在能够处理所有测试用例。我有点失望,因为我花了那么多尝试和错误才把它弄好,但至少我现在可以解决我的公式了。 谢谢!