我是用一個小的多目標整數規劃問題,玩的解釋: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)。
對不起,我的無知。我從來沒有見過類型縮小的方式。我想我是通過升職而不是降級來完全灌輸的。 –
看到我編輯的答案。實質上,聲明的變量的類型是固定的,因爲它們是這樣聲明的。而你使用簡單的常量假設必要的類型來使周圍的表達式得到很好的輸入。的確非常危險!但這是在無類型設置下工作的成本。 –
非常感謝。這是很好的知道。 –