Python - 优化不平等系统

时间:2016-06-03 08:43:22

标签: python z3 solver z3py

我正在研究Python中的一个程序,其中一小部分涉及优化方程/不等式系统。理想情况下,我本来想做的就像在Modelica中一样,写出方程并让解算器处理它。

解算器和线性编程的操作有点超出我的舒适范围,但我决定尝试。问题是程序的一般设计是面向对象的,组合方程有很多不同的可能性,以及一些非线性,所以我无法将其转化为线性规划问题(但我可能错了)。

经过一番研究后,我发现Z3求解器似乎做了我想做的事。我想出了这个(这看起来像我想要优化的典型情况):

from z3 import *

a = Real('a')
b = Real('b')
c = Real('c')
d = Real('d')
e = Real('e')
g = Real('g')
f = Real('f')
cost = Real('cost')

opt = Optimize()
opt.add(a + b - 350 == 0)
opt.add(a - g == 0)
opt.add(c - 400 == 0)
opt.add(b - d * 0.45 == 0)
opt.add(c - f - e - d == 0)
opt.add(d <= 250)
opt.add(e <= 250)

opt.add(cost == If(f > 0, f * 50, f * 0.4) + e * 40 + d * 20 + 
  If(g > 0, g * 50, g * 0.54))

h = opt.minimize(cost)
opt.check()
opt.lower(h)
opt.model()

现在这个工作,并给我我想要的结果,尽管它不是非常快(我需要解决这样的系统数千次)。 但我不确定我是否正在使用正确的工具(Z3是一个“定理证明者”)。

API基本上就是我所需要的,但我很好奇其他包是否允许类似的语法。或者我应该尝试以不同的方式制定问题以允许标准LP方法? (虽然我不知道怎么做)

2 个答案:

答案 0 :(得分:1)

Z3是我为这种灵活的方程组找到的最强大的求解器。 Z3是MIT许可证下发布的绝佳选择。

有许多不同类型的工具具有重叠的用例。你提到了线性编程 - 还有定理证明,SMT求解器和许多其他类型的工具。尽管营销本身是一个定理证明者,但Z3通常作为SMT求解器销售。目前,SMT求解器在耦合代数方程的灵活和自动化解决方案方面处于领先地位,并且在布尔,实数和整数方面具有不等式,而在SMT求解器领域,Z3是王者。看一下the results of the last SMT comp if you want evidence of this.如果说你的方程式是线性的,那么你可能也会发现CVC4的性能更好。到处购物并不会有什么坏处。

如果你的方程具有非常受控的形式(例如,最小化某些约束条件下的某些函数),那么使用GSL或NAG等数值库可能会获得更好的性能。但是,如果你真的需要灵活性,那么我怀疑你会找到比Z3更好的工具。

答案 1 :(得分:1)

最好的解决方案可能是使用ILP求解器。您的问题可以表示为整数线性编程(ILP)实例。有许多ILP求解器,有些可能比Z3表现更好。对于只有7个变量,任何体面的ILP求解器都应该非常快速地找到解决方案。

唯一棘手的是条件表达式(If(...))。但是,作为@Erwin Kalvelagen suggests,可以使用变量拆分来处理条件。例如,引入变量fplusfminus,其中包含约束f = fplus - fminusfplus >= 0以及fminus >= 0。现在,您可以将If(f > 0, f * 50, f * 0.4)替换为50 * fplus - 0.4 * fminus。在这种情况下,这将是等效的。

变量分裂并不总是有效。您必须考虑是否可能引入虚假解决方案(fplus > 0fminus > 0)。但在这种情况下,虚假解决方案永远不会是最优的 - 可以证明最优解决方案永远不会是最优的。因此,变量分割在这里工作正常。

如果您确实有条件语句,但变量拆分不起作用,您通常可以使用https://cs.stackexchange.com/q/12102/755处的技术将问题表述为ILP的实例。