当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。
让我们来看看Mathorcup (C题)!
CS团队倾注了大量时间和心血,深入挖掘解决方案。通过ARIMA时序预测,多目标优化等算法,设计了明晰的项目,团队努力体现在每个步骤,确保方案既创新又可行,为大家提供了全面而深入的洞见噢~
完整内容可以在文章末尾领取!
第一个问题是建立货量预测模型,对57个分拣中心未来30天每天及每小时的货量进行预测。
假设分拣中心
S
C
i
SC_i
SCi的每天货量为
Q
i
(
t
)
Q_i(t)
Qi(t),其中
t
t
t为天数,
i
=
1
,
2
,
.
.
.
,
57
i=1,2,...,57
i=1,2,...,57。根据历史数据,我们可以得到每个分拣中心过去30天的每小时货量
Q
i
(
h
)
Q_i(h)
Qi(h),其中
h
h
h为小时数,
i
=
1
,
2
,
.
.
.
,
57
i=1,2,...,57
i=1,2,...,57。我们可以假设
Q
i
(
h
)
Q_i(h)
Qi(h)与每天货量
Q
i
(
t
)
Q_i(t)
Qi(t)之间存在线性关系,即:
Q
i
(
h
)
=
a
i
Q
i
(
t
)
+
b
i
Q_i(h) = a_i Q_i(t) + b_i
Qi(h)=aiQi(t)+bi
其中,
a
i
a_i
ai和
b
i
b_i
bi为分拣中心
S
C
i
SC_i
SCi的参数,可以通过历史数据进行拟合得到。
根据问题1的要求,我们需要对57个分拣中心未来30天每天及每小时的货量进行预测。假设未来第
t
t
t天的每小时货量为
Q
i
(
h
)
Q_i(h)
Qi(h),我们可以通过以下公式进行预测:
Q
i
(
h
)
=
a
i
Q
i
(
t
)
+
b
i
Q_i(h) = a_i Q_i(t) + b_i
Qi(h)=aiQi(t)+bi
Q
i
(
t
)
=
∑
h
=
1
24
Q
i
(
h
)
Q_i(t) = \sum_{h=1}^{24} Q_i(h)
Qi(t)=h=1∑24Qi(h)
其中,
t
=
31
,
32
,
.
.
.
,
60
t=31,32,...,60
t=31,32,...,60,
h
=
1
,
2
,
.
.
.
,
24
h=1,2,...,24
h=1,2,...,24,
i
=
1
,
2
,
.
.
.
,
57
i=1,2,...,57
i=1,2,...,57。
对于每个分拣中心
S
C
i
SC_i
SCi,我们可以通过历史数据拟合出参数
a
i
a_i
ai和
b
i
b_i
bi,从而可以计算出未来30天每天及每小时的货量。具体来说,我们可以通过最小二乘法拟合出
a
i
a_i
ai和
b
i
b_i
bi,使得历史数据和拟合的曲线最接近。拟合的公式为:
min
a
i
,
b
i
∑
h
=
1
30
(
Q
i
(
h
)
−
(
a
i
Q
i
(
t
)
+
b
i
)
)
2
\min_{a_i,b_i} \sum_{h=1}^{30} (Q_i(h) - (a_i Q_i(t) + b_i))^2
ai,biminh=1∑30(Qi(h)−(aiQi(t)+bi))2
通过最小二乘法可以求出
a
i
a_i
ai和
b
i
b_i
bi的最优解,从而得到每个分拣中心未来30天每小时的货量预测值
Q
i
(
h
)
Q_i(h)
Qi(h)和每天的货量预测值
Q
i
(
t
)
Q_i(t)
Qi(t)。
最后,我们可以将预测结果写入结果表1和表2中,完成对第一个问题的建模。
设57个分拣中心的货量为 x 1 , x 2 , . . . , x 57 x_1, x_2, ..., x_{57} x1,x2,...,x57, 各中心的历史数据为 x 1 , h , x 2 , h , . . . , x 57 , h x_{1, h}, x_{2, h}, ..., x_{57, h} x1,h,x2,h,...,x57,h, 则可以建立一个简单的线性回归模型来预测未来的货量:
x i , f = β 0 + β 1 x i , h x_{i, f} = \beta_0 + \beta_1x_{i, h} xi,f=β0+β1xi,h
其中, x i , f x_{i, f} xi,f 为第 i i i 个分拣中心未来的货量预测值, β 0 \beta_0 β0 和 β 1 \beta_1 β1 为模型的系数,可以通过历史数据的最小二乘法来求解。
对于每天的货量预测,可以使用历史每天的数据来求解,对于每小时的货量预测,可以使用历史每小时的数据来求解。
此外,在建立预测模型的过程中,还可以考虑其他影响因素,如节假日、促销活动等,来进一步提高预测的准确性。
我们将问题抽象为一个典型的时间序列预测问题,其中时间序列是每个分拣中心每天及每小时的货量。我们可以使用经典的时间序列预测方法ARIMA(Autoregressive Integrated Moving Average)来建立货量预测模型。
ARIMA模型包含三个部分:自回归(AR)部分、差分(I)部分和移动平均(MA)部分。具体的数学公式如下:
AR部分: y t = ϕ 1 y t − 1 + ϕ 2 y t − 2 + . . . + ϕ p y t − p + ϵ t y_t = \phi_1 y_{t-1} + \phi_2 y_{t-2} + ... + \phi_p y_{t-p} + \epsilon_t yt=ϕ1yt−1+ϕ2yt−2+...+ϕpyt−p+ϵt
MA部分: y t = θ 1 ϵ t − 1 + θ 2 ϵ t − 2 + . . . + θ q ϵ t − q + ϵ t y_t = \theta_1 \epsilon_{t-1} + \theta_2 \epsilon_{t-2} + ... + \theta_q \epsilon_{t-q} + \epsilon_t yt=θ1ϵt−1+θ2ϵt−2+...+θqϵt−q+ϵt
I部分: Δ y t = y t − y t − 1 = μ + ϵ t \Delta y_t = y_t - y_{t-1} = \mu + \epsilon_t Δyt=yt−yt−1=μ+ϵt
其中, y t y_t yt表示时间序列在时刻 t t t的值, ϕ \phi ϕ和 θ \theta θ分别表示AR部分和MA部分的系数, p p p和 q q q分别表示AR部分和MA部分的阶数, ϵ t \epsilon_t ϵt为白噪声, Δ y t \Delta y_t Δyt表示时间序列在时刻 t t t的一阶差分, μ \mu μ为时间序列的均值。
根据问题描述,我们可以将每个分拣中心每天的货量作为时间序列,使用ARIMA模型来预测未来30天每天的货量。同时,我们也可以将每个分拣中心每小时的货量作为时间序列,使用ARIMA模型来预测未来30天每小时的货量。
在建立ARIMA模型之前,我们需要对时间序列进行平稳性检验。如果时间序列不平稳,我们需要对其进行差分处理,直到得到平稳时间序列。然后,我们可以使用自相关图(ACF)和偏自相关图(PACF)来确定AR部分和MA部分的阶数。最后,我们可以使用最小均方误差(MSE)来选择最优的模型。
建立好ARIMA模型后,我们可以使用历史数据来训练模型,然后对未来30天每天及每小时的货量进行预测。最后,将预测结果写入结果表1和表2中。=
# 导入相关库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# 读取附件1和附件2中的数据
df_daily = pd.read_csv('附件1.csv')
df_hourly = pd.read_csv('附件2.csv')
# 对附件1中的数据进行处理,计算每个分拣中心过去4个月每天的平均货量,并按照分拣中心进行分组
df_daily['daily_avg'] = df_daily.mean(axis=1)
df_daily_avg = df_daily.groupby('分拣中心').agg({'daily_avg': 'mean'})
# 对附件2中的数据进行处理,计算每个分拣中心过去30天每小时的平均货量,并按照分拣中心和小时进行分组
df_hourly['hourly_avg'] = df_hourly.mean(axis=1)
df_hourly_avg = df_hourly.groupby(['分拣中心', '小时']).agg({'hourly_avg': 'mean'})
# 创建线性回归模型
model = LinearRegression()
# 预测每个分拣中心未来30天每天的货量
x = np.array(df_daily_avg.index).reshape(-1, 1)
y = np.array(df_daily_avg['daily_avg']).reshape(-1, 1)
model.fit(x, y)
daily_pred = model.predict(np.arange(58, 88).reshape(-1, 1))
# 预测每个分拣中心未来30天每小时的货量
hourly_pred = []
for i in range(57):
x = np.array(df_hourly_avg.iloc[i * 30:(i + 1) * 30].index).reshape(-1, 1)
y = np.array(df_hourly_avg.iloc[i * 30:(i + 1) * 30]['hourly_avg']).reshape(-1, 1)
model.fit(x, y)
hourly_pred.extend(model.predict(np.arange(25, 55).reshape(-1, 1)))
# 将预测结果写入结果表1和表2中
df_daily_pred = pd.DataFrame({'分拣中心': np.arange(1, 58), '每天货量预测': daily_pred.flatten()})
df_hourly_pred = pd.DataFrame({'分拣中心': np.repeat(np.arange(1, 58), 30), '小时': np.tile(np.arange(1, 31), 57), '每小时货量预测': hourly_pred})
df_daily_pred.to_csv('结果表1.csv', index=False)
df_hourly_pred.to_csv('结果表2.csv', index=False)
# 绘制图表,观察预测结果
plt.figure()
plt.plot(df_daily_avg.index, df_daily_avg['daily_avg'], 'o-', label='历史平均货量')
plt.plot(np.arange(58, 88), daily_pred, 'o-', label='预测平均货量')
plt.legend()
plt.xlabel('分拣中心')
plt.ylabel('每天货量')
plt.xticks(np.arange(1, 58))
plt.show()
plt.figure()
plt.plot(df_hourly_avg.loc[1]['hourly_avg'].index, df_hourly_avg.loc[1]['hourly_avg'], 'o-', label='历史平均货量')
plt.plot(np.arange(25, 55), hourly_pred[0:30], 'o-', label='预测平均货量')
plt.legend()
plt.xlabel('小时')
plt.ylabel('每小时货量')
plt.xticks(np.arange(1, 31))
plt.show()
第二个问题是:根据过去90天的各分拣中心之间运输线路平均货量和未来30天分拣中心之间运输线路变化情况,建立货量预测模型,预测未来30天每天及每小时的货量,并将预测结果写入结果表3和表4中。
问题2的数学建模:
定义:
D i D_i Di表示第i个分拣中心的货量;
T j T_j Tj表示第j天的货量;
H i j H_{ij} Hij表示第i个分拣中心第j天的小时货量;
V i j V_{ij} Vij表示第i个分拣中心第j天的每小时货量;
R i j R_{ij} Rij表示第i个分拣中心第j天的每小时人效指标;
P i j P_{ij} Pij表示第i个分拣中心第j天的预测货量;
T T T表示未来30天;
N N N表示分拣中心数量;
M M M表示运输线路数量;
X i j X_{ij} Xij表示第i个分拣中心第j天的实际货量;
Y i j Y_{ij} Yij表示第i个分拣中心第j天的实际每小时货量;
Z i j Z_{ij} Zij表示第i个分拣中心第j天的实际每小时人效指标;
C i C_i Ci表示第i个分拣中心的正式工数量;
F i F_i Fi表示第i个分拣中心的临时工数量;
G G G表示分拣中心每天的班次数量;
B i B_i Bi表示第i个分拣中心每天的出勤人数;
目标函数:
m i n ∑ i = 1 N ∑ j = 1 T ( P i j − X i j ) 2 + ∑ i = 1 N ∑ j = 1 T ∑ k = 1 G ( B i − R i j Y i j ) 2 min\sum_{i=1}^{N}\sum_{j=1}^{T}(P_{ij}-X_{ij})^2+\sum_{i=1}^{N}\sum_{j=1}^{T}\sum_{k=1}^{G}(B_i-R_{ij}Y_{ij})^2 min∑i=1N∑j=1T(Pij−Xij)2+∑i=1N∑j=1T∑k=1G(Bi−RijYij)2
约束条件:
X i j = ∑ k = 1 M H i k , j = 1 , 2 , . . . , T , i = 1 , 2 , . . . , N X_{ij}=\sum_{k=1}^{M}H_{ik},j=1,2,...,T,i=1,2,...,N Xij=∑k=1MHik,j=1,2,...,T,i=1,2,...,N
Z i j = X i j V i j , j = 1 , 2 , . . . , T , i = 1 , 2 , . . . , N Z_{ij}=\frac{X_{ij}}{V_{ij}},j=1,2,...,T,i=1,2,...,N Zij=VijXij,j=1,2,...,T,i=1,2,...,N
Y i j = X i j R i j , j = 1 , 2 , . . . , T , i = 1 , 2 , . . . , N Y_{ij}=\frac{X_{ij}}{R_{ij}},j=1,2,...,T,i=1,2,...,N Yij=RijXij,j=1,2,...,T,i=1,2,...,N
∑ j = 1 T ∑ k = 1 G B i = 30 × C i , i = 1 , 2 , . . . , N \sum_{j=1}^{T}\sum_{k=1}^{G}B_i=30\times C_i,i=1,2,...,N ∑j=1T∑k=1GBi=30×Ci,i=1,2,...,N
∑ k = 1 G B i = 1 , i = 1 , 2 , . . . , N \sum_{k=1}^{G}B_i=1,i=1,2,...,N ∑k=1GBi=1,i=1,2,...,N
C i + B i = F i , i = 1 , 2 , . . . , N C_i+B_i=F_i,i=1,2,...,N Ci+Bi=Fi,i=1,2,...,N
0 ≤ B i ≤ C i , i = 1 , 2 , . . . , N 0\leq B_i\leq C_i,i=1,2,...,N 0≤Bi≤Ci,i=1,2,...,N
0 ≤ F i ≤ 200 , i = 1 , 2 , . . . , N 0\leq F_i\leq 200,i=1,2,...,N 0≤Fi≤200,i=1,2,...,N
0 ≤ Y i j ≤ 25 , j = 1 , 2 , . . . , T , i = 1 , 2 , . . . , N 0\leq Y_{ij}\leq 25,j=1,2,...,T,i=1,2,...,N 0≤Yij≤25,j=1,2,...,T,i=1,2,...,N
0 ≤ Z i j ≤ 20 , j = 1 , 2 , . . . , T , i = 1 , 2 , . . . , N 0\leq Z_{ij}\leq 20,j=1,2,...,T,i=1,2,...,N 0≤Zij≤20,j=1,2,...,T,i=1,2,...,N
P i j = ∑ k = 1 M H i k , j = T + 1 , T + 2 , . . . , T + 24 , i = 1 , 2 , . . . , N P_{ij}=\sum_{k=1}^{M}H_{ik},j=T+1,T+2,...,T+24,i=1,2,...,N Pij=∑k=1MHik,j=T+1,T+2,...,T+24,i=1,2,...,N
H i k = α k D i + ∑ l = 1 M β k l D l , l = 1 , 2 , . . . , N , i = 1 , 2 , . . . , N H_{ik}=\alpha_kD_i+\sum_{l=1}^{M}\beta_{kl}D_l,l=1,2,...,N,i=1,2,...,N Hik=αkDi+∑l=1MβklDl,l=1,2,...,N,i=1,2,...,N
∑ k = 1 M β k l = 1 , l = 1 , 2 , . . . , N \sum_{k=1}^{M}\beta_{kl}=1,l=1,2,...,N ∑k=1Mβkl=1,l=1,2,...,N
α k D i + D k > 0 , i = 1 , 2 , . . . , N \alpha_kD_i+D_k>0,i=1,2,...,N αkDi+Dk>0,i=1,2,...,N
D i ≥ 0 , i = 1 , 2 , . . . , N D_i\geq 0,i=1,2,...,N Di≥0,i=1,2,...,N
其中, α k \alpha_k αk为第k个运输线路上第i个分拣中心的货量占比, β k l \beta_{kl} βkl为第k个运输线路上第l个分拣中心对第i个分拣中心货量的影响因子。上述模型可以通过线性规划的方法求解,得到未来30天每天及每小时的货量预测结果。
根据问题描述,货量预测模型需要考虑历史货量、物流网络配置和运输线路的变化情况,因此可以使用时间序列分析的方法来预测未来30天每天及每小时的货量。
首先,可以利用过去90天各分拣中心之间的各运输线路平均货量数据,建立一个线性回归模型,得到各运输线路的平均货量与分拣中心货量的关系。然后,根据未来30天分拣中心之间运输线路的变化情况,调整线性回归模型中各运输线路的系数,得到新的线性回归模型。
其次,根据过去4个月的每天货量数据和过去30天的每小时货量数据,可以建立ARIMA模型,对每个分拣中心每天的货量和每小时的货量进行预测。ARIMA模型可以考虑历史数据中的趋势和季节性,以及数据的自相关性和平稳性,从而更准确地预测未来的货量。
最后,将线性回归模型和ARIMA模型的预测结果结合起来,得到最终的货量预测结果。具体地,可以将线性回归模型得到的每个分拣中心的货量与ARIMA模型得到的每天和每小时的货量相乘,得到未来30天的每天和每小时的货量预测值。
公式表示如下:
线性回归模型: Y = β 0 + β 1 X 1 + β 2 X 2 + . . . + β n X n Y = \beta_0 + \beta_1X_1 + \beta_2X_2 + ... + \beta_nX_n Y=β0+β1X1+β2X2+...+βnXn
其中, Y Y Y表示分拣中心货量, X 1 X_1 X1、 X 2 X_2 X2、…、 X n X_n Xn表示各运输线路平均货量, β 0 \beta_0 β0、 β 1 \beta_1 β1、 β 2 \beta_2 β2、…、 β n \beta_n βn表示线性回归模型的系数。
ARIMA模型: Y t = μ + ϕ 1 Y t − 1 + ϕ 2 Y t − 2 + . . . + ϕ p Y t − p + θ 1 ε t − 1 + θ 2 ε t − 2 + . . . + θ q ε t − q + ε t Y_t = \mu + \phi_1Y_{t-1} + \phi_2Y_{t-2} + ... + \phi_pY_{t-p} + \theta_1\varepsilon_{t-1} + \theta_2\varepsilon_{t-2} + ... + \theta_q\varepsilon_{t-q} + \varepsilon_t Yt=μ+ϕ1Yt−1+ϕ2Yt−2+...+ϕpYt−p+θ1εt−1+θ2εt−2+...+θqεt−q+εt
其中, Y t Y_t Yt表示t时刻的货量, μ \mu μ表示模型的常数项, ϕ 1 \phi_1 ϕ1、 ϕ 2 \phi_2 ϕ2、…、 ϕ p \phi_p ϕp表示ARIMA模型的自回归系数, θ 1 \theta_1 θ1、 θ 2 \theta_2 θ2、…、 θ q \theta_q θq表示ARIMA模型的移动平均系数, ε t \varepsilon_t εt表示误差项。
最终的货量预测结果可以表示为: Y f o r e c a s t = Y r e g r e s s i o n ∗ Y A R I M A Y_{forecast} = Y_{regression} * Y_{ARIMA} Yforecast=Yregression∗YARIMA
其中, Y f o r e c a s t Y_{forecast} Yforecast表示最终的货量预测结果, Y r e g r e s s i o n Y_{regression} Yregression表示线性回归模型得到的货量预测结果, Y A R I M A Y_{ARIMA} YARIMA表示ARIMA模型得到的货量预测结果。
通过以上方法,可以对57个分拣中心未来30天每天及每小时的货量进行预测,并将预测结果写入结果表3和表4中。由于使用了历史数据和运输线路的变化情况,因此预测结果更加准确,可以为分拣中心的货量预测提供更多的参考依据。
设第 i i i个分拣中心未来第 t t t天的货量为 Q i t Q_{i}^{t} Qit,第 i i i个分拣中心未来第 t t t小时的货量为 q i t q_{i}^{t} qit, Q i t ^ \hat{Q_{i}^{t}} Qit^和 q i t ^ \hat{q_{i}^{t}} qit^分别为预测值。根据过去90天各分拣中心之间的运输线路平均货量和未来30天分拣中心之间运输线路变化情况,可以建立如下模型:
minimize ∑ i = 1 57 ( ∑ t = 1 30 ( ∣ Q i t − Q i t ^ ∣ + ∑ h = 1 24 ∣ q i t − q i t ^ ∣ ) ) subject to ∑ i = 1 57 ∑ t = 1 30 Q i t ^ = ∑ i = 1 57 ∑ t = 1 30 Q i t ∑ i = 1 57 ∑ t = 1 30 ∑ h = 1 24 q i t ^ = ∑ i = 1 57 ∑ t = 1 30 ∑ h = 1 24 q i t ∑ i = 1 57 ∑ t = 1 30 q i t ^ = ∑ i = 1 57 ∑ t = 1 30 ∑ h = 1 24 Q i t ^ \begin{equation} \begin{aligned} & \text{minimize} && \sum_{i=1}^{57} \left( \sum_{t=1}^{30} \left( \left| Q_{i}^{t} - \hat{Q_{i}^{t}} \right| + \sum_{h=1}^{24} \left| q_{i}^{t} - \hat{q_{i}^{t}} \right| \right) \right) \\ & \text{subject to} && \sum_{i=1}^{57} \sum_{t=1}^{30} \hat{Q_{i}^{t}} = \sum_{i=1}^{57} \sum_{t=1}^{30} Q_{i}^{t} \\ & && \sum_{i=1}^{57} \sum_{t=1}^{30} \sum_{h=1}^{24} \hat{q_{i}^{t}} = \sum_{i=1}^{57} \sum_{t=1}^{30} \sum_{h=1}^{24} q_{i}^{t} \\ & && \sum_{i=1}^{57} \sum_{t=1}^{30} \hat{q_{i}^{t}} = \sum_{i=1}^{57} \sum_{t=1}^{30} \sum_{h=1}^{24} \hat{Q_{i}^{t}} \end{aligned} \end{equation} minimizesubject toi=1∑57(t=1∑30( Qit−Qit^ +h=1∑24 qit−qit^ ))i=1∑57t=1∑30Qit^=i=1∑57t=1∑30Qiti=1∑57t=1∑30h=1∑24qit^=i=1∑57t=1∑30h=1∑24qiti=1∑57t=1∑30qit^=i=1∑57t=1∑30h=1∑24Qit^
其中,第一个约束保证预测值和实际值的总货量相等,第二个约束保证预测值和实际值的总小时货量相等,第三个约束保证每天的预测值和小时预测值之间的关系。该模型的目标函数为预测值和实际值的绝对差值的总和,即预测值和实际值的误差之和最小。通过求解该模型,可以得到最佳的预测值 Q i t ^ \hat{Q_{i}^{t}} Qit^和 q i t ^ \hat{q_{i}^{t}} qit^,并将其写入结果表3和表4中。
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
# 读取附件1和附件2的数据
df_day = pd.read_csv('附件1.csv')
df_hour = pd.read_csv('附件2.csv')
# 根据过去90天各分拣中心之间运输线路平均货量和未来30天分拣中心之间运输线路变化情况,建立货量预测模型
# 首先计算每天每个分拣中心的平均货量
avg_day = df_day.mean(axis=1)
# 将过去90天的运输线路平均货量和未来30天运输线路变化情况合并为一个数据集
df_avg = pd.read_csv('附件3.csv')
df_change = pd.read_csv('附件4.csv')
df_avg = pd.concat([df_avg, df_change], axis=1)
# 建立线性回归模型,预测未来每天每个分拣中心的货量
model = LinearRegression()
model.fit(df_avg, avg_day)
pred_day = model.predict(df_avg)
# 将预测结果写入结果表3
df_result3 = pd.DataFrame({'日期': pd.date_range(start='2020-07-01', periods=30),
'分拣中心': df_day.columns,
'预测货量': pred_day})
df_result3.to_csv('结果表3.csv', index=False)
# 预测每小时的货量
# 首先计算每小时每个分拣中心的平均货量
avg_hour = df_hour.mean(axis=1)
# 将过去90天的运输线路平均货量和未来30天运输线路变化情况合并为一个数据集
df_avg = pd.read_csv('附件3.csv')
df_change = pd.read_csv('附件4.csv')
df_avg = pd.concat([df_avg, df_change], axis=1)
# 建立线性回归模型,预测未来每小时每个分拣中心的货量
model = LinearRegression()
model.fit(df_avg, avg_hour)
pred_hour = model.predict(df_avg)
# 将预测结果写入结果表4
df_result4 = pd.DataFrame(columns=['日期', '分拣中心', '时段', '预测货量'])
for date in pd.date_range(start='2020-07-01', periods=30):
for i in range(6):
for j in range(57):
df_result4 = df_result4.append({'日期': date,
'分拣中心': df_day.columns[j],
'时段': i,
'预测货量': pred_hour[j]}, ignore_index=True)
df_result4.to_csv('结果表4.csv', index=False)
第三个问题是基于分拣中心货量预测结果,针对人员安排班次及小时人效指标,如何合理安排人员,以尽可能降低人员成本的问题。
min ∑ d = 1 30 ∑ t = 1 6 ∑ s = 1 57 ( N d , t , s f ∗ C f + N d , t , s t ∗ C t ) ∑ t = 1 6 N d , t , s f = N d , s f ∑ t = 1 6 N d , t , s t = N d , s t N d , s f + N d , s t = N d , s N d , t , s f ≤ M a x f ∗ N d , t , s t ≤ M a x t f , t , s , d ∈ N + \begin{equation} \begin{split} &\min\sum_{d=1}^{30}\sum_{t=1}^{6}\sum_{s=1}^{57}(N_{d,t,s}^{f}*C_{f}+N_{d,t,s}^{t}*C_{t})\\ &\sum_{t=1}^{6}N_{d,t,s}^{f}=N_{d,s}^{f}\\ &\sum_{t=1}^{6}N_{d,t,s}^{t}=N_{d,s}^{t}\\ &N_{d,s}^{f}+N_{d,s}^{t}=N_{d,s}\\ &N_{d,t,s}^{f}\leq Max_{f}*N_{d,t,s}^{t}\leq Max_{t}\\ &f,t,s,d\in \mathbb{N}^{+} \end{split} \end{equation} mind=1∑30t=1∑6s=1∑57(Nd,t,sf∗Cf+Nd,t,st∗Ct)t=1∑6Nd,t,sf=Nd,sft=1∑6Nd,t,st=Nd,stNd,sf+Nd,st=Nd,sNd,t,sf≤Maxf∗Nd,t,st≤Maxtf,t,s,d∈N+
模型目标:
min
∑
d
=
1
30
∑
t
=
1
6
∑
s
=
1
57
(
N
d
,
t
,
s
f
∗
C
f
+
N
d
,
t
,
s
t
∗
C
t
)
\begin{equation} \min\sum_{d=1}^{30}\sum_{t=1}^{6}\sum_{s=1}^{57}(N_{d,t,s}^{f}*C_{f}+N_{d,t,s}^{t}*C_{t}) \end{equation}
mind=1∑30t=1∑6s=1∑57(Nd,t,sf∗Cf+Nd,t,st∗Ct)
模型约束条件:
每天分拣中心人员总数等于正式工和临时工人数之和:
∑
t
=
1
6
N
d
,
t
,
s
f
=
N
d
,
s
f
∑
t
=
1
6
N
d
,
t
,
s
t
=
N
d
,
s
t
N
d
,
s
f
+
N
d
,
s
t
=
N
d
,
s
每个班次正式工和临时工人数小于等于最大人数:
N
d
,
t
,
s
f
≤
M
a
x
f
∗
N
d
,
t
,
s
t
≤
M
a
x
t
f
,
t
,
s
,
d
∈
N
+
\begin{equation} \begin{split} &每天分拣中心人员总数等于正式工和临时工人数之和:\\ &\sum_{t=1}^{6}N_{d,t,s}^{f}=N_{d,s}^{f}\\ &\sum_{t=1}^{6}N_{d,t,s}^{t}=N_{d,s}^{t}\\ &N_{d,s}^{f}+N_{d,s}^{t}=N_{d,s}\\ &每个班次正式工和临时工人数小于等于最大人数:\\ &N_{d,t,s}^{f}\leq Max_{f}*N_{d,t,s}^{t}\leq Max_{t}\\ &f,t,s,d\in \mathbb{N}^{+} \end{split} \end{equation}
每天分拣中心人员总数等于正式工和临时工人数之和:t=1∑6Nd,t,sf=Nd,sft=1∑6Nd,t,st=Nd,stNd,sf+Nd,st=Nd,s每个班次正式工和临时工人数小于等于最大人数:Nd,t,sf≤Maxf∗Nd,t,st≤Maxtf,t,s,d∈N+
模型解释:该模型目标是为了使得每天的人员成本最小。约束条件一是保证每天每个分拣中心的总人数等于正式工和临时工人数之和,约束条件二是保证每个班次的正式工和临时工人数小于等于最大人数。
针对第三个问题,可以按照以下步骤进行人员安排:
-
首先根据货量预测结果,计算每个分拣中心每天需要的人员总数。假设总人数为N,其中正式工人数为M,临时工人数为N-M。
-
根据每个分拣中心的出勤率,可以计算出每个分拣中心的实际出勤人数。假设出勤率为p,实际出勤人数为Mp和(N-M)p。
-
将每个分拣中心的出勤人数平均分配到每个班次中,得到每个班次需要的正式工和临时工人数,记为 M i M_i Mi和 ( N − M ) i (N-M)_i (N−M)i,其中i为班次的编号。
-
根据每个班次的人数限制条件,可以得到以下不等式:
M i ≤ M , ( N − M ) i ≤ N − M M_i \leq M, \quad (N-M)_i \leq N-M Mi≤M,(N−M)i≤N−M
- 为了使得每天的小时人效尽量均衡,可以设置一个目标函数,使得各班次的小时人效之和最小:
m i n ∑ i = 1 6 M i M + ( N − M ) i N − M min \quad \sum_{i=1}^{6} \frac{M_i}{M} + \frac{(N-M)_i}{N-M} mini=1∑6MMi+N−M(N−M)i
-
将以上目标函数和约束条件输入到线性规划模型中,即可得到每个班次需要的正式工和临时工人数。
-
最后,根据每个班次的人数安排情况,可以计算出每个分拣中心每天需要的总人天数,记为 T i T_i Ti,其中i为天数的编号。
-
为了使得总人天数尽可能少,可以设置一个目标函数,使得总人天数最小:
m i n ∑ i = 1 30 T i min \quad \sum_{i=1}^{30} T_i mini=1∑30Ti
- 将以上目标函数和约束条件输入到线性规划模型中,即可得到最终的人员安排方案。
总的来说,该问题可以转化为一个线性规划问题,通过设置合适的目标函数和约束条件,可以得到最优的人员安排方案。同时,为了保证正式工的出勤率和连续出勤天数的限制,可以在目标函数中加入相应的惩罚项,使得模型能够兼顾所有约束条件。
根据问题2的货量预测结果,可以得到每个分拣中心每天及每小时的预测货量。根据人员安排班次及小时人效指标,可以得到每个分拣中心每天及每小时需要的人员数量。因此,可以将问题3建立为一个最小化总人天数的优化问题,其中每天的人天数为每个分拣中心每天所需人员数量的总和,总人天数为所有分拣中心30天的总和。优化目标函数如下:
m
i
n
∑
i
=
1
57
∑
t
=
1
30
∑
j
=
1
6
x
i
j
t
min \quad \sum_{i=1}^{57} \sum_{t=1}^{30} \sum_{j=1}^{6} x_{ijt}
mini=1∑57t=1∑30j=1∑6xijt
其中,
x
i
j
t
x_{ijt}
xijt表示第i个分拣中心在第t天第j个班次的人员数量,取值为0或1。当
x
i
j
t
=
1
x_{ijt}=1
xijt=1时,表示第i个分拣中心在第t天第j个班次有人员出勤;当
x
i
j
t
=
0
x_{ijt}=0
xijt=0时,表示没有人员出勤。约束条件如下:
∑
j
=
1
6
x
i
j
t
=
1
∀
i
,
t
\sum_{j=1}^{6} x_{ijt} = 1 \quad \forall i,t
j=1∑6xijt=1∀i,t
表示每个分拣中心每天只能有一个班次有人员出勤。
∑
i
=
1
57
∑
j
=
1
6
x
i
j
t
=
N
t
∀
t
\sum_{i=1}^{57} \sum_{j=1}^{6} x_{ijt} = N_t \quad \forall t
i=1∑57j=1∑6xijt=Nt∀t
表示每个班次的总人数为当天所有分拣中心需要的人员数量。
∑
i
=
1
57
∑
t
=
1
30
x
i
j
t
≤
M
∀
j
\sum_{i=1}^{57} \sum_{t=1}^{30} x_{ijt} \leq M \quad \forall j
i=1∑57t=1∑30xijt≤M∀j
表示每个班次的总人数不能超过最大可用人数M。
∑
t
=
1
30
∑
j
=
1
6
x
i
j
t
≤
0.85
×
30
∀
i
\sum_{t=1}^{30} \sum_{j=1}^{6} x_{ijt} \leq 0.85 \times 30 \quad \forall i
t=1∑30j=1∑6xijt≤0.85×30∀i
表示每名正式工的出勤率不能超过85%。
∑
j
=
1
6
x
i
j
t
≤
1
∀
i
,
t
\sum_{j=1}^{6} x_{ijt} \leq 1 \quad \forall i,t
j=1∑6xijt≤1∀i,t
表示每个分拣中心每天只能有一个班次有人员出勤。
x
i
j
t
∈
{
0
,
1
}
∀
i
,
j
,
t
x_{ijt} \in \{0,1\} \quad \forall i,j,t
xijt∈{0,1}∀i,j,t
表示决策变量为0或1。
综上所述,问题3的数学模型为:
m
i
n
∑
i
=
1
57
∑
t
=
1
30
∑
j
=
1
6
x
i
j
t
min \quad \sum_{i=1}^{57} \sum_{t=1}^{30} \sum_{j=1}^{6} x_{ijt}
mini=1∑57t=1∑30j=1∑6xijt
s
.
t
.
∑
j
=
1
6
x
i
j
t
=
1
∀
i
,
t
s.t. \quad \sum_{j=1}^{6} x_{ijt} = 1 \quad \forall i,t
s.t.j=1∑6xijt=1∀i,t
∑
i
=
1
57
∑
j
=
1
6
x
i
j
t
=
N
t
∀
t
\sum_{i=1}^{57} \sum_{j=1}^{6} x_{ijt} = N_t \quad \forall t
i=1∑57j=1∑6xijt=Nt∀t
∑
i
=
1
57
∑
t
=
1
30
x
i
j
t
≤
M
∀
j
\sum_{i=1}^{57} \sum_{t=1}^{30} x_{ijt} \leq M \quad \forall j
i=1∑57t=1∑30xijt≤M∀j
∑
t
=
1
30
∑
j
=
1
6
x
i
j
t
≤
0.85
×
30
∀
i
\sum_{t=1}^{30} \sum_{j=1}^{6} x_{ijt} \leq 0.85 \times 30 \quad \forall i
t=1∑30j=1∑6xijt≤0.85×30∀i
∑
j
=
1
6
x
i
j
t
≤
1
∀
i
,
t
\sum_{j=1}^{6} x_{ijt} \leq 1 \quad \forall i,t
j=1∑6xijt≤1∀i,t
x
i
j
t
∈
{
0
,
1
}
∀
i
,
j
,
t
x_{ijt} \in \{0,1\} \quad \forall i,j,t
xijt∈{0,1}∀i,j,t
# 导入相关库
import pandas as pd
import numpy as np
from scipy.optimize import minimize
# 读取数据
df_volume = pd.read_csv('附件1.csv', encoding='gbk') # 读取过去4个月的每天货量数据
df_hour_volume = pd.read_csv('附件2.csv', encoding='gbk') # 读取过去30天每小时货量数据
df_route_volume = pd.read_csv('附件3.csv', encoding='gbk') # 读取过去90天各分拣中心之间的运输线路平均货量数据
df_new_route = pd.read_csv('附件4.csv', encoding='gbk') # 读取未来30天分拣中心之间的运输线路变化数据
# 定义函数
def objective(x):
"""构建优化目标函数,最小化总人天数"""
return np.sum(np.ceil(x))
def constraint_1(x):
"""约束条件1:每天货量处理完成的基础上,安排的人天数尽可能少"""
return np.sum(np.ceil(x)) - np.sum(df_volume['货量'])
def constraint_2(x):
"""约束条件2:每天的实际小时人效尽量均衡"""
return np.std(x)
def constraint_3(x):
"""约束条件3:正式工的出勤率尽量均衡"""
return np.std(np.ceil(x[:6])) # 假设每天分为6个班次,计算每天正式工的出勤率
# 定义初始值
x0 = np.ones(len(df_volume)) # 初始值为每天每个分拣中心都有一个人出勤
# 定义约束条件
con1 = {'type': 'ineq', 'fun': constraint_1}
con2 = {'type': 'ineq', 'fun': constraint_2}
con3 = {'type': 'ineq', 'fun': constraint_3}
# 定义范围
bounds = [(0, 100) for i in range(len(df_volume))] # 假设每天每个分拣中心最多100人出勤
# 优化求解
res = minimize(objective, x0, method='SLSQP', bounds=bounds, constraints=[con1, con2, con3])
print("优化结果:")
print(res)
# 将结果写入表5中
df_result = pd.DataFrame(columns=['分拣中心', '班次', '出勤人数'])
df_result['分拣中心'] = df_volume['分拣中心']
df_result['班次'] = ['00:00-08:00', '05:00-13:00', '08:00-16:00', '12:00-20:00', '14:00-22:00', '16:00-24:00'] * len(df_volume)
df_result['出勤人数'] = np.ceil(res.x)
# 输出结果
print("结果表5:")
print(df_result)
# 第四个问题:研究特定分拣中心的排班问题,以SC60为例
# 定义函数
def objective(x):
"""构建优化目标函数,最小化总人天数"""
return np.sum(np.ceil(x))
def constraint_1(x):
"""约束条件1:每天货量处理完成的基础上,安排的人天数尽可能少"""
return np.sum(np.ceil(x)) - np.sum(df_volume['货量'])
def constraint_2(x):
"""约束条件2:每天的实际小时人效尽量均衡"""
return np.std(x)
def constraint_3(x):
"""约束条件3:正式工的出勤率尽量均衡"""
return np.std(np.ceil(x[:6])) # 假设每天分为6个班次,计算每天正式工的出勤率
def constraint_4(x):
"""约束条件4:正式工的出勤率不能高于85%"""
return np.sum(x[:6])/len(x[:6]) - 0.85 # 假设每天分为6个班次,计算每天正式工的出勤率
def constraint_5(x):
"""约束条件5:连续出勤天数不能超过7天"""
return np.sum(x[6:]) - 7 # 假设每天分为6个班次,计算每天正式工的出勤率
# 定义初始值
x0 = np.ones(len(df_volume)) # 初始值为每天每个分拣中心都有一个人出勤
# 定义约束条件
con1 = {'type': 'ineq', 'fun': constraint_1}
con2 = {'type': 'ineq', 'fun': constraint_2}
con3 = {'type': 'ineq', 'fun': constraint_3}
con4 = {'type': 'ineq', 'fun': constraint_4}
con5 = {'type': 'ineq', 'fun': constraint_5}
# 定义范围
bounds = [(0, 100) for i in range(len(df_volume))] # 假设每天每个分拣中心最多100人出勤
# 优化求解
res = minimize(objective, x0, method='SLSQP', bounds=bounds, constraints=[con1, con2, con3, con4, con5])
print("优化结果:")
print(res)
# 将结果写入表6中
df_result = pd.DataFrame(columns=['分拣中心', '班次', '正式工出勤', '临时工出勤'])
df_result['分拣中心'] = df_volume['分拣中心']
df_result['班次'] = ['00:00-08:00', '05:00-13:00', '08:00-16:00', '12:00-20:00', '14:00-22:00', '16:00-24:00'] * len(df_volume)
df_result['正式工出勤'] = np.ceil(res.x[:6])
df_result['临时工出勤'] = np.ceil(res.x[6:])
# 输出结果
print("结果表6:")
print(df_result)
该段文字的第四个问题是:针对特定分拣中心,确定未来30天每名正式工及临时工的班次出勤计划,并计算出勤率和雇佣临时工数量。
设分拣中心SC60共有p个班次,每个班次需要q名正式工和r名临时工。假设第i个班次的货量为 H i H_i Hi,第i个班次中第j名正式工的出勤天数为 n i j n_{ij} nij,第i个班次中第j名正式工的出勤率为 α i j \alpha_{ij} αij,每个班次中需要雇佣的临时工数量为 m i m_i mi,则有以下数学模型:
目标函数:最小化雇佣临时工的总人天数,即 min ∑ i = 1 p m i \min \sum_{i=1}^{p} m_i min∑i=1pmi
约束条件:
-
每个班次中正式工的总出勤天数等于30天,即 ∑ j = 1 q n i j = 30 , i = 1 , ⋯ , p \sum_{j=1}^{q} n_{ij} = 30, i=1,\cdots,p ∑j=1qnij=30,i=1,⋯,p
-
每个班次中临时工的总出勤天数等于30天,即 30 m i = ∑ j = 1 r n i j , i = 1 , ⋯ , p 30m_i = \sum_{j=1}^{r} n_{ij}, i=1,\cdots,p 30mi=∑j=1rnij,i=1,⋯,p
-
正式工的出勤率不能超过85%,即 α i j = n i j 30 ≤ 0.85 , i = 1 , ⋯ , p , j = 1 , ⋯ , q \alpha_{ij} = \frac{n_{ij}}{30} \leq 0.85, i=1,\cdots,p, j=1,\cdots,q αij=30nij≤0.85,i=1,⋯,p,j=1,⋯,q
-
正式工的连续出勤天数不能超过7天,即 n i j ≤ 7 , i = 1 , ⋯ , p , j = 1 , ⋯ , q n_{ij} \leq 7, i=1,\cdots,p, j=1,\cdots,q nij≤7,i=1,⋯,p,j=1,⋯,q
-
每个班次中临时工的数量不能超过正式工的数量,即 m i ≤ q , i = 1 , ⋯ , p m_i \leq q, i=1,\cdots,p mi≤q,i=1,⋯,p
-
每个班次中的实际小时人效尽量均衡,即 H i q + r ≈ H j q + r , i , j = 1 , ⋯ , p \frac{H_i}{q+r} \approx \frac{H_j}{q+r}, i,j=1,\cdots,p q+rHi≈q+rHj,i,j=1,⋯,p
-
每个班次中正式工的出勤率尽量均衡,即 α i j ≈ α k l , i , j , k , l = 1 , ⋯ , p \alpha_{ij} \approx \alpha_{kl}, i,j,k,l=1,\cdots,p αij≈αkl,i,j,k,l=1,⋯,p
-
每个班次的总人数等于q+r,即 q + r = m i , i = 1 , ⋯ , p q + r = m_i, i=1,\cdots,p q+r=mi,i=1,⋯,p
-
正式工和临时工的数量为整数,即 q , r , m i ∈ Z , i = 1 , ⋯ , p q,r,m_i \in \mathbb{Z}, i=1,\cdots,p q,r,mi∈Z,i=1,⋯,p
综合以上目标函数和约束条件,可以得到如下数学模型:
min ∑ i = 1 p m i s.t. ∑ j = 1 q n i j = 30 , i = 1 , ⋯ , p 30 m i = ∑ j = 1 r n i j , i = 1 , ⋯ , p α i j = n i j 30 ≤ 0.85 , i = 1 , ⋯ , p , j = 1 , ⋯ , q n i j ≤ 7 , i = 1 , ⋯ , p , j = 1 , ⋯ , q m i ≤ q , i = 1 , ⋯ , p H i q + r ≈ H j q + r , i , j = 1 , ⋯ , p α i j ≈ α k l , i , j , k , l = 1 , ⋯ , p q + r = m i , i = 1 , ⋯ , p q , r , m i ∈ Z , i = 1 , ⋯ , p \begin{align} \min \sum_{i=1}^{p} m_i \\ \text{s.t.} \quad & \sum_{j=1}^{q} n_{ij} = 30, i=1,\cdots,p \\ & 30m_i = \sum_{j=1}^{r} n_{ij}, i=1,\cdots,p \\ & \alpha_{ij} = \frac{n_{ij}}{30} \leq 0.85, i=1,\cdots,p, j=1,\cdots,q \\ & n_{ij} \leq 7, i=1,\cdots,p, j=1,\cdots,q \\ & m_i \leq q, i=1,\cdots,p \\ & \frac{H_i}{q+r} \approx \frac{H_j}{q+r}, i,j=1,\cdots,p \\ & \alpha_{ij} \approx \alpha_{kl}, i,j,k,l=1,\cdots,p \\ & q + r = m_i, i=1,\cdots,p \\ & q,r,m_i \in \mathbb{Z}, i=1,\cdots,p \end{align} mini=1∑pmis.t.j=1∑qnij=30,i=1,⋯,p30mi=j=1∑rnij,i=1,⋯,pαij=30nij≤0.85,i=1,⋯,p,j=1,⋯,qnij≤7,i=1,⋯,p,j=1,⋯,qmi≤q,i=1,⋯,pq+rHi≈q+rHj,i,j=1,⋯,pαij≈αkl,i,j,k,l=1,⋯,pq+r=mi,i=1,⋯,pq,r,mi∈Z,i=1,⋯,p
假设分拣中心SC60未来30天每天的货量为
Q
S
C
60
(
t
)
Q_{SC60}(t)
QSC60(t),其中
t
t
t为从当前开始的天数,该中心当前已雇佣的正式工人数为
n
n
n,每人每天出勤的班次数为
x
i
(
i
=
1
,
2
,
.
.
.
,
n
)
x_i(i=1,2,...,n)
xi(i=1,2,...,n),其中
x
i
x_i
xi为0或1,表示第
i
i
i名正式工在该班次是否出勤。根据题目要求,正式工的出勤率不能高于85%,即
∑
i
=
1
n
x
i
⩽
0.85
×
30
=
25.5
\sum_{i=1}^{n}x_i\leqslant 0.85\times 30=25.5
i=1∑nxi⩽0.85×30=25.5
又因为每名正式工每天只能出勤一个班次,所以
∑
i
=
1
n
x
i
⩽
1
\sum_{i=1}^{n}x_i\leqslant 1
i=1∑nxi⩽1
综合以上两个条件,得出
∑
i
=
1
n
x
i
=
1
\sum_{i=1}^{n}x_i=1
i=1∑nxi=1
该式表示所有正式工必须出勤一个班次。另外,每个班次需要雇佣的临时工数量为
m
j
(
j
=
1
,
2
,
.
.
.
,
6
)
m_j(j=1,2,...,6)
mj(j=1,2,...,6),其中
m
j
m_j
mj为整数,表示第
j
j
j个班次需要雇佣的临时工数量。根据题目要求,每个班次的人数不能超过60,即
∑
i
=
1
n
x
i
+
m
j
⩽
60
\sum_{i=1}^{n}x_i+m_j\leqslant 60
i=1∑nxi+mj⩽60
综合以上条件,可以建立如下模型:
m
i
n
∑
j
=
1
6
m
j
s
.
t
.
∑
i
=
1
n
x
i
=
1
∑
i
=
1
n
x
i
+
m
j
⩽
60
,
j
=
1
,
2
,
.
.
.
,
6
x
i
∈
{
0
,
1
}
,
i
=
1
,
2
,
.
.
.
,
n
m
j
∈
Z
+
,
j
=
1
,
2
,
.
.
.
,
6
min\quad \sum_{j=1}^{6}m_j \\ s.t. \quad \sum_{i=1}^{n}x_i=1 \\ \sum_{i=1}^{n}x_i+m_j\leqslant 60,\quad j=1,2,...,6 \\ x_i\in \{0,1\},\quad i=1,2,...,n \\ m_j\in \mathbb{Z}_+,\quad j=1,2,...,6 \\
minj=1∑6mjs.t.i=1∑nxi=1i=1∑nxi+mj⩽60,j=1,2,...,6xi∈{0,1},i=1,2,...,nmj∈Z+,j=1,2,...,6
其中,
Z
+
\mathbb{Z}_+
Z+表示非负整数集合。该模型的目标函数为最小化临时工的雇佣数量,约束条件为每个班次的人数不能超过60,且所有正式工必须出勤一个班次。该模型可以通过线性规划求解,得出每个班次需要雇佣的临时工数量,从而确定正式工的出勤计划。同时,可以计算出正式工的出勤率和总的雇佣临时工数量,从而满足题目要求。
研究特定分拣中心的排班问题,这里不妨以SC60为例,假设分拣中心SC60当前有200名正式工,请基于问题2的预测结果建立模型,确定未来30天每名正式工及临时工的班次出勤计划,即给出未来30天每天六个班次中,每名正式工将在哪些班次出勤,每个班次需要雇佣多少临时工,并写入结果表6中。每名正式工的出勤率(出勤的天数除以总天数30)不能高于85%,且连续出勤天数不能超过7天。要求在每天货量处理完成的基础上,安排的人天数尽可能少,每天的实际小时人效尽量均衡,且正式工出勤率尽量均衡。该段文字的第四个问题是:针对特定分拣中心,确定未来30天每名正式工及临时工的班次出勤计划,并计算出勤率和雇佣临时工数量。
首先,根据问题2的预测结果,我们可以得到分拣中心SC60未来30天每天及每小时的货量预测值。然后,我们将每天分为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。假设每个班次需要的正式工人数分别为 x 1 , x 2 , x 3 , x 4 , x 5 , x 6 x_1, x_2, x_3, x_4, x_5, x_6 x1,x2,x3,x4,x5,x6,需要的临时工人数分别为 y 1 , y 2 , y 3 , y 4 , y 5 , y 6 y_1, y_2, y_3, y_4, y_5, y_6 y1,y2,y3,y4,y5,y6,则每天需要的总人数为 x 1 + y 1 , x 2 + y 2 , x 3 + y 3 , x 4 + y 4 , x 5 + y 5 , x 6 + y 6 x_1+y_1, x_2+y_2, x_3+y_3, x_4+y_4, x_5+y_5, x_6+y_6 x1+y1,x2+y2,x3+y3,x4+y4,x5+y5,x6+y6,总人天数为 x 1 + y 1 + x 2 + y 2 + x 3 + y 3 + x 4 + y 4 + x 5 + y 5 + x 6 + y 6 x_1+y_1+x_2+y_2+x_3+y_3+x_4+y_4+x_5+y_5+x_6+y_6 x1+y1+x2+y2+x3+y3+x4+y4+x5+y5+x6+y6。为了使总人天数最小,我们可以建立如下优化模型:
min x 1 , x 2 , x 3 , x 4 , x 5 , x 6 , y 1 , y 2 , y 3 , y 4 , y 5 , y 6 x 1 + y 1 + x 2 + y 2 + x 3 + y 3 + x 4 + y 4 + x 5 + y 5 + x 6 + y 6 \min_{x_1, x_2, x_3, x_4, x_5, x_6, y_1, y_2, y_3, y_4, y_5, y_6} \ x_1+y_1+x_2+y_2+x_3+y_3+x_4+y_4+x_5+y_5+x_6+y_6 x1,x2,x3,x4,x5,x6,y1,y2,y3,y4,y5,y6min x1+y1+x2+y2+x3+y3+x4+y4+x5+y5+x6+y6
约束条件为:
{ x 1 + y 1 ≥ 1 30 ∑ i = 1 30 预测 值 i × 25 , x 2 + y 2 ≥ 1 30 ∑ i = 1 30 预测 值 i × 25 , x 3 + y 3 ≥ 1 30 ∑ i = 1 30 预测 值 i × 25 , x 4 + y 4 ≥ 1 30 ∑ i = 1 30 预测 值 i × 25 , x 5 + y 5 ≥ 1 30 ∑ i = 1 30 预测 值 i × 25 , x 6 + y 6 ≥ 1 30 ∑ i = 1 30 预测 值 i × 25 , \begin{cases} x_1+y_1 \geq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 25,\\ x_2+y_2 \geq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 25,\\ x_3+y_3 \geq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 25,\\ x_4+y_4 \geq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 25,\\ x_5+y_5 \geq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 25,\\ x_6+y_6 \geq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 25,\\ \end{cases} ⎩ ⎨ ⎧x1+y1≥301∑i=130预测值i×25,x2+y2≥301∑i=130预测值i×25,x3+y3≥301∑i=130预测值i×25,x4+y4≥301∑i=130预测值i×25,x5+y5≥301∑i=130预测值i×25,x6+y6≥301∑i=130预测值i×25,
{ x 1 + y 1 ≤ 1 30 ∑ i = 1 30 预测 值 i × 85 % , x 2 + y 2 ≤ 1 30 ∑ i = 1 30 预测 值 i × 85 % , x 3 + y 3 ≤ 1 30 ∑ i = 1 30 预测 值 i × 85 % , x 4 + y 4 ≤ 1 30 ∑ i = 1 30 预测 值 i × 85 % , x 5 + y 5 ≤ 1 30 ∑ i = 1 30 预测 值 i × 85 % , x 6 + y 6 ≤ 1 30 ∑ i = 1 30 预测 值 i × 85 % , \begin{cases} x_1+y_1 \leq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 85\%,\\ x_2+y_2 \leq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 85\%,\\ x_3+y_3 \leq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 85\%,\\ x_4+y_4 \leq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 85\%,\\ x_5+y_5 \leq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 85\%,\\ x_6+y_6 \leq \frac{1}{30}\sum_{i=1}^{30}预测值_i \times 85\%,\\ \end{cases} ⎩ ⎨ ⎧x1+y1≤301∑i=130预测值i×85%,x2+y2≤301∑i=130预测值i×85%,x3+y3≤301∑i=130预测值i×85%,x4+y4≤301∑i=130预测值i×85%,x5+y5≤301∑i=130预测值i×85%,x6+y6≤301∑i=130预测值i×85%,
{ x 1 + y 1 ≤ 200 , x 2 + y 2 ≤ 200 , x 3 + y 3 ≤ 200 , x 4 + y 4 ≤ 200 , x 5 + y 5 ≤ 200 , x 6 + y 6 ≤ 200 , \begin{cases} x_1+y_1 \leq 200,\\ x_2+y_2 \leq 200,\\ x_3+y_3 \leq 200,\\ x_4+y_4 \leq 200,\\ x_5+y_5 \leq 200,\\ x_6+y_6 \leq 200,\\ \end{cases} ⎩ ⎨ ⎧x1+y1≤200,x2+y2≤200,x3+y3≤200,x4+y4≤200,x5+y5≤200,x6+y6≤200,
{ x 1 + y 1 ≤ 7 , x 2 + y 2 ≤ 7 , x 3 + y 3 ≤ 7 , x 4 + y 4 ≤ 7 , x 5 + y 5 ≤ 7 , x 6 + y 6 ≤ 7 , \begin{cases} x_1+y_1 \leq 7,\\ x_2+y_2 \leq 7,\\ x_3+y_3 \leq 7,\\ x_4+y_4 \leq 7,\\ x_5+y_5 \leq 7,\\ x_6+y_6 \leq 7,\\ \end{cases} ⎩ ⎨ ⎧x1+y1≤7,x2+y2≤7,x3+y3≤7,x4+y4≤7,x5+y5≤7,x6+y6≤7,
x 1 , x 2 , x 3 , x 4 , x 5 , x 6 , y 1 , y 2 , y 3 , y 4 , y 5 , y 6 ≥ 0 x_1, x_2, x_3, x_4, x_5, x_6, y_1, y_2, y_3, y_4, y_5, y_6 \geq 0 x1,x2,x3,x4,x5,x6,y1,y2,y3,y4,y5,y6≥0
其中,预测值 i i i表示第 i i i天的货量预测值。求解上述模型得到每天需要的正式工人数和临时工人数,从而得到每天的出勤人数和总人天数。然后,根据每天的出勤人数和总人天数,可以计算出每天的实际小时人效,从而判断是否均衡。同时,还需要根据每天的出勤人数和总人天数,可以计算出每名正式工的出勤率。如果发现某名正式工出勤率过高,可以考虑将其调整为出勤率较低的班次,从而实现正式工出勤率的均衡。最后,根据每天的出勤人数和总人天数,可以计算出每天需要雇佣的临时工数量,并将结果写入结果表6中。
# import numpy as np
import pandas as pd
# 读取数据
df = pd.read_excel('附件1.xlsx', sheet_name='Sheet1')
# 提取SC60分拣中心的数据
sc60 = df[df['分拣中心'] == 'SC60']
# 构建输入数据
data = sc60[['日期', '包裹量']].set_index('日期')
# 构建模型
from statsmodels.tsa.arima_model import ARIMA
# 训练模型
model = ARIMA(data, order=(1, 1, 1)).fit()
# 预测未来30天每小时的货量
pred = model.predict(start=len(data), end=len(data) + 30 * 24 - 1, dynamic=True)
# 将预测结果写入结果表
result = pd.DataFrame({
'日期': pd.date_range(start=data.index.max() + pd.Timedelta(hours=1), periods=30 * 24, freq='H'),
'预测每小时货量': pred.tolist()
})
result.to_excel('结果表6.xlsx', index=False)
更多内容具体可以看看我的下方名片!里面包含有认证杯一手资料与分析!
另外在赛中,我们也会陪大家一起解析认证杯的一些方向
关注 CS数模 团队,数模不迷路~