【问题标题】:How do I make a constraint elastic in PuLP?如何在纸浆中使约束具有弹性?
【发布时间】:2021-08-01 13:34:07
【问题描述】:

我正在处理一个生产分配问题,销售订单必须分配给三个生产工厂。

我在 Python 中使用 PuLP,在我尝试使约束“有弹性”之前,它可以正常工作。当销售订单总额大于总产能时需要弹性,我必须增加工厂的产能,尽管有“惩罚”。 (因为加班生产会增加成本)。

在纸浆的这方面缺乏用户友好的文档(很抱歉),我遇到了一些困难。为了应用“makeElasticSubProblem”,我需要给约束命名。但是,a) 当我使用prob += lpSum([alloc[s][l]for s in so]) <= cap_dict[l], 'Myname' 的传统语法时,并且当我在下一行使用 Myname 时,Python 会返回一条 Myname 未定义的消息。 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])

【问题讨论】:

    标签: python optimization constraints linear-programming pulp


    【解决方案1】:

    我更喜欢明确地这样做。这使它不再是一个黑匣子。

    你的约束看起来像

     sum(s, a[s,l]) <= cap[l]
    

    现在添加一个变量overcap[l],边界为[0,20%*cap[l]],然后写:

     sum(s, a[s,l]) <= cap[l] + overcap[l]
    

    并为目标添加惩罚(最大化所以使用 -):

      .... - sum(l,penalty[l]*overcap[l])     
    

    最后,向用户报告overcap[l] 的非零值。

    【讨论】:

      猜你喜欢
      • 2015-02-01
      • 1970-01-01
      • 2022-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 2017-03-31
      相关资源
      最近更新 更多