在excel表中给定以下格式的输入数据:
1.库存[pl,p][t]其中pl是工厂,p是产品,t是时间范围。
1.客户订单参考表-A列:销售订单,B列:客户。每个客户可以有多个销售订单,每个销售订单有多个产品。
1.客户来源参考表-A列:客户,B列:工厂。注意-一个客户可以有多个工厂,他们可以从那里采购。
- Cost[p,pl]['Cost']其中pl是工厂,p是产品。
1.价格[c,p]['Price']其中c是成本,p是产品。 - Order[o,p,t]['Quantity'],其中o是销售订单,p是产品,t是时间展望期。此处t是交货日期。
如果一个数量没有被用来满足客户订单,那么这个数量将被添加到下一个时间范围中,所以我需要一个变量,该变量的预计库存为projstock[pl,p,t]。项目库存=库存[t-1]+库存[t]-用于满足客户需求的数量。另一个变量是确定将从哪个工厂履行销售订单。每个销售订单应由一个地点履行。客户、销售订单和产品之间的关系将根据输入数据进行维护。
这种交付最大化与低成本(总价格-产品的总成本)和没有预算限制.
由于某种原因,约束似乎没有提供从同一地点采购订单中所有产品的预期结果,如果库存不可用,它不应该得到履行。
from pulp import *
import pandas as pd
import timeit
start = timeit.default_timer()
simple_master_path = "C:\\Users\\aadav\\Desktop\\Pulp Sample.xlsx"
# Read simple master with index
stock = pd.read_excel(simple_master_path, sheet_name='Stock', index_col=(0,1))
stockavl=stock.loc[stock['Key Figure']=='Stock Available'].fillna(0)
cost = pd.read_excel(simple_master_path, sheet_name='Cost', index_col=(0,1))
price = pd.read_excel(simple_master_path, sheet_name='Price', index_col=(0,1))
order = pd.read_excel(simple_master_path, sheet_name='Order', index_col=(0,1,2))
custord = pd.read_excel(simple_master_path, sheet_name='CustOrder', index_col=(0,1))
custordsum = pd.read_excel(simple_master_path, sheet_name='Custsum', index_col=(0,1))
custsrc = pd.read_excel(simple_master_path, sheet_name='Customer Source', index_col=(0,1))
time = pd.read_excel(simple_master_path, sheet_name='Time', index_col=(0))
def get_unique_list(df, index, filter_column=None, filter_criteria=None):
x = df.reset_index([index])
if filter_column:
y = x.loc[x[filter_column]==filter_criteria, index].unique()
else:
y = x[index].unique()
return y
cust= get_unique_list(df=order, index='Customer')
ord= get_unique_list(df=order, index='Sales Order')
plnt= get_unique_list(df=stock, index='Plant')
prod= get_unique_list(df=stock, index='Product')
tw= get_unique_list(df=time, index='Time')
m=LpProblem("Model", LpMaximize)
from itertools import product
ordinx =[ (o,c,p) for o,c,p in itertools.product(ord,cust,prod) if (o,c,p) in order.index ]
delv =[ (c,o,p,pl,t) for (o,c,p),pl,t in itertools.product(ordinx,plnt,tw) if (pl,p) in stockavl.index if (c,pl) in custsrc.index if (pl,p) in cost.index if (c,p) in price.index]
ocpl =[ (o,c,pl) for o,c,pl in itertools.product(ord,cust,plnt) if (o,c) in custord.index if (c,pl) in custsrc.index ]
projstock = LpVariable.dicts("x",[(pl,p,t) for (pl,p) in stockavl.index for t in tw],
lowBound=0, upBound=None, cat='LpInteger')
delivery = LpVariable.dicts("y",[(c,o,p,pl,t) for (c,o,p,pl,t) in delv], lowBound=0, upBound=None, cat='LpInteger')
#objective function
m+= (lpSum([(price.loc[c,p]['Price']-cost.loc[pl,p]['Cost'])*delivery[(c,o,p,pl,t)] for (c,o,p,pl,t) in delv if t>=44945]))
#constraints
#constraint 1
for o,c,pl in ocpl:
for p in prod:
if (o,c,p) in order.index:
m+=lpSum(delivery[(c,o,p,pl,t)] for t in tw)==lpSum(order.loc[o,c,p]['Quantity'])
#constraint 2
for o,c,pl in ocpl:
m+=lpSum(delivery[(c,o,p,pl,t)] for p in prod if (o,c,p) in order.index for t in tw)==lpSum(custordsum.loc[c,o]['Sum of Quantity'])
#constraint 3
for o,c,p in order.index:
plants = [pl for (c_, o_, p_, pl, t) in delivery.keys() if c_ == c and o_ == o and p_==o]
m += lpSum(len(set(plants))) <= 1
#constraint 4
for o,c,p in order.index:
m+=lpSum(delivery[(c,o,p,pl,t)] for pl in plnt for t in tw if (c,pl) in custsrc.index if (pl,p) in stockavl.index)==lpSum(order.loc[o,c,p]['Quantity'])
#constraint 5
for pl,p in stockavl.index:
for t in tw:
m+=lpSum(delivery[(c,o,p,pl,t)] for o,c in custord.index if (o,c,p) in order.index if (c,pl) in custsrc.index) <= lpSum(projstock[(pl,p,t)])
#constraint 6
for pl,p in stockavl.index:
for t in tw:
if t == 44945:
m += projstock[(pl,p,t)] == stockavl.loc[pl,p][t] - lpSum(delivery[(c,o,p,pl,t)] for c in cust for o in ord if (o,c,p) in order.index if (c,pl) in custsrc.index)
else:
m += projstock[(pl,p,t)] == projstock[(pl,p,t-1)] - lpSum(delivery[(c,o,p,pl,t)] for c in cust for o in ord if (o,c,p) in order.index if (c,pl) in custsrc.index) + stockavl.loc[pl,p][t]
#constraint 7
for c,o,p,pl,t in delivery.keys():
if (o,c,p) in order.index:
m+= lpSum(t) <= order.loc[o,c,p]['Delivery Date']
m.solve()```
2条答案
按热度按时间voase2hg1#
你的预处理做得很差,我相信你遗漏了一个步骤。你没有展示你加载数据的方式,也没有展示你的任何框架的构造,这在这里是非常重要的。你使用了单字母变量和很多生成器,你不应该使用任何一个。作为一个起点,考虑
股票列只在累积求和时有用,如果使用
scipy.optimize
,它将变成稀疏矩阵;我不熟悉PuLP,但是有一个等价物,稍后我将详细介绍这个例子。ztigrdn82#
这里你忽略的线性规划概念是一个all or nothing约束。我没有深入到你的模型中,另一个解决方案在导入数据方面有一些好的想法。但是作为一个开始,我会做一个小得多的第二个“玩具”数据集来排除故障。
因此,您只想从一个地点采购订单,并且只有在他们有库存的情况下。因此,您需要一个二进制变量来指示订单是否从给定的工厂完成。类似于:
然后(如果在其他地方没有这样做),您希望通过对所有工厂的每个订单进行求和来防止多个订单履行,类似于:
然后将所有订单的数量链接到此订单,类似于(您需要使用其他变量展开):
然后确保您没有强制执行所有订单的约束,这可能是不可行的
然后整理你的目标函数,(1)对所有完成的订单给予信贷,(2)对成本收取一些(负的,小的)惩罚,并使其最大化。
在计算成本惩罚时,需要做一些数学运算。假设您总是在可能的情况下交付订单,您需要做的是将最大成本惩罚加权为略小于履行订单的价值,以确保求解程序总是选择交付,而不是最小化成本。