对三种内置调度算法在完全相同条件下各执行 20 场仿真(共 60 场),用统计方法给出算法间的量化差异与结论。本文所有数字均来自 scripts/algorithm_benchmark.py 的批量运行结果(原始数据存于 results/benchmarks/algorithm-benchmark-20seeds.json),可复现。
| 项目 | 取值 |
|---|---|
| 路网 | grid50(50×50 网格,9.8 km 见方) |
| 基线车队 | 200 辆 |
| 仿真时长 | 60 分钟 |
| 订单总量 | 1200 单(全程均匀 20 单/分钟) |
| 取消等待 | 120 s |
| 派单周期 | 5 s |
| 种子 | 20260901 – 20260920(连续 20 个) |
三种算法在同一 seed 下的需求流逐单一致(需求生成只依赖种子,与算法无关),因此同 seed 的两次运行可做配对比较,能有效剔除需求随机性带来的噪声。
200 辆车、平均行程约 11 分钟,理论运力上限约 20 单/分钟;20 单/分的到达率使系统处于深度过饱和(完成率被压制在 45% 左右)。选择重载场景是因为前期实验证实:轻载下三种算法表现趋同,差异只在供给紧张时显现。
| 算法 | 参数 |
|---|---|
| 最近邻(nearest) | 默认 |
| 分区匈牙利(regional_hungarian) | 3×3 分区、升级阈值 X=3 单 / Y=45 s、扩区 1 环 |
| 匈牙利全局匹配(greedy_hungarian) | 默认 |
20 个种子的均值与 95% 置信区间:
| 指标 | 最近邻 | 分区匈牙利 | 匈牙利 |
|---|---|---|---|
| 完成率 | 43.7% ± 0.4pp | 55.5% ± 3.8pp | 58.3% ± 3.6pp |
| 完成订单(单) | 523.9 | 666.0 | 699.2 |
| 平均接驾(s) | 412.9 ± 7.0 | 249.3 ± 52.9 | 217.8 ± 46.8 |
| P90 接驾(s) | 997 ± 12 | 547 ± 148 | 450 ± 132 |
| 平均排队(s) | 68.6 | 45.4 | 41.5 |
| 平均接驾车程(s) | 397.0 | 225.1 | 192.1 |
| 司机收入(元) | 6970 | 8814 | 9237 |
| 平台收入(元) | 1743 | 2203 | 2309 |
| 单场运行耗时(s) | 38.6 ± 3.3 | 36.0 ± 3.3 | 38.0 ± 2.5 |
完成率对比(误差线为 95% 置信区间):
平均接驾时长对比:
P90 接驾时长对比:
同种子配对差(实验组 − 基准组)的均值与 95% 置信区间,以及 20 个种子中差值为正的个数:
| 对比 | 完成率差 | 平均接驾差 | P90 接驾差 |
|---|---|---|---|
| 匈牙利 − 最近邻 | +14.6pp ± 3.5pp | −195.1s ± 47.2s | −546s ± 132s |
| 分区匈牙利 − 最近邻 | +11.8pp ± 3.7pp | −163.6s ± 51.2s | −450s ± 142s |
| 匈牙利 − 分区匈牙利 | +2.8pp ± 4.5pp | −31.5s ± 61.4s | −96s ± 171s |
完成率置信区间不跨零(配对意义下差异显著);平均接驾与 P90 的改善在全部 20 个种子方向一致。匈牙利与分区匈牙利之间的差距置信区间跨零,未达到统计显著。
分区匈牙利的逐种子结果呈明显的双峰分布:多数种子(14/20)与全局匈牙利几乎持平(完成率 59–62%),少数种子(6/20)退化为与最近邻相当的水平(42–44%)。前者拖高了均值方差(接驾置信区间 ±52.9s 明显宽于全局的 ±46.8s)。
退化的机制推测与升级触发条件有关:分区求解后,只有「区域内等待 ≥ 45 s 的未匹配订单 ≥ 3 单」的区域才会扩区跨区匹配。某些种子下需求的空间分布使各区域的等待订单达不到该阈值,跨区匹配未被激活,区域内无车可配的订单只能等待或取消。调参方向:降低 X(如 3 → 1)或增加扩区环数,可减少此类退化,代价是更多的跨区远距离接驾。
单场运行墙钟耗时(含仿真推进)三者基本持平(约 36–39 s)。分区匈牙利通过空间分治把单次指派的矩阵规模缩小了一个量级,多轮求解的额外开销与全局方案的单次大矩阵求解相当;最近邻虽然单次撮合最轻,但在重载下更多的派单轮次抵消了这一优势。该耗时包含仿真推进本身,仅作量级参考。
- 重载场景下,两种匈牙利类算法对最近邻的优势具有统计显著性:完成率 +12~15 个百分点,平均接驾缩短 164–195 s,P90 缩短 450–546 s,全部 20 个种子方向一致。
- 分区匈牙利与全局匈牙利在本实验中未达到统计显著差异(完成率差 +2.8pp,置信区间跨零),平均意义上以约 12% 的完成率差距换取了同量级的派单计算可扩展性。
- 分区匈牙利存在少数种子的行为退化(双峰分布),可通过放宽升级阈值缓解;这是后续调参与算法迭代的明确方向。
- 三种算法的单场运行耗时无实质差别;派单计算开销在本规模下不构成瓶颈。
- 选型建议:常规运行推荐分区匈牙利(折中档);对完成率有极致要求且订单规模可控时使用全局匈牙利;最近邻仅建议作为轻载或调试基线。
分区匈牙利随后按「以需求为中心的动态半径」方案重写(替代静态 3×3 分区,长等待订单触发半径倍增扩区),并在完全相同的条件下重跑 20 种子。四种实现的对比(均值 ± 95% 置信区间):
| 指标 | 最近邻 | 匈牙利 | 分区匈牙利(静态分区) | 分区匈牙利(动态半径) |
|---|---|---|---|---|
| 完成率 | 43.7% ± 0.4pp | 58.3% ± 3.6pp | 55.5% ± 3.8pp | 49.3% ± 3.7pp |
| 平均接驾(s) | 412.9 ± 7.0 | 217.8 ± 46.8 | 249.3 ± 52.9 | 301.0 ± 74.3 |
| P90 接驾(s) | 997 ± 12 | 450 ± 132 | 547 ± 148 | 701 ± 194 |
| 平均接驾车程(s) | 397.0 | 192.1 | 225.1 | 330.8 |
| 单场运行耗时(s) | 38.6 ± 3.3 | 38.0 ± 2.5 | 36.0 ± 3.3 | 51.6 ± 8.7 |
配对差异(动态半径 − 各实现,20 种子):
| 对比 | 完成率差 | 平均接驾差 | P90 差 | 接驾车程差 |
|---|---|---|---|---|
| vs 最近邻 | +5.6pp ± 3.7pp | −111.9s ± 73.8s | −295.2s ± 194.1s | −110.3s ± 72.6s |
| vs 匈牙利 | −9.0pp ± 4.1pp | +83.2s ± 72.2s | +250.9s ± 190.4s | +94.7s ± 71.3s |
| vs 静态分区 | −6.2pp ± 5.2pp | +51.7s ± 89.4s | +154.6s ± 237.4s | +61.7s ± 89.9s |
(完成率差的置信区间以差值比例计;单场运行耗时含仿真推进。)
结果显示:动态半径版仍优于最近邻(完成率 +5.6pp 显著),但明显弱于静态分区版与全局匈牙利(完成率 −6.2pp 与 −9.0pp,置信区间不跨零),且单场耗时最高。原因在于静态分区版每 tick 对每个区域做一次完整的批内最优指派,而动态半径版按随机扫描序逐单求解、先到先得不可撤回——批被拆碎后,配对质量回落到「顺序贪心」级别,随机化只是消除了系统性偏向,并未恢复批内最优。逐种子完成率同样呈双峰:约 14 个种子停在最近邻水平(42–46%),6 个种子跳到全局水平(58–63%)。
若继续迭代,方向是把「逐单求解」恢复为「每连通分量每 tick 求解一次」(半径定范围、连通分量定批次),兼得动态半径的语义与批内最优;或将扫描序从纯随机改为按等待时长优先。
分区匈牙利随后将扫描序从纯随机改为等待时长优先(先到先服务),并在完全相同的条件下重跑 20 种子。四种实现的对比(均值 ± 95% 置信区间):
| 指标 | 最近邻 | 匈牙利 | 分区匈牙利(静态分区) | 分区匈牙利(随机扫描) | 分区匈牙利(等待优先扫描) |
|---|---|---|---|---|---|
| 完成率 | 43.7% ± 0.4pp | 58.3% ± 3.6pp | 55.5% ± 3.8pp | 49.3% ± 3.7pp | 54.7% ± 3.6pp |
| 平均接驾(s) | 412.9 ± 7.0 | 217.8 ± 46.8 | 249.3 ± 52.9 | 301.0 ± 74.3 | 189.4 ± 72.8 |
| P90 接驾(s) | 997 ± 12 | 450 ± 132 | 547 ± 148 | 701 ± 194 | 407 ± 190 |
| 平均接驾车程(s) | 397.0 | 192.1 | 225.1 | 330.8 | 178.0 |
| 平均排队(s) | 68.6 | 41.5 | 45.4 | 48.5 | 28.3 |
| 单场运行耗时(s) | 38.6 ± 3.3 | 38.0 ± 2.5 | 36.0 ± 3.3 | 51.6 ± 8.7 | 51.7 ± 8.6 |
等待优先扫描版相对各基线的逐种子配对差(20 种子):
| 对比 | 完成率差 | 平均接驾差 | P90 接驾差 | 接驾车程差 |
|---|---|---|---|---|
| vs 最近邻 | +11.0pp ± 3.5pp | −223.5s ± 70.4s | −589.9s ± 185.7s | −219.0s ± 68.9s |
| vs 匈牙利全局 | −3.6pp ± 4.3pp | −28.4s ± 76.7s | −43.8s ± 201.8s | −14.1s ± 76.8s |
| vs 静态分区 | −0.8pp ± 2.5pp | −59.9s ± 48.5s | −140.1s ± 124.7s | −47.1s ± 46.9s |
结论要点:
- 等待优先扫描全面优于纯随机扫描:完成率 +0.8pp(不显著)、接驾 −59.9s(显著)、P90 −140s(显著)、车程 −47s(显著)。
- 等待优先扫描版与全局匈牙利在所有指标上的配对差置信区间均跨零——分区方案在扫描序改为等待时长优先后追平了全局匹配。
- 对最近邻的优势进一步扩大到 +11pp 完成率、−223s 接驾,置信区间不跨零。
- 代价是单场运行耗时上升约 35%–40%(更多的区域求解与扩区计算),在派单周期 5 秒、单次限时 500 毫秒的约束下仍可接受。
uv run python scripts/algorithm_benchmark.py --seeds 20 --out .tmp-run/benchmark.json脚本位于 scripts/algorithm_benchmark.py,输出逐场结果 JSON;本文图表由该 JSON 生成(docs/assets/bench-*.svg)。