案例 026 步行街最后 200 米:停车点选址与步行指派的两级配送
案例 026 步行街最后 200 米:停车点选址与步行指派的两级配送
摘要:上下九核心段禁入电动车,骑手只能停在外围再步行送达。本文建立两级(停车点—步行)选址-路径模型:\(z_{ip}\) 指派客户、\(y_{pq}\) 排停车点顺序、\(W_p\) 用线性化取最大步行半径,以 Gurobi 求最优。结果表明:总时间 31.05 min,其中步行往返 19.12 min(占 62%)、车行 7.93 min;单程步行上限低于 3.9 min 时无可行指派,可行域左边界由最远客户单独决定。
关键词:外卖配送;两级配送;步行街;选址-路径;Gurobi
1 问题提出
1.1 问题是什么
上下九、北京路的核心段全天禁入电动车。骑手只能把车停在外围,剩下最后一段靠走:3 个外围停车点(P1—P3)、8 个步行街内客户,单程步行 0.11—282 m,步行速度 75 m/min。核心段约 0.52 km × 0.44 km,客户分布在 8 个门牌上。
决定每个客户由哪个停车点服务、三个停车点按什么顺序走,使"车行 + 步行往返 + 交付"的总时间最小,且任何一次单程步行不超过 4.0 min。
表 1 客户坐标、份数与到三个停车点的步行距离
| 客户 | 坐标 /km | 份数 | 到 P1 /m | 到 P2 /m | 到 P3 /m |
|---|---|---|---|---|---|
| C1 | (-0.18, 0.08) | 1 | 178 | 512 | 402 |
| C2 | (-0.06, 0.08) | 1 | 282 | 396 | 365 |
| C3 | (0.06, 0.08) | 2 | 396 | 282 | 365 |
| C4 | (0.18, 0.08) | 1 | 512 | 178 | 402 |
| C5 | (-0.18, 0.30) | 2 | 178 | 512 | 228 |
| C6 | (-0.06, 0.30) | 1 | 282 | 396 | 152 |
| C7 | (0.06, 0.30) | 1 | 396 | 282 | 152 |
| C8 | (0.18, 0.30) | 2 | 512 | 178 | 228 |
三个停车点的容量各 3 份,合计 9 份刚好盖住 11 份——容量不紧,紧的是"最后 200 米":最近停车点最远的一位客户要走 282 m,正好压着 4.0 min 的线。
1.2 为什么要优化
- 步行是纯加时:车行 1 km 约 4 min,步行 1 km 要 13 min,同一段距离用脚走贵三倍;
- 停车点顺序影响车行:三个点构成一个 3 点 TSP,走错顺序多绕 0.4 km;
- 指派与顺序耦合:把客户分给"最近的点"往往让某个点的步行半径变长,总时间反而上升。
1.3 Gurobi 如何求解
\(z_{ip}\) 表示客户 \(i\) 由停车点 \(p\) 服务,\(y_{pq}\) 表示停车点之间的车行弧,\(w_p\) 表示该点是否启用,\(W_p\) 为该点的最大单程步行时间。\(W_p\) 用"最大化约束"线性化(目标里带正系数,等价于取最大):
模型 46 个变量、77 条约束,0.00 s 求得最优。
2 数学模型
2.1 符号说明
客户集 \(I\)(8 个)、停车点集 \(P\)(3 个)、出发点 \(0\);\(\delta_{ip}\) 为客户到停车点的步行距离(km,常数表);\(v_w=75\) m/min;\(d_{pq}\) 为停车点间车行距离;\(v=15\) km/h;\(s=0.5\) min 为每户交付时间;\(C=3\) 为单点容量;\(\bar W=4.0\) min 为单程步行上限。
2.2 目标函数
2.3 约束条件
每个客户恰好指派一次,且只能派给启用的停车点:
停车点进出度与启用一致(只走用到的点):
子回路消除:
步行上限:
2.4 规模与性质
4 个车行节点、24 个指派变量,约束 77 条。这是两级选址—路径问题(2E-LRP)的简化:上层是 3 点 TSP,下层是带容量与步行半径的指派。规模小,可整数求解;难点在"半径"这个非线性 max,用式 (6) 的线性化绕开。
3 Gurobi 求解实现
3.1 建模要点
for p in range(NP):
for i in range(NC):
m.addConstr(W[p] >= wt[p, i] * z[p, i]) # W_p 即该点最大步行
m.addConstr(quicksum(z[p, i] for i in range(NC)) <= CAP * w[p])
m.addConstr(quicksum(yc[p+1, j] ...) == w[p]) # 只走启用的点
m.addConstr(T >= drive + 2 * quicksum(W) + SER * NC)
一条实现细节:\(\max\) 不做 \(\max\) 约束,用"\(\ge\) + 目标正系数"实现。\(W_p\) 在目标里系数为 \(+2\),任何可行解都会把它压到下界,于是 \(W_p\) 自动等于 \(\max_i\{\cdot\}\)。这样既保持线性,又不用 addGenConstrMax。
3.2 求解结果
表 2 最优两级方案
| 指标 | 数值 |
|---|---|
| 停车点顺序 | S → P1 → P3 → P2 → S |
| 车行里程 /km | 1.98 |
| 车行时间 /min | 7.93 |
| 步行往返 /min | 19.12 |
| 交付 /min | 4.00 |
| 总时间 /min | 31.05 |
| 最大单程步行 /min | 3.76 |
8 个客户的指派是:P1 负责 C1、C2、C5;P2 负责 C3、C4、C8;P3 负责 C6、C7。
4 结果分析
4.1 空间结构
图 1 中蓝方块是三个外围停车点,绿气泡是步行街内的客户,橙色虚线是步行段,蓝色箭头是车行路线。最优方案不是"就近指派":C2 被派给了更远一点的 P1,因为它所在的那条巷子离两个点的距离只差 83 m,换点可以腾出容量给别人。

图 1 停车点、客户与两级路线
图 2 把每个客户放进"到最近点距离—改去次近点的额外距离"平面。点越靠近右上,换点的代价越大;横轴 300 m 的竖线是 4 min 上限。绝大多数点集中在 100—300 m 之间,说明步行街的几何尺度恰好卡在"走得到但走不快"的区间。

图 2 客户的最近与次近停车点距离
4.2 时间的构成
图 3 的瀑布把 31.05 min 拆开:车行 7.93 min、三个点的步行往返合计 19.12 min、交付 4.00 min。步行占了 62%,比车行还多——这就是"最后 200 米"的真实成本。

图 3 总时间的时间构成
图 4 是累计时间阶梯,每上一个台阶是一次"到点 + 步行往返 + 交付"。三段的斜率差异明显:车行段平缓,步行段陡。总时间对停车点数量几乎线性,这也是容量一旦收紧就要多点跑的原因。

图 4 按到访顺序的累计时间
4.3 灵敏度
图 5 把车行速度从 10 拉到 24 km/h:总时间由 35.01 min 降到 28.07 min,车行时间由 11.90 min 降到 4.96 min。总时间的降幅只有车行时间降幅的 100%——因为另外 19.12 min 的步行是车速管不到的。

图 5 总时间与车行时间随车速的变化
图 6 把车速与步速同时扫:左上角(车快、步也快)最浅,右下角最深。提步速比提车速更值钱:步速每提 7 m/min 省的时间,约等于车速提 4 km/h 的效果,因为步行时间在总时间里占 62%。

图 6 总时间关于车速与步速的热图
图 7 收紧单点容量:3 份时总时间 31.05 min、用 3 个点;放宽到 6 份时 26.30 min、用 2 个点。容量是"要不要多点跑"的开关:容量一旦小于 4 份,三个点就必须全用上。

图 7 总时间与使用点数随单点容量的变化
4.4 可行前沿与分点分解
图 8 把"单程步行上限—总时间"画成前沿:左侧灰区是"8 单无法全部指派"的不可行区,界在 3.9 min。边界右边一条水平线——上限只要过了 3.9 min 就不再是瓶颈,再放宽一分钱也不省。决定这条竖线的是最远那位客户:C2 到最近停车点 282 m。

图 8 步行上限的可行前沿与不可行区
图 9 是 8 个客户单程步行时间的 CDF:中位数 2.37 min,最大 3.76 min,全部落在 4.0 min 以内。半数客户要走 2 min 以上,这段路是无法用车速弥补的。

图 9 单程步行时间的累计分布
图 10 按停车点拆时间:P1 7.53 min 步行、P2 7.53 min、P3 4.06 min。步行时间与"该点最远客户"成正比,与客户数几乎无关——所以把远客户集中到一个点,比平均分摊更省。

图 10 各停车点的时间分解
5 结论
- 8 个客户、3 个外围停车点,最优总时间 31.05 min(车行 7.93 + 步行 19.12 + 交付 4.00),最大单程步行 3.76 min,未越 4.0 min 红线。
- 停车点顺序为 S → P1 → P3 → P2 → S,车行仅 1.98 km;时间的大头是步行(62%),不是车行。
- 最优指派不等于"就近指派":容量与半径同时起作用,把远客户集中到一点反而更省。
- 单程步行上限低于 3.9 min 时问题不可行,可行域的左边界由最远客户(C2,282 m)单独决定。
- \(W_p\) 用"\(\ge\) + 目标正系数"取最大,比
addGenConstrMax更省事,也是两级配送模型的标准写法。
参考文献
[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号