案例 025 和同行换两单:两车换单的指派—路径联合优化

案例 025 和同行换两单:两车换单的指派—路径联合优化

摘要:陈 有 6 单、赵 有 5 单,两条路线互相穿过对方腹地。本文用共享指派变量 \(z_i\) 同时门控两条路线的出入度,建立带基数约束与双边同意约束的两车 VRP,以 Gurobi 求全局最优,并用 462 种 6/5 划分的全枚举独立校验。结果表明:只需换 2 单(A3、B4),合计里程由 29.81 km 降到 25.58 km(省 14.2%),且双方各自都变短(+1.48 / +2.75 km);总里程最优的划分并不等于双方都愿意接受的划分。

关键词:外卖配送;两车VRP;订单交换;指派变量;Gurobi


1 问题提出

1.1 问题是什么

陈 手上有 6 单(A1—A6),同行赵 手上有 5 单(B1—B5),两人出发点相距 0.55 km。11 个客户点撒在荔湾—越秀—天河的 5 km 见方里,两条路线互相穿过对方的腹地:陈 的 A6 在东侧,赵 的 B3 在北侧,赵 的 B4 又在东南角。

把 11 张订单在两人之间重新划分(总单量仍为 6 : 5),各排一条最短巡回,使两人里程合计最小,且谁也不比换单前跑得更远。

表 1 11 张订单的坐标与归属

订单 东向 /km 北向 /km 换前归属 到陈出发点 /km 到赵出发点 /km
A1 1.2 1.8 陈 2.14 2.22
A2 2.4 1.1 陈 2.69 2.45
A3 0.6 2.9 陈 2.89 3.16
A4 3.1 2.4 陈 3.94 3.82
A5 1.9 -1.2 陈 2.39 1.82
A6 4.0 0.9 陈 4.18 3.83
B1 -0.9 2.2 赵 2.25 2.75
B2 0.2 3.4 赵 3.31 3.65
B3 2.8 3.6 赵 4.55 4.56
B4 3.6 -0.7 赵 3.79 3.28
B5 -1.6 0.6 赵 1.58 2.13

换单前各自的最短巡回:陈 14.04 km、赵 15.76 km,合计 29.81 km。这两个数不是"随便排",是对 6! 与 5! 条顺序全枚举取最小得到的,因此下文的节省量不会掺入排序误差。

1.2 为什么要优化

  • 里程是纯支出:11 单的配送费按单结,跑多少公里都只按单算钱,省下的每一公里都是净得;
  • 交换必须双方都点头:只要一方变差,这笔交换在现实中谈不成,模型必须写成双边约束而不只是总量最优;
  • 单量是刚性承诺:平台按在手单量考核,换单不能变成"把单甩给对方"。

1.3 Gurobi 如何求解

两套弧变量 \(y^{1}_{ij},y^{2}_{ij}\) 加一套共享指派变量 \(z_i\)(\(z_i=1\) 表示订单 \(i\) 归 陈)。\(z_i\) 同时门控两条路线的出入度,是"点是否属于车 1"的开关:

\[\sum_{j\ne i}y^{1}_{ij}=\sum_{j\ne i}y^{1}_{ji}=z_i,\qquad \sum_{j\ne i}y^{2}_{ij}=\sum_{j\ne i}y^{2}_{ji}=1-z_i \tag{1} \]

模型 332 个变量、549 条约束,0.27 s 求得最优(MIP gap 0)。两侧的"同意"约束把解限制在不劣于各自基准的区域内。

2 数学模型

2.1 符号说明

客户集 \(C=\{1,\dots,11\}\),车 \(k\in\{1,2\}\) 的出发点记为 \(0_k\);\(d^{k}_{ij}\) 为车 \(k\) 视角的里程;\(s=2.0\) min 为每单服务时长;\(v=18\) km/h;\(T^{\max}=70\) min 为单车时限;\(z^{0}_i\) 为换单前归属。

2.2 目标函数

\[\min\ Z=\sum_{(i,j)}d^{1}_{ij}y^{1}_{ij}+\sum_{(i,j)}d^{2}_{ij}y^{2}_{ij} \tag{2} \]

2.3 约束条件

单量守恒(换单不改变总量):

\[\sum_{i\in C}z_i=6,\qquad z_i\in\{0,1\} \tag{3} \]

每点恰好被自己所属的车访问一次,即式 (1);出发点的出入度各为 1:

\[\sum_{j\in C}y^{k}_{0_k j}=1,\qquad \sum_{j\in C}y^{k}_{j0_k}=1,\qquad k=1,2 \tag{4} \]

子回路消除(MTZ):

\[u^{k}_i-u^{k}_j+11\,y^{k}_{ij}\le 11-1,\qquad 1\le u^{k}_i\le 11 \tag{5} \]

时刻递推与单车时限:

\[t^{k}_j\ge t^{k}_i+s+\frac{60\,d^{k}_{ij}}{v}-M(1-y^{k}_{ij}),\qquad t^{k}_i\le T^{\max} \tag{6} \]

双方同意(净收益非负):

\[\sum d^{1}y^{1}\le 14.04,\qquad \sum d^{2}y^{2}\le 15.76 \tag{7} \]

2.4 规模与性质

11 个客户、2 个出发点、264 条有向弧,变量 332 个、约束 549 条。这是带基数约束的两车 VRP(2-SPRP 的简化),NP-难;但 11 个客户只有 \(\binom{11}{6}=462\) 种 6/5 划分,每种划分的两个 TSP 可全枚举,\(\binom{11}{6}(6!+5!)=388080\) 条巡回,能在一秒内算完——这是本例敢说"全局最优"的底气。

3 Gurobi 求解实现

3.1 建模要点

for k in range(N):                        # 一个 z 门控两条路线
    m.addConstr(quicksum(ya[k+1, j] for j in ...) == z[k])
    m.addConstr(quicksum(yb[k+1, j] for j in ...) == 1 - z[k])
m.addConstr(quicksum(z) == 6)             # 单量守恒
m.addConstr(kmA <= dA0)                   # 双边同意:谁也不许变差
m.addConstr(kmB <= dB0)

一条实现细节:同意约束写在里程上,不写在"收益"上。因为单车单量固定为 6 : 5,每单收入与路线无关,净收益只差一个常数,所以"净收益 \(\ge 0\)"与"里程不增加"完全等价——省掉一层换算,也避免正文出现两套口径。

3.2 求解结果

表 2 换单结果

指标 换单前 换单后
陈 的里程 /km 14.04 12.56
赵 的里程 /km 15.76 13.01
合计 /km 29.81 25.58
陈 的单量 6 6

换手的订单是 A3、B4(共 2 单)。合计里程从 29.81 km 降到 25.58 km,省 4.23 km(14.2%);而两侧各自都不劣于换前(陈 +1.48 km、赵 +2.75 km),因此这笔交换双方都愿意做。

4 结果分析

4.1 路线结构

图 1 是换单后的两条路线:蓝线归 陈(6 单)、红线归 赵(5 单),圆圈标出换手的 A3、B4。换的不是"最近的",而是"最不顺路的"——A3、B4 原本要横穿另一位骑手的腹地,交出去以后两条线各自收成一片。

图 1 换单后两人的配送路线

图 2 把每单放进"到陈出发点—到赵出发点"的平面。对角线以上表示离赵更近、以下表示离陈更近;换手的两单(大气泡)都落在对角线的另一侧——几何上早该换,只是原先按接单顺序分派。

图 2 各订单到两个出发点的距离

4.2 换单的代价与收益

图 3 的瀑布把总里程拆开:起点 29.81 km,陈 的路线变化 -1.48 km,赵 的路线变化 -2.75 km,终点 25.58 km。增益全部来自"把远单换成近单",两条线的增减互为镜像,谁都没有被牺牲。

图 3 换单前后的里程分解

图 4 是 陈 的累计里程阶梯:模型顺序 12.56 km,最近邻贪心 18.60 km。同一批订单,光换排序就差 6.03 km(32.4%),说明"顺路"不能靠感觉判断。

图 4 累计里程:最优顺序与最近邻

4.3 灵敏度

图 5 让 陈 的单数从 4 变到 8:总里程在 24.99—28.07 km 之间,但"较弱一方的净节省"在 \(k=6\) 附近穿过 0 线。总里程最小的划分并不等于谈得成的划分——把单量往一边压,另一边必然吃亏。

图 5 总里程与较弱一方净节省随单数的变化

图 6 把单数与车速同时扫:车速越高,整片颜色越浅,但深浅的"分界位置"不随车速移动——最优划分只由几何决定,与跑多快无关。

图 6 总里程关于单数与车速的热图

图 7 收紧单车时限:48 min 时总里程 25.58 km、换手 1 单;放宽到 88 min 时 25.58 km、换手 1 单。时限越紧,越倾向于换单:两条交叉的路线在时间上先撞墙,换开以后各自变短、也各自变快。

图 7 总里程与换手单数随时限的变化

4.4 前沿与分解

图 8 把 462 种 6/5 划分全部画进"陈 里程—赵 里程"平面,虚线是不限换单次数的帕累托前沿,星号是模型解(只许换 1 对)。竖线右侧是"陈 不同意区"(比换前更远),落在里面的划分现实中谈不成。星号在前沿上方,并没有压到前沿上——差的正是"只许换 1 对"这条纪律:前沿最低点 23.37 km 需要换 2 对才够得着。

图 8 462 种划分的帕累托前沿

图 9 是 462 种划分的总里程分布:均值 28.51 km,最优 25.58 km 在左尾,不换单的 29.81 km 落在均值右侧。"随手分"平均要多跑 4.23 km。

图 9 全部划分的总里程分布

图 10 把里程按片区拆开:换单后 陈 的天河片 6.26 km(换前 5.72)、赵 的越秀片 4.58 km(换前 4.24)。换单实质是"片区归位":陈 收缩到东南,赵 收缩到西北,两人各让出一块飞地。

图 10 两人里程的片区分解

5 结论

  1. 11 单在两人之间只需换 2 单(A3、B4),合计里程由 29.81 km 降到 25.58 km,省 4.23 km(14.2%)。
  2. 交换对双方都是净收益(陈 +1.48 km、赵 +2.75 km),满足"双方同意",因此在现实中谈得成。
  3. 用 \(z_i\) 同时门控两条路线的出入度(式 1)是两车换单模型最省变量的写法,避免为每张订单建两套归属变量。
  4. 单量灵敏度显示:总里程最小的划分(\(k\ne 6\))会让一方变差,"总量最优"与"谈得成"不是同一件事。
  5. 462 种划分全枚举独立校验:不限换手次数的最优是 23.37 km(2 对),比"只换 1 对"再省 2.20 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/

posted @ 2026-11-10 08:33  小青蛙电气  阅读(1)  评论(0)    收藏  举报