我正在研究生产分配问题,其中销售订单必须分配到三个生产工厂。
我在 Python 中使用 PuLP,这工作得很好,直到我尝试使约束变得“弹性”。当销售订单总数大于总产能时,就需要弹性,我必须增加工厂的产能,尽管会受到“惩罚”。 (因为加班生产会增加成本)。
我陷入了 PuLP 这方面缺乏用户友好文档的困境(很抱歉这么说),并遇到了一些困难。为了应用“makeElasticSubProblem”,我需要为约束命名。但是,a)当我使用传统语法时prob += lpSum([alloc[s][l]for s in so]) <= cap_dict[l], 'Myname'
,当我在下一行中使用“我的名字”时,Python 返回一条消息“我的名字未定义”。 b) 当我使用以下语法时:Myname = LpConstraintlpSum([alloc[s][l]for s in so]), sense = 1, rhs = cap_dict[l])
,名称被接受,但名称后面的弹性定义似乎被脚本“忽略”。
有人可以提示我我做错了什么吗?谢谢!
下面是我的代码的简化版本(使用 Python 3.8.2 64 位):
from pulp import *
# define the locations and their production capacity
#---------------------------------------------------
location = ['locA', 'locB', 'locC']
capacity = [90, 60, 20]
cap_dict = dict(zip(location, capacity))
# define the sales orders (so) and their volumes (demand)
#--------------------------------------------------------
so = ['s1', 's2', 's3', 's4', 's5']
demand = [20,10,15,8,5]
order_dict = dict(zip(so, demand))
# define the problem
#-------------------
prob = LpProblem("Production_planning",LpMaximize)
# define the decision variables
#------------------------------
alloc = LpVariable.dicts("Alloc", (so, location), cat='Integer')
# set the objective function
#---------------------------
prob += lpSum(alloc[s][l] for s in so for l in location)
# define the constraints
#-----------------------
# 1) allocations should be positive
for s in so:
for l in location:
prob += (alloc[s][l] >= 0)
# 2) allocation limited by the capacity of the location
for l in location:
prob += lpSum([alloc[s][l] for s in so]) <= cap_dict[l]
# 3) Location A should receive > 50% of all the allocations
prob += (alloc[s]['locA'] >= lpSum(alloc[s][l] for l in location)/2)
# 4) allocation limited by the amount ordered
for s in so:
prob += lpSum([alloc[s][l] for l in location]) <= order_dict[s]
# solve the optimization problem
#-------------------------------
prob.solve()
print("Status :", LpStatus[prob.status])
for v in prob.variables():
if "Alloc_" in v.name:
if v.varValue > 0:
print(v.name, v.varValue)
在定义了以下容量约束之后,位置 C 的约束的 20% 向上弹性的规范将被忽略(如果我增加销售订单,程序将向位置 C 分配任何大量金额,没有任何限制):
# capacity constraints:
#---------------------
# same definition for locations A and B
for l in ['locA', 'locB']:
prob += lpSum([alloc[s][l] for s in so]) <= cap_dict[l]
# different and specific definition for location C, where an elastic capacity increase needs to be introduced:
cap_locC = LpConstraint(lpSum([alloc[s][l]for s in so]), sense = 1, rhs = cap_dict['locC'])
elastic_cap_locC = cap_locC.makeElasticSubProblem(penalty = 100, proportionFreeBoundList = [0,0.2])