运筹调度 / 01

运筹优化问题如何建模

运筹优化最核心的能力,不是先会某个求解器,而是能把业务问题写成数学问题。模型写偏了,后面算法再高级也很难救。

很多业务场景本质都是资源分配:订单分给哪个骑手,广告预算花在哪些流量上,仓库货品放在哪个库位,客服排班怎么覆盖高峰,优惠券发给哪些用户。这些问题共同点是:资源有限、目标多、约束多、需要决策。

建模的三件套

任何优化问题都先问三件事:

  1. 决策变量:我到底要决定什么。
  2. 目标函数:我想最大化或最小化什么。
  3. 约束条件:哪些事情不能违反。

例如骑手调度:

  • 决策变量:订单 i 是否分配给骑手 j
  • 目标函数:最小化超时、空驶、等待和补贴成本。
  • 约束条件:每个订单最多分给一个骑手,骑手容量有限,预计到店和送达时间不能超过阈值。

从业务语言到数学语言

业务说法通常是模糊的:

晚高峰骑手不够,希望提升准时率,同时不要花太多补贴。

转成建模语言:

  • 需求:每个区域每个时间片的订单量。
  • 供给:骑手可服务时长和当前位置。
  • 决策:排多少骑手、给多少补贴、是否跨区调度。
  • 目标:最小化超时成本 + 补贴成本 + 空闲成本。
  • 约束:预算上限、骑手工作时长、区域服务范围、最小准时率。

好的建模,就是把含糊的业务诉求变成可以计算、可以求解、可以评估的形式。

决策变量怎么选

变量选得太细,问题难求解;变量选得太粗,方案不够可执行。

例如排班问题:

  • 粗粒度变量:某区域某小时需要多少骑手。
  • 细粒度变量:某个骑手是否在某个 15 分钟时间片服务某区域。

粗粒度适合规划,细粒度适合执行。真实系统常分层建模:先做区域产能规划,再做个体排班,再做实时调度。

目标函数怎么写

目标函数不要只写单一指标。业务优化通常是多目标折中。

一个物流调度目标可以写成:

minimize:
  超时成本
+ 用户等待成本
+ 骑手空驶成本
+ 商家等待成本
+ 补贴成本
+ 公平性惩罚

权重不是随便拍脑袋。权重来自业务优先级、历史数据、实验结果和敏感性分析。如果权重很难确定,可以把一部分目标改成约束,比如“准时率必须高于 95%,在此基础上最小化成本”。

约束比目标更重要

很多优化问题失败,不是因为目标函数不好,而是漏了关键约束。

常见约束包括:

  • 容量约束:一个骑手最多带几单,一个仓库最多存多少货。
  • 时间约束:订单必须在承诺时间内完成。
  • 预算约束:补贴、广告消耗、运营成本不能超。
  • 公平性约束:不能总把差单分给同一批骑手。
  • 稳定性约束:策略变化不能太频繁。
  • 合规约束:某些用户、内容、交易不能触碰红线。

面试时主动讲约束,会显得你理解真实业务。

可求解性

不是所有写出来的模型都能在线求解。工业系统里常常要在几十毫秒到几秒内给结果,所以要考虑问题规模。

如果变量数量是订单数乘骑手数,城市级调度会非常大。常见处理方式:

  • 先做候选裁剪,只保留可行订单-骑手边。
  • 按区域或时间窗口分解。
  • 用启发式替代精确求解。
  • 设置求解时间上限,拿可行近似解。
  • 离线求全局规划,在线做局部修正。

经典例子:补贴分配

假设有一批骑手和多个补贴档位,目标是在预算内最大化接单增量。

变量:

x_{i,k} = 骑手 i 是否获得补贴档位 k

目标:

maximize sum uplift_{i,k} * x_{i,k}

约束:

sum cost_{i,k} * x_{i,k} <= budget
每个骑手最多选择一个补贴档位
关键区域供给缺口必须被覆盖

这里的 uplift 不是普通接单概率,而是“给补贴相比不给补贴增加的接单概率”。所以这个问题把因果推断和运筹优化连起来了。

建模面试怎么答

遇到开放题,不要马上说算法名。先说:

  1. 我会先明确决策对象。
  2. 然后定义目标和约束。
  3. 再判断这是匹配、路径、排班、预算分配还是组合优化。
  4. 最后根据规模选择精确求解、启发式还是分层策略。

标准回答:

我会先把业务问题拆成变量、目标和约束。变量决定我们能控制什么,目标函数表达业务收益,约束保证方案可执行。然后根据问题规模和实时性选择求解方式:小规模可以用 ILP 或 min-cost flow,大规模在线场景会做候选裁剪、分区求解和启发式近似,并通过仿真和线上实验验证效果。

下一篇建议继续看: