【问题标题】:Adding a binary constraint in Pulp python without violating the linearity constraint在 Pulp python 中添加二元约束而不违反线性约束
【发布时间】:2020-04-09 20:30:35
【问题描述】:

尊敬的 Python 用户,

我正在使用 Pulp 构建多周期多产品计划模型。 该模型应该做的事情相当简单:在满足需求的同时,根据最低的持有和生产成本计划生产。

我有以下数据:

periods = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
products = ['A', 'B', 'C']

我创建了以下变量:

prod_vars = pulp.LpVariable.dicts('production', [(i,j) for i in products for j in periods],0) 
inv_vars = pulp.LpVariable.dicts('inventory', [(i,j) for i in products for j in periods],0)

有 2 个限制条件,1 个始终满足需求,1 个始终低于生产能力。 请注意,有一个数据框 (input_data) 用于检索该时期给定需求的值。

for i in products:
    for j in periods[1:]: 
        model.addConstraint(pulp.LpConstraint(
                    e=inv_vars[(i,j-1)] + prod_vars[(i,j)] - inv_vars[(i,j)],
                sense=pulp.LpConstraintEQ,
                name='inv_balance_'  + str(i)+ str(j),
                rhs=input_data[i][j-1]))

for j in periods:
model.addConstraint(pulp.LpConstraint(
    e=(pulp.lpSum(prod_vars[(i,j)] for i in products)),
    sense=pulp.LpConstraintLE,
    name='total_production_capacity'+str(j),
    rhs=(input_data['production_capacity'][j-1])

然后我添加成本函数并设定目标:

total_production_cost = production_cost*pulp.lpSum(prod_vars)
total_holding_cost =holding_cost * pulp.lpSum(inv_vars)

目标 = 总持有成本 + 总生产成本 + 激活成本 model.setObjective(目标)

这个模型工作得很好,给了我这样的输出。 prod_vars: (A,1) =5, (B,1)=10, (C,1)=15 依此类推所有时期。 但是:我想惩罚生产多种产品的系统。即,在选择生产第二种或第三种产品时增加固定成本。然后,生产更多的产品 A 并持有几个月的库存然后每月生产 A 会更有利。我尝试添加另一个变量:

use_vars = pulp.LpVariable.dicts('uselocation', [(i,j) for i in products for j in periods] , 0,1,pulp.LpBinary)

并添加使用变量的固定成本:

activation_cost = pulp.lpSum(activation_cost*use_vars[(i,j)] for i in products for j in periods)

我认为我需要在两个约束中将我的 prod_vars 乘以我的 use_vars。但是,如果我在我的第一个库存约束中这样做,Pulp 会给出我的约束不再是线性的错误。

有人知道我怎样才能做到这一点吗? 在此先感谢:)

【问题讨论】:

    标签: python constraints linear-programming pulp


    【解决方案1】:

    我想惩罚生产多种产品的系统。 IE。, 在选择生产第二种或第三种产品时增加固定成本。

    最好远离代码,从数学上看。

    Let x(i,t)>=0 be the production of item i in period t 
    

    当我们需要计数时,我们需要二进制变量。所以,介绍一下:

    y(i,t) = 1 if item i is produced in period t
             0 otherwise
    

    然后我们可以添加

    x(i,t) <= M*y(i,t)   (M large enough constant: i.e. capacity)
    

    这实现了y(i,t)=0 =&gt; x(i,t)=0。我们不必担心x(i,t)=0 =&gt; y(i,t)=0 的其他方式,因为它由目标处理(最小化成本)。

    为了增加生产 2 或 3 个产品的特殊成本,我们需要一个二进制变量:

    count(k,t) = 1 if the number of products produced is k (k=0,1,2,3)
               = 0 otherwise
    

    这可以计算为:

     y(A,t)+y(B,t)+y(C,t) = 1*count(1,t)+2*count(2,t)+3*count(3,t)   
     count(1,t)+count(2,t)+count(3,t) <= 1
    

    现在您可以在成本计算中添加:100*count(2,t)+200*count(3,t)。 (注意:为了完整起见:我假设 3 种产品的成本至少与 2 种产品的成本一样大。

    【讨论】:

      【解决方案2】:

      要实现您的意图,您可以添加连接 prod_varsuse_vars 的附加约束,例如(伪代码):

      prod_vars[(i, j)] >= use_vars[(i, j)] forall i, j
      prod_vars[(i, j)] <= M * use_vars[(i, j)] forall i, j
      

      其中M 可以设置为max(input_data['production_capacity'])

      这样做你不需要修改原来的约束。

      【讨论】:

        猜你喜欢
        • 2021-12-08
        • 2018-05-24
        • 1970-01-01
        • 2020-01-14
        • 1970-01-01
        • 2017-03-01
        • 2014-11-09
        • 1970-01-01
        相关资源
        最近更新 更多