2026数模国赛游记
2026 数学建模国赛复盘。写于比赛结束后,在文件夹里已经出现 v1、v2、v3、v4、“v3回滚”和若干个
绝对不会再改最终版的时候。

比赛结束以后,我有几天不太愿意打开那个文件夹。主要是看见就有点生理性困倦。
里面的东西实在太多了v1 后面有 v2,v2 后面是 v3,接着是 v4,中间还夹着一个“v3回滚”。做到后面,文件名已经彻底失去参考价值。得看修改时间,得翻交付说明,有时候还要打开结果表,用第一问的费用认亲。
现在想起来,模型名称基本忘得差不多了,有一句话倒是记得很牢:
这个数到底是从哪里来的?
有次两个表里的数字对不上,我们往回翻了半天。一个用的旧代码,一个用的新代码,名字还差不多。另一次更蠢,附件里是功率,进模型时忘了乘 1/6 小时。数字大得离谱还好,至少一眼就能看出有鬼。最烦的是那种看起来很正常的,图也画得很顺,直到另一个地方对不上,我们才发现前面某一步早就歪了。
我们做的是 C 题,内容是含光伏和储能的小区微网购电。第一问给出一个典型日,后面逐渐加入负荷和光伏误差、日内预报更新、实时电价波动。刚读题时,感觉这是一道模型路线很清楚的题:线性规划打底,再接预测、风险控制和滚动优化。平时学过的词几乎都能找到位置。
那个时候我还以为,难点大概是模型。
年轻。
后来有一个凌晨,我们在纠结 00:10 到底是什么意思。
附件里一天有 144 个时刻,从 00:10 一直排到第二天的 00:00。我们一开始很自然地把 00:10 理解成 00:10—00:20 这个时段的开始。再往后检查,发现原始数据更合理的解释其实是:它代表 00:00—00:10 这个区间的结束时刻。官方结果模板又像是整体向后挪了十分钟,两边并不完全一致。
十分钟听起来很小,但 SOC 要沿着 144 个时段往后传。错一格以后,后面的表基本都得跟着倒霉。那天我们本来在讨论算法,结果对着 Excel 表头看了很久。
差不多从那时起,我对数模比赛的理解变了点。公式写完以后,还有一大堆很碎的事。一个表头就能卡半天,文件名也能把人绕晕。题目里那些看着像废话的句子,过几个小时还得翻回来重新读。
先在这里插一件发生得更晚、但不写出来总觉得对不起这篇游记的事。
可恶的 xpx 和愚蠢的我使用全年的数据优化决定参数导致透视。
是的,全年。正常流程应该用前面的数据定参数,再把后面的时间段留着评价。xpx 一轮轮比较窗口、分位数和执行策略,顺手把全年都看完了。等我们反应过来,测试集已经被盘包浆,10—12 月也没脸再叫“完全没见过的外部测试”。模型人还站在年初,调参的人已经跑到年末,拿着答案往回招手。
发现的时候已经来不及了。程序和论文都做了大半,真要重新划数据,后面几问也得陪着重跑。于是我们只能在论文里面口糊,写成“时间后置评价”“每日决策保持因果”。后面又补了一句实话:团队已经看过全年部分结果,10—12 月不能算完全陌生的样本。
学术表达:选择偏差。
队内表达:一队蠢货。
这件事和 00:10 的表头一样,公式里看不出来,却能让一整套漂亮结果突然变得心虚。先记在这里,后面再接着假装我们的过程是按顺序推进的。
天真
第一问的未来是已知的。电价、负荷和光伏预测都已经给出,我们只需要决定每个时段买多少电,电池什么时候充、什么时候放。
模型最后写成了一个确定性线性规划。电池当然不能随便用,容量和充放电速度都卡着,充进去以后还会损耗。题目又要求一天从 6000 kWh 开始,结束时回到 6000 kWh,靠最后把电池掏空省钱这条路也堵上了。
结果跑出来时,我们确实松了一口气。典型日计划购电量为 59,482.70 kWh,现金费用为 35,126.95 元。从图上看,储能大体在低价时段吸收电量,在高价时段释放,至少直觉上说得通。

那会儿我对“求解成功”这四个字还有点迷信。程序返回最优解,就觉得这一问差不多结束了。后面一查,SOC 差点被我们看漏。再往下看,同时充放电和能量平衡也得单独核对。求解成功只能说明程序算完了,离“这东西能用”还隔着挺远。
求解器只会忠实地解决我们写给它的问题。我们有没有把题写对,它一概不管。
第一问比较顺,给了我们一种后面也会顺着做下去的错觉。人一旦顺利两个小时,就会误以为后面两天也归自己管。 很快第二问就把这种错觉拿走了。
怀疑人生
第二问从“已知未来”变成了“每天零点先决定”。当天真实负荷和光伏还没有发生,但购电计划已经要签。买少了,临时补电要付五倍价格;买多了,那部分合同电又不能自动变回钱。
我们最早的注意力全放在预测上。光是窗口长度就改了好几轮,后来又折腾同星期权重。我那时总觉得模型复杂一点,写进论文会比较像样,“上周同一时段”听着实在太朴素。
数据跑完,负荷的周周期很明显,用上周同槽做预测,光伏取前七天同槽均值,效果比原来的长窗口方案还好。正式评价期是 2025 年 2 月 1 日到 12 月 31 日,共 334 天。F1 方案的负荷 MAE 为 176.80 kW、RMSE 为 244.29 kW,光伏 MAE 为 153.40 kW;净负荷 MAE 约为 273.35 kW。
这些数字刚出来时,我们有点兴奋。预测误差降了这么多,后面的调度费用应该也会跟着下降吧。
并没有这么简单。

少预测 100 kWh,可能要用五倍价格临时补。多预测 100 kWh,可能变成付了钱又没用掉的合同电。MAE 觉得这俩一样大,钱包显然有自己的看法。
后面我们把中心预测和风险余量拆开。中心预测管一个大概,风险余量再看过去一段时间的误差,多垫一点。中途版本用的是 30 天窗口、alpha=0.8 和 36 个时段的滚动窗口。交稿前又重新筛了一遍,最终提交版变成了 W=35、alpha=0.805、H=49。alpha=0.8 有普通电价和五倍应急价那层解释,后面那一点点小数则来自参数比较。看到这里就能理解前面为什么要骂 xpx 了:0.005 看着很小,背后已经把全年数据翻来覆去看过。
现在写起来像一套完整方案,当时完全是一团。年度费用不对,我们就去翻结算代码。翻完没找到问题,又一路查到执行器,接着发现某个版本偷看了未来真实值。那批结果只能删掉重跑。程序刚停,论文里的表已经集体过期。中间还穿插着 xpx 全年调参事件。严谨得我们后来专门写了好几页解释为什么它还算因果。
有一段时间,我们像是在和结果讨价还价。残差窗口试 21、30、45 天,分位试 0.8、0.9、0.95,执行器在贪心和滚动 LP 之间来回比较。数字不好看,第一反应就是再改一点。全年数据也这么被看穿了:试得太多,边界又没提前钉死。后面总算停手,和悟道没关系,单纯是没时间了。

表
第三问允许每天在 0、6、12、18 点接收新的光伏预报,也允许更新后面的购电合同。
这听起来几乎没有悬念。信息更新了,模型可以重新计算,结果理应比一整天不调整更好。我们当时确实这么想,所以第一次看到最终费用时,大家先去找 bug。
下面这张表来自 9 月 12 日左右的旧分支。它当时已经能完整跑完 Q1—Q4,我们一度把它当成接近最终的结果:
| 场景 | 现金费用/元 | 应急购电/kWh | 闲置合同/kWh |
|---|---|---|---|
| Q2 固定价、无调整 | 14,890,440.41 | 304,774.78 | 1,442,540.28 |
| Q3 固定价、滚动调整 | 14,975,463.69 | 320,219.85 | 1,181,814.50 |
| Q4-2 分时价、无调整 | 15,667,460.85 | 303,418.23 | 1,434,537.98 |
| Q4-3 分时价、滚动调整 | 15,763,512.43 | 317,107.65 | 1,154,872.48 |
按这套旧参数,固定电价下滚动调整多支出 85,023.28 元;进入分时电价后,又多了 96,051.58 元。
这个结果很别扭,看起来完全不像“改进算法”该交出来的成绩。我们从合同更新一路查到费用公式,还怀疑过已经执行的时段被程序改写。折腾一圈,数字还在那里,甚至没有因为我们多看几眼就自己变小。
滚动更新确实减少了闲置合同。Q3 比 Q2 少了大约 26.07 万 kWh,Q4-3 比 Q4-2 少了大约 27.97 万 kWh。调整费用和预测偏差又把这部分收益吃了回去,应急购电量还略有增加。我们围着这个结论检查了很久,甚至已经想好论文里怎么解释“更新越多未必越省”。

我以前写课程论文时,会下意识觉得新方法必须比基线好。模型复杂一点、信息多一点、优化频繁一点,最后就应该出现一条更低的曲线。否则文章好像不知道怎么写。
这道题最后没有给我们这种方便。
新预报拿到了,钱可不会自动掉下来。合同每动一次都要付代价,预测本身也照样会错。电池那边要是已经顶到边界,新计划再聪明也接不住。所以“预报更及时”听着很对,落到账上完全是另一回事。
这组结果最后没有进提交论文,但我们也没删。它留在旧目录里,刚好说明参数、执行器和比较口径一换,故事可以整个翻面。
交稿前那轮重跑真的把故事翻过来了。最终论文里,Q2 用 W=35、alpha=0.805、H=49;Q3 用 W=35、alpha=0.7725、H=6,并在 6:00、12:00、18:00 更新预报和合同。最终提交的主要结果如下:
| 最终提交方案 | 年度现金费用/元 | 应急购电/kWh | 闲置合同/kWh |
|---|---|---|---|
| Q2 日前固定合同 | 14,786,101.35 | 245,483.29 | 1,596,110.94 |
| Q3 不使用日内新预报的基线 | 15,230,376.12 | 334,601.06 | — |
| Q3 启用 6、12、18 时预报 | 14,664,345.40 | 210,761.48 | 1,228,166.90 |
| Q4-2 波动电价、固定合同 | 17,378,687.69 | 570,732.66 | — |
| Q4-3 波动电价、可调合同 | 15,465,962.60 | 210,394.02 | — |
Q3 基线采用另一套参数,不能直接拿 Q2 那行做差。按论文里的同口径消融,三个日内预报全部启用后节省 566,030.72 元,降幅约 3.72%,应急购电减少 123,839.58 kWh。三次更新合计 1002 个事件,摊下来,单次更新最多值 564.90 元。旧版里那句“更新反而更贵”,到最终稿变成了“12 点的更新最值钱”。我们看着新表,多少有一点被自己背刺的感觉。


电价
第四问又把实时电价放了进来。到这里,模型已经不像第一问那样干净了。我们不但不知道明天的光伏和负荷,也不能假定零点就知道全天真实电价。
价格预测最后拿历史同槽价格打底,再用当天已经发生的价格偏差往后修。方法挺朴素,好处是每一步用了什么都说得清,也没站在年末替年初指点江山。
最终提交版里,Q4-2 固定合同费用为 17,378,687.69 元,Q4-3 可调合同降到 15,465,962.60 元,省了 1,912,725.09 元,降幅 11.01%。应急购电也从 570,732.66 kWh 降到 210,394.02 kWh,少了 63.14%。这和旧版“可调合同还贵 9.61 万”的结论完全相反。看到这里,我们已经不敢再用“显然”两个字了。
论文还跑了一个提前知道真实电价的理想下界。Q4-3 的理想费用是 15,383,049.81 元,现有方案只高 0.54%。价格预测仍有误差,不过总费用已经离那条理想线不远。


四问做到这里,论文里那条技术路线终于看起来像是从一开始就计划好的:确定性调度、因果预测、残差风险、滚动执行、合同调整、价格预测。
真实过程当然没这么规整。框架图是最后补的,所以显得很有预谋。
最早的代码把很多东西揉在一起,出了问题也不知道该怪谁。后面每查到一处,就顺手拆一层。做到第三问时,我们才发现“拿到新预报”和“多运行一次优化”也混了。论文里的框架图画得很整齐,代码可没有这么配合。
漂亮结果往往最危险
睡得少还算好办,困了趴一会儿。不确定比较磨人。
一套程序跑了很久,结果很好,后来发现它用了未来信息。这种时候删掉它比删掉一个明显报错的程序难得多。明显错误的结果没人会留恋,漂亮结果会让人忍不住想:能不能换一种解释,或者它其实也勉强合理?
做当前时刻的决策,却看到了这个时段结束后才知道的真实负荷,这已经属于事后重放了。费用再低也没用。
还有一些错误没有这么戏剧化,只是词没有对齐。有人说“购电量”时指计划合同,有人指实际消纳,还有一处表格把应急购电也算了进去。每个人单独看都觉得自己的表达没问题,合到一张表里就会差出一截。
后来我们做了术语表。最先处理的就是“购电量”,因为这个词已经被三个人用了三种意思。后面又陆续补了最终合同、应急购电和弃购。刚开始觉得有点过头,没几天就天天回来查。求解器报错至少肯吱一声,术语混乱通常要等到对表时才发作。
版本也很乱。v4 未必处处比 v3 稳,新方案可能还没跑完年度回测。旧目录不敢删,回滚也得留着,至少里面那套东西知道怎么复现。
评审意见进来以后,项目差不多重做了一次。其中一条问两个执行器拿到的信息是否公平,我们当场就有点心虚。接着又查出规划 SOC 和实际执行没完全接上。模型一改,年度结果得重新跑,旧图和正文也跟着报废。
那段时间的心情不太好概括。着急肯定有,更多的是一种“已经做了这么多,怎么还有这么多不能确定”的疲惫。后来反倒平静了,因为可以做的事情只剩下一件:把每条结论往回追,追到它的代码、数据和假设。
没有奇迹,只有文件
提交前,我们做的事情已经不太像外界想象中的数学建模了。
最后那段时间基本都耗在核对上。365 天的数据先过一遍,SOC 和母线平衡再过一遍。有人盯 CSV,有人对 Excel,论文里每改一个数就去搜全文。PDF 编出来以后还得看匿名信息。支撑材料和 AI 使用说明也堆在旁边,少哪个都不行。
最后一天没发生什么奇迹。大部分时间都在看表格、日志和 PDF。到了上传前,脑子里只剩一个念头:这次千万别点错文件。模型还能不能再提高一点,来不及了,下辈子吧。


本来想在这里升华一下,但算了
比赛里当然也学了不少模型,可结束后最先忘掉的就是那些名词。过一阵子再想,留下来的全是一些很具体的毛病,比如看到漂亮结果会先怀疑它偷没偷看未来。
以后再看到一张特别漂亮的结果图,我大概会先问一句:
你到底偷看了多少答案?
- Title: 2026数模国赛游记
- Author: 椿咲璃音
- Created at : 2026-09-20 17:00:00
- Updated at : 2026-09-20 17:25:05
- Link: https://jackerytu.github.io/2026/09/20/2026数模国赛游记/
- License: This work is licensed under CC BY-NC-SA 4.0.