铛铛!小秘籍来咯!
小秘籍团队独辟蹊径,以ARIMA时序预测,目标规划等强大工具,构建了解决复杂问题的独特方案。比例分配,负载均衡的妙用,为降低非法野生动物贸易提供新视角。通过综合分析,描绘出概率、成功与关键因素之间的精妙关系,为客户量身打造创新解决方案。小秘籍团队,始终引领着建模问题求解的风潮。 抓紧小秘籍,我们出发吧~
抓紧小秘籍,我们出发吧~
完整内容可以在文章末尾领取!

2024 Mathorcup高校数学建模挑战赛(C题)| 物流网络货量预测 | 建模秘籍&文章代码思路大全-LMLPHP

第一个问题是建立货量预测模型,对57个分拣中心未来30天每天及每小时的货量进行预测。

假设每个分拣中心的货量预测值为 P i , d P_{i,d} Pi,d,其中 i i i表示分拣中心的编号, d d d表示日期, h h h表示小时。根据题目描述,我们可以得到如下公式:

P i , d = f ( H i , d − 1 , H i , d − 2 , . . . , H i , d − 4 , W i , T d ) P_{i,d} = f(H_{i,d-1}, H_{i,d-2}, ..., H_{i,d-4}, W_i, T_d) Pi,d=f(Hi,d1,Hi,d2,...,Hi,d4,Wi,Td)

其中, H i , d − j H_{i,d-j} Hi,dj表示分拣中心 i i i d − j d-j dj天的货量, W i W_i Wi表示分拣中心 i i i的物流网络配置信息, T d T_d Td表示日期 d d d的特征信息。

在这个模型中,我们使用历史货量、物流网络配置信息和日期特征信息来预测未来的货量。历史货量可以反映出分拣中心的日常运作情况,物流网络配置信息可以反映出分拣中心之间的运输线路关系,日期特征信息可以反映出节假日等因素对货量的影响。

具体的预测方法可以使用多种机器学习算法,如线性回归、决策树、随机森林等。我们可以使用历史数据来训练模型,并通过交叉验证等方法来选择最优的算法和参数。

对于每小时的货量预测,可以将时间粒度缩小,使用同样的方法来预测每个分拣中心每小时的货量。

最终的预测结果可以写入结果表1和表2中。

对于每天的货量预测,可以使用ARIMA(Autoregressive Integrated Moving Average)模型。ARIMA模型是一种基于时间序列的统计模型,可以将时间序列数据转换为平稳序列,并通过自相关和偏相关函数的分析,确定最佳的自回归和移动平均参数。假设时间序列为 x t {x_t} xt,其中 t t t表示时间,ARIMA模型可以表示为:

ϕ ( B ) ( 1 − B ) d x t = θ ( B ) ϵ t \phi(B)(1-B)^d x_t = \theta(B)\epsilon_t ϕ(B)(1B)dxt=θ(B)ϵt

其中, B B B为延迟算子, ϕ ( B ) \phi(B) ϕ(B) θ ( B ) \theta(B) θ(B)为自回归和移动平均算子, d d d为差分阶数, ϵ t \epsilon_t ϵt为白噪声。通过对历史货量数据进行差分,将非平稳序列转换为平稳序列,然后根据自相关和偏相关函数的图像,确定最佳的模型参数,从而进行未来每天的货量预测。

其次,对于每小时的货量预测,可以使用ARIMAX(Autoregressive Integrated Moving Average with Exogenous Variables)模型。ARIMAX模型在ARIMA模型的基础上,增加了外部变量的影响,因此可以更准确地预测货量。假设外部变量为 z t {z_t} zt,ARIMAX模型可以表示为:

ϕ ( B ) ( 1 − B ) d x t = θ ( B ) ϵ t + ψ ( B ) z t \phi(B)(1-B)^d x_t = \theta(B)\epsilon_t + \psi(B)z_t ϕ(B)(1B)dxt=θ(B)ϵt+ψ(B)zt

其中, ψ ( B ) \psi(B) ψ(B)为外部变量的影响项。通过对历史每小时货量数据进行差分,然后根据自相关和偏相关函数的图像,确定最佳的模型参数,从而进行未来每小时的货量预测。

需要注意的是,对于分拣中心数量较多的情况,建议将分拣中心按照地理位置或其他相关特征分组,分别建立模型进行预测,可以提高预测的准确性。

在模型建立完成后,可以利用历史数据进行模型参数的优化,比如通过交叉验证等方法确定模型的最佳参数,从而提高预测的准确性。最后,根据预测结果,可以制定相应的调度和调配计划,合理安排分拣中心的货量和人员,从而提高物流网络的运作效率和降低成本。

解:

我们可以根据历史货量数据,构建一个时间序列模型来预测未来的货量。首先,对于每个分拣中心,我们可以将过去的每天货量数据进行平滑处理,得到一个近似的每日货量趋势。具体来说,我们可以使用移动平均法来平滑数据,即计算过去k天的平均货量作为当天的预测值。这样,我们就可以得到每个分拣中心过去4个月的每天平滑后的货量数据。

假设第 i i i个分拣中心过去4个月的每天平滑后的货量数据为 y i ( t ) , t = 1 , 2 , . . . , 120 y_i(t), t=1,2,...,120 yi(t),t=1,2,...,120。其中, t t t表示时间, t = 1 t=1 t=1表示过去4个月的第一天, t = 120 t=120 t=120表示过去4个月的最后一天。我们可以使用指数平滑法来拟合这个平滑后的货量数据,得到一个近似的每日货量趋势函数 f i ( t ) f_i(t) fi(t)。具体来说,我们可以使用一阶指数平滑法,即:

f i ( t ) = α y i ( t − 1 ) + ( 1 − α ) f i ( t − 1 ) , t = 2 , 3 , . . . , 120 f_i(t)=\alpha y_i(t-1)+(1-\alpha)f_i(t-1), t=2,3,...,120 fi(t)=αyi(t1)+(1α)fi(t1),t=2,3,...,120

其中, α \alpha α称为平滑系数,它控制着过去数据对预测结果的影响程度。 α \alpha α的取值范围为 0 < α < 1 0<\alpha<1 0<α<1,一般来说, α \alpha α越大,过去数据对预测结果的影响越大。根据经验,我们可以取 α = 0.3 \alpha=0.3 α=0.3。这样,我们就可以得到每个分拣中心的每日货量趋势函数 f i ( t ) f_i(t) fi(t)

接下来,我们可以使用指数平滑法来预测未来的货量。具体来说,我们可以使用一阶指数平滑法来预测未来的每日货量,即:

y ^ i ( t + 1 ) = α y i ( t ) + ( 1 − α ) y ^ i ( t ) , t = 1 , 2 , . . . , 30 \hat{y}_i(t+1)=\alpha y_i(t)+(1-\alpha)\hat{y}_i(t), t=1,2,...,30 y^i(t+1)=αyi(t)+(1α)y^i(t),t=1,2,...,30

其中, y ^ i ( t + 1 ) \hat{y}_i(t+1) y^i(t+1)表示第 i i i个分拣中心未来30天每天的货量预测值。

为了更准确地预测每小时的货量,我们可以根据过去30天的每小时货量数据,计算出每小时的平均货量,并使用指数平滑法来预测未来的每小时货量。具体来说,我们可以使用一阶指数平滑法来预测未来的每小时货量,即:

y ^ i ( h + 1 ) = α y i ( h ) + ( 1 − α ) y ^ i ( h ) , h = 1 , 2 , . . . , 24 \hat{y}_i(h+1)=\alpha y_i(h)+(1-\alpha)\hat{y}_i(h), h=1,2,...,24 y^i(h+1)=αyi(h)+(1α)y^i(h),h=1,2,...,24

其中, y ^ i ( h + 1 ) \hat{y}_i(h+1) y^i(h+1)表示第 i i i个分拣中心未来30天每小时的货量预测值, h h h表示小时, h = 1 h=1 h=1表示过去30天的第一个小时, h = 24 h=24 h=24表示过去30天的最后一个小时。

综上所述,我们可以使用指数平滑法来预测未来的货量,具体步骤如下:

  1. 对每个分拣中心的过去4个月每天货量数据进行平滑处理,得到近似的每日货量趋势函数 f i ( t ) , t = 1 , 2 , . . . , 120 f_i(t), t=1,2,...,120 fi(t),t=1,2,...,120

  2. 使用一阶指数平滑法来预测未来的每日货量,即:

y ^ i ( t + 1 ) = α y i ( t ) + ( 1 − α ) y ^ i ( t ) , t = 1 , 2 , . . . , 30 \hat{y}_i(t+1)=\alpha y_i(t)+(1-\alpha)\hat{y}_i(t), t=1,2,...,30 y^i(t+1)=αyi(t)+(1α)y^i(t),t=1,2,...,30
2024 Mathorcup高校数学建模挑战赛(C题)| 物流网络货量预测 | 建模秘籍&amp;文章代码思路大全-LMLPHP

  1. 根据过去30天的每小时货量数据,计算出每小时的平均货量,并使用一阶指数平滑法来预测未来的每小时货量,即:

y ^ i ( h + 1 ) = α y i ( h ) + ( 1 − α ) y ^ i ( h ) , h = 1 , 2 , . . . , 24 \hat{y}_i(h+1)=\alpha y_i(h)+(1-\alpha)\hat{y}_i(h), h=1,2,...,24 y^i(h+1)=αyi(h)+(1α)y^i(h),h=1,2,...,24

最终,我们得到了57个分拣中心未来30天每天及每小时的货量预测值。这些预测值可以写入结果表1和表2中。

代码如下:

import pandas as pd
from sklearn.linear_model import LinearRegression

#读取附件1和附件2的数据
df_daily = pd.read_excel('附件1.xlsx')
df_hourly = pd.read_excel('附件2.xlsx')

#将数据按分拣中心分组
group_daily = df_daily.groupby('分拣中心').sum()
group_hourly = df_hourly.groupby('分拣中心').sum()

#对每个分拣中心建立线性回归模型
model_daily = LinearRegression()
model_hourly = LinearRegression()

#用过去4个月的每日货量作为自变量,建立每天货量的模型
model_daily.fit(group_daily['过去4个月每日货量'].values.reshape(-1,1), group_daily['未来30天每天货量'].values.reshape(-1,1))

#用过去30天的每小时货量作为自变量,建立每小时货量的模型
model_hourly.fit(group_hourly['过去30天每小时货量'].values.reshape(-1,1), group_hourly['未来30天每小时货量'].values.reshape(-1,1))

#预测未来30天每天的货量
daily_pred = model_daily.predict(group_daily['过去4个月每日货量'].values.reshape(-1,1))
#将预测结果写入结果表1
group_daily['预测未来30天每天货量'] = daily_pred

#预测未来30天每小时的货量
hourly_pred = model_hourly.predict(group_hourly['过去30天每小时货量'].values.reshape(-1,1))
#将预测结果写入结果表2
group_hourly['预测未来30天每小时货量'] = hourly_pred

#将结果保存为excel文件
group_daily.to_excel('结果表1.xlsx')
group_hourly.to_excel('结果表2.xlsx')

第二个问题是基于过去90天各分拣中心之间的运输线路平均货量以及未来30天分拣中心之间运输线路的变化情况,对57个分拣中心未来30天每天及每小时的货量进行预测,并将预测结果写入结果表3和表4中。

H i , j , t H_{i,j,t} Hi,j,t为分拣中心i在t时刻的货量, R i , j , t R_{i,j,t} Ri,j,t为分拣中心i到j的运输线路, C i , j , t C_{i,j,t} Ci,j,t为分拣中心i到j的货量占比, H i , t H_{i,t} Hi,t为分拣中心i在t时刻的小时货量, D i , j D_{i,j} Di,j为分拣中心i到j的距离, T T T为未来的时间段, C i , j , t C_{i,j,t} Ci,j,t可以按照线路的平均货量计算,即 C i , j , t = R i , j , t ∑ j = 1 57 R i , j , t C_{i,j,t}=\frac{R_{i,j,t}}{\sum_{j=1}^{57}R_{i,j,t}} Ci,j,t=j=157Ri,j,tRi,j,t,则问题2可以建模为如下的优化问题: min ⁡ H i , t , H i , j , t ∑ t = 1 T ∑ i = 1 57 ∑ j = 1 57 H i , j , t D i , j s.t. H i , t = ∑ j = 1 57 H i , j , t , i = 1 , … , 57 , t = 1 , … , T H i , t = ∑ j = 1 57 C i , j , t H i , j , t , i = 1 , … , 57 , t = 1 , … , T H i , j , t ≥ 0 , i = 1 , … , 57 , j = 1 , … , 57 , t = 1 , … , T \begin{split}\min_{H_{i,t},H_{i,j,t}}&\sum_{t=1}^T\sum_{i=1}^{57}\sum_{j=1}^{57}H_{i,j,t}D_{i,j}\\\text{s.t.}&H_{i,t}=\sum_{j=1}^{57}H_{i,j,t},i=1,\dots,57,t=1,\dots,T\\&H_{i,t}=\sum_{j=1}^{57}C_{i,j,t}H_{i,j,t},i=1,\dots,57,t=1,\dots,T\\&H_{i,j,t}\geq 0,i=1,\dots,57,j=1,\dots,57,t=1,\dots,T\end{split} Hi,t,Hi,j,tmins.t.t=1Ti=157j=157Hi,j,tDi,jHi,t=j=157Hi,j,t,i=1,,57,t=1,,THi,t=j=157Ci,j,tHi,j,t,i=1,,57,t=1,,THi,j,t0,i=1,,57,j=1,,57,t=1,,T其中第一个约束保证每个分拣中心的每天货量等于每小时货量之和,第二个约束保证每个分拣中心的每天货量等于其到其他分拣中心的运输货量之和。该模型的目标函数为总的运输距离,即希望通过调整每个分拣中心的货量,使得总的运输距离最小。

第二个问题的目标是根据过去90天各分拣中心之间的运输线路平均货量以及未来30天分拣中心之间运输线路的变化情况,预测未来30天每天及每小时的货量。为了解决这个问题,可以采用时间序列预测的方法,即通过分析历史数据的趋势和周期性,来预测未来一段时间的数据。具体而言,可以采用ARIMA模型(自回归移动平均模型)来进行预测。

ARIMA模型是一种常用的时间序列分析方法,它能够很好地处理非平稳的时间序列数据。ARIMA模型的核心思想是通过对时间序列数据进行差分运算,使其变成平稳的数据,然后再建立自回归模型和移动平均模型,来拟合时间序列数据的趋势和周期性。ARIMA模型的参数包括自回归阶数p、差分阶数d和移动平均阶数q,通过对这些参数的选择和拟合,可以得到最优的ARIMA模型来进行预测。

在本问题中,可以将每个分拣中心的每天货量作为一个时间序列数据,对其进行差分运算,获取平稳的数据。然后,根据过去90天各分拣中心之间的运输线路平均货量以及未来30天分拣中心之间运输线路的变化情况,来选择ARIMA模型的参数。最后,使用拟合好的ARIMA模型来预测未来30天每个分拣中心的每天及每小时货量,将预测结果写入结果表3和表4中。

在选择ARIMA模型参数的过程中,可以使用一些常用的方法,比如自相关函数(ACF)和偏自相关函数(PACF)来辅助选择p和q的值。同时,可以通过一些评价指标来评估模型的拟合效果,比如均方根误差(RMSE)和平均绝对误差(MAE),以此来选择最优的模型。

总的来说,通过建立ARIMA模型,可以很好地解决第二个问题,预测未来30天每天及每小时的货量,并将预测结果写入结果表3和表4中。同时,通过选择合适的模型参数和评价指标,可以提高预测的准确性和稳定性。

问题2:建立货量预测模型,对57个分拣中心未来30天每天及每小时的货量进行预测,将预测结果写入结果表3和表4中。

解决方案:

根据问题描述,问题2可以分为两部分:一是预测57个分拣中心未来30天每天的货量,二是预测57个分拣中心未来30天每小时的货量。以下分别介绍两部分的解决方案。

  1. 预测57个分拣中心未来30天每天的货量

首先,根据过去90天各分拣中心之间的运输线路平均货量,可以得到每个分拣中心之间的平均每天货量,记为 A i j A_{ij} Aij,其中 i i i为起点分拣中心, j j j为终点分拣中心。然后,根据未来30天分拣中心之间运输线路的变化情况,可以得到每个分拣中心之间的每天运输货量的变化情况,记为 B i j B_{ij} Bij。因此,未来30天每天每个分拣中心的总货量可以表示为:

C i = ∑ j = 1 57 ( A i j + B i j ) C_{i}=\sum_{j=1}^{57} (A_{ij}+B_{ij}) Ci=j=157(Aij+Bij)

其中, C i C_{i} Ci表示第 i i i个分拣中心未来30天每天的总货量。将该公式应用到每个分拣中心,就可以得到57个分拣中心未来30天每天的货量预测结果,即结果表3中的数据。

  1. 预测57个分拣中心未来30天每小时的货量

根据过去30天每小时的货量数据,可以得到每个分拣中心过去30天每小时的平均货量,记为 D i D_{i} Di,其中 i i i为分拣中心。然后,根据未来30天每小时的货量变化情况,可以得到每个分拣中心未来30天每小时的总货量变化情况,记为 E i E_{i} Ei。因此,未来30天每小时每个分拣中心的总货量可以表示为:

F i = ∑ j = 1 30 ( D i + E i ) F_{i}=\sum_{j=1}^{30} (D_{i}+E_{i}) Fi=j=130(Di+Ei)

其中, F i F_{i} Fi表示第 i i i个分拣中心未来30天每小时的总货量。将该公式应用到每个分拣中心,就可以得到57个分拣中心未来30天每小时的货量预测结果,即结果表4中的数据。

综上所述,根据过去90天各分拣中心之间的运输线路平均货量以及未来30天分拣中心之间运输线路的变化情况,可以得到57个分拣中心未来30天每天及每小时的货量预测结果,并将其分别写入结果表3和表4中。

# 导入所需的包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# 读取附件1-4的数据
df1 = pd.read_excel('附件1.xlsx')
df2 = pd.read_excel('附件2.xlsx')
df3 = pd.read_excel('附件3.xlsx')
df4 = pd.read_excel('附件4.xlsx')

# 合并附件1和附件2的数据,即过去4个月和过去30天的货量数据
df = pd.concat([df1, df2], axis=1)

# 对每个分拣中心进行预测
for center in df.columns:
    # 构建训练集和测试集
    X = df[center].dropna().index.values.reshape(-1, 1)
    y = df[center].dropna().values.reshape(-1, 1)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)

    # 训练线性回归模型
    lr = LinearRegression()
    lr.fit(X_train, y_train)

    # 预测未来30天每天的货量
    future_days = np.arange(len(df1[center]), len(df[center])+30).reshape(-1, 1)
    y_pred = lr.predict(future_days)

    # 将预测结果写入结果表1和表2中
    df.loc[len(df1)+30:, center] = y_pred.reshape(-1)

# 对分拣中心之间的运输线路进行预测
# 创建一个空的DataFrame用于存放预测结果
df_result = pd.DataFrame(columns=['start_center', 'end_center', 'avg_load'])
# 遍历附件3中的运输线路
for index, row in df3.iterrows():
    # 获取起始分拣中心和结束分拣中心的名称
    start_center = row['start']
    end_center = row['end']
    # 获取过去90天该运输线路的平均货量
    avg_load = row['avg_load']
    # 获取未来30天该运输线路的变化情况
    change = df4.loc[df4['start'] == start_center, end_center].values[0]
    # 根据变化情况对平均货量进行调整
    if change < 0:
        # 若变化为负数,表示该运输线路货量下降,对平均货量进行降低
        avg_load = avg_load * (1 + change)
    else:
        # 若变化为正数,表示该运输线路货量上升,对平均货量进行增加
        avg_load = avg_load * (1 + change)

    # 将预测结果写入结果表3中
    df_result.loc[len(df_result)] = [start_center, end_center, avg_load]

# 根据预测结果计算各分拣中心未来30天每小时的货量
# 创建一个空的DataFrame用于存放预测结果
df_hour = pd.DataFrame(columns=list(range(24)))
# 遍历附件1中的分拣中心
for center in df1.columns:
    # 获取该分拣中心在附件3中的运输线路
    df_temp = df_result[df_result['end_center'] == center]
    # 根据运输线路计算每个小时的货量
    for hour in range(24):
        load = 0
        for index, row in df_temp.iterrows():
            # 获取起始分拣中心和该分拣中心的运输线路
            start_center = row['start_center']
            load_avg = row['avg_load']
            # 根据每小时的货量变化情况对平均货量进行调整
            change = df4.loc[df4['start'] == start_center, center].values[0]
            if change < 0:
                load_avg = load_avg * (1 + change)
            else:
                load_avg = load_avg * (1 + change)
            # 计算每个小时的货量
            load += load_avg / 24
        # 将预测结果写入结果表4中
        df_hour.loc[center, hour] = load

# 将预测结果写入结果表3和表4中
df_result.to_excel('结果表3.xlsx', index=False)
df_hour.to_excel('结果表4.xlsx')

# 以下为平均货量的可视化展示
plt.figure(figsize=(10, 8))
sns.barplot(x='start_center', y='avg_load', data=df_result)
plt.xticks(rotation=45)
plt.xlabel('Start Center')
plt.ylabel('Avg Load')
plt.title('Avg Load for Each Start Center')
plt.show()

# 以下为每个分拣中心每小时的货量可视化展示
plt.figure(figsize=(10, 8))
sns.lineplot(data=df_hour.T)
plt.xlabel('Hour')
plt.ylabel('Load')
plt.title('Load for Each Hour')
plt.legend(bbox_to_anchor=(1.02, 1), loc=2, borderaxespad=0)
plt.show()

问题3:根据附件1-4,请基于问题2的预测结果建立模型,给出未来30天每个分拣中心每个班次的出勤人数,并写入结果表5中。要求在每天的货量处理完成的基础上,安排的人天数(例如30天每天出勤200名员工,则总人天数为6000)尽可能少,且每天的实际小时人效尽量均衡。

设每个分拣中心的货量预测为 Q i Q_i Qi,每个分拣中心共有 T T T个班次,每个班次需要安排的总人数为 n i n_i ni,每个班次使用的正式工人数为 m i m_i mi,使用的临时工人数为 k i k_i ki

首先,根据每个分拣中心的货量预测,可以得到每个分拣中心每天的总货量 Q i Q_i Qi,则每个班次需要处理的平均货量为 Q i T \frac{Q_i}{T} TQi

其次,根据问题2的假设,每个分拣中心的正式工最高小时人效为25包裹/小时,临时工最高小时人效为20包裹/小时。则每个班次需要的工作时间为 Q i 25 m i + 20 k i \frac{Q_i}{25m_i+20k_i} 25mi+20kiQi小时。
2024 Mathorcup高校数学建模挑战赛(C题)| 物流网络货量预测 | 建模秘籍&amp;文章代码思路大全-LMLPHP

因此,每个班次需要安排的总人数 n i n_i ni可表示为:
n i = m i + k i = ( Q i 25 m i + 20 k i ) × 1 8 × 1 Q i T = T 200 \begin{equation} n_i = m_i + k_i = (\frac{Q_i}{25m_i+20k_i})\times \frac{1}{8} \times \frac{1}{\frac{Q_i}{T}} = \frac{T}{200} \end{equation} ni=mi+ki=(25mi+20kiQi)×81×TQi1=200T
通过上述公式,可以得到每个班次需要安排的总人数,从而可以得到每个班次需要的正式工人数和临时工人数,即 m i m_i mi k i k_i ki

为了达到每天安排的人天数尽可能少的目标,可以设置一个变量 N N N,表示每天需要安排的总人数。则 N N N可以表示为:
N = ∑ i = 1 57 n i = ∑ i = 1 57 T 200 = 57 T 200 \begin{equation} N = \sum_{i=1}^{57}n_i = \sum_{i=1}^{57}\frac{T}{200} = \frac{57T}{200} \end{equation} N=i=157ni=i=157200T=20057T

为了使每天的实际小时人效尽量均衡,可以设置一个变量 E E E,表示每天的实际小时人效。则 E E E可以表示为:
E = ∑ i = 1 57 Q i N T \begin{equation} E = \frac{\sum_{i=1}^{57}Q_i}{NT} \end{equation} E=NTi=157Qi

因此,问题3可以建模为以下数学模型:
min ⁡ N s.t. N = 57 T 200 E = ∑ i = 1 57 Q i N T m i + k i = T 200 , i = 1 , 2 , ⋯   , 57 25 m i + 20 k i ≥ Q i , i = 1 , 2 , ⋯   , 57 0 ≤ m i ≤ T 200 , i = 1 , 2 , ⋯   , 57 0 ≤ k i ≤ T 200 , i = 1 , 2 , ⋯   , 57 m i ∈ Z ≥ 0 , i = 1 , 2 , ⋯   , 57 k i ∈ Z ≥ 0 , i = 1 , 2 , ⋯   , 57 \begin{equation} \begin{aligned} & \min & & N \\ & \text{s.t.} & & N = \frac{57T}{200} \\ & & & E = \frac{\sum_{i=1}^{57}Q_i}{NT} \\ & & & m_i + k_i = \frac{T}{200}, \quad i = 1,2, \cdots, 57 \\ & & & 25m_i + 20k_i \geq Q_i, \quad i = 1,2, \cdots, 57 \\ & & & 0 \leq m_i \leq \frac{T}{200}, \quad i = 1,2, \cdots, 57 \\ & & & 0 \leq k_i \leq \frac{T}{200}, \quad i = 1,2, \cdots, 57 \\ & & & m_i \in \mathbb{Z}_{\geq 0}, \quad i = 1,2, \cdots, 57 \\ & & & k_i \in \mathbb{Z}_{\geq 0}, \quad i = 1,2, \cdots, 57 \\ \end{aligned} \end{equation} mins.t.NN=20057TE=NTi=157Qimi+ki=200T,i=1,2,,5725mi+20kiQi,i=1,2,,570mi200T,i=1,2,,570ki200T,i=1,2,,57miZ0,i=1,2,,57kiZ0,i=1,2,,57

其中, N N N表示每天需要安排的总人数, T T T表示每个分拣中心的班次数, E E E表示每天的实际小时人效, m i m_i mi表示每个分拣中心使用的正式工人数, k i k_i ki表示每个分拣中心使用的临时工人数, Q i Q_i Qi表示每个分拣中心的货量预测。约束条件1保证每天安排的总人数不变,约束条件2保证每天的实际小时人效不变,约束条件3保证每个班次需要处理的货量相同,约束条件4保证每个班次需要的工作时间相同,约束条件5和6保证每个班次使用的正式工和临时工人数不超过总人数,约束条件7和8保证每个班次使用的正式工和临时工人数为非负整数。

首先,根据问题2的预测结果,我们可以得到每个分拣中心在未来30天每天每小时的货量情况。为了尽可能少的使用人力资源,我们可以采用动态规划的方法来确定每个分拣中心每个班次的出勤人数。

设第t天第i个分拣中心的第j个班次的最优人数为 N i j ∗ N_{ij}^* Nij,则有以下递推关系式:
N i j ∗ = min ⁡ k = 0 j − 1 { N i k ∗ + N i j − k ∗ } + N j N_{ij}^* = \min \limits_{k=0}^{j-1} \left\{N_{ik}^* + N_{ij-k}^* \right\} + N_j Nij=k=0minj1{Nik+Nijk}+Nj
其中, N i j ∗ N_{ij}^* Nij表示第t天第i个分拣中心在第j个班次的最优人数, N j N_j Nj为第j个班次的人数指标,即正式工和临时工的人数上限。

根据上述递推关系式,我们可以得到每个分拣中心每个班次的最优人数。为了保证每天的实际小时人效尽量均衡,我们可以将每天的货量平均分配到各个班次,即每个班次的货量比例与人数比例相同。假设第t天第i个分拣中心的总货量为 V i t V_{it} Vit,则第j个班次的货量为:
V i j = V i t ∑ j = 1 6 N i j ∗ N i j ∗ V_{ij} = \frac{V_{it}}{\sum \limits_{j=1}^{6} N_{ij}^*} N_{ij}^* Vij=j=16NijVitNij
为了保证每天的货量处理完成,我们还需要满足以下约束条件:
∑ i = 1 57 ∑ j = 1 6 N i j ∗ = 6000 \sum \limits_{i=1}^{57} \sum \limits_{j=1}^{6} N_{ij}^* = 6000 i=157j=16Nij=6000
∑ i = 1 57 ∑ j = 1 6 V i j = ∑ i = 1 57 V i t \sum \limits_{i=1}^{57} \sum \limits_{j=1}^{6} V_{ij} = \sum \limits_{i=1}^{57} V_{it} i=157j=16Vij=i=157Vit
其中,6000为总人天数, ∑ i = 1 57 V i t \sum \limits_{i=1}^{57} V_{it} i=157Vit为总货量。

根据以上条件,我们可以建立一个线性规划模型,求解出每个分拣中心每个班次的最优人数,从而实现在保证每天货量处理完成的基础上,尽可能少的使用人力资源,且每天的实际小时人效尽量均衡。

综上所述,我们可以通过动态规划和线性规划的方法,根据问题2的预测结果建立模型,给出未来30天每个分拣中心每个班次的出勤人数,并将结果写入结果表5中。

问题3:假设每个分拣中心有60名正式工,在人员安排时将优先使用正式工,若需额外人员将使用临时工。请基于问题2的预测结果建立模型,给出未来30天每个分拣中心每个班次的出勤人数,并写入结果表5中。

解:
首先,根据问题2的预测结果,得到每个分拣中心每天的货量 L i d L_i^d Lid及每小时的货量 L i h L_i^h Lih,其中 i i i表示第 i i i个分拣中心, d d d表示第 d d d天, h h h表示第 h h h小时。根据题目描述,每个分拣中心需要安排的人员包括正式工和临时工,设每个分拣中心的正式工人数为 x i x_i xi,临时工人数为 y i y_i yi,则每个分拣中心每天需要处理的货量为:

L i d = x i ⋅ 8 ⋅ H i d + y i ⋅ 8 ⋅ H i d L_i^d = x_i \cdot 8 \cdot H_i^d + y_i \cdot 8 \cdot H_i^d Lid=xi8Hid+yi8Hid

其中 H i d H_i^d Hid表示第 i i i个分拣中心第 d d d天每小时的人效,8表示每人每天出勤8个小时。

根据题目要求,每个分拣中心每天分为6个班次,分别为:00:00-08:00,05:00-13:00,08:00-16:00,12:00-20:00,14:00-22:00,16:00-24:00,每个人员(正式工或临时工)每天只能出勤一个班次。设每个分拣中心每个班次需要出勤的正式工人数为 a i , j a_{i,j} ai,j,需要出勤的临时工人数为 b i , j b_{i,j} bi,j,其中 i i i表示第 i i i个分拣中心, j j j表示第 j j j个班次,满足如下条件:

∑ j = 1 6 a i , j ≤ x i , ∑ j = 1 6 b i , j ≤ y i , ∀ i \sum_{j=1}^{6}a_{i,j} \leq x_i, \quad \sum_{j=1}^{6}b_{i,j} \leq y_i, \quad \forall i j=16ai,jxi,j=16bi,jyi,i

即每个分拣中心每天需要安排的正式工人数不能超过正式工总数,临时工也类似。

为了保证每天的实际小时人效尽量均衡,可以设定一个最小的人效阈值,表示每个班次需要达到的最小人效水平,设为 H m i n H_{min} Hmin,则有:

H i d ≥ H m i n , ∀ i , d H_i^d \geq H_{min}, \quad \forall i, d HidHmin,i,d

为了保证每天的实际小时人效尽量均衡,可以设定一个最大的人效阈值,表示每个班次需要达到的最大人效水平,设为 H m a x H_{max} Hmax,则有:

H i d ≤ H m a x , ∀ i , d H_i^d \leq H_{max}, \quad \forall i, d HidHmax,i,d

为了使得每天的人员安排尽可能少,可以设定一个最小的人效差值,表示每个班次人效的差值不能超过该阈值,设为 H d i f f H_{diff} Hdiff,则有:

H m a x − H m i n ≤ H d i f f H_{max} - H_{min} \leq H_{diff} HmaxHminHdiff

为了使得人员安排尽可能少,可以设定一个最小的人员阈值,表示每个分拣中心每天至少需要安排的人员总数,设为 P m i n P_{min} Pmin,则有:

8 ⋅ P m i n ≤ x i + y i , ∀ i 8 \cdot P_{min} \leq x_i + y_i, \quad \forall i 8Pminxi+yi,i

为了使得每天安排的人员尽可能少,可以设定一个最大的人员阈值,表示每个分拣中心每天至多需要安排的人员总数,设为 P m a x P_{max} Pmax,则有:

8 ⋅ P m a x ≥ x i + y i , ∀ i 8 \cdot P_{max} \geq x_i + y_i, \quad \forall i 8Pmaxxi+yi,i

为了使得正式工的出勤率尽可能均衡,可以设定一个最小的出勤率阈值,表示每名正式工的出勤率不能低于该阈值,设为 R m i n R_{min} Rmin,则有:

∑ j = 1 6 a i , j 30 ≥ R m i n , ∀ i \frac{\sum_{j=1}^{6}a_{i,j}}{30} \geq R_{min}, \quad \forall i 30j=16ai,jRmin,i

为了保证每名正式工连续出勤天数不能超过7天,可以使用0-1变量 x i , j , d x_{i,j,d} xi,j,d表示第 i i i个分拣中心的第 j j j个班次是否在第 d d d天出勤,如果出勤则 x i , j , d = 1 x_{i,j,d} = 1 xi,j,d=1,否则 x i , j , d = 0 x_{i,j,d} = 0 xi,j,d=0,则有:

∑ j = 1 6 x i , j , d ≤ 7 , ∀ i , d \sum_{j=1}^{6}x_{i,j,d} \leq 7, \quad \forall i, d j=16xi,j,d7,i,d

为了使得每天的实际小时人效尽量均衡,可以设定一个最小的时间差值,表示每个班次的时间差值不能超过该阈值,设为 T d i f f T_{diff} Tdiff,则有:

T m a x − T m i n ≤ T d i f f T_{max} - T_{min} \leq T_{diff} TmaxTminTdiff

为了计算每个班次的时间差值,可以使用0-1变量 y i , j , d y_{i,j,d} yi,j,d表示第 i i i个分拣中心的第 j j j个班次是否在第 d d d天出勤,如果出勤则 y i , j , d = 1 y_{i,j,d} = 1 yi,j,d=1,否则 y i , j , d = 0 y_{i,j,d} = 0 yi,j,d=0,则有:

y i , j , d ≥ x i , j , d + 1 − x i , j , d , ∀ i , j , d y_{i,j,d} \geq x_{i,j,d+1} - x_{i,j,d}, \quad \forall i, j, d yi,j,dxi,j,d+1xi,j,d,i,j,d

其中 d + 1 d+1 d+1表示第 d + 1 d+1 d+1天, d d d表示第 d d d天,即如果第 d d d天出勤,则第 d + 1 d+1 d+1天也需要出勤,否则不需要。

综上所述,可以建立如下混合整数规划模型:

min ⁡ ∑ i = 1 57 ∑ j = 1 6 ( a i , j + b i , j ) \min \sum_{i=1}^{57}\sum_{j=1}^{6}(a_{i,j}+b_{i,j}) mini=157j=16(ai,j+bi,j)
s . t . L i d = x i ⋅ 8 ⋅ H i d + y i ⋅ 8 ⋅ H i d , ∀ i , d s.t. \quad L_i^d = x_i \cdot 8 \cdot H_i^d + y_i \cdot 8 \cdot H_i^d, \quad \forall i, d s.t.Lid=xi8Hid+yi8Hid,i,d
H i d ≥ H m i n , ∀ i , d H_i^d \geq H_{min}, \quad \forall i, d HidHmin,i,d
H i d ≤ H m a x , ∀ i , d H_i^d \leq H_{max}, \quad \forall i, d HidHmax,i,d
H m a x − H m i n ≤ H d i f f H_{max} - H_{min} \leq H_{diff} HmaxHminHdiff
8 ⋅ P m i n ≤ x i + y i , ∀ i 8 \cdot P_{min} \leq x_i + y_i, \quad \forall i 8Pminxi+yi,i
8 ⋅ P m a x ≥ x i + y i , ∀ i 8 \cdot P_{max} \geq x_i + y_i, \quad \forall i 8Pmaxxi+yi,i
∑ j = 1 6 a i , j 30 ≥ R m i n , ∀ i \frac{\sum_{j=1}^{6}a_{i,j}}{30} \geq R_{min}, \quad \forall i 30j=16ai,jRmin,i
∑ j = 1 6 x i , j , d ≤ 7 , ∀ i , d \sum_{j=1}^{6}x_{i,j,d} \leq 7, \quad \forall i, d j=16xi,j,d7,i,d
T m a x − T m i n ≤ T d i f f T_{max} - T_{min} \leq T_{diff} TmaxTminTdiff
y i , j , d ≥ x i , j , d + 1 − x i , j , d , ∀ i , j , d y_{i,j,d} \geq x_{i,j,d+1} - x_{i,j,d}, \quad \forall i, j, d yi,j,dxi,j,d+1xi,j,d,i,j,d
∑ j = 1 6 a i , j ≤ x i , ∑ j = 1 6 b i , j ≤ y i , ∀ i \sum_{j=1}^{6}a_{i,j} \leq x_i, \quad \sum_{j=1}^{6}b_{i,j} \leq y_i, \quad \forall i j=16ai,jxi,j=16bi,jyi,i
x i , j , d , y i , j , d ∈ { 0 , 1 } , ∀ i , j , d x_{i,j,d}, y_{i,j,d} \in \{0,1\}, \quad \forall i, j, d xi,j,d,yi,j,d{0,1},i,j,d
x i , y i ∈ Z + , ∀ i x_i, y_i \in \mathbb{Z}^+, \quad \forall i xi,yiZ+,i

其中, L i d L_i^d Lid表示第 i i i个分拣中心第 d d d天的货量, H i d H_i^d Hid表示第 i i i个分拣中心第 d d d天每小时的人效, x i x_i xi表示第 i i i个分拣中心的正式工人数, y i y_i yi表示第 i i i个分拣中心的临时工人数, H m i n H_{min} Hmin表示最小的人效阈值, H m a x H_{max} Hmax表示最大的人效阈值, H d i f f H_{diff} Hdiff表示人效差值阈值, P m i n P_{min} Pmin表示最小的人员阈值, P m a x P_{max} Pmax表示最大的人员阈值, R m i n R_{min} Rmin表示最小的出勤率阈值, T m i n T_{min} Tmin表示最小的时间阈值, T m a x T_{max} Tmax表示最大的时间阈值。模型的目标函数为最小化总人数,约束条件包括每个分拣中心每天需要处理的货量、人效的最小和最大阈值、人效差值阈值、每个分拣中心每天需要安排的人员总数的最小和最大阈值、正式工的出勤率、连续出勤天数不能超过7天、时间差值阈值、0-1变量的约束和正式工和临时工的取值范围。

通过求解该模型,可以得到每个分拣中心每天每个班次的出勤人数,从而得到未来30

# 导入必要的库
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression

# 读取附件1-4的数据
df1 = pd.read_csv('附件1.csv')
df2 = pd.read_csv('附件2.csv')
df3 = pd.read_csv('附件3.csv')
df4 = pd.read_csv('附件4.csv')

# 将附件1-4的数据进行合并,方便后续处理
df = pd.concat([df1, df2, df3, df4], ignore_index=True)

# 根据分拣中心和时间进行分组,计算每个分拣中心每天及每小时的平均货量
df_mean = df.groupby(['分拣中心', '时间']).mean()

# 将平均货量作为新的特征,重命名为“平均货量”
df_mean = df_mean.rename(columns={'货量': '平均货量'})

# 将附件3中分拣中心之间的平均货量作为新的特征,重命名为“线路平均货量”
df_mean = df_mean.merge(df3, on='分拣中心')

# 构建线性回归模型,预测每个分拣中心每天的货量
X = df_mean[['线路平均货量', '分拣中心']]
y = df_mean['平均货量']
lr = LinearRegression()
lr.fit(X, y)

# 使用模型预测每个分拣中心未来30天每天的货量
pred = lr.predict(df_mean[['线路平均货量', '分拣中心']])

# 将预测结果写入结果表1中
df_mean['预测货量'] = pred

# 计算每个分拣中心未来30天每天的总货量
df_total = df_mean.groupby('分拣中心').sum()

# 根据每个分拣中心未来30天每天的总货量,计算每个分拣中心未来30天每天的每小时货量
df_total['每小时货量'] = df_total['预测货量'] / 24

# 将每个分拣中心未来30天每天的每小时货量写入结果表2中
df_result2 = pd.DataFrame({'分拣中心': df_total.index, '每小时货量': df_total['每小时货量']})
df_result2.to_csv('结果表2.csv', index=False)

# 构建线性回归模型,预测每个分拣中心每小时的货量
X = df_mean[['线路平均货量', '分拣中心']]
y = df_mean['平均货量']
lr = LinearRegression()
lr.fit(X, y)

# 使用模型预测每个分拣中心未来30天每小时的货量
pred = lr.predict(df_mean[['线路平均货量', '分拣中心']])

# 将预测结果写入结果表1中
df_mean['预测货量'] = pred

# 将预测结果写入结果表3和表4中
df_result3 = df_mean[['分拣中心', '时间', '预测货量']].rename(columns={'预测货量': '每天货量'})
df_result3.to_csv('结果表3.csv', index=False)
df_result4 = df_mean[['分拣中心', '时间', '预测货量']].rename(columns={'预测货量': '每小时货量'})
df_result4.to_csv('结果表4.csv', index=False)

# 根据预测结果,计算每个分拣中心每个班次的出勤人数
df_people = df_mean.groupby(['分拣中心', '时间']).sum()

# 根据预测结果,确定每个分拣中心每个班次的出勤人数
df_people['每班人数'] = np.ceil(df_people['预测货量'] / df_people['每小时货量'])
df_people = df_people.reset_index()

# 将每个分拣中心每个班次的出勤人数写入结果表5中
df_result5 = df_people[['分拣中心', '时间', '每班人数']]
df_result5.to_csv('结果表5.csv', index=False)

# 定义函数,计算每个分拣中心每天的实际人天数
def get_people_days(df):
    df['人天数'] = df['每班人数'] * 6
    return df

# 将每个分拣中心每个班次的出勤人数重新按天进行分组,并计算每天的实际人天数
df_people = df_people.groupby('分拣中心').apply(get_people_days)

# 根据每个分拣中心每天的实际人天数,计算每个分拣中心未来30天的总人天数
df_total = df_people.groupby('分拣中心').sum()

# 计算每个分拣中心未来30天的总人天数
total_days = df_total['人天数'].sum()

# 根据每个分拣中心未来30天的总人天数,计算每个分拣中心每天的实际小时人效
df_total['实际小时人效'] = df_total['预测货量'] / df_total['人天数'] / 6

# 将每个分拣中心每天的实际小时人效写入结果表5中
df_result5['实际小时人效'] = df_total['实际小时人效']
df_result5.to_csv('结果表5.csv', index=False)

# 定义函数,计算每个分拣中心每个班次的出勤人数
def get_people(df, people):
    # 计算每个分拣中心每个班次的出勤人数
    df['每班人数'] = np.ceil(df['预测货量'] / df['实际小时人效'])
    # 如果出勤人数超过正式工数量,则将超过的部分用临时工补足
    df['每班临时工数'] = np.where(df['每班人数'] > people, df['每班人数'] - people, 0)
    df['每班人数'] = np.where(df['每班人数'] > people, people, df['每班人数'])
    return df

# 根据分拣中心和时间进行分组,根据每个分拣中心每天的实际小时人效,计算每个分拣中心每个班次的出勤人数
df_people = df_people.groupby(['分拣中心', '时间']).apply(get_people, people=60)

# 将每个分拣中心每个班次的出勤人数写入结果表6中
df_result6 = df_people[['分拣中心', '时间', '每班人数', '每班临时工数']]
df_result6.to_csv('结果表6.csv', index=False)

第四个问题是建立模型,确定未来30天每名正式工及临时工的班次出勤计划,并给出未来30天每天六个班次中,每名正式工将在哪些班次出勤,每个班次需要雇佣多少临时工。

首先,根据问题1和问题2的预测结果,可以得到每个分拣中心未来30天每天及每小时的货量预测值 Q i ( d ) Q_i^{(d)} Qi(d) Q i ( h ) Q_i^{(h)} Qi(h),其中 i i i代表分拣中心编号, d d d代表天数, h h h代表小时。同时,根据问题3中的假设,每个分拣中心有60名正式工,因此总的正式工人数为 N = 60 × 57 = 3420 N=60\times57=3420 N=60×57=3420

接下来,假设每个班次的工作时间为8小时,那么每天的工作班次数为6个,可以得到每个班次的开始时间 t k t_k tk,其中 k k k代表班次编号,如下所示:

t 0 = 0 小时 ,   t 1 = 5 小时 ,   t 2 = 8 小时 ,   t 3 = 12 小时 ,   t 4 = 14 小时 ,   t 5 = 16 小时 t_0=0\text{小时},\ t_1=5\text{小时},\ t_2=8\text{小时},\ t_3=12\text{小时},\ t_4=14\text{小时},\ t_5=16\text{小时} t0=0小时, t1=5小时, t2=8小时, t3=12小时, t4=14小时, t5=16小时

每个班次的结束时间为上一个班次的开始时间加8小时,即 t k = t k − 1 + 8 t_k=t_{k-1}+8 tk=tk1+8,其中 t 0 = 0 t_0=0 t0=0

假设每名正式工在每个班次的小时人效为 p i j ( k ) p_{ij}^{(k)} pij(k),其中 i i i代表分拣中心编号, j j j代表正式工编号, k k k代表班次编号。根据问题1和问题2的条件,可以得到每个班次的正式工小时人效的最大值为25包裹/小时,临时工小时人效的最大值为20包裹/小时。

根据以上假设和条件,可以得到每名正式工在每个班次的工作时间为 8 × p i j ( k ) 8\times p_{ij}^{(k)} 8×pij(k)小时,因此每个班次需要雇佣的正式工人数为:

m i j ( k ) = 8 × p i j ( k ) 25 m_{ij}^{(k)}=\frac{8\times p_{ij}^{(k)}}{25} mij(k)=258×pij(k)

每个班次需要雇佣的临时工人数为:

n i ( k ) = Q i ( h ) 20 − m i j ( k ) n_{i}^{(k)}=\frac{Q_i^{(h)}}{20}-m_{ij}^{(k)} ni(k)=20Qi(h)mij(k)

因此,每个班次需要的总人数为 N i ( k ) = m i j ( k ) + n i ( k ) N_{i}^{(k)}=m_{ij}^{(k)}+n_{i}^{(k)} Ni(k)=mij(k)+ni(k),其中 i i i代表分拣中心编号, j j j代表正式工编号, k k k代表班次编号。

接下来,为了使得每天的实际小时人效尽量均衡,可以将每个班次的总人数按照每个分拣中心的货量比例进行分配,即:

N i ( k ) = Q i ( h ) ∑ i = 1 57 Q i ( h ) × N N_{i}^{(k)}=\frac{Q_i^{(h)}}{\sum_{i=1}^{57}Q_i^{(h)}}\times N Ni(k)=i=157Qi(h)Qi(h)×N

其中 i i i代表分拣中心编号, k k k代表班次编号。这样可以保证每个班次的人数与每个分拣中心的货量成正比,从而实现每天的实际小时人效尽量均衡。

最后,为了使得每天的人天数尽可能少,可以将每个分拣中心每天的总人数按照每个班次的需求人数比例进行分配,即:
2024 Mathorcup高校数学建模挑战赛(C题)| 物流网络货量预测 | 建模秘籍&amp;文章代码思路大全-LMLPHP

n i ( d ) = N i ( k ) ∑ k = 1 6 N i ( k ) × N i ( k ) n_{i}^{(d)}=\frac{N_{i}^{(k)}}{\sum_{k=1}^{6}N_{i}^{(k)}}\times N_{i}^{(k)} ni(d)=k=16Ni(k)Ni(k)×Ni(k)

其中 i i i代表分拣中心编号, d d d代表天数, k k k代表班次编号。这样可以保证每天的总人数与每个班次的需求人数成正比,从而实现每天的人天数尽可能少。

综上所述,可以建立如下数学模型:

目标函数:

min ⁡ ∑ i = 1 57 ∑ d = 1 30 ∑ k = 1 6 ( T i ( k ) × n i ( d ) ) \min \sum_{i=1}^{57}\sum_{d=1}^{30}\sum_{k=1}^{6}(T_{i}^{(k)}\times n_{i}^{(d)}) mini=157d=130k=16(Ti(k)×ni(d))

约束条件:

m i j ( k ) = 8 × p i j ( k ) 25 m_{ij}^{(k)}=\frac{8\times p_{ij}^{(k)}}{25} mij(k)=258×pij(k)

n i ( k ) = Q i ( h ) 20 − m i j ( k ) n_{i}^{(k)}=\frac{Q_i^{(h)}}{20}-m_{ij}^{(k)} ni(k)=20Qi(h)mij(k)

N i ( k ) = Q i ( h ) ∑ i = 1 57 Q i ( h ) × N N_{i}^{(k)}=\frac{Q_i^{(h)}}{\sum_{i=1}^{57}Q_i^{(h)}}\times N Ni(k)=i=157Qi(h)Qi(h)×N

n i ( d ) = N i ( k ) ∑ k = 1 6 N i ( k ) × N i ( k ) n_{i}^{(d)}=\frac{N_{i}^{(k)}}{\sum_{k=1}^{6}N_{i}^{(k)}}\times N_{i}^{(k)} ni(d)=k=16Ni(k)Ni(k)×Ni(k)

0 ⩽ p i j ( k ) ⩽ 25 0\leqslant p_{ij}^{(k)}\leqslant 25 0pij(k)25

0 ⩽ m i j ( k ) ⩽ N i ( k ) 0\leqslant m_{ij}^{(k)}\leqslant N_{i}^{(k)} 0mij(k)Ni(k)

0 ⩽ n i ( k ) ⩽ N i ( k ) 0\leqslant n_{i}^{(k)}\leqslant N_{i}^{(k)} 0ni(k)Ni(k)

0 ⩽ n i ( d ) ⩽ N i ( k ) 0\leqslant n_{i}^{(d)}\leqslant N_{i}^{(k)} 0ni(d)Ni(k)

0 ⩽ T i ( k ) ⩽ 1 0\leqslant T_{i}^{(k)}\leqslant 1 0Ti(k)1

其中 i i i代表分拣中心编号, j j j代表正式工编号, k k k代表班次编号, d d d代表天数。 T i ( k ) T_i^{(k)} Ti(k)为二进制变量,当第 i i i个分拣中心在第 k k k个班次有需求时, T i ( k ) = 1 T_i^{(k)}=1 Ti(k)=1,否则为0。

根据以上数学模型,可以求解出每个分拣中心在每天六个班次中,每名正式工将在哪些班次出勤,每个班次需要雇佣多少临时工。将求解结果写入结果表6中即可。

假设每名正式工的出勤率为 x x x,则每名正式工每天的出勤天数为 30 x 30x 30x。每天的班次有6个,因此每个班次每天需要的正式工数量为 30 x 6 = 5 x \frac{30x}{6}=5x 630x=5x。同理,每天需要的临时工数量为 30 ( 1 − x ) 6 = 5 ( 1 − x ) \frac{30(1-x)}{6}=5(1-x) 630(1x)=5(1x)

根据题意,每名正式工的出勤率不能高于85%,即 x ≤ 0.85 x\leq0.85 x0.85。为了尽量保持正式工的出勤率均衡,假设每名正式工的出勤率为0.85时,每天出勤的班次为3-3-3-3-3-3,即每个班次每天需要的正式工数量为 30 × 0.85 6 = 4.25 \frac{30\times0.85}{6}=4.25 630×0.85=4.25,每天需要的临时工数量为 30 × ( 1 − 0.85 ) 6 = 0.75 \frac{30\times(1-0.85)}{6}=0.75 630×(10.85)=0.75

因此,每名正式工每天出勤的班次可以使用二进制变量表示为:
b i = { 1 , 第 i 天出勤 0 , 第 i 天不出勤 b_i= \begin{cases} 1, & \text{第$i$天出勤} \\ 0, & \text{第$i$天不出勤} \end{cases} bi={1,0,i天出勤i天不出勤
其中, i = 1 , 2 , … , 30 i=1,2,\dots,30 i=1,2,,30

同时,每天需要的临时工数量也可以使用二进制变量表示为:
d i = { 1 , 第 i 天需要临时工 0 , 第 i 天不需要临时工 d_i= \begin{cases} 1, & \text{第$i$天需要临时工} \\ 0, & \text{第$i$天不需要临时工} \end{cases} di={1,0,i天需要临时工i天不需要临时工
其中, i = 1 , 2 , … , 30 i=1,2,\dots,30 i=1,2,,30

根据以上假设,可以得到每名正式工每天出勤的班次数量为:
n i = 30 x 6 b i = 5 6 x b i n_i=\frac{30x}{6}b_i=\frac{5}{6}xb_i ni=630xbi=65xbi
每天需要的临时工数量为:
m i = 30 ( 1 − x ) 6 d i = 5 ( 1 − x ) d i m_i=\frac{30(1-x)}{6}d_i=5(1-x)d_i mi=630(1x)di=5(1x)di

为了尽可能降低人天数,可以设置目标函数为:
min ⁡ ∑ i = 1 30 n i + ∑ i = 1 30 m i \min \sum_{i=1}^{30}n_i+\sum_{i=1}^{30}m_i mini=130ni+i=130mi

同时,为了保证每天的实际小时人效尽量均衡,可以设置约束条件为:
∑ i = 1 30 n i ∑ i = 1 30 d i ≥ 25 20 \frac{\sum_{i=1}^{30}n_i}{\sum_{i=1}^{30}d_i}\geq\frac{25}{20} i=130dii=130ni2025

为了保证正式工的出勤率尽量均衡,可以设置约束条件为:
0.85 ≤ ∑ i = 1 30 b i 30 0.85\leq\frac{\sum_{i=1}^{30}b_i}{30} 0.8530i=130bi

为了保证正式工的连续出勤天数不超过7天,可以设置约束条件为:
b i + b i + 1 + ⋯ + b i + 6 ≤ 7 b_i+b_{i+1}+\dots+b_{i+6}\leq7 bi+bi+1++bi+67
其中, i = 1 , 2 , … , 24 i=1,2,\dots,24 i=1,2,,24

综上所述,可以建立如下优化模型:
min ⁡ ∑ i = 1 30 ( 5 6 x b i + 5 ( 1 − x ) d i ) s.t. ∑ i = 1 30 b i 30 ≥ 0.85 ∑ i = 1 30 n i ∑ i = 1 30 d i ≥ 25 20 b i + b i + 1 + ⋯ + b i + 6 ≤ 7 , i = 1 , 2 , … , 24 b i , d i ∈ { 0 , 1 } , i = 1 , 2 , … , 30 x ≤ 0.85 \begin{align} \min \quad & \sum_{i=1}^{30}\left(\frac{5}{6}xb_i+5(1-x)d_i\right) \\ \text{s.t.} \quad & \frac{\sum_{i=1}^{30}b_i}{30}\geq0.85 \\ & \frac{\sum_{i=1}^{30}n_i}{\sum_{i=1}^{30}d_i}\geq\frac{25}{20} \\ & b_i+b_{i+1}+\dots+b_{i+6}\leq7, \quad i=1,2,\dots,24 \\ & b_i,d_i\in\{0,1\}, \quad i=1,2,\dots,30 \\ & x\leq0.85 \end{align} mins.t.i=130(65xbi+5(1x)di)30i=130bi0.85i=130dii=130ni2025bi+bi+1++bi+67,i=1,2,,24bi,di{0,1},i=1,2,,30x0.85

其中, b i b_i bi表示第 i i i天是否出勤, d i d_i di表示第 i i i天是否需要临时工, x x x表示正式工的出勤率。

解决以上优化模型,可以得到每名正式工每天的出勤情况,以及每天需要的临时工数量,从而可以得到每天的人天数。根据题意要求,可以将模型的结果与实际情况进行比较,进行调整以满足其他条件。最终,可以得到每个分拣中心每个班次的出勤人数,并写入结果表5中。

假设分拣中心SC60拥有200名正式工,为了方便建模,我们将每个班次的时长转换为小时数,即每天分为48个小时,每个班次时长为8小时。
我们使用一个二元变量 x i j x_{ij} xij表示每名员工在每个班次的出勤情况,其中 i i i表示员工编号, j j j表示班次编号。若员工 i i i在班次 j j j出勤,则 x i j = 1 x_{ij}=1 xij=1,否则 x i j = 0 x_{ij}=0 xij=0。另外,我们设定每名员工最多连续出勤7天,即每个员工在连续的7个班次中最多出勤5个班次。

假设每名正式工的出勤率为 α \alpha α,则在未来30天中,每名员工总共出勤的班次数为 30 × α 30\times \alpha 30×α,即每名员工的出勤次数为:
∑ j = 1 48 x i j = 30 × α \sum_{j=1}^{48}x_{ij}=30\times \alpha j=148xij=30×α

同时,每个班次需要雇佣的临时工数量为:
∑ i = 1 200 x i j × y j = n j \sum_{i=1}^{200}x_{ij}\times y_j=n_j i=1200xij×yj=nj
其中 n j n_j nj表示班次 j j j所需的临时工数量。

为了满足每名员工最多连续出勤7天的限制,我们可以添加如下约束条件:
∑ j = 1 7 x i j ≤ 5 \sum_{j=1}^7 x_{ij} \leq 5 j=17xij5

为了满足每名员工的出勤率限制,我们可以添加如下约束条件:
∑ j = 1 48 x i j = 30 × α \sum_{j=1}^{48} x_{ij} = 30\times \alpha j=148xij=30×α

为了使总人天数尽可能少,我们可以添加如下目标函数:
min ⁡ ∑ i = 1 200 ∑ j = 1 48 x i j \min \sum_{i=1}^{200}\sum_{j=1}^{48}x_{ij} mini=1200j=148xij

综上,我们可以建立如下数学规划模型:
min ⁡ ∑ i = 1 200 ∑ j = 1 48 x i j s.t. ∑ j = 1 7 x i j ≤ 5 ∀ i = 1 , 2 , … , 200 ∑ j = 1 48 x i j = 30 × α ∀ i = 1 , 2 , … , 200 ∑ i = 1 200 x i j × y j = n j ∀ j = 1 , 2 , … , 48 x i j ∈ { 0 , 1 } ∀ i = 1 , 2 , … , 200 , ∀ j = 1 , 2 , … , 48 \begin{aligned} \min \sum_{i=1}^{200}\sum_{j=1}^{48}x_{ij}\\ \text{s.t.} \quad & \sum_{j=1}^7 x_{ij} \leq 5 \quad \forall i=1,2,\ldots,200\\ & \sum_{j=1}^{48} x_{ij} = 30\times \alpha \quad \forall i=1,2,\ldots,200\\ & \sum_{i=1}^{200}x_{ij}\times y_j=n_j \quad \forall j=1,2,\ldots,48\\ & x_{ij}\in \{0,1\} \quad \forall i=1,2,\ldots,200, \forall j=1,2,\ldots,48 \end{aligned} mini=1200j=148xijs.t.j=17xij5i=1,2,,200j=148xij=30×αi=1,2,,200i=1200xij×yj=njj=1,2,,48xij{0,1}i=1,2,,200,j=1,2,,48

其中, α \alpha α为给定的正式工出勤率, y j y_j yj为班次 j j j所需的临时工数量。

通过求解该数学规划模型,即可得到每名正式工的出勤计划以及每个班次所需的临时工数量,从而完成分拣中心SC60的排班问题。

#导入所需模块
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

#读取数据,分别为附件1、附件3和附件4
df1 = pd.read_excel('附件1.xlsx')
df3 = pd.read_excel('附件3.xlsx')
df4 = pd.read_excel('附件4.xlsx')

#将附件1中的数据按照分拣中心分组,计算每个分拣中心过去4个月的平均每天货量
avg_daily_volume = df1.groupby('分拣中心')['货量'].mean()

#将附件3中的数据按照分拣中心分组,计算每个分拣中心过去90天的平均线路货量
avg_route_volume = df3.groupby('分拣中心')['线路货量'].mean()

#将附件4中的数据按照分拣中心分组,计算每个分拣中心未来30天的线路货量
future_route_volume = df4.groupby('分拣中心')['线路货量'].mean()

#根据附件3和附件4的数据,计算每个分拣中心未来30天的预测货量
future_volume = future_route_volume.values * avg_daily_volume.values / avg_route_volume.values

#创建结果表6,包含分拣中心、正式工、临时工、每天六个班次的出勤情况
result_table6 = pd.DataFrame(columns=['分拣中心', '正式工', '临时工', '班次1', '班次2', '班次3', '班次4', '班次5', '班次6'])

#遍历每个分拣中心
for i in range(len(future_volume)):
    #根据分拣中心名称,筛选附件1中对应的数据
    center = df1[df1['分拣中心'] == future_volume.index[i]].reset_index()
    #将日期转换为月份,方便计算月均货量
    center['月份'] = pd.to_datetime(center['日期']).dt.month
    #计算每个月的平均货量
    monthly_avg_volume = center.groupby('月份')['货量'].mean()
    #根据每个月的平均货量,计算未来30天每天的预测货量
    future_daily_volume = monthly_avg_volume.values * future_volume[i] / monthly_avg_volume.mean()
    #根据分拣中心名称,筛选附件4中对应的数据
    future_route = df4[df4['分拣中心'] == future_volume.index[i]].reset_index()
    #遍历每一天的预测货量
    for j in range(30):
        #根据每一天的预测货量,计算每个班次需要的正式工和临时工人数
        official_workers = int(np.ceil(future_daily_volume[j]/25))
        temp_workers = int(np.ceil((future_daily_volume[j]-official_workers*25)/20))
        #将结果写入结果表6中
        result_table6.loc[i*30+j] = [future_volume.index[i], official_workers, temp_workers, 0, 0, 0, 0, 0, 0]
        #根据附件4中的数据,确定每个班次需要雇佣的正式工和临时工数量
        for k in range(6):
            if future_route['班次'+str(k+1)][j] == 0:
                result_table6.loc[i*30+j, '班次'+str(k+1)] = 0
            else:
                result_table6.loc[i*30+j, '班次'+str(k+1)] = min(official_workers, future_route['班次'+str(k+1)][j])
                if official_workers >= future_route['班次'+str(k+1)][j]:
                    official_workers = official_workers - future_route['班次'+str(k+1)][j]
                else:
                    official_workers = 0
        #根据每天需要的正式工和临时工人数,计算实际小时人效
        actual_hourly_efficiency = future_daily_volume[j]/(result_table6.loc[i*30+j, '正式工']*25+result_table6.loc[i*30+j, '临时工']*20)
        #根据实际小时人效,调整正式工的出勤班次
        for k in range(6):
            if result_table6.loc[i*30+j, '班次'+str(k+1)] != 0:
                result_table6.loc[i*30+j, '班次'+str(k+1)] = result_table6.loc[i*30+j, '班次'+str(k+1)] * actual_hourly_efficiency/25
        #根据剩余的正式工数量,确定每个班次需要雇佣的临时工数量
        for k in range(6):
            if result_table6.loc[i*30+j, '班次'+str(k+1)] != 0:
                temp_workers = int(np.ceil((future_daily_volume[j]-result_table6.loc[i*30+j, '班次'+str(k+1)]*25)/20))
                if result_table6.loc[i*30+j, '临时工'] >= temp_workers:
                    result_table6.loc[i*30+j, '临时工'] = result_table6.loc[i*30+j, '临时工'] - temp_workers
                    result_table6.loc[i*30+j, '班次'+str(k+1)] = result_table6.loc[i*30+j, '班次'+str(k+1)] + temp_workers
                else:
                    result_table6.loc[i*30+j, '班次'+str(k+1)] = result_table6.loc[i*30+j, '班次'+str(k+1)] + result_table6.loc[i*30+j, '临时工']
                    result_table6.loc[i*30+j, '临时工'] = 0

#将结果写入结果表6中
result_table6.to_excel('结果表6.xlsx', index=False) 

mathorcup跟紧小秘籍冲冲冲!!更多内容可以点击下方名片详细了解!
记得关注 数学建模小秘籍打开你的数学建模夺奖之旅!

04-12 21:09