如何在Python中使用PuLP GLPK编写混合整数线性规划(MILP)的决策变量的IF条件?

5

我正在尝试使用PuLP和GLPK求解混合整数线性规划问题,涉及IT技术。迄今为止,我已经成功地解决了一些基本的优化问题,包括约束条件:

prob = LpProblem("MILP", LpMinimize)
x1 = LpVariable("x1",lowBound=0, cat = 'Binary')
x2 = LpVariable("x2", cat = 'Continuous')
prob += 4*x1 + x2, "Objective Function"
prob += x2 - 4*x1 <= 0
prob += x2 - 2*x1 >= 0
status = prob.solve()
LpStatus[status]
value(x1), value(x2), value(prob.objective)

这样可以得到最佳结果,其中x1 = 1.0,x2 = 3.0,目标函数 = 7.0

我想知道如何解决一个带有if条件的优化问题,例如以下约束条件:

x1 > 0 IF x2 > 2

或者类似于:

x1 > 0 IF x2 == 3

基本上,我如何将if条件语句集成到MILP约束中。
1个回答

6
你要寻找的搜索词是"指示变量"或"big-M约束"。
据我所知,PULP并不直接支持指示变量,因此采用big-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))

我们希望当 x2 > 2 时存在限制条件 x1 <= 0。当 x2 <= 2 时,不存在这样的限制条件(x1 可以是正数或负数)。 首先,我们创建一个二进制变量:
b1 = LpVariable("b1", cat='Binary')

选择这个表示条件x2 > 2的选项。实现这个条件最简单的方法是添加一个约束:

M1 = 1e6
prob += b1 >= (x2 - 2)/M1

这里的 M1 是大M值。需要选择它,以使对于可能的 x2 的最大值,表达式 (x2-2)/M 的值为 <=1。它应该尽可能小,以避免数值/缩放问题。在这里,一个10的值就足够了(x2的上限是10)。
要理解这个约束条件的工作原理,请考虑以下情况:当 x2<=2 时,右侧最多为0,因此没有影响(二进制变量的下限已设置为0)。但是,如果 x2>2,则右侧将强制 b1 大于0,并且作为二进制变量,它将被强制为1。
最后,我们需要构建所需的约束条件:
M2 = 1e3
prob += x1 <= M2*(b1 - 1)

为了更好地理解这个约束条件的工作方式,考虑以下情况:如果b1是true(1),则该约束条件是活动的并且变为:x1 <= 0。如果b1是false(0),则该约束条件变成x1 <= M2,前提是M2足够大,这将不会产生任何效果(在这里,它可以小到10,因为x1已经有一个上界为10)。

在上面的完整代码中,如果您改变目标函数中x1的系数,您应该会注意到b1被激活/去激活,并且对x1应用了额外的约束条件,就如预期那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接