likes
comments
collection
share

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

作者站长头像
站长
· 阅读数 87

一.基础方法

1.线性规划

田忌赛马的故事大家都听过,这其实是古人(孙膑)在运筹学上的实践。实际业务场景中,线性规划的方法也有重要应用。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

2.举个简单例子

(1)基本情况

目前想在上海工厂、湖州工厂、昆明工厂生产A、B两个产品。 已知A、B产品每批次的生产量为:

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过, 已知各个工厂生产A、B产品,每个批次所需要耗费的时长是:

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过, 基于现实问题,目前约束条件是:1.本月需求量,A至少100,B至少200。2.上海工厂最多只能投入30个时长,湖州工厂最多只能投入60个时长,昆明工厂最多只能投入80个时长。 另外,各个工厂生产A、B的成本是:

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

求解:需要生产多少批次?在哪个工厂生产?花费的费用最少?

(2)分析求解

假设生产批次为X,需要列矩阵的方式来求解各个工厂生产各个产品,则需要设6个X(X1,X2,X3,X4,X5,X6)。 我们需要列出aX>y的不等式,目前X设好了,就需要对照上面的已知条件,用列矩阵的方式,找出每个X的系数。 如图,按照产量+时长的约束条件,一一列好每个工厂生产A、B产品所需要的系数。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(3)列不等式

矩阵里面,每一行可以看作系数a,目标值的结果放在黄色位置,在excel里面可以用sumproduct作数组乘法运算。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

可以利用WPS的规划求解来计算目标X.

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(4) 结果

最终结果如下,各个工厂的建议生产批次

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

以上就是用Excel完成的简单线性规划问题的求解,实际上我们每个工厂需要生产的产品很多,那我们列的系数矩阵会很大(大概1000行*1000列),最后矩阵的列举与求解,也需要很大计算量。因此用Python去作计算。

3.实际业务需求与数据

3.1 业务背景

(1).有一份各个工厂、各产线能生产不同产品的产能表。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(2).已经根据目前订单情况,预测了未来三个月各个产品的缺口情况。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(3).根据这份需求缺口,需要求解出各个产品分别在哪个工厂生产,才能使生产成本最小。假设生产批次为X,A为每批次的产量,B为需求量,cost_xs为生产一个批次产品的成本系数。则需要计算满足不等式AX>=B(简化为,-AX<=-B)的情况下,使 生产成本=cost_xs*X 最小。

3.2 数据计算

(1) 读取数据

#引入包
import pandas as pd
import numpy as np
import pulp
import time
import sys
import datetime
from dateutil.relativedelta import relativedelta

#读取数据
path='C:/Users/****/案例/'
data=pd.read_excel(path+"数据集.xlsx", sheet_name='源数据集')
data_ys=pd.read_excel(path+"数据集.xlsx", sheet_name='约束')

基础数据是722*7列,各个工厂生产各个产品的产量信息、成本信息

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(2) 按时间需求扩展行列

目前需求缺口的数据是9月,10月,11月的,因此需要对现有的生产数据进行扩展。

#分月标识赋值
a=[9.1, 9.2, 10.1, 10.2, 11.1, 11.2] #需要预测9月上下旬,10月上下旬,11月上下旬的生产批次
for i in range(len(a)):
    data_dp.iloc[int((len(data_dp)/6)*i):int((len(data_dp)/6)*(i+1)),1]=a[i]

#月份赋值
data_dp["月份"]=data_dp["分月标识"].map(lambda x:round(x))
data_dp["矩阵类型"]="单品生产矩阵"

纵向扩展后的数据表如下

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(3) 搭建生产矩阵的表头

##得出第一个矩阵,data_dp
##第二个转置矩阵
data_zz=data_dp.T.reset_index(drop=True)
data_zz

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

需要扩展行列都是4332*4332的矩阵。

#创建初始大矩阵函数
#第一个参数为:转置矩阵  第二个参数为:原矩阵  
def cjjz(dataframe_1,dataframe_2): #(data_zz,data_dp)
    #创建一个数据表
    li = dataframe_2.columns.tolist()
    data_jiu=pd.DataFrame(0,index=li,columns=li).reset_index(drop=True)
    #左右连接
    data_jiu=pd.concat([data_jiu,data_zz],axis=1).reset_index(drop=True)
    #上下连接
    data_jiu=pd.concat([data_jiu,data_dp],axis=0).reset_index(drop=True)
    #重置列名
    data_jiu.columns=list(range(data_jiu.shape[1]))
    #矩阵内容填充为0
    data_jiu.iloc[dataframe_1.shape[0]:,dataframe_2.shape[1]:]=0
    
    return data_jiu

接下来创建初始矩阵。

#调用函数,创建初始矩阵
data_xin=cjjz(data_zz,data_dp)
data_xin.iloc[8:,8:]=data_xin.iloc[8:,8:].astype(int)
data_xin1=np.array(data_xin)
data_xin2=np.array(data_xin)

最终搭建的初始矩阵如图。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(4) 求生产矩阵的系数A

生产矩阵的系数计算,就是当行列的产品标识信息,月份信息相等时,才有产量/批次信息。另外,np.array的数值类型的计算速度要比dataFrame快很多,所以用np.array的数据类型作计算。

for i in data_xin.index.tolist():  # 遍历han
    for j in data_xin.columns.tolist():  # 遍历lie,columns
        # 假设列和行索引都是基于1开始的,因此需要减去1来获取正确的索引位置
        if (data_xin1[i][2]<=data_xin1[2][j]) and  (data_xin1[i][5]==data_xin1[5][j]): #横着月份小于等于竖着&产品代码相等
            # 如果月份和产品代码相等,取第8列的值(列索引为7),并取负数
            data_xin2[i][j]=data_xin[8][j]*(-1)
        else:
            # 如果不匹配,将当前位置的值设置为0
            data_xin2[i][j]=0

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

将计算结果赋值给原有的矩阵。

##赋值刚才求解的数
data_xin.iloc[10:,10:]=pd.DataFrame(data_xin2).iloc[10:,10:]

(5) 需求缺口矩阵B

将每种物料的需求缺口匹配进来。

#匹配每一行物料代码的需求缺口
data_ys_a = pd.merge(data_xin.iloc[:,:10],data_ys,  how='left',left_on=[2,5],right_on=['月份','产品编码'])

(6) 整理列不等式的数据

目前需求缺口矩阵、成本系数矩阵、系数A都有了。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

将数据列转换成np.array的数据格式,以供后续进行计算。

# 使用pulp,求最小值
prob = pulp.LpProblem("min_zhi", sense=pulp.LpMinimize)

#数据准备,系数A,B  A*X<=B
A = np.array(data_xin.iloc[10:,10:]) ##(-A*X)<=(-B), 系数A
B = np.array(data_ys_a.iloc[10:,15:])
cost_xs = np.array(data_xin.iloc[10:,9]) ##成本=cost_xs*X , 系数cost_xs

#给B降维
B=B.flatten()#需求缺口
#构建X
var=[] 
for i in range(len(data_ys_a.iloc[10:,15:].index)):#遍历行
        var.append(pulp.LpVariable(f'x{i}', lowBound=0,cat='Integer'))
        
var_sz=np.array(var)

最终的数据列如下。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(7) 列不等式,求解

遍历数据行,让每一行的产量>缺口,并保证目标函数成本最小。

#目标函数  lpDot可以将两个列表的对应位相乘再相加
prob += pulp.lpDot(cost_xs,var_sz) ##所有工厂生产的成本*批次之和最小

#计算式1,产能
jss_1=np.dot(A,var_sz)
for i in range(jss_1.shape[0]):
    prob+=jss_1[i]<=B[i]

# 求解 使用默认的CBC求解器求解问题
prob.solve(pulp.PULP_CBC_CMD(timeLimit=600))
print(f'优化结果:{pulp.value(prob.objective)}')

最终的优化的目标函数最小值

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

(8) 导出X,即每个产品的最小生产批次

#计算结果
x_sx=[]
x_xsz=[]
for v in prob.variables():
    x_sx.append(v.name)
    x_xsz.append(v.varValue)
#列表转为dataframe
test = pd.DataFrame({'x顺序':x_sx,'x值':x_xsz})
#修改字符类型
test["x顺序"]= test["x顺序"].astype('string')
#创建未知数表
shuchu=pd.DataFrame(data=var,columns=["x顺序"],dtype=str)
#连接表
data_aa=pd.merge(shuchu,test,how="left",left_on=['x顺序'],right_on=['x顺序'])

#最初数据源与结果拼接
data_result=pd.concat([data_dp,data_aa],axis=1)

最终的计算结果如下。各个工厂、各个月份需要生产的产品批次数。

项目-线性规划&Python矩阵求解,在供应链供需产能问题中的应用一.基础方法 1.线性规划 田忌赛马的故事大家都听过,

4.结语

以上是个简单案例,实际业务情况会更复杂,会涉及更多数据清洗、列更多的不等式,拼接更多矩阵以计算系数。

转载自:https://juejin.cn/post/7405503376698228747
评论
请登录