案例 028 顺路把退货带回去:配送与退货取件的混合路线
案例 028 顺路把退货带回去:配送与退货取件的混合路线
摘要:9 单配送之外还有 3 个退货点合计 5 件,车上退货格只能放 5 件,驿站必须最后到。本文建立混合取送 VRP:\(y_{ij}\) 走弧、\(u_i\) 定次序、\(g_i\) 递推车上件数,把驿站钉死为终点以消除对称解。结果表明:最优里程 20.05 km,比纯配送的 15.94 km 只多 4.11 km(25.8%),峰值载重恰好 5 件;容量低于 5 时问题不可行。
关键词:外卖配送;混合取送;退货;容量;Gurobi
1 问题提出
1.1 问题是什么
9 单正常配送、3 个客户要顺手退快递(共 5 件),所有退货最后统一交到菜鸟驿站。车上的退货格只能放 5 件——5 件刚好装满,一件都不能多带。
排一条从出发点出发、依次处理 9 单配送与 3 个退货取件、最后停在驿站的路线,使总里程最小,且车上退货件数任何时刻不超过 5。
表 1 13 个节点的坐标与属性
| 节点 | 类型 | 坐标 /km | 件数 |
|---|---|---|---|
| D1 | 配送 | (0.9, 1.2) | 0 |
| D2 | 配送 | (1.8, 1.9) | 0 |
| D3 | 配送 | (0.5, 2.6) | 0 |
| D4 | 配送 | (2.4, 0.6) | 0 |
| D5 | 配送 | (-0.7, 1.9) | 0 |
| D6 | 配送 | (1.2, -1.1) | 0 |
| D7 | 配送 | (2.9, 2.7) | 0 |
| D8 | 配送 | (-1.4, 0.8) | 0 |
| D9 | 配送 | (0.2, -1.9) | 0 |
| R1 | 退货 | (2.1, 3.3) | 2 |
| R2 | 退货 | (-1.9, 2.4) | 2 |
| R3 | 退货 | (3.4, -0.5) | 1 |
| ST | 驿站 | (0.6, -0.9) | — |
纯配送(不含退货)的最短巡回是 15.94 km;加上三个退货点并收在驿站,变成 20.05 km,绕行 4.11 km(25.8%)。
1.2 为什么要优化
- 退货是白捡的钱:驿站按件结算,绕行成本远低于收益,但绕不好会拖垮整趟;
- 容量 5 件是硬顶:三个点合计正好 5 件,取件顺序一错就装不下;
- 驿站必须在最后:中途折返驿站等于多跑一个来回。
1.3 Gurobi 如何求解
\(y_{ij}\) 走弧,\(u_i\) 为访问次序,\(g_i\) 为车上退货件数(流量变量)。驿站固定为终点,把"最后访问"写成 \(u_{ST}=n-1\):
模型 209 个变量、355 条约束,0.05 s 求得最优。
2 数学模型
2.1 符号说明
节点集 \(V\)(出发点 \(0\)、配送客户 \(D\)、退货点 \(R\)、驿站 \(ST\)),共 14 个;\(d_{ij}\) 为里程;\(q_j\) 为节点 \(j\) 的退货件数(配送客户为 0);\(C=5\);\(u_i\) 为访问次序。
2.2 目标函数
2.3 约束条件
一进一出:
次序递推与子回路消除:
驿站固定终点:
容量流量递推:
2.4 规模与性质
14 个节点、182 条弧、14 个次序变量与 14 个流量变量,约束 355 条。这是混合取送 VRP(VRP with Mixed Pickup and Delivery)的简化:配送是"送",退货是"取",两者共用一条路线。把驿站钉死在终点能砍掉大量对称解——否则同一路线可以从任意位置接上驿站,等价解成倍增加。
3 Gurobi 求解实现
3.1 建模要点
m.addConstr(u[IDX_ST] == k - 1) # 驿站固定最后
for i, j in arc: # 容量用流量变量
m.addConstr(g[j] >= g[i] + qd[j] - CAP * (1 - y[i, j]))
m.addConstrs((u[i] - u[j] + (k - 1) * y[i, j] <= k - 2 for i, j in arc if i and j))
一条实现细节:容量不建"件数 ≤ C"的整体约束,而是逐弧递推。整体约束只能管住总量,管不住"中途某一段装爆";逐弧递推把每段的载重都写进 \(g_i\),才真正等价于"车上最多 5 件"。
3.2 求解结果
表 2 最优混合路线
| 指标 | 数值 |
|---|---|
| 访问顺序 | D → D8 → R2 → D5 → D3 → R1 → D7 → D2 → D1 → D4 → R3 → D6 → D9 → ST |
| 总里程 /km | 20.05 |
| 纯配送里程 /km | 15.94 |
| 退货绕行 /km | 4.11 |
| 峰值退货件数 /件 | 5 |
| 驿站停靠次数 | 1 |
三个退货点插入后只多跑 4.11 km,平均每件退货的绕行成本 821 m。
4 结果分析
4.1 路线的形状
图 1 中蓝点是配送客户、橙三角是退货点、绿方块是驿站。路线先向北把 D3、R1、D7 一带扫掉,再折回西南取 R2,最后收在驿站——退货点不是专门跑一趟,而是"顺路"塞进配送段之间的空隙。

图 1 配送与退货混合路线
图 2 把 13 个节点放进"距离—件数"平面:退货点(三角)都在外圈且件数少,配送客户(圆点)件数多。外圈少件数的点最适合当"顺路点",因为它们不占容量、只多跑一点路。

图 2 各节点的距离与件数
4.2 绕行的代价
图 3 的瀑布把里程拆开:纯配送 15.94 km,依次插入 R2、R1、R3,合计 20.05 km。三个点合起来的增量只有 4.11 km,因为每个点都落在既有路径的"折角"上。

图 3 退货点逐个插入的里程增量
图 4 是车上退货件数的阶梯:R2 之后 2 件、R1 之后 4 件、R3 之后 5 件,一路顶到容量线但没越界。峰值恰好等于 5——这也是容量再小一件就无解的原因。

图 4 车上退货件数的累计
4.3 灵敏度
图 5 把退货容量从 3 放宽到 8:容量小于 5 时不可行(右轴可行标志掉到 0),5 及以上里程不变(20.05 km)。容量在这里是"开关"而不是"成本"——它不改变最优路线,只决定有没有解。

图 5 最优里程与可行性随退货容量的变化
图 6 是容量与退货件数缩放的热图:右下角(件数多、容量小)空白,左上角最深。件数每多一件,最小可行容量就抬一格——两者是 1:1 的关系。

图 6 最优里程关于容量与件数的热图
图 7 只改退货点个数:0 个 15.94 km、1 个 16.69 km、2 个 18.36 km、3 个 20.05 km。边际绕行递减:第一个点最贵(要专门拐出去),后面两个几乎是捎带。

图 7 最优里程与绕行增量随退货点个数的变化
4.4 前沿与分解
图 8 把"容量—里程"画成前沿:左侧灰区是装不下 5 件的不可行区,右侧是一条水平线。这条水平线说明容量约束在最优解上"不紧"——峰值恰好 5,再放宽也只是留余量,不会省路。

图 8 退货容量的可行前沿
图 9 是 200 次随机最近邻的里程分布:均值 24.64 km、最好 19.61 km,模型最优 20.05 km 贴在左尾。"随手顺路"平均要多跑 4.60 km(19%)。

图 9 200 次随机贪心的里程分布
图 10 把里程按段型拆开:配送段 12.98 km、退货绕行 4.91 km、回驿站 1.08 km。退货相关的里程只占 30%,其余都是本来就要跑的配送段。

图 10 里程的段型分解
5 结论
- 9 单配送 + 3 个退货点 + 1 个驿站,最优路线 D → D8 → R2 → D5 → D3 → R1 → D7 → D2 → D1 → D4 → R3 → D6 → D9 → ST,总里程 20.05 km。
- 退货只带来 4.11 km 的绕行(25.8%),平均每件 821 m——顺路取件的成本远低于专程。
- 车上退货件数峰值恰好等于容量 5 件,容量再小一件即无解;容量是"可行性开关",不是"成本项"。
- 把驿站钉死为终点(\(u_{ST}=13\))消除了大量对称解,是这类混合取送模型能快速求解的关键。
- 200 次随机贪心的均值 24.64 km 比最优多 4.60 km,说明"顺路"必须算,不能凭感觉。
参考文献
[1] Gurobi Optimization LLC. Gurobi Optimizer Reference Manual[Z]. 2024.
[2] Kellerer H, Pferschy U, Pisinger D. Knapsack Problems[M]. Berlin: Springer, 2004.
[3] Martello S, Toth P. Knapsack Problems: Algorithms and Computer Implementations[M]. Chichester: John Wiley & Sons, 1990.
[4] 司守奎, 孙玺菁. 数学建模算法与应用[M]. 3 版. 北京: 国防工业出版社, 2021.
复现方式:python batch.py;数据与结果见同目录 .csv / .json,图见 figs/

浙公网安备 33010602011771号