您要查找的搜索词是“指示变量”或“big-M 约束”。
据我所知,PULP 不直接支持指示变量,因此大 M 约束是可行的方法。
一个简单的例子:
x1 <= 0 IF x2 > 2
from pulp import *
prob = LpProblem("MILP", LpMaximize)
x1 = LpVariable("x1", lowBound=0, upBound=10, cat = 'Continuous')
x2 = LpVariable("x2", lowBound=0, upBound=10, cat = 'Continuous')
prob += 0.5*x1 + x2, "Objective Function"
b1 = LpVariable("b1", cat='Binary')
M1 = 1e6
prob += b1 >= (x1 - 2)/M1
M2 = 1e3
prob += x2 <= M2*(1 - b1)
status = prob.solve()
print(LpStatus[status])
print(x1.varValue, x2.varValue, b1.varValue, pulp.value(prob.objective))
我们想要一个约束x1 <= 0
存在时x2 > 2
. When x2 <= 2
不存在这样的约束(x1
可以是正数也可以是负数)。
首先我们创建一个二进制变量:
b1 = LpVariable("b1", cat='Binary')
选择这个来代表条件x2 > 2
。实现此目的的最简单方法是添加约束:
M1 = 1e6
prob += b1 >= (x2 - 2)/M1
Here M1
是大M值。需要选择这样的值,以便获得最大可能的值x2
表达方式(x2-2)/M
is <=1
。它应该尽可能小,以避免数值/缩放问题。这里可以使用值 10 (x2
上限为 10)。
要了解此约束的工作原理,请考虑以下情况,对于 x2x2>2右手边会强制b1
大于 0 - 作为二进制变量,它将被强制为 1。
最后,我们需要构建所需的约束:
M2 = 1e3
prob += x1 <= M2*(b1 - 1)
再次为了理解这个约束是如何工作的,请考虑以下情况,如果 b1 为真(1
) 约束处于活动状态并变为:x1 <= 0
。如果 b1 为假('0'),则约束变为x1 <= M2
, 假如M2
足够大,这不会有任何影响(这里它可以小到 10x1
上限已经为 10。
在上面的完整代码中,如果您改变系数x1
在目标函数中你应该注意到b1
被激活/去激活并且附加约束应用于x1
正如预期的那样。