如何使用 Python 中的 PuLp 包实现库存重新分配的线性优化

问题描述

我正在尝试使用 Python 中的 PuLp 包实现线性优化,以解决库存不平衡/重新分配问题。我在网上找到了一个解决方https://www.bluepiit.com/blog/inventory-rebalancing-part2/,但在实施时遇到了一些问题。

  1. 我看到他在使用数据字典。他是如何使用/导入原始数据到模型中的?我假设如下:
holding_cost_dataset = pd.read_csv('holding cost dataset.csv')
holding_cost = holding_cost_dataset.to_dict()

transportation_cost_dataset = pd.read_csv('transportation cost dataset.csv')
transportation_cost = transportation_cost_dataset.to_dict()

但是还有什么?使用了多少/什么词典?满足_需求是字典吗?如果不是,那是什么?是 demand_dic

dataset = pd.read_csv('example dataset.csv')
demand_dic = dataset.to_dict()

这整个实现似乎是针对一个项目的。如何将其更改为用于多个项目?数组?矩阵?

这是原始代码(我插入了?):

import pulp
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# -----------------------------------------------------------------------------
 
# import data
 
# ?????? 
 
# -----------------------------------------------------------------------------
 
# Define decision variables
 
u_stores = ['A','B','C']
indexes = ['A_B','A_C','B_A','B_C','C_A','C_B']
 
transfer_variables = pulp.LpVariable.dicts(name='X',indexs=indexes,lowBound=0,cat='Integer')
 
binary_transfer_variables = pulp.LpVariable.dicts(name='Y',upBound = 1,cat='Integer')
 
ending_inventory_variables = pulp.LpVariable.dicts(name='EI',indexs=u_stores,cat='Integer')
 
satisfied_demand = pulp.LpVariable.dicts(name='SD',cat='Integer')
 
 
'''
u_stores holds a list as ['A','C'].
 
indexes holds list as ['A_B','C_B']
 
transfer_variables define transferred quantity between given stores.
 
binary_transfer_variables define whether transfer happened between given stores or not
 
ending_inventory_variables define remaining stock at store at the end of period given that sale happened according to demand
 
satisfied_demand defines the number of units sold at a given store according to new stock (after transfer) and given demand
'''
 
# -----------------------------------------------------------------------------
 
# Define and initialize model
 
model = pulp.LpProblem(name='Inventory_Redistribution',sense=pulp.LpMinimize)
 
# Objective function
 
total_logistic_cost = pulp.lpSum([transportation_cost.loc[tv.split('_')[0]][tv.split('_')[1]]*transfer_variables[tv] for tv in transfer_variables.keys()])
total_holding_cost = pulp.lpSum([holding_cost[s]*ending_inventory_variables[s] for s in u_stores])
 
objective = total_holding_cost + total_logistic_cost
 
model.setobjective(objective)
 
# -----------------------------------------------------------------------------
 
# DEFINE CONSTRAINTS
 
# M = arbitrary large number
M = 1000 # ?
# MTQ = threshold for minimum transfer quantity for given item
MTQ = 50 # ?
 
# Setting up binary variable,if transfer happens
 
'''
Mathematical representation
Y[X,Y] - X[X,Y] <= 0
X[X,Y] - M*Y[X,Y] <= 0
'''
 
for key,value in transfer_variables.items():
    model.addConstraint(pulp.LpConstraint(
    e = binary_transfer_variables[key] - transfer_variables[key],sense = pulp.LpConstraintLE,name = 'Y_'+key+'_1',rhs = 0
    ))
   
    model.addConstraint(pulp.LpConstraint(
    e = transfer_variables[key] - M*binary_transfer_variables[key],name = 'Y_'+key+'_2',rhs = 0
    ))
   
    
# Minimum transfer quantity
 
'''
Mathematical representation
X[X,Y] - MTQ*Y[X,Y] >= 0
'''
 
for key,value in transfer_variables.items():
    model.addConstraint(pulp.LpConstraint(
    e = transfer_variables[key]-MTQ * binary_transfer_variables[key],sense = pulp.LpConstraintGE,name = 'MTQ_'+key,rhs = 0
    ))
   
# Transfer quantity and destination demand
 
'''
Mathematical representation
X[X,Y] - Demand[Y] <= 0
'''
 
for key,value in transfer_variables.items():
    model.addConstraint(pulp.LpConstraint(
    e = transfer_variables[key] - demand_dic[key.split('_')[1]],name = 'TQ_DEST_DE_'+key,rhs = 0
    ))
   
# satisfied demand
 
'''
Mathematical representation
SD[store] - Demand[store] <= 0
SD[store] - Stock[store] - TO[store] + TI[store] <=0
where TO stands for Transfer Out from store,and TI stands for Transfer In
'''
 
for s in u_stores:   
    model.addConstraint(pulp.LpConstraint(
    e = satisfied_demand[s] - demand_dic[s],name = 'SD_DE_'+s,rhs = 0
    ))
   
    model.addConstraint(pulp.LpConstraint(
    e = satisfied_demand[s] - closing_dic[s] - pulp.lpSum([transfer_variables[v] for v in transfer_variables.keys() if s in v.split('_')[1]]) + pulp.lpSum([transfer_variables[v] for v in transfer_variables.keys() if s in v.split('_')[0]]),name = 'SD_INV_'+s,rhs = 0
    ))
 
# ending inventory level
 
'''
Mathematical representation
EI[store] - Stock[store] - TO[store] + TI[store] + SD[store] = 0
'''
 
for s in u_stores:
    model.addConstraint(pulp.LpConstraint(
    e = ending_inventory_variables[s] - closing_dic[s] - pulp.lpSum([transfer_variables[v] for v in transfer_variables.keys() if s in v.split('_')[1]]) + pulp.lpSum([transfer_variables[v] for v in transfer_variables.keys() if s in v.split('_')[0]]) + satisfied_demand[s],sense = pulp.LpConstraintEQ,name = 'EI_'+s,rhs = 0
    ))
   
# -----------------------------------------------------------------------------
 
# Solving model and extracting suggested transfers
 
# solve model
 
model.solve()
pulp.LpStatus[model.status]
 
# Gives 'Optimal' Solution

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)