运筹调度 / 01
运筹优化问题如何建模
运筹优化最核心的能力,不是先会某个求解器,而是能把业务问题写成数学问题。模型写偏了,后面算法再高级也很难救。
很多业务场景本质都是资源分配:订单分给哪个骑手,广告预算花在哪些流量上,仓库货品放在哪个库位,客服排班怎么覆盖高峰,优惠券发给哪些用户。这些问题共同点是:资源有限、目标多、约束多、需要决策。
建模的三件套
任何优化问题都先问三件事:
- 决策变量:我到底要决定什么。
- 目标函数:我想最大化或最小化什么。
- 约束条件:哪些事情不能违反。
例如骑手调度:
- 决策变量:订单
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 不是普通接单概率,而是“给补贴相比不给补贴增加的接单概率”。所以这个问题把因果推断和运筹优化连起来了。
建模面试怎么答
遇到开放题,不要马上说算法名。先说:
- 我会先明确决策对象。
- 然后定义目标和约束。
- 再判断这是匹配、路径、排班、预算分配还是组合优化。
- 最后根据规模选择精确求解、启发式还是分层策略。
标准回答:
我会先把业务问题拆成变量、目标和约束。变量决定我们能控制什么,目标函数表达业务收益,约束保证方案可执行。然后根据问题规模和实时性选择求解方式:小规模可以用 ILP 或 min-cost flow,大规模在线场景会做候选裁剪、分区求解和启发式近似,并通过仿真和线上实验验证效果。
下一篇建议继续看: