案例 084 预约单和即时单怎么配

案例 084 预约单和即时单怎么配

摘要:预约单 4.8 元/单、履约率 98%,即时单 5.6 元/单、空驶率 20%。把两个折扣乘进去,有效单价是 \(4.70\) 元与 \(4.48\) 元——名义价高的即时单反而低 0.22 元,这是题面点出的那笔账。但在 10.5 h、预约单不超过 12 单的约束下,LP 最优解是 \(10.5\) 张即时单、收益 47.04 元,一张预约单都不接:因为预约单占 1.15 h,折成每小时只有 \(4.09\) 元,比即时单的 \(4.48\) 元还低。两张约束的影子价分别是 \(4.48\) 元/h 与 0.00 元,多 1 h 全部投即时单。整数化后最优解翻转为 7 张即时加 3 张预约、收益 45.47 元,与松弛值差 1.57 元(3.33%)。主灵敏度给出两个临界:按单价算空驶率超过 16.00% 就该转预约,按工时算要 26.96%,而整数排班下正好是 16.00%——用 LP 的 26.96% 做决策会晚 11 个百分点。

关键词:产品组合;有效单价;影子价格;整数化偏差;空驶率临界

1 问题提出

1.1 问题是什么

一位骑手当晚有 10.5 h 可售工时,平台同时派两类单:预约单提前 2 h 锁定,单价 4.8 元、履约率 98%,单均占 1.15 h(要去指定地点等);即时单随抢随走,单价 5.6 元、空驶率 20%,单均占 1.0 h。另有平台规则:预约单最多派 12 单。两类单的差别只有两个数字,但它们分别落在"收入"和"工时"两个维度上,配比问题就此产生。

表 1 两类单的参数与折算

单型 名义单价 / 元 履约率 空驶率 有效单价 / 元 单均工时 / h 每小时贡献 /(元/h)
预约单 4.80 0.98 — 4.70 1.15 4.09
即时单 5.60 — 0.20 4.48 1.00 4.48

\[e_{r}=4.8\times 0.98=4.70,\qquad e_{i}=5.6\times(1-0.20)=4.48\tag{1} \]

式 (1) 是本案例的第一笔账:即时单名义贵 0.8 元,扣掉 20% 空驶后只剩 4.48 元,比预约单少 0.22 元。折扣率 20% 大于溢价率 16.7%,价格优势被空驶率整口吃掉。

1.2 为什么要优化

第一,两个折扣的方向相反。 预约单打的是"履约折扣"(2%),即时单打的是"空驶折扣"(20%),前者小一个数量级。但履约折扣只影响收入,空驶折扣同时影响收入与有效工时——即时单空驶的那 20% 时间,骑手是拿不到的。题面给的 12 单上限也够不着:10.5 h 除以 1.15 h 只有 9.13 单,冗余 2.87 单,它的影子价注定是 0。

第二,单价的排序和工时的排序不一致。 按单价比,\(4.48<4.70\),预约单赢;按每小时比,\(4.48>4.09\),即时单赢。两条排序打架时,约束的松紧决定谁说了算:10.5 h 是硬上限,所以每小时口径才是决策口径,单价口径只能解释"为什么大家觉得即时单亏"。

1.3 Gurobi 如何求解

2 个连续变量、2 条约束,单次求解在毫秒级,因此可以放心把参数扫遍:空驶率 9 点加 40 点细网格、履约率 5 点、上限 5 点、二维网格 4$\times$5,合计 136 次。整数版把两个变量改成整数即可,用来测量"单量不可分"造成的偏差;影子价直接读约束的 \(\pi\),再用有限差分复核。

2 数学模型

2.1 符号与目标函数

\(x_{r}\) 预约单量,\(x_{i}\) 即时单量;\(p_{r}=4.8\)、\(p_{i}=5.6\) 名义单价;\(q=0.98\) 履约率;\(\delta=0.20\) 空驶率;\(t_{r}=1.15\)、\(t_{i}=1.0\) 单均工时;\(T=10.5\) 可售工时;\(C=12\) 预约单供给上限;\(e_{r}=p_{r}q\)、\(e_{i}=p_{i}(1-\delta)\) 有效单价。目标函数取"跑完这一单平均能落袋多少":

\[\max\ Z=e_{r}x_{r}+e_{i}x_{i}=4.704\,x_{r}+4.480\,x_{i}\tag{2} \]

即时单 5.6 元里有 1.12 元是空驶的白跑,不能进目标函数。

2.2 约束、规模与性质

\[1.15\,x_{r}+1.00\,x_{i}\le 10.5\tag{3} \]

\[x_{r}\le 12,\qquad x_{r},x_{i}\ge 0\tag{4} \]

式 (3) 是工时,式 (4) 是供给上限。两变量 LP 的最优解必在顶点:把式 (3) 写成 \(x_{i}=10.5-1.15x_{r}\) 代入式 (2),得 \(Z=47.04-0.392x_{r}\),斜率 \(-0.392<0\),所以 \(x_{r}\) 越小越好,取 0。这个斜率正是"预约单每小时少赚 0.39 元";而 \(x_{r}\le 12\) 在最优解处松弛 12 单、影子价为 0,两条约束里只有工时在咬。136 次求解全部在根节点闭合。

3 Gurobi 求解实现

3.1 建模要点

xr = m.addVar(lb=0, vtype=GRB.CONTINUOUS if relax else GRB.INTEGER)   # 预约单量
xi = m.addVar(lb=0, vtype=GRB.CONTINUOUS if relax else GRB.INTEGER)   # 即时单量
ct = m.addConstr(1.15 * xr + 1.00 * xi <= 10.5, "time")
cc = m.addConstr(xr <= 12, "cap")
m.setObjective(4.8 * 0.98 * xr + 5.6 * (1 - 0.20) * xi, GRB.MAXIMIZE)
print(ct.Pi, cc.Pi)   # 4.48, 0.00

系数一定要写成 4.8 * 0.98 而不是 4.70,否则扫空驶率时无法与 5.6 联动。\(\pi\) 的读法要小心:对 \(\le\) 约束,最大化问题的 \(P_i\) 为正,表示"右端增加 1 单位目标增加多少",单位分别是元/h 与 元/单。

3.2 求解结果

表 2 四个方案的单量结构与收益

方案 预约单 / 张 即时单 / 张 占用工时 / h 收益 / 元 与 LP 差
全预约 9.13 0 10.50 42.95 -4.09
全即时 0 10.5 10.50 47.04 0.00
LP 最优 0.0 10.5 10.50 47.04 0.00
整数最优 3 7 10.45 45.47 1.57

LP 最优恰是全即时(表 2 第二、三行同解):10.5 张即时单、47.04 元,影子价 \(4.48\) 元/h 与 0.00 元。整数最优翻成 3 张预约加 7 张即时,收益 45.47 元,比松弛低 1.57 元(3.33%)。

4 结果分析

4.1 两笔账:0.22 元与 0.39 元

图 1 有效单价棒棒糖:即时单 5.60 被空驶率削到 4.48,低于预约单的 4.70

图 2 可行单量组合的收益气泡:气泡大小是占用工时,颜色是组合里的预约单张数

图 1 把第一笔账画成两根棒棒糖:即时单从 5.60 掉到 4.48,掉幅 1.12 元;预约单从 4.80 掉到 4.70,只掉 0.10 元。1.12 元是"预约单价低 8%"(0.38 元)的三倍,所以"即时单单价高"这句话在扣完空驶后不成立。第二笔账藏在横轴里:即时单 1 h 赚 4.48 元,预约单 1.15 h 赚 4.70 元,折成每小时只有 4.09 元。图 2 把这层关系摊开——收益沿总单量单调上升,颜色越深(预约单越多)的组合越靠下,因为同样 10 张单里每多换一张预约单,就多占 0.15 h、少赚 0.224 元。两笔账方向相反:单价上预约单赢 0.22 元,工时上即时单赢 0.39 元。

4.2 影子价:多 1 h 投哪类单

图 3 四方案对比:全即时与 LP 最优同解 47.04 元,整数最优掉到 45.47 元

图 4 整数方案的 10.5 h 排布:7 张即时单打底,3 张预约单填尾

图 3 的四根柱子说明三件事。第一,全预约只有 42.95 元,比全即时少 4.09 元——把 10.5 h 全押在"稳"上,代价是 9% 的收益。第二,LP 最优与全即时同解,说明在本案的参数下预约单一张都不值得接。第三,整数最优 45.47 元,比 LP(也就是全即时)少 1.57 元——整数化的损失不是"少接单",而是"换了单":10.5 h 抹成 10 单后空出 0.5 h,正好塞进 3 张预约单(图 4 排到 10.45 h,余 0.05 h),于是结构从"全即时"翻转成"7 即时 + 3 预约"。关于"多 1 h 投哪类单",答案由影子价直接给出:工时约束的影子价是 \(4.48\) 元/h,等于即时单的有效单价,说明边际上的 1 h 全部投即时单,投预约单只能拿到 \(4.09\) 元。预约上限的影子价是 0.00 元,因为 \(x_{r}=0\) 时它松弛了整整 12 单;即使全转预约,最多也只能排 9.13 单,上限 12 单在数学上永远不可能紧。

4.3 空驶率临界:16.00% 还是 26.96%

图 5 空驶率主灵敏度:27% 附近最优值由斜线拐成水平,预约单量从 0 跳到 9.13

图 6 空驶率与履约率的二维热图:最优预约占比只有 0 与 100 两种颜色

图 5 的折线在 26.96% 处折断:左侧斜率为 \(-10.5\times 5.6=-58.8\) 元/单位空驶率,右侧变成水平——因为空驶率再涨,最优解已经全转预约,收益只由预约单决定。精确临界由"每小时收益相等"给出:

\[\frac{e_{r}}{t_{r}}=\frac{p_{i}(1-\delta^{\ast})}{t_{i}}\ \Longrightarrow\ \delta^{\ast}=1-\frac{4.704}{1.15\times 5.6}=0.269565\tag{5} \]

即 26.96%。但这是 LP 的口径,它允许把"0.5 单即时单"折算成"半小时"。按单价比,临界只要 \(1-4.704/5.6=16.00\%\);按整单排班算(10 张单里换 3 张),临界同样是 16.00%——LP 把临界高估了 11.0 个百分点,因为它在 10.5 h 里凑出了半张单。图 6 是二维版本:横轴履约率(96%—100%)、纵轴空驶率(20%—31%),格子里是"最优预约占比"。整片颜色只有 0 与 100 两种——这个模型是角点解,不存在"配一半"的最优。分界线随履约率上升而向左移动:履约率越高,预约单越早接管;本案参数(20%,98%)落在最左下角的 0 区,距离分界线还有 8 个百分点的空驶率余量。

4.4 上限的第三维与前沿

图 7 预约供给上限的第三维:上限在 20%/24% 空驶率下完全无效,30% 时才沿 9.13 单封顶

图 8 收益—单量帕累托前沿:10.5 单之外是不可行域,整数前沿止于 10 单

图 7 把上限拉开:空驶率 20% 与 24% 的两条线是水平的,上限从 4 加到 12 一分不涨,影子价恒为 0;只有空驶率加到 30%(此时已全转预约)才出现爬升,并在 9.13 单处封顶——那个位置由工时决定,不由题面的 12 单决定。所以"预约单供给上限 12 单"这条约束在本案例里从头到尾没有咬过一次,它是数据里的噪声,不是模型的结构。图 8 是收益—单量前沿:阶梯每上一格就是多接一张单,价格在 4.48 元到 4.70 元之间,到 10 单为止;右侧阴影是"单量不可行"区,因为再多一单至少要 1 h,10.5 h 装不下 11 单。LP 的星号落在 10.5 单——那个点是一个数学存在、现实中不存在的半张单。

4.5 履约率波动:把赔付算进去

图 9 履约率 96%—100% 波动下的日收益分布:均值 45.38 元,标准差 6.14 元

图 10 两类单的贡献分解:整数方案里预约单只贡献 14.11 元,却把空档填满

履约率 98%$\pm$2% 意味着每 100 单里有 2—4 单要赔。设失败一单赔付 \(c_{p}=2.0\) 元(超时券加重新派单的通信与空驶),预约单的单均期望收益变成

\[e_{r}(q)=4.8q-2.0(1-q)=6.8q-2.0\tag{6} \]

\(q=0.98\) 时单均 \(e_{r}=4.664\) 元,比不计赔付的 4.70 元少 0.04 元。用这个系数重解整数模型,最优解仍是 7 即时 + 3 预约、收益 45.35 元(比全即时多 0.55 元)。逐点扫描见表 3。

表 3 履约率波动下的整数最优(含赔付)

履约率 预约单单均 / 元 7+3 方案 / 元 全即时 / 元 差额 / 元
96% 4.528 44.94 44.80 +0.144
97% 4.596 45.15 44.80 +0.348
98% 4.664 45.35 44.80 +0.552
99% 4.732 45.56 44.80 +0.756
100% 4.800 45.76 44.80 +0.960

结论不变,但余量很薄:整单价口径下预约单被即时单反超的临界履约率是

\[q^{\ast}=\frac{e_{i}+c_{p}}{p_{r}+c_{p}}=\frac{4.48+2.0}{4.8+2.0}=0.952941\tag{7} \]

即 95.29%,比题目给的波动下界 96% 只低 0.71 个百分点。也就是说,履约率掉到 95.3% 以下,7+3 就会被 10 张即时单取代;在 96%—100% 的区间里,"接 3 张预约单"始终成立,但优势从 0.96 元缩到 0.14 元。若把赔付也算进 LP 的工时口径,临界空驶率从 26.96% 抬到 27.58%——赔付越大,越应该少碰预约单。图 9 是日内视角:把 7 张即时单的空驶、3 张预约单的履约都做成随机,跑 2 万次模拟,日收益均值 45.38 元、标准差 6.14 元,P10 为 36.80 元、P90 为 53.60 元,有 44% 的日子不如"10 张即时单拿 44.80 元"。期望优势 0.55 元只相当于 0.09 个标准差,靠它吃饭是不现实的;真正稳的是那 0.45 h 的产能利用——它把空档从 0.5 h 压到 0.05 h(图 10),这部分不吃概率。

5 结论

  1. 空驶率把即时单的有效单价从 5.60 打到 4.48,比预约单的 4.70 低 0.22 元;但折成每小时排序反转,即时单 4.48 元/h、预约单 4.09 元/h。 前者是题面那笔账,它只解释"为什么即时单看着不划算";而工时是硬约束,所以 LP 最优是全即时 47.04 元,一张预约单都不接。
  2. 两张约束里只有工时在咬。 小时影子价 4.48 元/h(等于即时单有效单价),预约上限影子价 0.00 元;12 单上限比工时能排出的 9.13 单多 2.87 单,这条约束从头到尾没有生效过。
  3. 整数化不是少赚一点,而是换了个方案。 10.5 单抹成 10 单、空出 0.5 h,正好塞进 3 张预约单,最优解变成 7 即时 + 3 预约、45.47 元,与松弛差 1.57 元(3.33%)。用 LP 的"全即时"去排班,等于白扔 0.45 h。
  4. 空驶率临界要分三个口径说:单价 16.00%、整数排班 16.00%、LP 工时 26.96%。 差的那 11 个百分点全是 LP 允许"半张单"造成的;拿 LP 临界去定策略,会一直拖到空驶率 27% 才转预约,而实际上 16% 就该转了。
  5. 履约率 98%$\pm$2% 不改变结论,但余量只有 0.7 个百分点。 赔付 2.0 元时临界履约率 95.29%,区间内 7+3 始终最优,优势从 0.96 元缩到 0.14 元;而日收益标准差有 6.14 元,这点期望优势在单日尺度上看不见——该看的是它填掉的 0.45 h 空档,不是它多赚的 5 毛钱。

参考文献

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

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