首页 > 解决方案 > 如何在纸浆优化中限制变量?

问题描述

我正在尝试使用预测的成本和销售额来优化产品的整体销售额(为期 3 个月)。我当前的数据如下所示

>     Month |    sales quantity  | discount % | Total inventory
      1     |         12         |    5       |      45
      1     |         23         |    9       |      45
      1     |         40         |    15      |      45
      2     |         23         |    5       |      45

根据预测的销售额,每个月都有一些折扣。Total inventory是所有月份的库存总和。我正在尝试使用纸浆最大化整体销售额,但优化结果总是选择sales quantity每个月的最高值,大部分时间超过Total inventory. 当总销售额超过时,

我需要将值上限(为零) 。sales quantityTotal inventory

保持类似的约束lpSum(x[i]*sales_quantity[i] for i in unique_months) < total_inventory会导致不可行的解决方案。我的一小段代码:

import pulp as lp 

# `data` is a DataFrame contains above data
x = LpVariable.dicts("x", range(0, len(data)), 0, 1, LpBinary) 

prob = lp.LpProblem("test problem", lp.LpMaximize)

# obj function
prob += lpSum(x[i] * data.loc[i, 'sales quantity'] for i in range(0, len(data)))

# constraints
prob += lpSum(x[i] * data.loc[i, 'sales quantity'] for i in range(0, len(data))) >= threshold_inventory_to_clear

# constraints to select each month(without missing any)
for j in list(data['Month'].unique()):
    if j == data['Month'].max():
       break
    sub_idx_current = data[data['Month'] == j].index
    sub_idx_next = data[data['Month'] == j + 1].index
    prob += lpSum(x[idx_current] * data.loc[idx_current, 'Month'] for idx_current in sub_idx_current) \
                        <= lpSum(x[idx_next] * data.loc[idx_next, 'Month'] for idx_next in sub_idx_next)

# Need to replace this constraints with some calling logic
prob += lpSum(x[i]*data.loc[i, 'sales quantity'] for i in range(0, len(data)) < total_inventory

标签: pythonoptimizationpulp

解决方案


如果我正确理解您的问题,您可以选择每月出售或不出售?并且您希望最大化您的收入,这样您的销售量不会超过您的库存。我不确定您是否正在处理多种产品。

如果我正确理解了您的问题,那么以下内容应该可以在 4 个不同的时间段内为单个产品解决问题。

import pulp
import pandas as pd

max_quantity = 45
df = pd.DataFrame({
    "sales_quantity": [12,23,40,23],
    "discount": [5,9,15,5]
})

prob = pulp.LpProblem("MaxSales", pulp.LpMaximize)

X = [pulp.LpVariable('var_'+str(i), 0, 1, pulp.LpBinary) for i, sq in enumerate(df['sales_quantity'])]
prob += pulp.LpAffineExpression({X[i]: (100-df['discount'][i])*df['sales_quantity'][i] 
                                 for i in range(0,len(df))}, name='Objective')
prob += pulp.LpAffineExpression({X[i]: df['sales_quantity'][i] for i in range(0,len(df))})<=max_quantity, "Max Inventory"
prob.solve()
print(prob)
print("Revenue: " + str(pulp.value(prob.objective)))
print([pulp.value(x) for x in X])

输出:

MaxSales:
MAXIMIZE
1140*var_0 + 2093*var_1 + 3400*var_2 + 2185*var_3 + 0
SUBJECT TO
Max_Inventory: 12 var_0 + 23 var_1 + 40 var_2 + 23 var_3 <= 45

VARIABLES
0 <= var_0 <= 1 Integer
0 <= var_1 <= 1 Integer
0 <= var_2 <= 1 Integer
0 <= var_3 <= 1 Integer

Revenue: 3400.0
[0.0, 0.0, 1.0, 0.0]

如果我误解了什么,请告诉我。我无权发表评论,因此无法事先要求澄清。


推荐阅读