先说结论:今年金地杯E题表面在考“供电系统能耗优化”,实际是在考“牵引计算 + 双层优化调度 + 多目标权衡”,三个能力缺一不可。很多队拿到题就去翻储能容量配置的论文,结果做出来全是UPS选型报告,没抓住“牵引供电系统”和“高速铁路”这两个限定词背后的物理细节,亏大了。
这篇内容我按去年辅导山西省赛队伍的经验来写,把整道题的建模链路、代码骨架、论文呈现方式完整串一遍。没有具体题目数据也能用,因为赛题再怎么变,牵引供电能耗优化的物理内核和建模套路就那几条主线,掌握了主干,换什么数据都能接得住。
1. 高速铁路牵引供电系统的能耗拆解:先搞清楚电到底消耗在哪
很多队伍一上来就建个“列车-电网”黑箱模型,用几个微分方程描述功率流动,然后直接上优化算法。这种做法的最大问题是没有区分能耗的性质——列车运行能耗、牵引网损耗、变电所自身损耗,这三者的物理机制完全不同,优化手段也完全不同。混在一起建模的结果就是:算法跑得再漂亮,论文评审一眼就看出你对系统没理解。
1.1 从接触网到车轮:一条完整的能量传递链路
我先画一条完整链路:牵引变电所 → 接触网(架空线) → 受电弓 → 车载变压器 → 牵引变流器 → 牵引电机 → 轮对。列车牵引时,能量从电网侧流向轮对,方向单一;但再生制动时,牵引电机变成发电机,能量反向从轮对流向变流器,再通过接触网回馈到牵引变电所,供同一供电臂内的其他列车使用,或者被变电所的再生能量吸收装置消耗掉。
这条链路里藏着两个题目最常挖的坑。
第一个坑是单向导通问题。牵引变电所里的整流器通常是单向导通装置,再生能量只能被同供电臂内正在牵引的列车吸收,如果这时候供电臂内没有其他列车牵引,再生能量就会抬升接触网电压。电压一旦超过保护阈值,再生制动就会被抑制,列车只能改用电阻制动把能量白白烧掉。这个机制在赛题数据里通常体现为“再生制动利用率”或“网压越限次数”这类中间指标。
第二个坑是牵引网阻抗的非线性。接触网的电阻不是常数,它随温度、随电流大小变化,而且分段供电臂的阻抗计算要考虑列车位置。如果题目给了牵引变电所位置、列车运行图和线路纵断面数据,你得能算出任意时刻、任意列车位置下的网损——这是一道典型的分布参数电路题,不是一道黑箱回归题。
1.2 能耗构成的数学刻画:三个核心公式必须能写出来
我在辅导学生时要求团队里至少两个人能手写出以下三组公式,缺一组后面优化就是空中楼阁。
第一组是列车牵引力与运行阻力。牵引力由牵引特性曲线给出,通常按速度分档,是列车速度的查表函数;运行阻力按戴维斯方程展开:
[ F_r = a + bv + cv^2 + F_g ]
其中 (a) 是滚动阻力系数,(b) 与速度线性相关,(c) 是空气阻力系数,(F_g) 是坡道附加阻力(坡道上为 (mg \sin\theta) 的简化形式)。这一步算不对,后面所有速度曲线优化都会偏离真实物理边界。
第二组是能耗积分:
[ E = \int_0^T P(t),dt = \int_0^T \frac{F_t(t) \cdot v(t)}{\eta_m \cdot \eta_g \cdot \eta_c(t)},dt ]
其中 (\eta_m) 是电机效率,(\eta_g) 是传动效率,(\eta_c(t)) 是变流器效率。注意变流器效率不是常数,它是负载率的函数,低负载率下效率急剧下降——这个细节在节能优化时非常关键,因为优化算法会把某些时段功率压得很低,结果总能耗反而上升。
第三组是供电臂潮流关系。一个牵引变电所带上下行两个供电臂,每瞬间每个供电臂内有若干列车。设变电所输出电流为 (I_s),各列车取流为 (I_i),由于列车位置不同,到变电所的距离不同,牵引网压降和网损需按多节点网络计算:
[ \Delta U_j = \sum_{i} I_i R_{ij}, \quad P_{loss} = \sum_{i} I_i^2 R_i ]
如果题目给的线路长度不长、列车数量不多(比如一个供电臂内不超过6列车),完全可以构建精确的多节点网络模型,不必用等效电阻近似——这个细节写进论文,评审会认为你们组真正理解了系统。
1.3 多数队伍忽略的三个隐含条件
根据我对近几年这类赛题的观察,出题人总会在题干里埋几个不起眼的参数:供电臂长度、列车编组重量、再生制动回馈效率上限、牵引变电所间距。这些参数看似只是背景信息,实际直接决定优化空间的大小。
供电臂长度决定了一个供电臂内同时存在的列车数。臂长越短,再生能量能被利用的机会就越少,优化时刻表的效果就越差,这时储能或变电所协同调控就更有价值。
列车编组重量和运行阻力系数决定了牵引能耗占绝对主导还是制动能耗占相对主导。重载列车牵引能耗占80%以上,节能重点在速度曲线优化;轻量动车组的再生制动比例更高,节能重点在再生能量利用。
变电所间距决定了网压水平。间距大,末端电压偏低,列车再生制动时更容易触发网压越限保护,这是约束条件里的隐形杀手。
一句话总结:读题阶段的核心任务不是背概念,而是把这些隐含条件全部列成一个参数表,并把每个参数对优化目标的影响方向写出来。这一步做得越细,后面的建模方向越不容易跑偏。
2. 三层优化策略:时刻表、速度曲线、储能系统各管一段
能耗优化不是一个单层问题,而是三层耦合优化:线路层面的运行图优化(什么时刻发车、列车之间间隔多少)、单列车层面的速度曲线优化(站间怎么开车最省电)、供电系统层面的能量调配优化(再生能量怎么储存、怎么跨车利用)。赛题最典型的难度设计是要求你至少做两层,把三层全打通就能拿国奖级别的分。
2.1 第一层:站间速度曲线优化——离线计算,在线查表
单列车站间运行的速度曲线直接决定牵引能耗和制动能量的大小。经典做法是“惰行点优化”:列车以最大牵引力加速到巡航速度,然后惰行滑行一段距离,再制停到站。惰行开始得越早越省电,但到达时间会变长。所以这是个带时间约束的连续优化问题:
[ \min J = \int_0^T P_{traction}(t),dt \quad \text{s.t.} \quad t_{run} \le T_{max}, ; v \le v_{limit}\left(s\right) ]
我的建议是不要一上来就用遗传算法。先用动态规划把基准解算出来,动态规划的状态是“位置—速度—时间”的三维栅格,虽然在站间距离长时网格数爆炸,但作为小规模基准解完全够用,而且跑出来的曲线物理上合理、没有抖动,拿来做插图非常漂亮。然后在这个基准解上用遗传算法或粒子群做局部精调,搜最优惰行点。
需要特别提醒的是,很多论文写“用模拟退火优化速度曲线”,但完全没有考虑冲击约束和乘客舒适度约束——加速度变化率的限幅、制动减速度不能超过0.8m/s²这类约束。加上这些约束后的曲线才是能实际用的曲线,不加约束的解在仿真里很好看,但评审专家会追问可实现性。
2.2 第二层:运行图优化——让一辆车的制动能量被另一辆车的牵引吸收
两辆车在同一个供电臂内,前车再生制动产生能量,后车正在牵引加速需要能量,如果这两件事时间上对齐,再生能量利用率就能显著提升。运行图优化的本质就是调整各车站发车时间,使得供电臂内“再生制动时段”和“牵引加速时段”尽量重合。
建立目标函数时,以一个牵引变电所供电臂为单元,时间步长取1秒(对齐运行图最小间隔),目标是最小化变电所每小时从电网取用的总电量。这个目标比单纯“最大化再生能量利用率”更本质——因为再生能量即使被吸收了,也是供给了同一供电臂的其他列车,电网侧取电量下降才是真正省下了能耗费。
约束包括:首末班时间固定、追踪间隔不小于设计最小间隔(通常3—5分钟)、车站停站时间上下限、快慢车越行约束(如果题目里有不同停站方案的车次)。发车时间可以离散化处理,每个车站的发车时刻相对于基准图的偏移量作为决策变量。这就变成了一个混合整数规划或约束优化问题,规模不大时用遗传算法足够。
去年我带的一个队在这个环节吃了大亏:只优化了上行列车,没优化下行列车,结果供电臂内同时段上下行列车的再生能量匹配关系完全没利用上。高速铁路通常上下行运行图高度对称,但发车时刻可以错开,上下行其实是能量互补的天然载体——这个点想通了,方案的新颖度立刻上一个台阶。
2.3 第三层:储能系统容量配置与能量管理策略
如果题目延伸问储能系统(地面储能或车载储能),那就进入了容量配置+能量管理策略的双层优化。上层以储能容量为决策变量,目标函数是储能带来的电费节省减去投资分摊成本;下层给定储能容量下,优化储能充放电策略(即能量管理系统EMS)。
储能容量配置不能拍脑袋按“最大再生能量×全时段”估算,那是典型的冗余设计。合理做法是:用典型日运行图仿真,统计再生能量未被利用的时长和大小分布,再按储能全生命周期成本模型,做净现值最大的容量优化。
储能充放电策略建议用线性规划或模型预测控制(MPC)。用MPC时,预测时域取3—5分钟,控制时域取30秒,利用短期运行图信息和列车位置信息动态决策储能此刻该充还是该放、功率多大——这个策略的代码实现也不算复杂,但写进论文就是加分项,因为它展示了你们理解了“优化不是算一次,而是滚动实施”的工程逻辑。
三层优化做完,还要把它们串起来:最外层运行图优化改动发车时刻,中间层速度曲线优化给出各车不同区间的最优运行曲线,最内层储能EMS在给定运行图和速度曲线基础上做实时调度。整个架构分三层,但数据流是双向的,代码里一定要处理好耦合结构,不要做三个孤立的模块互相不通信。
3. 代码实现架构:仿真驱动优化,数据分两层存储
到了编程部分,很多队伍习惯边想边写,最后代码一坨,跑完连自己都不知道在算什么。数学建模比赛的代码不需要上生产环境,但一定要有清晰的分层和模块边界。我建议的队伍代码结构是“数据层—仿真层—优化层—结果层”四层分离,每个模块做成独立函数,输入输出接口统一用DataFrame或字典。
3.1 数据层:不是所有数据都能直接喂给模型
赛题给的数据可能是Excel表格,也可能是一堆离散曲线。你需要先做数据清洗和插值:牵引力特性曲线、阻力系数、供电臂电阻、列车质量等数据通常给的是离散点,要统一插值到1秒步长的时间轴上。运行图数据里可能有缺失或异常值,比如发车时刻空缺、停站时间负值,都要按最朴素的合理值填充并记录在README文档里——这点很重要,因为赛后论文里要写数据处理说明。
我强烈建议把线路数据、列车数据、运行图数据分开三个配置文件(YAML或JSON),而不是全部写死在主脚本里。原因很简单:赛题如果中途更新数据(这种情况太常见了),改配置比重写代码效率高一个量级。去年的经验是,组委会可能在开赛后24小时内修正某个参数,如果代码里到处硬编码,改参数就是灾难。
3.2 仿真层:1秒步长前向推演,状态记录不遗漏
仿真层是整个系统的核心引擎,输入是运行图(各列车的发车时刻、停站时间)+ 速度曲线库(各列车在各区间的最优速度曲线)+ 供电网络参数,输出是每个时间步的系统状态矩阵。
我按以下步骤实现:
- 初始化供电臂内所有列车的位置、速度、工况(牵引/惰行/制动/停站)、取流大小。
- 在每个时间步,根据当前速度曲线查表得到该车的牵引力或制动力。
- 计算每列车当前能耗(牵引为正,制动为负但受制于最大再生功率)。
- 汇总供电臂内所有列车当前时刻的功率需求,计算变电所总输出电流和网压。
- 记录本时间步所有状态到DataFrame,然后推进到下一秒。
关键点是再生制动的处理逻辑。列车制动时,电机能产生的最大再生电功率 = 机械制动功率 × 电机效率 × 变流器效率。但能否全部回馈到电网,要看网压是否越限。如果供电臂内有其他列车正在牵引吸收功率,再生能量被消纳;否则网压上升,超过阈值后再生功率被限制,剩余部分假设由电阻消耗掉。这个限制逻辑要用代码模拟出来——这里是最容易出bug的地方,很多队伍的仿真结果里再生能量利用率高得不合常理,就是没写这段限压逻辑。
另外,1秒步长虽然精度够,但一趟车跑一个区间要3—5分钟,一张运行图20列车、全天18小时运行的话,全时段仿真数据量很大。建议按典型时段(比如早高峰1小时、平峰1小时、晚高峰1小时)来仿真,同时将全天运行图整体平移得到这三段的输入。这样既覆盖了负荷变化规律,又不至于计算量大到没法迭代优化。
3.3 优化层:遗传算法写得好不好,看三个细节
遗传算法在数学建模里已经被用到滥,但用得好不好差距仍然很大。我的三个细节建议:
第一,编码方式要贴合问题。运行图优化里每个决策变量是发车时刻的偏移秒数,用实数编码即可,但要注意范围约束——偏移不能太大,否则违反追踪间隔。在初始化种群时就把每个基因限制在可行域内,而不是在适应度函数里罚太多,收敛速度快很多。
第二,适应度函数要能区分层次。最外层适应度取电网总取电量(或用能费用),但约束违反度要单独计算,用“罚函数+约束重建”混合:越限不严重时给惩罚项,越限严重时直接重新生成个体。这样能保证种群多样性,不会因为一两个不可行解把搜索方向带偏。
第三,多目标处理要提前想清楚。如果赛题要求同时优化能耗和旅时或准点率,建议不要用加权求和,直接用NSGA-II或MOEA/D做帕累托前沿。前沿画出来之后,用折衷解(距离原点最近的点)作为推荐方案,论文里还可以放前沿图,比单点解直观得多。
以下是一个简单的遗传算法骨架,可以直接抄来改:
import numpy as np import pandas as pd def fitness(individual, sim_engine): offset_dict = decode_individual(individual) # 发车时间偏移映射 df_state = sim_engine.run_with_offset(offset_dict) energy = df_state['grid_energy'].sum() penalty = sim_engine.constraint_violation(df_state) return energy + penalty def genetic_algorithm(sim_engine, n_pop=50, n_gen=100): bound_low, bound_high = -120, 120 # 发车偏移量范围(秒) pop = np.random.uniform(bound_low, bound_high, (n_pop, n_vars)) for gen in range(n_gen): scores = np.array([fitness(ind, sim_engine) for ind in pop]) # 选择、交叉、变异(略) # 每次迭代保留精英解 return best_individual实际跑起来,50个种群、100代进化,每次仿真如果控制在0.5秒以内,总耗时大约40分钟到1个多小时——这个计算量在比赛节奏下可以接受。如果仿真慢,优先优化仿真代码,用numpy矩阵化替代for循环,比改优化算法效率高得多。
3.4 结果层:每次实验的参数要可复现,跑批要留档
优化做完了,结果层的整理决定论文能不能顺利写出来。我要求队伍在代码里加一个自动跑批的脚本:定义几组对照实验(比如“无优化”“仅速度曲线优化”“速度曲线+运行图协同优化”“再加储能”),一键跑完并保存每组实验的能耗组成柱状图、电网取电功率曲线、再生能量利用统计表。
实验参数和随机种子必须全部记录在输出文件名里,例如exp3_runoff_opt_seed42_result.csv。为什么我要强调种子?因为遗传算法是随机算法,如果不固定种子,同一组参数跑两次结果可能差5%,论文里写“优化后节能18%”就站不住脚。把种子固定下来,结果可复现,答辩被质疑时也能当场重跑。
4. 评卷标准里的得分点与你最容易丢分的地方
数学建模比赛能不能拿奖,很大程度上取决于论文能不能让评审在8分钟内抓住你们的工作量和技术含量。接下来我根据多次评审观察和带队经验,拆解论文各部分的得分逻辑。
4.1 摘要:这是在卖方案,不是在复述题目
摘要占的隐形权重极高,很多评审看完摘要就给论文定了档。写摘要的核心不是“我们做了什么”的流水账,而是“你们发现了什么问题、用什么方法、得到什么结果、比谁好多少”。句式建议:
针对高速铁路牵引供电系统能耗优化问题,本文构建了“速度曲线—运行图—储能配置”三层协同优化框架。在速度曲线层,采用动态规划求解放电时间约束下能耗最优的惰行策略;在运行图层,以供电臂内再生能量匹配最大化为目标优化发车时刻;在储能层,基于全生命周期成本模型确定最优储能容量。结果表明,三层协同优化后,牵引变电所日取电量较基准运行图下降18.6%,再生能量利用率从41%提升到76%,同时列车晚点率未受影响。
一段话把“问题—方法—结果—价值”讲透了。如果结果里有同比,就把同比数值放大强调;不要写“本模型具有较好的推广性”这种正确的废话,评审只会得出“你们没什么亮点可写”的结论。
4.2 模型对比:同题不同解的差异必须摆出来
另一个易丢分点是只写最终方案,不给对比基准。竞赛评分很看重“模型进化过程”的展示——比如先建了最简单的定时发车仿真模型,算出的能耗作为Base Case;然后加入速度曲线优化,节能8%;再加入运行图协同,节能15%;最后加储能,节能18.6%。每一步的能耗、费用、再生利用率列一张表,评审判定你们的工作量和技术深度就有了直观依据。
还要写模型的灵敏度和鲁棒性分析。敏感性分析做哪个参数?通常做最不确定的一个,比如负荷预测偏差、再生制动效率误差。给参数上下浮动10%,看优化结果的节能率变化。如果节能率变化不超过±2个百分点,说明方案稳健;如果变化很大,说明你们对某个参数过于敏感,需要讨论如何在线修正——这两种结论都能展现工程思维的成熟度,别怕暴露方案缺点,真实工程里本来就没有完美方案。
4.3 论文作图:能耗曲线图优先级别最高
图表好不好看直接影响评审观感。不说废话,几张关键图必须画:
- 速度曲线对比图:优化前后的速度—距离曲线(最好加一条惰行速度的对比线),直观展示惰行优化。
- 电网取电功率曲线:24小时(或典型小时)的变电所取电功率曲线,基线方案与优化方案叠加对比,阴影面积就是节省的能量,视觉冲击力极强。
- 再生能量流向图:可以用堆叠面积图表示列车牵引能耗、再生回馈量、被其他列车吸收量、被电阻消耗量,四块面积一眼看清能量的去向。
- 帕累托前沿图(如果做了多目标),横轴是旅时或晚点率,纵轴是能耗,曲线上的点代表一组折衷解。
作图工具不限定,matplotlib、seaborn、Origin都行,关键是图的清晰度和标注完整——坐标轴单位、图例、数据标签都不能少。我见过很多队伍的专业内容其实做得很好,但图做得潦草,坐标轴没单位,导致评审对数据可信度产生怀疑。
5. 常见踩坑记录与省赛拿奖的通用建议
最后这部分是我最想说的:一年年带队下来,能力强的队伍很多,但最后翻车的基本都翻在这些看似不起眼的地方。
5.1 踩坑实录:去年E题队伍在最后6小时改坏参数的教训
去年我协调过的一支队伍,模型已经全部跑通,节能率报出15%,论文也写到了结论部分。但有个队员在最后阶段想调整一下储能容量参数,手滑把电池效率从0.92改成了0.2,重新跑了一次仿真后,他看到节能率变成4%,以为是模型有bug,慌里慌张改代码,结果把优化器的收敛条件也改坏了,最终提交的版本里储能策略基本失效,整体节能率只剩7%。
这个案例的教训不是“细心点就行”,而是工作流里必须有版本管理。代码和数据文件用git在比赛第一天就建好仓库,每完成一个稳定版本就打一次tag,任何参数修改必须走配置文件或命令行参数,禁止直接改脚本里的常量。还应固定实验矩阵,除非发现物理逻辑错误,否则比赛最后半天不应该再改优化参数,只允许做结果可视化。
5.2 省赛拿奖的通用建议:队伍分工、时间分配和论文写作节奏
省赛通常三天左右,时间分配推荐是“第一天全面理解题目+搭框架,第二天早上出基线仿真、下午出第一版优化结果,第三天上午完成全部实验和敏感性分析,下午写论文,预留3小时给跑图和排版”。
队内分工按“建模、编程、写作”三角色,但编程角色至少要写一半的模型思路,写作角色要从第一天就开始写问题背景和数据描述部分,不要等结果出来再动笔——第一天的写作未必是最终版本,但框架和语言习惯可以先定下来。
论文模板提前准备好,图表样式、字体、编号规范用学校的论文模板即可,省赛对格式要求不算苛刻,但公式编号统一、图表标题完整这些基本功不能丢。参考文献要多引近三年的期刊和会议论文,尤其是IEEE Transactions on Intelligent Transportation Systems、铁道学报、中国铁道科学这类期刊上关于列车运行优化和再生制动能量利用的文章,不用担心找不到,Google Scholar搜“train trajectory optimization regenerative braking”就能筛出一堆。
最后再说一个容易被忽略的点——获奖后要准备答辩或经验分享的话,一定要把代码里每个函数的输入输出和物理含义标记清楚,把决策变量、单位、维度写在文档里。我见过不止一次,提交的论文代码里变量名是a、b、c1、x2,没有注释,连作者自己都解释不清。这在答辩时是致命的,因为评委很可能挑一个中间量问你“这个数为什么这么大”,你如果翻了半天代码才反应过来,现场会很尴尬。
说实话,这类赛题每年题型可能有变,但评委欣赏的永远是“物理理解到位、建模层次清晰、代码规范可复现、论文图表漂亮言之有物”的队伍。四条做到三条,配上完整的三层优化链路和不错的节能数