案例090 雨天的红灯
案例090 雨天的红灯
摘要:暴雨天闯红灯省 40 秒,雨天事故率升到 2.5 倍。按题面口径重算单次成本:事故 \(2.5\times10^{-4}\times18000=4.50\) 元、罚款 \(0.15\times50=7.50\) 元、扣分折算 8.00 元,合计 20.00 元(题面写 11.2 元,差 8.80 元),减去省时收益 0.16 元,净亏 19.84 元/次。以 5 个路口的 0-1 变量 \(z_l\) 建 \(\min\sum c_lz_l\)、\(\sum z_l\le0\) 的合规模型,最优值 \(Z^{*}=0\);放宽到 \(\sum z_l\le1\) 得 19.83 元,两者之差 -19.83 元/次即违规的隐含价值,为负。再以罚函数(罚价=期望罚款 7.50 元)软化合规,模型闯 4 个路口、自报赚 7.17 元、实亏 75.06 元,说明合规不能用价格替代;临界罚款 \(F^{*}_l=v_{\mathrm{sub}}s_l/(60q_l)\) 为 47.3—73.7 元。罚款调到 0,违规仍亏 12.33 元——事故期望不因没被抓而消失。
关键词:合规硬约束;违规的隐含价值;罚函数失效;期望成本;闯红灯
1 问题提出
1.1 问题是什么
暴雨天,红灯还有 40 秒。闯过去,这一单能赶上;不闯,就超时。题面把这件事算成一道加减法:事故期望 4.50 元 + 罚款 7.50 元 + 扣分折算 8.00 元 = 20.00 元,减去省下的 40 秒值 0.16 元,净亏 19.84 元——不闯。
这道题看起来太简单,简单到不值得建模。但它有两个值得做的理由。第一,题面给的数字对不上:写的是 11.2 元,三项实算是 20.00 元,差 8.80 元。如果照抄 11.2 元往下算,结论仍然是"不闯",但"违规到底多贵"会被低估 44%。一个结论正确、数字错误的模型,比没有模型更危险,因为它会被引用。第二,"不闯"这个结论在多强的约束下成立:如果允许闯一个呢?如果把"合规"从硬约束改成罚函数呢?合规一旦被标价,价格低到什么程度模型就会翻?
我们把"合规"写成硬约束 \(\sum_l z_l = 0\),再跑放宽版(允许闯 1 个、且必须省够 40 秒)和罚函数版(软约束、罚价等于期望罚款 7.50 元),三个目标值放在一起,差额就是违规的隐含价值:-19.83 元/次。按题面原数算是 \(-11.04\) 元/次,按实算口径是 -19.83 元/次——两个数都是负的,方向一致,量级差近一倍。违规不但不合规,在经济上也是负收益。
1.2 为什么要优化
三条理由。其一,数字本身要复核:题面三项指标与结果差 8.80 元,这类"结论对、过程错"的引用最容易被继承,也最难被发现。其二,"不合规"需要一个价签:只有把它折算成元/次,才能和"省 40 秒"放在同一把尺子上比,否则讨论永远停在"应该不应该"。其三,约束的形式会改变答案:同一个模型,\(\sum z_l\le 0\) 与"违规罚 50 元"给出完全不同的解——这不是参数问题,是建模问题。
1.3 Gurobi 如何求解
建模为 5 个 0-1 变量、1 条主约束的整数规划,四次求解(合规 / 只放宽 / 放宽且赶上 / 罚函数)全部根节点收敛,最长 <0.01 s。另用 \(2^{5}=32\) 个子集穷举复核,与 Gurobi 相差 0(数值零)。式 (6) 的临界罚款用解析式直接生成,与逐点求解一致。
2 数学模型
2.1 符号说明
路口 \(l=1,\dots,5\);省时 \(s_l=34\)—48 s;平均时间价值 \(v=0.24\) 元/min;赶单边际价值 \(v_{\mathrm{sub}}=13.0\) 元/min;增量事故率 \(\Delta p_l=1.5p_{0l}\)(1.50—3.60 次/万次);事故损失 \(L=18000\) 元;被拍概率 \(q_l=0.10\)—0.22;罚款 \(F=50\) 元;扣分折算 \(D=8.00\) 元;0-1 变量 \(z_l\)。
2.2 目标函数与约束条件
设路口 \(l=1,\dots,5\),闯灯省时 \(s_l\) 秒(34—48 s),平均时间价值 \(v=0.24\) 元/min;\(p_{0l}\) 为雨天基线事故率,闯灯后升至 \(2.5p_{0l}\),增量 \(\Delta p_l=1.5p_{0l}\);一次事故期望损失 \(L=18000\) 元;被拍概率 \(q_l\)(0.10—0.22),罚款 \(F=50\) 元;扣 3 分折算 \(D=8.00\) 元。\(z_l\in\{0,1\}\) 表示是否在该路口闯灯。单次闯灯的期望成本为
基准口径(\(\Delta p=2.5\times10^{-4}\)、\(q=0.15\)、\(s=40\) s)代入:4.50 + 7.50 + 8.00 − 0.16 = 19.84 元。三项实算 20.00 元,题面写的 11.20 元复算不出来;差额 8.80 元与扣分折算 8.00 元同量级,最可能是题面把扣分项漏计(或折半)后再有 0.80 元的取整差。本文一律按实算口径,并在结果文件里同时保留两个数。
合规模型把"不许闯"写成硬约束,不是一个可以花钱赎买的罚项:
约束右端为 0,可行域只剩 \(z\equiv 0\),\(Z^{*}=0\)。把右端放宽到 1 得放宽版(式 3);注意式 (3) 必须带上"省够 40 秒"这一条:只把右端从 0 放宽到 1、不要求赶上,模型仍然选 \(z\equiv0\)(目标值还是 0)——因为每个 \(c_l\) 都是正数,违规连"被需要"的价值都没有。违规之所以出现在场景里,唯一原因是"不闯就赶不上"。
就是"允许违规一次"的隐含价值。它为负,含义是:合规约束不是"牺牲效率换安全",它直接把一个负收益的选项删掉了——删掉之后目标反而更小(这里是 0 对 19.83)。
罚函数版故意把合规写成可交易的价格:不设硬约束,把"违规"按期望罚款 7.50 元计价,按赶单的边际时间价值 \(v_{\mathrm{sub}}=13.0\) 元/min 计收益,
系数 \(q_lF-v_{\mathrm{sub}}s_l/60\) 在 4 个路口转负,模型于是选了 L1、L2、L3、L4。
2.3 规模与性质
5 个 0-1 变量、1 条约束,无连续决策。规模小到可以完全复核:32 个子集穷举与 Gurobi 差 0(数值零),说明结论全部落在系数上而不是算法上。真正的难点不在求解,而在"合规"该写成约束还是写成罚项——这一处建模选择决定了模型会不会建议闯灯。
3 Gurobi 求解实现
3.1 建模要点
五个 0-1 变量、1 条约束,Gurobi 四次求解全部在根节点收敛,最长 <0.01 s。
m.addConstr(gp.quicksum(z[i] for i in range(n)) <= kmax, name="comply")
m.addConstr(gp.quicksum(S_S[i] * z[i] for i in range(n)) >= sreq, name="catch")
m.setObjective(gp.quicksum(cost[i] * z[i] for i in range(n)), GRB.MINIMIZE)
合规版与放宽版只差两行:kmax 从 0 改成 1,再加一条"必须省够 40 秒"的覆盖约束;罚函数版换一套系数、kmax 取 5。代码没有技巧,全部工作在系数怎么来:事故项用的是"闯灯相对不闯灯的增量率"乘以"一次事故的期望损失",不是"赔个餐费";罚款项用的是"被拍概率"乘以"单次罚款",不是"闯一次罚 50";扣分项用的是"3 分折 8.00 元",不是"分不要钱"。
校验。 五个变量共 \(2^{5}=32\) 个子集,穷举与 Gurobi 的最优值相差 0(数值零)。表 1 是逐路口明细,净成本从 15.56 元(体育东路)到 25.29 元(环市东路),全为正。
表 1 五个路口的闯灯参数与单次成本(损失 1.8 万元、罚款 50 元、扣分折算 8 元)
| 路口 | 名称 | 省时 / s | 增量事故率 / 万次 | 被拍概率 | 事故项 / 元 | 罚款项 / 元 | 净成本 / 元 | 临界罚款 / 元 |
|---|---|---|---|---|---|---|---|---|
| L1 | 体育东路 | 34 | 1.50 | 0.10 | 2.70 | 5.00 | 15.56 | 73.7 |
| L2 | 中山一立交 | 38 | 2.00 | 0.12 | 3.60 | 6.00 | 17.45 | 68.6 |
| L3 | 客村立交 | 42 | 2.50 | 0.15 | 4.50 | 7.50 | 19.83 | 60.7 |
| L4 | 珠江隧道口 | 46 | 3.00 | 0.18 | 5.40 | 9.00 | 22.22 | 55.4 |
| L5 | 环市东路 | 48 | 3.60 | 0.22 | 6.48 | 11.00 | 25.29 | 47.3 |
表 2 三种建模方式的对照:合规能不能被价格替代
| 方案 | 约束形式 | 选中路口 | 模型目标 / 元 | 真实净成本 / 元 | 判定 |
|---|---|---|---|---|---|
| 合规版 | \(\sum z_l\le 0\) | — | 0.00 | 0.00 | 不闯灯,唯一可行解 |
| 放宽版 | \(\sum z_l\le 1,\ \sum s_lz_l\ge40\) | L3 | 19.83 | 19.83 | 赶上这单,最便宜也要 19.83 元 |
| 罚函数版 | \(\sum z_l\le 5\),罚价 7.5 元 | L1、L2、L3、L4 | -7.17 | 75.06 | 自报赚 7.17,实亏 75.06 |
三个数字连起来读:合规 0.00;放宽到 1 个,最优也只能挑最便宜的那个路口,仍要付 19.83 元;罚函数版自报赚 7.17 元,把漏计的事故 16.20 元、扣分 32.00 元和时间价值高估 34.03 元补回来,实际亏 75.06 元,误差 82.23 元。
3.2 求解结果
合规版 \(z\equiv 0\)、\(Z^{*}=0.00\) 元;放宽版 \(z=[0 0 1 0 0]\)、\(Z^{*}=19.83\) 元;罚函数版 \(z=[1 1 1 1 0]\)、目标 -7.17 元、真实 75.06 元;只放宽不要求赶上则 \(Z^{*}=0.00\)。四次求解最长 <0.01 s。
4 结果分析
4.1 结构:三项成本谁说了算

图 1 单次闯灯成本的三项拆解(事故 4.50、罚款 7.50、扣分 8.00)与合计,虚线为题面给的 11.20 元
图 1 把式 (1) 的三个正项和一项负项画成五根棒。事故 4.50 元、罚款 7.50 元、扣分 8.00 元,三根都不短;合起来 20.00 元,是题面 11.20 元的 1.79 倍。最右边那根绿棒(省时收益 0.16 元)短到几乎看不见——它只有合计成本的 0.8%。这张图是整个案例的体检报告:不是某一项特别贵,而是"省 40 秒"这件事本身太便宜,任何一项成本单独拿出来都压得住它。扣分项 8 元是三项里最大的一项,恰恰是题面最容易被漏掉的一项。

图 2 五个路口的省时—净成本散点(气泡大小为被拍概率),省的几十秒只值一两毛钱
图 2 换个切法:横轴省时、纵轴净成本,气泡大小是被拍概率。五个点全在零线之上 15 元以上,而且排布有规律——省时越多的路口(环市东路 48 秒)净成本越高,因为省时收益涨得慢(每秒 0.004 元)、而事故与罚款涨得快。等收益线(0.24 元/min 的斜率)贴着地面,五个点离它有 10—25 元的高度差。"我很急"这个理由要成立,需要时间价值涨到 28.6 元/min 以上,是本案的 119 倍。
4.2 决策:合规是硬约束,不是可以买断的罚项

图 3 三种建模方式的净成本:合规硬约束 0.00、放宽到 1 个 19.83、罚函数软约束自报 -7.17(真实 75.06)
图 3 是全篇的核心。合规版(\(\sum z_l\le 0\))目标 0.00 元,可行域只有一个点;放宽版(\(\le 1\)、须省够 40 秒)目标 19.83 元——五个路口里省时够 40 秒的只有 L3、L4、L5,模型挑了最便宜的客村立交,但仍然是亏 19.83 元;罚函数版把合规换成"罚价 = 期望罚款 7.50 元"的软约束,模型一口气闯了 4 个路口,自报赚 7.17 元——而它的真实成本是 75.06 元,漏计 82.23 元。三个数字的顺序说明:合规约束不是负担,它把一个负收益选项直接删掉了;罚函数版不是"放宽",是把一个不可定价的东西硬塞进了价格体系,一旦塞进去,模型就会顺着价格往下滑。

图 4 一趟五个路口的累积净成本(左轴)与累积省时(右轴):省 208 秒、净赔 100.35 元
图 4 把一趟五个路口摊开。五个都闯:累积成本一路爬到 100.35 元,右轴累积省时 208 秒;罚函数版闯四个:爬到 75.06 元;合规不闯:成本恒为 0。左轴和右轴的量级差了两个数量级——省 3.5 分钟,赔几十块钱。这就是"雨天红灯"这道题的全部结构:时间在这里不值钱,风险和罚款在这里很值钱。
4.3 主灵敏度:把罚款调到零,违规仍然亏

图 5 罚款额从 0 涨到 300 元时的单次净成本(左轴)与违规的隐含价值(右轴)
图 5 的横轴是罚款额,从 0 调到 300 元。左轴是两条净成本曲线(客村立交、体育东路),右轴是违规的隐含价值(式 4 的 \(\Delta Z\))。三条读法:其一,罚款涨到 300 元,客村立交的净成本从 12.33 元涨到 57.33 元,一路单调上升,最优解始终是"不闯"——罚多少都不改变决策,只改变违规有多贵。其二,右轴的隐含价值在罚款为 0 时已经是 -12.33 元,罚款从 0 涨到 50 元只让它再负 7.5 元,占比不到四成。其三,也是最要紧的一条:把罚款调到 0,客村立交的净成本仍有 12.33 元(事故 4.50 + 扣分 8.00 − 省时 0.17)。事故的期望值不会因为"没被抓"而消失,这是所有"罚得轻所以可以闯"的论证共同的漏洞。

图 6 罚款额 × 扣分折算 的单次净成本地形,全图无负值区
图 6 把罚款额与扣分折算摊成平面,颜色是单次净成本。整张图没有一个负值区:最浅的色块(罚款 0、扣分不折价)也有 4.33 元。这意味着在 (1) 式的口径下,任何参数组合都不会让闯灯变成正收益——除非把事故损失调到接近 0(那就等于宣布"撞了也不会有事"),或者把时间价值调到 10 元以上(那就是图 2 的等收益线)。星标 (50, 8) 落在"10—25 元"档的中部,离最近的可能翻正区域隔着整个色阶。
4.4 第三维与前沿:罚价失效的临界线在哪

图 7 第三维:挡住各路口所需罚款随赶单边际时间价值的变化,阴影为现行 50 元罚价的失效区
图 7 回答"罚函数为什么会失效"。把式 (5) 的系数令零,得到挡住第 \(l\) 个路口所需的罚款额
横轴是赶单的边际时间价值(超时扣 20 元、差 92 秒,合 13.0 元/min),纵轴是临界罚款。五条线从左下往右上走:越急,需要的罚款越高。本案罚价 50 元是一条水平虚线:13.0 元/min 对应的客村立交临界罚款是 60.7 元,已经高于 50 元,挡不住;只有当赶单价值降到 10.7 元/min 以下,50 元才重新有效。反过来,最容易被挡住的是环市东路(临界只要 47.3 元,50 元已够),最难挡的是体育东路(要 73.7 元)。这就是"罚函数定价过低"的准确含义:它把合规标了一个固定价格,而违规的收益随紧迫度浮动,价格一旦被浮动收益超过,约束就名存实亡。

图 8 省时—成本的组合前沿,红色阴影是合规约束下整片不可行的区域
图 8 是五个路口全部 32 种组合的省时—成本平面。灰点是"闯任意组合"的方案,蓝线是成本—省时前沿(给定省时下的最小成本),红色斜纹阴影是整个"省时 > 0"的区域——在合规约束 \(\sum z_l\le 0\) 下,它全部不可行。这是本案例最直白的一张图:合规不是把可行域"约束小一点",而是把它压成一个点。前沿本身也在零线之上:想多省一秒,成本就往上走,前沿永远不会跌到 0 以下。
4.5 分布与拆解:均值之外没有安慰

图 9 事故期望成本的 20000 次抽样分布与累计概率,左侧竖线是省时收益
图 9 处理一个常被忽略的问题:4.50 元是均值,不是每一次的实付。用对数正态描述增量事故率(中位 \(2.5\times10^{-4}\))与事故损失(中位 1.8 万元),20000 次抽样的乘积分布如上:中位数 4.46 元,长尾拖到 30 元以上。左侧那条几乎贴着纵轴的绿线是省时收益 0.17 元——事故项高于省时收益的样本占 100.0%。换句话说,"闯一次省 40 秒"这件事,在任何一个可能的参数实现下都不划算,不是"平均不划算"。

图 10 五个路口的三项成本堆叠(最右为五口合计),绿色菱形为省时收益的负向标注
图 10 把三项成本按路口堆叠。五个路口合计 22.7 元事故、38.5 元罚款、40.0 元扣分,省时收益合计只有 0.83 元(绿色菱形贴在零线上)。扣分项在每个路口都是最厚的一块(8.00 元),占单次成本的 40%;罚款项随被拍概率从 5 元涨到 11 元,是唯一随路口差异化的可政策变量。
再看一年:1080 次"赶时间遇红灯"的机会,每次都闯客村立交,一年亏 21419 元、期望摊上 0.27 次事故。21419 元不是一个大数字,它之所以小,恰恰是因为每次只亏 19.84 元——但事故不是按期望赔付的,它是一次性付清的。
5 结论
(1)题面的数要复核:三项实算 4.50 + 7.50 + 8.00 = 20.00 元,题面写 11.20 元,差 8.80 元(低估 44%)。差额与扣分折算 8.00 元同量级,最可能是漏计扣分项。结论(不闯)不变,但"违规有多贵"被低估了近一半。本文一律按实算口径,两个数都留在 results_090.json 里。
(2)合规版最优值为 0,放宽版为 19.83 元,隐含价值 -19.83 元/次:五个路口的净成本全为正(15.56—25.29 元),合规约束删掉的是一个负收益选项,而不是牺牲效率换取安全。
(3)合规是硬约束,不能被价格替代:罚函数版把合规标价成期望罚款 7.50 元,按赶单边际价值 13.0 元/min 计收益,模型闯了 4 个路口、自报赚 7.17 元,实际亏 75.06 元(漏计 82.23 元)。挡住各路口所需罚款 \(F^{*}_l=v_{\mathrm{sub}}s_l/(60q_l)\) 在 47.3—73.7 元之间,现行 50 元已经在失效区。
(4)罚款调到 0,违规仍亏 12.33 元:事故 4.50 + 扣分 8.00 − 省时 0.17。二维平面上(图 6)不存在负成本区,违规的代价主体从来不是罚款,而是事故的期望值——它不因"没被抓"而消失。
(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_090.py;数据与结果见同目录 .csv / .json,图见 figs/

浙公网安备 33010602011771号