案例 040 平台给的是区间,不是时刻:中点硬窗、双边界软窗与机会约束的三种处理
案例 040 平台给的是区间,不是时刻:中点硬窗、双边界软窗与机会约束的三种处理
摘要:平台只承诺「17:30—17:42 之间送达」,不承诺确切时刻。本文对同一批 10 单建统一的开放式路径 MILP,只替换约束 \(t_i\) 的三套写法:甲取区间中点当硬窗(\(t_i=m_i\),中点挤不下就甩单);乙把两端都写成软边界(越界即罚 0.5/2.0 元每分钟);丙承认到达抖动 \(\varepsilon\sim U(-\Delta,\Delta)\)、要求 \(P(a_i\le t_i+\varepsilon\le b_i)\ge\alpha\),并证明均匀分布下它等价于窗口两端各内缩 \((2\alpha-1)\Delta\)。标称成本甲 127.84、乙 5.85、丙 15.12 元;8000 次蒙特卡洛后,期望实际代价甲 127.84、乙 9.74、丙 8.07 元,有效准时率 50.0%/79.0%/84.3%。结论:甲用甩 5 单换「精确命中」,实际最差;乙账面最便宜,但把落点贴在窗左沿,均值、尾部、准时率三项全输给丙;丙的代价随 \(\alpha\) 陡增而准时率在 84.6% 处封顶,说明 \(W_i<2(2\alpha-1)\Delta\) 时 95% 承诺不是钱能买到的。
关键词:外卖配送;区间承诺;软时间窗;机会约束;均匀分布;Gurobi
1 问题提出
1.1 问题是什么
17:20,小哥在体育西路路口,手上 10 单。App 上给的承诺不是"17:35 送达",而是一段:"17:30—17:42 之间送达"。用户只在这段里接受,早到没人接、晚到要赔。
数据见表 1。10 张窗在时间轴上首尾相叠(每隔 4 min 开一张),空间上散布在 3 km 见方的天河南—珠江新城一带。窗口宽度 8—14 min,中点是平台心里的"那一个时刻",但这个时刻平台自己也说不准。
表 1 十单数据(时刻以 17:20 为零点,单位 min)
| 订单 | 送达点 | x / km | y / km | 区间 [a, b] | 宽度 W | 中点 m | 停靠 |
|---|---|---|---|---|---|---|---|
| O1 | 天河城A座 | 0.55 | 0.35 | [10, 22] | 12 | 16 | 2.0 |
| O2 | 体育东小区 | 0.35 | 1.05 | [13, 25] | 12 | 19 | 1.5 |
| O3 | 富力中心15F | 1.75 | 1.55 | [16, 30] | 14 | 23 | 2.5 |
| O4 | 冼村路口 | 1.30 | 0.95 | [20, 32] | 12 | 26 | 1.5 |
| O5 | 猎德小区 | 2.10 | 1.20 | [24, 36] | 12 | 30 | 1.5 |
| O6 | 员村四横路 | 2.55 | 0.55 | [28, 40] | 12 | 34 | 1.5 |
| O7 | 石牌桥 | 0.95 | 1.75 | [32, 46] | 14 | 39 | 1.5 |
| O8 | 天河南二路 | 0.75 | 0.60 | [36, 48] | 12 | 42 | 1.5 |
| O9 | 岗顶 | 1.95 | 0.90 | [42, 50] | 8 | 46 | 2.0 |
| O10 | 华景新城 | 2.30 | 1.95 | [46, 60] | 14 | 53 | 1.5 |
核心问题:区间是模糊承诺,三种处理方式各说各话——把中点当硬时刻、把两端都当软边界、还是把区间内当成均匀分布去做机会约束?三者的成本与违约风险差多少?

图 1 十单的空间结构与 B、C 两条最优路线(气泡大小=窗口宽度,红=窄窗)
1.2 为什么要优化
- "中点"是个假时刻:平台给区间,恰恰因为它对到达时刻没有把握;把它压成一个点,等于假装方差为零。
- 早到不是免费的:早到要等(等待占用时间,也占用下一单的时间),客户还可能不在家,本题按 0.5 元/min 计罚,是迟到罚 2.0 元/min 的四分之一。
- 风险要能标价:乙方案标称 5.85 元、蒙特卡洛期望却 9.74 元,差 3.88 元全是抖动撞出来的违约罚——不标价就无法在"账面便宜"与"实际便宜"之间选。
- 区间宽度是资源:宽窗自带缓冲,窄窗必须靠排程让路。谁该让路,只有把宽度写进模型才知道。

图 2 各单的区间中点与宽度(气泡=距出发点距离)
1.3 Gurobi 如何求解
10 单、11 个节点、111 条弧,用带时间递推的开放式路径 MILP 一次求解,弧变量 \(y_{ij}\) 定序、到达时刻 \(t_i\) 连续。三种处理只换约束 \(t_i\) 的那几行,模型骨架完全一样,因此成本差可以干净地归因于"对区间的假设"。求解墙钟 12.4 s(含全部灵敏度扫描)。
2 数学模型
2.1 符号说明
节点 \(0\) 为 17:20 的位置,\(i=1..10\) 为订单,\(E\) 为虚拟终点。\(y_{ij}\) 弧是否走;\(u_i\) 是否配送;\(t_i\) 计划送达时刻(服务开始);\([a_i,b_i]\) 平台区间;\(m_i=(a_i+b_i)/2\) 中点;\(W_i=b_i-a_i\) 窗宽;\(s_i\) 停靠耗时;\(\tau_{ij}\) 行驶时间;\(d_{ij}\) 弧长;\(\varepsilon_i\) 到达抖动;\(\Delta\) 抖动半宽;\(\alpha\) 达标率;\(\pi_e,\pi_l,\pi_d\) 早到、迟到、甩单的罚率;\(c_k\) 每公里成本。
2.2 目标函数
四项:行驶、早到越界、迟到越界、甩单。式 (1) 对三种处理都成立,差别只在 \(\delta^{e}_i,\delta^{l}_i\) 相对哪个区间取越界。
2.3 路径与时间递推
式 (2)(3)(4) 与案例 039 同构:入出度相等保证被甩的点不占时间轴,时间递推兼防子回路。
2.4 三种处理:只改"约束 \(t_i\) 的那几行"
甲 中点硬窗:把区间压成一个点。
\(\delta^{e}_i=\delta^{l}_i\equiv 0\),但 \(u_i\) 放开——中点太挤时只能甩单,赔 \(\pi_d\)。这是"平台说 17:36,就必须 17:36"的口径。
乙 双边界软窗:两端都罚,窗只罚不封。
\(\delta^{e},\delta^{l}\ge 0\),故早到与晚到都按分钟计罚,可行域永远非空。
丙 区间内均匀分布的机会约束:承认真实到达有抖动 \(\varepsilon_i\sim U(-\Delta,\Delta)\),要求落在平台区间内的概率不低于 \(\alpha\):
\(\varepsilon_i\) 均匀时,\([t_i-\Delta,t_i+\Delta]\) 与 \([a_i,b_i]\) 的重叠长度须达 \(2\Delta\alpha\),即
式 (8) 是本题最有用的一行:机会约束在均匀分布下退化成"窗口两端各内缩 \((2\alpha-1)\Delta\)",一个非线性概率约束变成了两条线性不等式,不必引入 0-1 变量或场景。当 \(W_i<2(2\alpha-1)\Delta\) 时式 (8) 为空——这就是"这么窄的窗根本给不出 \(\alpha\) 的承诺"的代数表达。丙在收缩窗上仍保留软罚(松弛量罚 8 元/min 量级),保证任何输入都有解。
2.5 规模与性质
10 个客户点、111 条弧,0-1 变量 121 个、约束 182 条、非零元 680 个,MIP gap 0.0e+00。三套模型规模一致,可比的不是规模而是假设。
3 Gurobi 求解实现
3.1 建模要点
s = DELTA * (2*alpha - 1) # 均匀分布下的内缩量
wa, wb = a + s, b - s # 式(8):机会约束的确定等价
m.addConstr(t[k] >= t[i] + srv[i] + TT[i,j] - M*(1 - y[i,j])) # 时间递推
m.addConstr(e[k] >= wa[k] - t[k] - M*(1 - u[k])) # 早到越界
m.addConstr(l[k] >= t[k] - wb[k] - M*(1 - u[k])) # 迟到越界
m.setObjective(0.6*km + 0.5*e.sum() + 2.0*l.sum() + 25*(1-u).sum())
三个要点:其一,统一骨架——甲把 (5) 的两行换成等式,丙把 \([a,b]\) 换成 \([a+s,b-s]\),其余一字不改,成本差才可归因;其二,早到必须显式建模——若只写 \(t_i\ge a_i\) 而不罚早到,求解器会把"早到 20 min 干等"当免费,这正是本题的经典坑;其三,抖动只进评价、不进模型——甲乙丙的计划都是确定性的,\(\varepsilon\) 用蒙特卡洛(8000 次抽样)后验,这样"标称成本"与"期望实际代价"两个口径才能分开报。
3.2 求解结果
表 2 三方案的代价拆解(元)与蒙特卡洛实测(8000 次)
| 方案 | 访问顺序 | 行驶 | 早到罚 | 迟到罚 | 甩单 | 标称合计 | 期望实际代价 | 有效准时率 |
|---|---|---|---|---|---|---|---|---|
| 甲 中点硬窗 | O1→O4→O6→O9→O10 | 2.84 | 0.00 | 0.00 | 125.00 | 127.84 | 127.84 | 50.0% |
| 乙 双边界软窗 | O1→O2→O4→O3→O5→O6→O8→O7→O9→O10 | 5.85 | 0.00 | 0.00 | 0.00 | 5.85 | 9.74 | 79.0% |
| 丙 机会约束 | O1→O2→O4→O3→O5→O6→O7→O8→O9→O10 | 5.93 | 3.62 | 5.57 | 0.00 | 15.12 | 8.07 | 84.3% |
丙标称最贵、实际最省:丙标称 15.12 元(行驶 5.93 + 早到 3.62 + 迟到 5.57),比乙的 5.85 元贵 9.27 元;但把 ±4 min 抖动加回去,乙的期望实际代价涨到 9.74 元(比标称多 3.88 元),丙反而降到 8.07 元,比乙低 1.67 元。乙的便宜全在账面上:它把落点贴在窗的左沿,赌"早到只罚 0.5 元/min、晚一点还留在窗里",抖动一往左推就掉出窗,95 分位代价 15.46 元比丙的 12.35 元高 3.10 元。
甲中点硬窗更直接:为了精确命中 10 个中点甩掉 5 单、赔 125 元,有效准时率 50.0%——"精确"是用覆盖率买的。丙的 84.3% 也低于 α=0.95:10 单挤在 36 min 的窗序里,收缩窗本身排不满,模型只能在窗上破 9.19 元软罚,这 0.107 的缺口就是"区间太窄"的实锤(图 8 的阴影区)。

图 3 乙、丙两方案的代价分解(菱形=蒙特卡洛期望实际代价;甲 127.84 元见图内说明)
4 结果分析
4.1 结构与过程
图 1 的两条路线差别不大(里程只差 0.12 km),差别全在在每张窗前停多久。B 敢在 17:30 的第一张窗刚到就送到,因为早到只罚 0.5 元/min;C 必须等到 \(a_i+3.6\) 之后才敢落点,于是路线被拉直、等待被摊到路上。图 2 把矛盾摊开:10 张窗里最窄的 8 min,机会约束一开口就要吃掉 7.2 min(90% 的窗宽),窄窗单在丙里几乎没有腾挪余地。图 4 是时间轴上的正面交锋:灰条是平台区间,浅蓝是收缩后的机会窗,叉/圆/菱形分别是甲乙丙的落点。A 的叉只出现在 5 行——另外 5 行空白,那就是被甩掉的单;B 的圆几乎都贴在灰条左端(早到、吃轻罚);C 的菱形全部落在浅蓝带内,位置普遍比 B 晚几分钟。

图 4 平台区间、收缩窗与三种处理的落点
4.2 灵敏度
图 5 扫抖动半宽 \(\Delta\):从 1 涨到 3.5,丙的代价从 6.23 元涨到 13.19 元(内缩量 \(0.9\Delta\) 变宽、可行域收紧,涨速越来越快),乙的实测准时率从 89.9% 掉到 80.1%。\(\Delta=4.5\) 那一格丙直接无解(曲线断点)——8 min 的窄窗容不下 \(2\times0.9\times4.5=8.1\) min 的内缩,式 (8) 为空。区间宽度决定了你能承诺到几成:抖动一旦吃满窗宽,机会约束不是变贵,而是不成立。图 6 把 \(\alpha\) 与 \(\Delta\) 放在一张热图上:同一行(\(\Delta\) 固定)从左到右颜色变深,\(\Delta=2.5\) 时 \(\alpha\) 每加 0.05 约多花 1.00 元;同一列(\(\alpha\) 固定)往下颜色变深,\(\Delta=4.5\) 且 \(\alpha\ge0.95\) 两格是空白(不可行)。\(\alpha\) 是钱,\(\Delta\) 是命:拿钱换 \(\alpha\) 是线性的,\(\Delta\) 一旦越界,多少钱都换不回来。图 7 换一维:把窗宽整体缩放 \(k\in[0.6,1.4]\)。\(k=1.4\) 时丙只要 7.28 元,\(k=0.6\) 时涨到 23.99 元,差 16.71 元;而甲的甩单数在 5 单上纹丝不动——中点硬窗根本看不见窗宽,它只看见中点。这是它最大的隐患:平台把区间放宽一倍,丙的成本立降,甲一分不降,因为它压根没用上那部分信息。

图 5 抖动半宽对丙方案总代价(左轴)与乙方案实测准时率(右轴)的影响

图 6 达标率 α 与抖动半宽 Δ 的联合影响(空白=不可行,星=本案)

图 7 窗宽缩放系数对丙方案总代价与甲方案甩单数的影响(双轴)
4.3 前沿、分布与逐单风险
图 8 把达标率 \(\alpha\) 从 0.50 扫到 0.99,画出代价—准时率平面:起点(\(\alpha=0.50\))79.0%、5.85 元,终点(\(\alpha=0.99\))84.6%、16.51 元。标称代价随 \(\alpha\) 单调涨 2.8 倍,准时率只在 75—85% 之间来回,\(\alpha=0.80\) 处甚至回落到 75.4%——内缩只校正了"落点在窗内的位置",没校正"10 单排不排得下":丙的 9.19 元软罚正是花在收缩窗上,而不是花在真正的准时率上。甲在图外(50.0%、127.84 元,价格超出纵轴一个量级,且被乙丙完全支配);乙最便宜但准时率最低(79.0%、5.85 元),丙在右上(84.3%、15.12 元)。红色阴影是 \(\alpha=0.95\) 右侧的不可达区——在 \(\Delta=4\) 的抖动下,光靠排程买不到 95%,只能加人、缩小配送半径或让平台放宽区间。图 9 是 8000 次抽样的实际代价分布:乙又宽又右偏(均值 9.74、中位 9.01、95 分位 15.46),丙窄得多(8.07/7.37/12.35)。两条 CDF 在 10 元附近交叉:一半的班次乙更便宜,另一半的班次乙贵得离谱。运营上要问的不是"平均多少钱",而是"最坏那天赔多少"。图 10 画的是逐单违约概率(没在窗内送达):甲在 5 个受服务的单上违约率 0%(中点命中、±4 抖动仍在窗内),但另外 5 单是 100%;乙最差的一单是窗宽最小的 O9(51%),丙把最差的一单压到 52%。平均准时率会骗人:甲在"被服务的单"上几乎不违约,整体却是 50%——甩单的 100% 是平均不出来的。

图 8 代价—有效准时率前沿与 α=0.95 的不可达区

图 9 8000 次抽样的实际代价分布与累计曲线

图 10 逐单违约概率:三种处理的风险分布差异
5 结论
- 区间不能当中点:甲把 10 张窗压成 10 个点,为精确命中甩掉 5 单、赔 125 元,标称 127.84 元、有效准时率 50.0%。它不是"保守做法",而是"用覆盖率换精确度",且对窗宽完全不敏感(图 7:\(k\) 从 0.6 扫到 1.4,甩单数恒为 5)。
- 双边界软窗账面最便宜、实际被支配:乙标称 5.85 元,抖动下期望 9.74 元、95 分位 15.46 元、准时率 79.0%;丙 8.07 元、12.35 元、84.3%。乙在均值、尾部、准时率三项上全输,它的低价是把落点贴在窗左沿、赌抖动往右走换来的。
- 机会约束的确定等价是一行代数:均匀分布下 \(P(a\le t+\varepsilon\le b)\ge\alpha\) 等价于 \(t\in[a+(2\alpha-1)\Delta,\ b-(2\alpha-1)\Delta]\),不用场景、不用 0-1,代价是窗口两端各让出 3.60 min。这条式子的用处不止求解:它直接给出"这张窗能不能被承诺"的判据 \(W_i\ge 2(2\alpha-1)\Delta\)。
- 承诺有上限,且不是钱能买的:\(\alpha\) 从 0.50 扫到 0.99,丙的标称代价从 5.85 涨到 16.51 元,准时率只从 79.0% 爬到 84.6%——离 95% 还差 10.4 个百分点。瓶颈是 10 单挤在 36 min 的窗序里,加钱只能买"更靠近窗心",买不到"更多时间"。
- 窗宽是硬通货:\(k=0.6\) 时丙要 23.99 元,\(k=1.4\) 时只要 7.28 元,差 16.71 元且路线不变。平台把区间各放宽 2 min,骑手侧成本降三成——放宽区间比催骑手便宜。
- 落地建议:派单时先用 \(2(2\alpha-1)\Delta/W_i\) 判断该单"能不能被承诺",比值超过 1 的(本案 O9,8 min 窗、\(\Delta=4\))必须优先排或直接放宽区间;\(\Delta\) 要分路段分时段标定,晚高峰跨江段实际可到 ±6 min,那时 \(\alpha=0.95\) 在 8 min 窗上不成立,只能降 \(\alpha\) 或加人手。
参考文献
[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号