案例 044 客户说「20:00 以后送」

案例 044 客户说「20:00 以后送」

摘要:9 单晚高峰配送中,第 9 单客户要求 20:00 以后送达,早到会被拒收。把这条约束的左边界做成硬约束、右边界做成软约束,用 Gurobi 建立带时间递推与等待变量的车辆路径混合整数模型,对比「禁止早到」「早到按等待计价」「早到即拒收」三种建模。结果显示:最短路线下骑手在 36.6 min(19:36.6)就抵达客户楼下,早到 23.4 min;硬左窗若不计等待,账面只多花 1.97 元,却有 8.20 元的闲置被挪出账外;早到罚金超过 0.51 元/min(约 31 元/h)时,弃单反而更划算;计入拒收概率后期望成本由 8.20 元升到 9.84 元,结论翻转。

关键词:硬软时间窗;早到等待;拒收风险;混合整数规划;罚金临界值


1 问题提出

1.1 问题是什么

晚高峰 19:00 从体育西路出发,车上有 9 单。前 8 单是平台承诺单(19:28 前送达),第 9 单是南洲花园的预约单,客户留言「20:00 以后送,早到家里没人」。于是这一单的时间窗是 \([60,\,90]\):左边界 20:00 是硬的(早到即被拒收),右边界 20:30 是软的(晚到只扣分)。

表 1 订单数据(时刻以 19:00 为 0,单位 min)

订单 送达点 距店 km 份数 类型 时间窗
01 天河城 0.7 1 普通 19:28
02 珠江新城 1.3 2 普通 19:28
03 猎德大道 1.9 2 普通 19:28
04 冼村路 0.9 1 普通 19:28
05 员村二横 2.2 2 普通 19:28
06 车陂南 2.5 1 普通 19:28
07 棠下村口 1.4 2 普通 19:28
08 岗顶 0.8 1 普通 19:28
09 南洲花园 1.5 1 预约 20:00–20:30

最短路线把 8 单串成一圈再折向第 9 单,里程 11.03 km,到第 9 单楼下才 36.6 min。也就是说,无论怎么排,这一单都要早到 23.4 min——早到不是路线没排好,而是 8 单送得太快。

1.2 为什么要优化

第一,早到不是"多等一会儿"这么简单:客户家里没人,敲门没人应,订单只能挂在门口或被拒收,拒收意味着收入归零还倒扣。

第二,等待时间是真金白银。骑手在楼下等的 23.4 min 里接不了别的单,按 21 元/h 折合 8.20 元,比这一单的里程成本还高。

第三,也是最容易出错的地方:如果模型里放了等待变量却不给它定价,早到惩罚恒等于 0,求解器会毫不犹豫地让骑手在楼下干等,报出一个"零成本"的假最优解。

1.3 Gurobi 如何求解

建模上是一条带时间递推的单车路径问题:二进制 \(x_{ij}\) 决定弧,连续变量 \(t_i\) 记录到达时刻,\(s_{ij}\) 记录每条弧上的磨蹭时间。左边界用 \(t_9 \ge 60\) 硬约束(方案 A)或早到量 \(e_9\) 软约束(方案 B);方案 C 用 0-1 变量 \(u\) 表示这单要不要接。预处理把 10 个节点的弧压缩到 90 条,分支定界在 0.1 s 内收敛,再用三次单参数扫描分别扰动早到罚金 \(p\)、超时罚金 \(\lambda\)、客户距离 \(d_9\),最后做二维网格定位临界面。

2 数学模型

2.1 符号说明

\(i,j\in\{0,1,\dots,10\}\) 为节点(0 与 10 是同一个驻点,分别作起点与终点),\(c_i\) 为停靠交付时间,\(\tau_{ij}\) 为骑行时间,\(d_i\) 为承诺时刻,\(r_9=60\) 为预约下界。决策变量为弧 \(x_{ij}\in\{0,1\}\)、到达时刻 \(t_i\ge 0\)、磨蹭 \(s_{ij}\ge 0\)、早到量 \(e_9\ge 0\)、接单指示 \(u\in\{0,1\}\)。

2.2 目标函数

三种方案共用同一个骨架,差别只在等待项与拒收项:

\[\min\ Z=\rho_d\sum_{i\ne j}\tau_{ij}x_{ij}+\lambda\sum_{i=1}^{9}\ell_i+p\Bigl(\sum_{i\ne j}s_{ij}+e_9\Bigr)+L_F(1-u)\tag{1} \]

其中 \(\rho_d=1.20\) 元/km 为里程成本,\(\lambda=0.8\) 元/min 为超时罚,\(p\) 为早到等待罚金,\(L_F=14.0\) 元为弃单损失(收入 12.0 元加平台罚 2 元)。方案 A 取 \(p=0\) 且强制 \(e_9=0\);方案 B 取 \(p=0.35\);方案 C 取 \(p=0.35\) 但令 \(\sum s_{ij}=0\)(不允许在楼下磨蹭)。

2.3 约束条件

时间递推沿弧传播,\(M\) 取候选弧规模的 4 倍:

\[t_j\ge t_i+c_i+\tau_{ij}+s_{ij}-M(1-x_{ij}),\qquad \forall (i,j)\tag{2} \]

"早到"由到达时刻与预约下界之差定义,只有接了这单才算:

\[e_9\ge r_9-t_9-M(1-u),\qquad e_9\ge 0\tag{3} \]

超时量对每单独立定义,右边界软在这里落地:

\[\ell_i\ge t_i-d_i,\qquad \ell_i\ge 0\tag{4} \]

流平衡保证每单被访问一次,且第 9 单的访问次数等于 \(u\);\(s_{ij}\le M x_{ij}\) 保证磨蹭只发生在走过的弧上。方案 A 额外加 \(t_9\ge r_9\),方案 C 额外加 \(s_{ij}=0\)。

2.4 规模与性质

10 节点、90 条候选弧、11 个连续时间变量、1 个 0-1 变量,模型是带时间窗的混合整数线性规划。由于时间沿弧严格递增,\(t\) 本身即可消除子回路,无需额外 MTZ 约束。松弛后是 LP,但其时间窗结构使 LP 界很松,必须靠分支定界。

3 Gurobi 求解实现

3.1 建模要点

关键的一条:等待必须显式进目标。代码里把等待拆成两处——弧上的磨蹭 \(s_{ij}\) 与客户楼下的早到 \(e_9\),合并成同一个 idle 表达式乘以 \(p\) 再加进目标。若只写 e9 >= 60 - t9 而不把 \(e_9\) 乘进目标,求解器会把所有空闲塞进最后一跳,早到惩罚恒为 0,得到"免费等待"的假解。

idle = gp.quicksum(s[i, j] for (i, j) in xs) + e9
obj = CD * mil + lam * late + p * idle      # 方案 B:等待显式计价

第二个细节是方案 C 的实现:把 \(s_{ij}\) 全部固定为 0 之后,\(t_9\) 只能等于纯作业时间 36.6 min,硬约束 \(t_9\ge 60\) 立刻把 \(u\) 压到 0——求解器自己"决定"弃单,而不是我们人为写死。

3.2 求解结果

表 2 三种建模的最优解对比(增量口径,相对"只送前 8 单")

方案 里程+超时 / 元 隐没闲置 / 元 等待或弃单 / 元 合计 / 元
A 硬左窗(不计等待) 13.23 8.20 0.00 15.60
B 早到显式计价 13.23 0.00 8.20 23.80
C 早到即拒收 11.26 0.00 14.00 27.63

方案 A 的账面增量只有 1.97 元,但它在目标里根本没有等待项,23.4 min 的闲置被挪到了账外;按 21 元/h 折算,真实增量是 1.97 + 8.20 元。方案 B 把这笔钱摆到台面上,成本立刻翻了几倍。方案 C 更干脆:既然不能等、早到就拒收,这单只能不接,直接损失 14.0 元。

4 结果分析

图 1 最优序的时序甘特(斜纹为早到等待)

4.1 时序结构 图 1 是最优序 08 → 01 → 02 → 03 → 04 → 05 → 06 → 07 → 09 的甘特。前 8 单在 19:31 前全部送完,骑行段被停靠交付切成小段,节奏很紧;最后一段斜插到南洲花园,36.6 min 抵达,剩下的 23.4 min 只能用斜纹的"早到等待"填满。注意这段等待的宽度和里程成本不在一个量级——它不是路线问题,而是时间窗结构造成的硬缺口。

图 2 距离—到达时刻散点(气泡为份数)

4.2 数据全景 图 2 把所有单摆在"距离—到达时刻"平面上:8 个普通单贴着 19:40 承诺线以下,第 9 单孤零零地悬在 36.6 min,距离承诺下界还有 23.4 min 的垂直落差。气泡大小是份数,第 9 单只有 1 份却占了最大的时间缺口,说明这份缺口与货量无关,只与预约时刻有关。

图 3 三种建模的增量成本分解

4.3 三方案对比 图 3 把增量成本拆成四块。方案 A 的柱子最短,但灰色斜纹那段"隐没的闲置"没有任何一项模型成本与之对应;方案 B 用实心橙色把同一段时间明码标价;方案 C 的柱子几乎全红——弃单损失 14.0 元,比方案 B 还贵 27.63 元之差。三条柱子的高度顺序(A < B < C)说明:把等待定价,方案 B 反而最省钱;拒收规则把 8.20 元的问题放大成 14.0 元的损失。

图 4 累计作业时间与累计里程

4.4 累计过程 图 4 的阶梯显示累计作业时间与累计里程。前 8 单每多送一单,两条阶梯同步抬升;到第 9 单时,里程几乎不涨(增量 1.64 km),时间却要再跳一大截——跳的这部分正是等待。累计里程曲线的末端斜率骤降,是"最后一单没有回头客"的典型形状。

图 5 早到罚金灵敏度与接单决策

4.5 主灵敏度:早到罚金临界值 图 5 让 \(p\) 从 0.05 扫到 1.00。等待成本随 \(p\) 线性上升,与弃单损失 14.0 元的水平线交于 \(p^\ast=0.51\) 元/min。这个临界值有闭式:

\[p^\ast=\frac{L_F-\rho_d\,\Delta_k}{e_9+\sum s_{ij}}\tag{5} \]

即"弃单能省下的钱"除以"必须等的时间"。\(p^\ast=0.51\) 元/min 折合 31 元/h,只有骑手时薪的 1.5 倍左右——平台只要把早到的等待补偿提到这个价位,理性骑手就会开始挑单、弃单。图 5 右轴的阶梯在 \(p^\ast\) 处从 1 掉到 0,正是这个翻转。

图 6 早到罚金 × 超时罚金的成本热图

4.6 二维灵敏度 图 6 把早到罚金 \(p\) 与超时罚金 \(\lambda\) 铺成 4×5 网格。左下角(两个罚金都小)成本最低,右上角最贵;本案参数(星标)落在网格的左中位置,成本 23.80 元左右。等高线在 \(p\) 方向更密,说明成本对早到罚金的弹性大于对超时罚金的弹性——因为第 9 单的 23.4 min 缺口是结构性的,而前 8 单的超时只有 3.0 min。

图 7 第 9 单距离的净收益与闲置时长

4.7 第三维:客户距离 图 7 把第 9 单的距离从 1.2 km 拉到 4.8 km。距离每多 1 km,净收益掉约 1.4 元(里程 + 骑行时间挤占等待时间),曲线在 $$d_9\approx 4.4$$ km 处跌破弃单线:超过这个距离,接单就是亏的。右轴的闲置时长同步缩短,因为路上花的时间正好填掉了缺口——距离越远,早到越少,这也解释了为什么远单的"早到罚金"反而不敏感。

图 8 等待—超时前沿与弃单区

4.8 前沿与弃单区 图 8 把 20 个网格点的(等待成本, 超时成本)画在平面上,非支配点连成前沿,从左下角的"零等待零超时"(理想点)向右上展开。前沿上方的阴影是弃单区:一旦总成本高过 14.0 元,接单就不如放弃。本案点(\(p=0.35,\lambda=0.8\))紧贴前沿下端,说明还有一点余量,但余量很薄。

图 9 相对承诺时刻的偏差分布与累计分布

4.9 偏差分布 图 9 是 9 单相对承诺时刻的偏差直方图与累计分布。前 8 单的偏差集中在 \(-3\) 到 \(+1\) min,累计曲线在 0 附近陡升;第 9 单一根柱子孤零零地立在 \(-23.4\) min,把累计分布拽出一个长尾。这条长尾就是拒收风险的来源:偏差越大,客户不开门的概率越高。

按经验把拒收概率写成 \(\pi(e)=\min(0.85,\,0.03e)\),23.4 min 早到对应 70% 的拒收概率,期望损失 9.84 元。把这项加进方案 B,接单的期望成本变成 20.00 元,高过弃单的 14.0 元——结论翻转:风险口径下应当弃单。

图 10 逐单边际里程贡献

4.10 边际贡献 图 10 用剔除单法算每单的边际里程成本:把某单从最优序里摘掉,两端直接相连能省多少。第 9 单(红色)的边际贡献排在中游,说明它在几何上并不"绕";真正让它贵的不是里程,而是那 23.4 min 的时间缺口。这也解释了为什么单纯优化路线解决不了这个问题。

5 结论

  1. 最短路线下骑手在 36.6 min 就抵达第 9 单楼下,早到 23.4 min,这是 8 单送得太快造成的结构性缺口,不是排程失误。

  2. 硬左窗模型如果把等待变量排除在目标之外,账面只多 1.97 元,实际隐藏 8.20 元闲置;这种"零成本"是建模假象,必须在目标里显式定价。

  3. 早到等待罚金的临界值是 \(p^\ast=0.51\) 元/min(31 元/h):低于它,等着划算;高于它,弃单划算。

  4. 早到即拒收的规则把 8.20 元的等待成本放大成 14.0 元的订单损失,是最差的建模方式;它的唯一用处是暴露规则本身的代价。

  5. 计入拒收概率后,早到 23.4 min 对应 70% 的拒收风险,期望损失 9.84 元,接单转为劣势——风险口径比确定性口径更早触发弃单。


参考文献

[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_044.py;数据与结果见同目录 .csv / .json,图见 figs/

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