浮点SMT逻辑是否比实际逻辑慢?

时间:2019-02-03 12:27:32

标签: haskell z3 smt sbv

我在Haskell中编写了一个应用程序,该应用程序调用Z3求解器来解决一些复杂公式的约束。感谢Haskell,我可以快速切换正在使用的数据类型。

在使用SBV的AlgReal类型进行计算时,我会在合理的时间内得到结果,但是切换到FloatDouble类型会使Z3消耗大约2Gb的RAM,甚至不会在30分钟内。

这是否意味着生产浮点解决方案需要更多时间,还是我这边有些错误?

1 个答案:

答案 0 :(得分:12)

与求解器性能有关的任何问题一样,不可能一概而论。 Christoph Wintersteiger(https://stackoverflow.com/users/869966/christoph-wintersteiger)将会是对此提出意见的专家,但是我不确定他对这个小组的关注程度如何。克里斯:如果您正在阅读本文,我很想听听您的想法!

这里还有比较苹果与橙色的风险:实数和浮点数是两种完全不同的逻辑,具有不同的决策程序,启发式算法和算法等。我敢肯定,您会发现一个问题优于另一个问题,没有明确的“表现”获胜者。

说了这么多,以下是使浮点(FP)变得棘手的一些事情:

  • 使用FP几乎不可能重写,因为像关联性这样的规则很简单 请勿用于FP加法/乘法。因此, 简化喷砂作业。

  • 类似地,a * 1/a == 1不适用于浮点数。 x + 1 /= x(x + a == x) -> (a == 0)以及您希望进行的许多其他“显而易见的”简化都没有。所有这些使推理变得复杂。

  • NaN值的存在使相等成为非自反的:没有任何事物与NaN相等,包括它本身。因此,用等值替换也有问题,并且需要附带条件。

  • 同样,+0-0的存在比较相等,但由于四舍五入而使行为复杂化。典型的示例是x == 0 -> fma(a, b, x) == a * b不成立(其中fma被融合为乘加运算),因为这两个表达式根据零的符号可以为不同的舍入模式产生不同的值。

  • 浮点数与整数和实数的组合引入了非线性,这对于求解器而言始终是一个软点。因此,如果您使用的是FP,建议不要将其与其他理论混合使用,因为组合本身会增加额外的复杂性。

  • 乘法,除法和余数(是的,有一个浮点余数运算!)之类的操作本质上非常复杂,并导致产生非常大的SAT公式。特别是,乘法是一种已知的操作,由于缺乏良好的变量排序和分解启发式方法,因此对大多数SAT / BDD引擎都构成了挑战。相当快地解决最终的位爆裂,从而产生极大的状态空间。我观察到,即使输入是完全具体的,求解器也很难处理FP除法和余数运算,请想象当它们完全是符号时会发生什么!

  • 实数的逻辑具有双指数复杂度的决策程序。但是,诸如Fourier-Motzkin消除(https://en.wikipedia.org/wiki/Fourier%E2%80%93Motzkin_elimination)之类的技术虽然保持指数级,但在实践中却表现出色。

  • FP求解器相对较新,这是一个新兴的研究领域。因此,现有的求解器趋向于非常保守,并且会快速爆炸,并将问题简化为位向量逻辑。我希望它们会随着时间的推移而改进,就像其他所有理论一样。

同样,我想强调的是,在这两种不同的逻辑上比较求解器性能是错误的,因为它们是完全不同的野兽。但希望以上几点说明了为什么在实践中浮点运算很棘手。

关于SMT求解器中IEEE754浮点数的处理的一本好论文是:http://smtlib.cs.uiowa.edu/papers/BTRW14.pdf。您可以看到它支持的无数操作,并可以了解其复杂性。