使用 PulP 进行 LP 优化。使用 IF 设置约束

LP Optimization with PulP. Using IF to set up constraints

正在寻找一种使用 IF ELSE 函数为我的优化问题设置约束的方法。归结为:如果常量 A 小于变量 B,则变量 D=0,否则 D=A-B。这里是 a clear formulation.

我收到错误

TypeError: '>' not supported between instances of 'int' and 'LpVariable'

有什么办法可以避免这种情况吗?

我的python脚本如下所示:

import pulp
import random

# setting up constants
t_0=1000
A=[]
for x in range(t_0):
    A.append(random.randint(1,10))


# initializing LP
LP = pulp.LpProblem('LP',pulp.LpMinimize)  

# adding variables
B = pulp.LpVariable("B", cat='Continuous', lowBound=0)  
D = pulp.LpVariable.dicts("D", range(t_0), cat=pulp.LpContinuous, lowBound=0)

# adding constraints
for t in range(t_0):

    if A[t] > B:
        LP += D[t]  == A[t] - B
    else:
        LP += D[t] == 0


LP += pulp.lpSum(D[t] for t in range(t_0)) 


status = LP.solve(pulp.CPLEX_PY(mip=True, msg=True, timeLimit=15,epgap=None))

print( 'LP status: ' + pulp.LpStatus[status] + '')

我不知道 PULP,但您正在寻找的是 CPLEX 中的 "indicator constraints"。检查 PULP 文档是否以及如何支持指标或逻辑约束。

不过还有一个选择:你的问题是

minimize sum D(t)
D(t) = A(t)-B if A(t) > B
D(t) = 0 if A(t) <= B

因为这试图最小化 D(t),在任何最优解中 D(t) 将尽可能小。所以你可以用

替换你的约束
D(t) >= A(t) - B
D(t) >= 0

如果 B >= A(t) 则第一个将微不足道地满足,第二个与 objective 一起将设置 D(t) = 0。类似地,如果 B < A(t) 那么第二个将很容易满足,第一个与 objective 一起将设置 D(t) = A(t) - B.

你应该尝试找到你在 docplex API

中的 "if_then" 的等价物

例如

from docplex.mp.model import Model

mdl = Model(name='buses')
nbbus40 = mdl.integer_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
mdl.minimize(nbbus40*500 + nbbus30*400)

mdl.solve()

for v in mdl.iter_integer_vars():
   print(v," = ",v.solution_value)

print()
print("with if nb buses 40 more than 3  then nbBuses30 more than 7")

mdl.add(mdl.if_then((nbbus40>=3),(nbbus30>=7)))
mdl.minimize(nbbus40*500 + nbbus30*400)

mdl.solve()

for v in mdl.iter_integer_vars():
    print(v," = ",v.solution_value)

给予

nbBus40  =  6.0
nbBus30  =  2.0

with if nb buses 40 more than 3  then nbBuses30 more than 7
nbBus40  =  0
nbBus30  =  10.0