2026年认证杯B题一出,不少队伍看到“微电网—电动车—建筑协同调度”就直接懵了。三个词拆开都认识,合在一起就不知道从哪下手。作为连续带过多年数模竞赛、自己也做过微电网优化调度相关项目的过来人,我想说:这道题看着唬人,但它本质上是一个标准的多主体能量管理优化问题,而且出题人把“电动车”和“建筑”这两个灵活性资源塞进来,恰恰是给了你拉开差距的空间。
这篇文章我会从题目本质理解、建模思路、优化模型搭建、求解代码框架、论文写作要点到常见坑位,一步步拆开来讲。既照顾到第一次打认证杯的新手,也会给出让老手能直接复用的方法。全程用我做实际微电网调度项目的思路来讲,不是教科书式的堆公式,而是你比赛时真正用得上的东西。
1. 题目理解与破题思路:这个题到底在考什么
1.1 三个主体的角色拆解
先别急着看数据,先把“微电网、电动车、建筑”这三个东西在题目里各扮演什么角色搞清楚,这是后面建模的地基。
微电网是整个园区的能量枢纽。它内部有光伏、储能,外部可以跟大电网买卖电。它的诉求是:在满足园区用电需求的前提下,尽量多消纳光伏、降低购电成本。注意,微电网不是孤立系统,它和外部电网之间有功率交互上限,这就是一个实实在在的约束。
电动车在这个题里是最灵活的角色。它既是负荷(要充电),又是电源(V2G放电),还是一个“移动的储能罐”。为什么说它是协同调度的关键?因为电动车在园区里停着的时间段,是完全可以参与充放电调度的。比如白天光伏大发的时候,让电动车多充电;晚上电价贵的时候,让电动车放电反哺园区。这就是“协同”二字的精髓——如果只把电动车当普通负荷,那这道题就白出了。
建筑在以往很多题目里是纯粹的负荷,但在协同调度框架下,建筑是柔性负荷。空调、暖气、通风这类系统有一定的热惯性——你把空调临时关掉半小时,室温不会立刻飙升,人体舒适度也不会马上崩掉。这种“短暂的弹性”就是建筑侧可以参与调度的资本。建筑可以通过提前预冷、蓄热、短时调整功率,配合整个园区的用能计划。
1.2 三天比赛时间怎么分配
三天时间看起来充裕,实际上很容易在前两天陷入模型泥潭。我的建议是:第一天上午把题意彻底吃透,下午开始搭建基础模型;第二天完成核心优化求解;第三天上午做灵敏度分析、可视化,下午集中写论文。如果第二天晚上模型还没跑通,第三天就会非常被动。
还有一点很多人忽略:认证杯是网络挑战赛,提交时间卡得很死。强烈建议第一天就把论文框架、摘要模板搭好,后续直接往里填结果。等最后再写论文,大概率会超时或者写得很仓促。
2. 四个核心模块的数学建模:把物理过程翻译成公式
2.1 光伏出力和基础负荷的时序建模
光伏是微电网里的主力电源,但它是个“看天吃饭”的角色。在确定性调度前提下,我们可以用典型日逐时出力曲线来描述,或者用如下简化模型:
P_pv(t) = P_STC × (G(t) / G_STC) × [1 - β × (T_cell(t) - T_STC)]
其中 P_STC 是标准测试条件下的额定功率,G(t) 是 t 时刻光照强度,β 是温度系数,T_cell 是电池板温度。实际比赛时,数据表里通常直接给了逐时光伏出力,就不用自己拟合了,但你要在论文里把公式写出来,表明你理解这个物理过程。
基础负荷就是园区内除电动车充电、空调之外的那些刚性用电,比如照明、办公设备、数据中心等。这个负荷不可调,只能满足。它的时序特点往往是早上和下午各有一个高峰,中午相对低一些。
这里有个容易出错的地方:单位和时间粒度的统一。如果时间是15分钟一个断面,所有功率单位是kW,那电量就是 kW × 0.25h。很多人算SOC迭代时忘记乘时间步长,导致能量不守恒,这类低级错误在阅卷时非常明显。
2.2 储能系统的SOC递推与损耗建模
储能(电池)是微电网调度的核心缓冲器。它的模型核心是SOC(荷电状态)递推方程,以及充放电功率限制。
SOC递推式(以15分钟为一个步长,Δt为小时数):
SOC(t+1) = SOC(t) + η_ch × P_ch(t) × Δt / E_bat - P_dis(t) × Δt / (η_dis × E_bat)
其中 η_ch 和 η_dis 是充电效率和放电效率,E_bat 是电池容量。注意充放电效率不对称是真实电池的特性,竞赛题里如果没给具体值,一般取0.9~0.95,并在论文假设里写清楚。
充放电功率约束:
0 ≤ P_ch(t) ≤ P_ch_max × u_ch(t) 0 ≤ P_dis(t) ≤ P_dis_max × u_dis(t) u_ch(t) + u_dis(t) ≤ 1
这组约束里 u_ch 和 u_dis 是0-1变量,表示同一时刻电池不能既充电又放电(物理上也不可能)。这就是为什么这道题本质上是混合整数线性规划(MILP),而不只是线性规划(LP)。有些队伍为了偷懒,直接允许充放电同时发生且用一个净功率变量代替,这在数学上能跑通,但在物理上是错的,容易被评委挑刺。
SOC还需要满足上下限约束和周期约束。周期约束很关键:一个调度周期结束后,SOC要回到初始值或者不低于某个值,否则下一个周期怎么继续运行?这体现了储能调度的可持续性。
2.3 电动车的移动储能模型:V2G的关键假设
电动车的建模要抓住三个要素:时间窗、充电需求、V2G能力。
时间窗是指每辆电动车在园区停靠的时间区间。只有在停靠区间内,电动车才能充电或放电。比如一辆车早上8点到园区,晚上18点下班离开,那它在 [8,18] 这个窗口内参与调度,离开时必须保证电量达到用户设定的目标(比如满电)。
假设园区有 N 辆电动车,聚合后的充电功率和放电功率为:
P_ev_ch(t) = Σ P_ev_ch,i(t) P_ev_dis(t) = Σ P_ev_dis,i(t)
约束条件包括:
- 每辆车的充电功率上限(取决于充电桩类型,比如7kW慢充或60kW快充)
- 每辆车的放电功率上限(V2G放电通常功率较低,取决于逆变器)
- 离开时SOC满足最低要求
最关键的是SOC递推和离开时的电量约束。如果一辆车18点离开,那么18点时它的SOC必须大于等于初始SOC加上用户期望增加的电量(或者达到用户设定值)。这个约束是硬约束,不能妥协——用户不会允许你把车开到园区然后亏电开回家。
在简化建模时,如果题目数据里只有聚合信息(没有每辆车的明细),那就把整个车队当成一个“大电池”,但要额外加一个约束:车队总电量在每个离开时刻不能低于车队总需求的一定比例。具体怎么简化,要看题目给的数据粒度,这个在论文里要做出合理解释。
2.4 建筑柔性负荷:热惯性模型的引入
建筑负荷这块,很多人只会把它当成“可削减负荷”,用一个比例系数去削减。但这样做太粗糙了,体现不出“协同”的深度。更好的做法是引入一阶等效热参数模型(RC模型)。
C_build × dT_in/dt = Q_gain(t) - (T_in(t) - T_out(t)) / R_build - Q_hvac(t)
其中 C_build 是建筑等效热容,R_build 是等效热阻,T_in 是室内温度,T_out 是室外温度,Q_hvac 是空调/暖通的制冷或制热功率。
离散化后:
T_in(t+1) = T_in(t) + [Q_gain(t) - (T_in(t)-T_out(t))/R_build - Q_hvac(t)] × Δt / C_build
空调电功率与制冷功率的关系可以近似为线性:P_ac(t) = Q_hvac(t) / COP,其中 COP 是能效比,通常取2.5~3.5。
有了这个模型,你就可以让空调用电功率在一定范围内浮动,同时保证室内温度在舒适区间 [T_min, T_max] 内。比如中午光伏大发、电价低的时候,可以提前把建筑温度降到下限,也就是“预冷”,等到下午电价高的时候,空调就可以少出力甚至停机,室内温度慢慢回升但仍在舒适区间内。这就是建筑侧的“储能”效应。
这个模型带来的直接好处是:你的论文里多了一个有物理依据的博弈空间,而不是简单地把负荷削掉一块,显得更有说服力,也更像一个真正的协同调度系统。
3. 协同调度优化模型:目标函数与约束的完整搭建
3.1 目标函数怎么定:经济性、碳排放与舒适度的平衡
这道题的第一问基本是经济性目标,即整个园区一个调度周期内的总运行成本最小。总成本通常包含以下几项:
- 与外部电网交互的成本:从电网购电的费用减去向电网售电的收益。
- 储能充放电的损耗成本:电池每充放一次都有寿命折损,可以折算成每千瓦时的成本。
- 电动车V2G放电的补偿成本:用户不会白白让你用他的电池放电,所以要有放电补贴。
- 建筑舒适度惩罚:如果室内温度偏离舒适区间中心值,可以加一个二次惩罚项。
目标函数写出来大概是这样:
min Σ [price_buy(t) × P_buy(t) - price_sell(t) × P_sell(t) + k_bat × (P_ch+P_dis) + k_ev × P_ev_dis + k_temp × (T_in(t) - T_ref(t))²]
其中 P_buy 和 P_sell 不能同时为正,需要引入0-1变量或者通过约束限制。price_buy 和 price_sell 是分时电价,通常卖电价低于买电价。
注意,目标函数里不要堆砌太多项,每一项都要有实际物理意义和参数来源。评委最反感的就是那种“拍脑袋造参数”的目标函数。每个参数怎么来的,要在论文里用数据说明。
3.2 约束条件的完整清单
把所有约束整理成一张表,就是你论文里最清晰的模型展示。
节点功率平衡约束(每个时刻):P_pv(t) + P_dis(t) + P_ev_dis(t) + P_buy(t) = P_load_base(t) + P_ch(t) + P_ev_ch(t) + P_ac(t) + P_sell(t),这是整个调度模型的核心等式,所有主体的功率都汇聚在这里。
储能相关约束:SOC递推式、充放电功率上下限、SOC上下限、周期始末SOC相等或相等或大于初始值。
电动车相关约束:每辆车在停靠窗口内才能充放电、充放电功率限制、离开时SOC满足最低要求、充放电互斥约束。
建筑热动态约束:室温递推方程、室温上下限约束、空调功率上下限。
电网交互约束:P_buy 不超过变压器容量限制,P_sell 不超过上网功率上限,以及购售电互斥约束。
把这些约束条件全部列出来,你会发现这其实是一个非常标准的MILP问题。决策变量有连续变量(各功率、SOC、室温)和0-1变量(充放电状态、购售电状态),问题的规模在竞赛范围内是完全可以高效求解的。
3.3 求解工具选型与代码实现框架
数学模型搭完之后,最关键的问题就是怎么求解。这里我强烈推荐用Python + cvxpy或者PuLP。如果你更熟悉MATLAB,用YALMIP + Gurobi也是可以的。但考虑到现在Python生态的普及度,以及CVXPY在处理这类问题时的简洁性,我下面以Python为例来写。
如果你用的是cvxpy,求解MILP需要一个MIP求解器,Gurobi和Cplex是商业的,但学生可以申请学术许可;开源方案里CBC和GLPK也能解决问题,只是大模型下速度会稍慢。比赛题目规模一般不大,CBC足够用了。
3.4 一份可以直接改的简化求解代码
我把核心框架贴出来。这里做了一些简化:聚合电动车为一个车队、空调用一阶RC模型。你拿到题目数据后,主要工作是改参数和细化约束。
import numpy as np import cvxpy as cp T = 96 # 15分钟一个断面,共24小时 dt = 0.25 # 时间步长,小时 # ---------- 参数输入(示例,比赛时替换为题目数据) ---------- # 分时电价:买电价格(元/kWh),96个断面 price_buy = np.array([0.8]*32 + [1.2]*16 + [0.6]*16 + [1.2]*16 + [0.8]*16) # 卖电价格,一般按燃煤标杆电价,这里取0.4 price_sell = np.full(T, 0.4) # 光伏出力,kW(题目会给典型日数据) pv = np.array([0]*20 + [10, 25, 50, 80, 120, 160, 200, 220, 240, 250, 245, 235, 215, 190, 150, 100, 60, 30, 10, 5, 0, 0, 0, 0, 0]*4)[:T] p_load_base = np.array([150]*T) # 基础负荷,kW # 储能参数 E_bat = 500 # 电池容量 kWh P_ch_max = 100 # 最大充电功率 kW P_dis_max = 100 # 最大放电功率 kW eta_ch = 0.95 # 充电效率 eta_dis = 0.95 # 放电效率 soc_min, soc_max = 0.1, 0.9 soc_init = 0.5 # 电动车聚合参数 E_ev_total = 800 # 车队电池总容量 kWh P_ev_ch_max = 120 # 聚合最大充电功率 kW P_ev_dis_max = 80 # 聚合最大放电功率 kW eta_ev_ch = 0.9 eta_ev_dis = 0.9 soc_ev_min = 0.3 # 离开时SOC下限 # 假设整个调度周期车队都会停靠,简化处理 # 建筑参数(一阶RC模型) C_build = 200 # 等效热容 kWh/℃ R_build = 10 # 等效热阻 ℃/kW T_out = np.full(T, 25) # 室外温度,简化 T_in_init = 24 T_min, T_max = 22, 26 COP = 3.0 P_ac_max = 60 # 空调最大用电功率 kW # ---------- 决策变量 ---------- P_buy = cp.Variable(T, nonneg=True) # 从电网购电 P_sell = cp.Variable(T, nonneg=True) # 向电网售电 P_ch = cp.Variable(T, nonneg=True) # 储能充电 P_dis = cp.Variable(T, nonneg=True) # 储能放电 soc = cp.Variable(T + 1) # 储能SOC P_ev_ch = cp.Variable(T, nonneg=True) # 电动车充电 P_ev_dis = cp.Variable(T, nonneg=True)# 电动车放电 soc_ev = cp.Variable(T + 1) # 电动车队SOC P_ac = cp.Variable(T, nonneg=True) # 空调用电功率 T_in = cp.Variable(T) # 室内温度 # 0-1变量:状态互斥 u_storage = cp.Variable(T, boolean=True) # 1=充电,0=放电 u_grid = cp.Variable(T, boolean=True) # 1=购电,0=售电 # ---------- 约束条件 ---------- constraints = [] # SOC递推 constraints += [soc[0] == soc_init] constraints += [soc[t+1] == soc[t] + eta_ch * P_ch[t] * dt / E_bat - P_dis[t] * dt / (eta_dis * E_bat) for t in range(T)] constraints += [soc_min <= soc[t] <= soc_max for t in range(T+1)] # 储能充放电互斥 constraints += [P_ch[t] <= P_ch_max * u_storage[t] for t in range(T)] constraints += [P_dis[t] <= P_dis_max * (1 - u_storage[t]) for t in range(T)] # 周期SOC回归 constraints += [soc[T] >= soc_init] # 电动车SOC递推和限制 constraints += [soc_ev[0] == 0.5] constraints += [soc_ev[t+1] == soc_ev[t] + eta_ev_ch * P_ev_ch[t] * dt / E_ev_total - P_ev_dis[t] * dt / (eta_ev_dis * E_ev_total) for t in range(T)] constraints += [soc_ev[T] >= soc_ev_min] # 调度结束时满足最低电量 constraints += [P_ev_ch[t] <= P_ev_ch_max for t in range(T)] constraints += [P_ev_dis[t] <= P_ev_dis_max for t in range(T)] # 建筑热动态 constraints += [T_in[0] == T_in_init] constraints += [T_in[t+1] == T_in[t] + ( - (T_in[t] - T_out[t]) / R_build - COP * P_ac[t] ) * dt / C_build for t in range(T-1)] constraints += [T_min <= T_in[t] <= T_max for t in range(T)] constraints += [P_ac[t] <= P_ac_max for t in range(T)] # 电网交互互斥 constraints += [P_buy[t] <= 500 * u_grid[t] for t in range(T)] constraints += [P_sell[t] <= 200 * (1 - u_grid[t]) for t in range(T)] # 节点功率平衡 constraints += [pv[t] + P_dis[t] + P_ev_dis[t] + P_buy[t] == p_load_base[t] + P_ch[t] + P_ev_ch[t] + P_ac[t] + P_sell[t] for t in range(T)] # ---------- 目标函数 ---------- cost_buy = cp.sum(price_buy @ P_buy) * dt income_sell = cp.sum(price_sell @ P_sell) * dt battery_battery = cp.sum(0.02 * (P_ch + P_dis)) * dt # 储能损耗成本 ev_compensation = cp.sum(0.05 * P_ev_dis) * dt # EV放电补贴 comfort_penalty = cp.sum(0.1 * cp.abs(T_in - 24)) * dt # 舒适度偏离惩罚 objective = cp.Minimize(cost_buy - income_sell + ev_compensation + comfort_penalty) # ---------- 求解 ---------- prob = cp.Problem(objective, constraints) prob.solve(solver=cp.CBC, verbose=True) print("总成本:", prob.value) print("购电量:", np.sum(P_buy.value) * dt) print("售电量:", np.sum(P_sell.value) * dt)拿到代码不要直接跑完就完事,要做两件事。第一,把输出结果对一遍量纲:成本是不是元、电量是不是kWh、功率是不是kW。第二,画逐时功率平衡曲线,检查每个时刻发电和用电是否严格相等。如果出现功率不平衡,大概率是时间步长乘错了。
3.5 常见问题与排查技巧实录
SOC越界。很多人发现SOC算出来是负的或超过1,原因是递推公式里放电那项分母上乘的效率和充电效率混用。记住一个口诀:充电效率乘在充电功率上,放电效率除在放电功率上。
求解器报错“infeasible”——模型无可行解,大概率是约束太紧了。先把电动车离开SOC约束放宽,再把建筑温度上下限放宽,看看哪个约束是瓶颈。这也是比赛论文中灵敏度分析的一部分:调整某参数看系统成本和可行域的变化。
0-1变量太多导致求解慢。如果题目规模很大,考虑把时间粒度从15分钟改成1小时,或者对电动车做聚合,减少0-1变量数量。
结果出现“同时充电和放电”的怪象。这就是没加互斥约束或互斥约束失效了。检查你写的u_storage条件是不是严格限制了同一时刻只有一个状态。
还有一个常被忽略的坑:分时电价有峰谷平三个时段,每个时段的时间边界必须和数据表完全对齐。差一个时间断面,结果会完全不同。拿到数据先画电价曲线,和常识对照一遍。
3.6 从确定性调度到不确定性优化
第一问用确定性模型就能解决,但第二问很可能引入不确定性,比如光伏出力预测误差、电动车到达时间随机等。这时候有两种主流处理方式。
第一种是随机规划:给光伏出力和EV到达时间设置几个典型场景,每个场景赋一个概率,目标函数变成所有场景的期望成本最小。这种方法逻辑清晰,但计算量会成倍增加。
第二种是鲁棒优化:只考虑光伏出力最差的情况(比如阴天),让调度方案在最恶劣条件下也满足所有约束。这种方法偏保守,但好处是不需要假设概率分布。
如果题目数据给了历史误差范围,我建议做随机规划;如果只给了一个波动区间,那鲁棒优化更合适。还有一条路是模型预测控制(MPC),把整个周期切成多个滚动窗口,每次只优化未来几个小时,然后不断滚动。这个方法在2017年电工杯A题和很多微电网论文里都是标配,写进论文里会显得你很有水平。具体做法是:先做一次日前调度给出计划值,然后在实时阶段每15分钟滚动优化一次,只执行第一步的指令。
4. 论文写作要点与获奖技巧:把模型“讲”给评委听
4.1 摘要怎么写出“拿到奖的感觉”
摘要是一篇数模论文的灵魂,评委大概率只精读摘要和结论。我的建议是:摘要控制在800字左右,含以下要素——题目要解决的问题、你建了什么模型、用什么方法求解、得到了什么关键结果、有什么有价值的结论。
不要用“本文研究了”这种干巴巴的写法。要直接写“针对微电网-电动车-建筑协同调度问题,建立了以总运行成本最小为目标的混合整数线性规划模型,综合考虑了储能寿命损耗、EV用户放电补偿和建筑热舒适度,通过……求解得到……”一上来就让评委知道你的工作量和方法论。
4.2 假设、符号表与图表的细节
数学建模论文最怕的是模型里出现了50个变量却没有一张符号表。建议所有变量和参数统一用表格列在模型开头:符号、含义、单位、取值来源,四列。这能大幅降低评委阅读难度。
假设部分不要写废话,比如“假设天气晴朗”这种。要写对模型有实际影响的假设,比如“假设电动车在调度周期内均停靠在园区且可参与V2G”“假设建筑热工参数不随温度变化”等,每条假设后面附一句为什么需要这个假设。
图表方面,不要只放软件默认配色图。逐时功率平衡图用堆叠面积图,把光伏、购电、放电堆在正半轴,把负荷、充电堆在负半轴,一眼就能看出供需平衡。SOC曲线用阶梯图,室内温度曲线旁边标注舒适区间上下界。这些图不需要多华丽,但信息量要大。
4.3 灵敏度分析:让评委觉得你的模型“不虚”
好的论文一定有灵敏度分析。针对这道题,可以做三类灵敏度分析:
- 电价变化对总成本的影响:把峰谷电价倍差从1.5倍调到3倍,看购电策略怎么变化。
- 电动车数量对园区成本的影响:车队规模从20辆增加到100辆,看V2G的收益何时饱和。
- 光伏渗透率对购电量的影响:光伏容量从100kW调到1MW,看购电成本下降的边际效应。
每个灵敏度分析画一张曲线图,然后给出你的解释。不需要所有结论都“意料之中”,有时候反直觉的结论反而更有价值。
4.4 论文行文的节奏
好的数模论文读起来像一篇科技报告,有清晰的逻辑流:问题重述→假设→符号说明→建模→求解→结果展示→分析→结论。建模和求解是核心,但结果分析和灵敏度分析才是拉开分数的地方。前面模型写得再漂亮,如果没有对结果做出有洞察力的解释,评委会觉得你是“跑了个程序但没理解问题”。
5. 一些贴士与经验总结
大赛前夜最容易出的状况是工具链没准备好。建议比赛第一天就开始建论文骨架,不要让建模和写作完全分离;比赛期间所有人都在高强度思考,建议队伍里指定一个“时间警察”,专门负责提醒进度和防止在某一步无限纠结。
如果第二问或第三问遇到不会的优化算法,不要慌。先判断它属于什么问题:如果是随机性,就用多个确定性场景逼近;如果主体之间目标冲突,可以试着做双层规划或者引入纳什均衡概念。但绝大多数情况下,评委更看重你把基础模型做扎实,而不是盲目堆砌高端算法。
最后再说一个我在实际微电网项目中踩过的坑:不要过度追求模型复杂度。有一个队伍把碳交易、需求响应、电池衰减全部塞进模型,结果参数全是瞎编的,求解出来的结果根本没有说服力。模型复杂度和数据可得性是匹配的,题目给了什么数据,就做什么层次的模型,这才是正道。把这个平衡拿捏好,获奖概率自然就上去了。