我是用一个小的多目标整数规划问题,玩的解释:Z3和浮点系数
在Z3(使用Python绑定),我们可以很优雅地说明这一点:
from z3 import *
x1,x2 = Ints('x1 x2')
z1,z2 = Reals('z1 z2')
opt = Optimize()
opt.set(priority='pareto')
opt.add(x1 >= 0, x2 >=0, x1 <= 2, x2 <= 2)
opt.add(x1 <= 2*x2)
# this version is ok:
# opt.add(z1 == x1 - 2*x2, z2 == -x1 + 3*x2)
# this truncates coefficients (round down to integer):
# opt.add(z1 == 0.5*x1 - 1.0*x2, z2 == -0.5*x1 + 1.5*x2)
# this one seems to work:
# opt.add(z1 == 0.5*ToReal(x1) - 1.0*ToReal(x2), z2 == -0.5*ToReal(x1) + 1.5*ToReal(x2))
opt.add(z1 == x1 - 2*x2, z2 == -x1 + 3*x2)
f1 = opt.maximize(z1)
f2 = opt.maximize(z2)
while opt.check() == sat:
print(opt.model())
这种正确解决,并给出:
[x1 = 2, x2 = 1, z2 = 1, z1 = 0]
[x1 = 0, x2 = 2, z2 = 6, z1 = -4]
[x1 = 2, x2 = 2, z2 = 4, z1 = -2]
[x1 = 1, x2 = 1, z2 = 2, z1 = -1]
[x1 = 1, x2 = 2, z2 = 5, z1 = -3]
正如我真正的问题浮点系数为工作目标,我除以2的目标:
opt.add(z1 == 0.5*x1 - 1.0*x2, z2 == -0.5*x1 + 1.5*x2)
这种模式应该给出变量x五个相同的解决方案。然而,当我们运行它,我们看到了一些错误的结果:
[x1 = 0, x2 = 0, z2 = 0, z1 = 0]
[x1 = 0, x2 = 2, z2 = 2, z1 = -2]
[x1 = 0, x2 = 1, z2 = 1, z1 = -1]
当我打印opt
我可以看到哪里出了问题:
(assert (= z1 (to_real (- (* 0 x1) (* 1 x2)))))
(assert (= z2 (to_real (+ (* 0 x1) (* 1 x2)))))
系数是默默截断,并转换为整数:0.5到达0和1.5变成1
一种解决方法似乎是:
opt.add(z1 == 0.5*ToReal(x1) - 1.0*ToReal(x2), z2 == -0.5*ToReal(x1) + 1.5*ToReal(x2))
这浮点系数转换为与其等同物理性:
(assert (= z1 (- (* (/ 1.0 2.0) (to_real x1)) (* 1.0 (to_real x2)))))
(assert (= z2 (+ (* (- (/ 1.0 2.0)) (to_real x1)) (* (/ 3.0 2.0) (to_real x2)))))
现在0.5变为(/ 1.0 2.0)
和1.5由(/ 3.0 2.0)
表示。
我的问题是:
- 这是截断 “作为设计的”?
- 我的解决方法是解决此问题的正确方法吗?或者我应该完全避免浮点系数?
- 打印的理性数字
(/ 1.0 2.0)
似乎暗示仍然存在浮点数。这真的是(/ 1 2)
? (我认为这些实际上是bigint)。
对不起,我的无知。我从来没有见过类型缩小的方式。我想我是通过升职而不是降级来完全灌输的。 –
看到我编辑的答案。实质上,声明的变量的类型是固定的,因为它们是这样声明的。而你使用简单的常量假设必要的类型来使周围的表达式得到很好的输入。的确非常危险!但这是在无类型设置下工作的成本。 –
非常感谢。这是很好的知道。 –