使用Python Pulp不允许使用最佳解决方案时出错

时间:2018-05-08 22:52:12

标签: mathematical-optimization linear-programming pulp

我有以下优化问题:

maximize(x1+x2+2x3+x4)

x1+x2+x3+x4 = 2

约束

其中xi = {0,1}(二进制变量)。

当我在Pulp中实现它时:

from pulp import *
x1 = pulp.LpVariable('x1', cat=LpBinary)
x2 = pulp.LpVariable('x2', cat=LpBinary)
x3 = pulp.LpVariable('x3', cat=LpBinary)
x4 = pulp.LpVariable('x4', cat=LpBinary)

prob = pulp.LpProblem('x1+x2+2*x3+x4', pulp.LpMaximize)
prob += lpSum([x1, x2, 2*x3, x4])
prob += lpSum([x1, x2, x3, x4]) == 2
prob.solve()

我得到了x1x2x3x4的解决方案。但是,我想不允许这个解决方案,在Pulp中添加另一个约束为x1+x3 < 2

prob += lpSum([x1, x3]) < 2

但是由于我在prob.solve()中有一个虚拟变量,所以我得不到一个好的解决方案。我应该使用其他约束还是我做错了什么?

2 个答案:

答案 0 :(得分:2)

运行prob += lpSum([x1, x3]) < 2时,会出现以下错误:

  

回溯(最近一次呼叫最后一次):文件&#34; xyz.py&#34;,第13行,          prob + = lpSum([x1,x3])&lt; 2 TypeError:&#39;&lt;&#39; LpAffineExpression&#39;的实例之间不支持和&#39; int&#39;

这是纸浆包装告诉您不能添加严格的不等式,这是优化求解器的标准要求。由于您的所有变量都是二进制值,<2<=1相同,并且进行此更改将使求解器满意:

prob += lpSum([x1, x3]) <= 1
prob.solve()
print(x1.value(), x2.value(), x3.value(), x4.value())
# 0.0 1.0 1.0 0.0

所以现在你得到一个不同的解决方案,其目标值为3(x2 = 1且x3 = 1)。

如果您想输出所有可能的解决方案,您可以使用循环来继续添加约束,从而不允许最佳解决方案,直到最佳目标值发生变化:

from pulp import *
x1 = pulp.LpVariable('x1', cat=LpBinary)
x2 = pulp.LpVariable('x2', cat=LpBinary)
x3 = pulp.LpVariable('x3', cat=LpBinary)
x4 = pulp.LpVariable('x4', cat=LpBinary)

prob = pulp.LpProblem('x1+x2+2*x3+x4', pulp.LpMaximize)
prob += lpSum([x1, x2, 2*x3, x4])
prob += lpSum([x1, x2, x3, x4]) == 2
prob.solve()
print(x1.value(), x2.value(), x3.value(), x4.value())

opt = prob.objective.value()
while True:
    prob += lpSum([x.value() * x for x in [x1, x2, x3, x4]]) <= 1 + 1e-6
    prob.solve()
    if prob.objective.value() >= opt - 1e-6:
        print(x1.value(), x2.value(), x3.value(), x4.value())
    else:
        break  # No more optimal solutions  

这产生了预期的输出:

# 1.0 0.0 1.0 0.0
# 0.0 1.0 1.0 0.0
# 0.0 0.0 1.0 1.0

答案 1 :(得分:1)

要查找所有解决方案,您需要进行以下修改

while True:
    prob += lpSum([x for x in [x1, x2, x3, x4] if x.value() >= 0.99]) <= sum([x.value() for x in [x1, x2, x3, x4]]) -1
    prob.solve()
    if prob.objective.value() >= opt - 1e-6:
        print(x1.value(), x2.value(), x3.value(), x4.value())
    else:
        break  # No more optimal solutions