做微电网能量管理这几年,我越来越觉得,最磨人的不是优化模型建不出来,而是预测数据总在“背叛”你——光伏中午还满发,下午云一过来直接掉一半;风电更是看天吃饭,晚高峰需要它出力的时候,它偏偏一动不动,搞得调度员只能手动调储能和联络线。这种场景下,随机优化、模型预测控制、鲁棒优化我都试过,其中鲁棒优化算是我个人觉得“最硬核也最稳妥”的一条路线。
这篇文章就把我近期用鲁棒优化做微电网经济调度的全过程整理出来,从为什么必须和不确定性硬刚,到数学建模、代码实现、参数调优,再到后面怎么把成果讲清楚,一次性说透。无论你是做微电网课题的研究生,还是搞综合能源平台、智能微电网ppt方案的在职工程师,这篇应该都能给你一些直接能抄的干货。
1. 微电网调度为什么绕不开不确定性
1.1 一套最基础的微电网长什么样
先把我习惯用的微电网模型摆出来。它不算复杂,但足够说明问题:一个交流微电网,里面包含一台燃气机组(或者柴油机)、一组光伏、一台风机、一套电化学储能,以及和上级电网相连的联络线,下面挂着一个区域负荷。
调度目标很直接:在满足负荷供电的前提下,让系统一天的总运行成本最低。这里说的成本包括燃气机组燃料费、从上级电网买电的费用,以及储能充放电带来的折算损耗;反过来,如果微电网富余电量卖给电网,还能形成一笔卖电收益。
能量管理系统(EMS)的核心任务就是做“日前调度”:假设我们知道未来24小时的负荷、光伏和风电出力预测,在机组启停、出力上下限、爬坡、储能荷电状态(SOC)等约束下,制定每个时段的运行计划。听起来就是一个经典的经济调度问题,线性规划就能解。
但问题恰恰出在“假设我们知道”这五个字上。
1.2 确定性优化的问题在哪
如果把预测值直接当成真实值去做优化,我把它叫“乐观调度”。乐观调度的典型翻车场景是这样的:
比如日前预测中午光伏出力10MW,你在制定计划时把这10MW当成了“可靠出力”,因此让燃气机组少发、储能少放电,甚至可能还安排向电网卖电。结果第二天实际光伏只有3MW,差额7MW怎么办?储能最多补1MW,联络线已经到上限,燃气机组爬坡又赶不上,最后只能切负荷或者紧急增购电,代价相当大。
负荷预测也是一样。工业园区的负荷受生产计划影响很大,居民负荷在天气突变时也经常超出预测区间。任何一个环节的预测失准,都会让开环调度方案失效。
这里有一个关键认知:对微电网调度来说,预测误差本身不是最可怕的,可怕的是调度方案没有为误差留出“安全余量”。而鲁棒优化要解决的就是这个问题——它在做决策时,不是把预测值当作唯一确定的输入,而是假设未来的不确定参数会落在某个集合内,然后要求无论集合内哪个值真实发生,调度方案都必须可行,不能出现失衡或越限。
1.3 鲁棒优化到底在“鲁棒”什么
鲁棒优化和随机优化的最大区别,在于对不确定性的描述方式。随机优化要给不确定性指定概率分布,然后去优化期望成本;而鲁棒优化更“硬气”,它不跟你讨论概率,它只问你一句话:你能接受的不确定范围到底在哪?
你把光伏出力预测写成“10MW,误差±30%”,那鲁棒优化就按7MW到13MW这个区间来准备方案;如果负荷预测写成“5MW,误差±15%”,调度就按4.25MW到5.75MW来考虑。
它追求的目标是:任何一个不确定参数落在这个集合里,系统都扛得住。
代价当然也有——解出的成本通常比确定性优化高,高出来的部分就是“为不确定性买的保险”。好的鲁棒模型,应该用尽量小的保险费用,买到足够强的抗风险能力。所以后续我特别强调不确定性集的选择,它直接决定结果质量。
如果你之前只用过MPC滚动优化,也可以把鲁棒优化和MPC组合起来用:用MPC做反馈修正,用鲁棒优化做日前计划的安全包络,两者并不冲突,反而是工程里很成熟的搭配。
2. 鲁棒优化的建模细节:从目标到对等模型
2.1 目标函数怎么定
我常用的目标函数是:
$$\min \sum_{t=1}^{T} \left( C_{fuel} P_{G,t} + C_{buy} P_{buy,t} - C_{sell} P_{sell,t} + C_{ess} |P_{ess,t}| \right)$$
其中:
- $P_{G,t}$ 是燃气机组t时段出力,$C_{fuel}$ 是单位燃料成本;
- $P_{buy,t}$ 是从电网购电功率,$C_{buy}$ 是购电电价;
- $P_{sell,t}$ 是向电网卖电功率,$C_{sell}$ 是售电电价;
- $P_{ess,t}$ 是储能充放电功率,取绝对值后乘以折算损耗成本 $C_{ess}$,用来表示充放电循环对电池寿命的影响。
这里有一个容易踩的坑:$C_{buy}$ 和 $C_{sell}$ 通常不相等,而且大多数场景下购电价比售电价贵,所以在约束里不能只写一条联络线功率变量,否则模型会自动把买和卖混成一条,产生“低买高卖”的虚构套利空间。正确做法是把联络线拆成两个非负变量,一个代表买电,一个代表卖电,并保证同一时刻至多一个大于0。
目标函数里暂时不放弃风弃光惩罚。原因是在鲁棒约束下,弃风弃光本身就是一种可行的调整手段,如果放在目标函数里,可能诱发优化器为了降低成本故意多弃,反而不利于新能源消纳。更稳妥的做法是把它设成硬约束之外的软约束,要么加高额惩罚,要么在结果分析阶段再看。
2.2 约束条件和不确定性集
系统的约束大致可以分四类。
功率平衡约束是每个时段的硬约束:
$$P_{G,t} + P_{PV,t}(\xi) + P_{WT,t}(\xi) + P_{ess,t} + P_{buy,t} - P_{sell,t} = P_{load,t}(\xi)$$
这里我用 $P_{PV,t}(\xi)$、$P_{WT,t}(\xi)$ 和 $P_{load,t}(\xi)$ 表示它们不是确定的数,而是随不确定向量 $\xi$ 变化的函数。
机组相关的约束包括出力上下限、爬坡约束、最小启停时间约束;储能相关的包括SOC递推方程、充放电功率限制;联络线约束包括交换功率上限和下级电网容量限制。
真正让问题变复杂的是不确定性集 $U$。我实际用过三类:
盒式不确定集是最直白的,它把每个不确定参数限制在一个区间:
$$U^{box} = { \xi : \xi_i^{min} \leq \xi_i \leq \xi_i^{max} }$$
椭球不确定集更像随机优化里的标准差理念,适合用历史误差协方差矩阵去刻画,但会让模型变成二阶锥规划,求解稍慢。
预算不确定集是最实用的一种,它在盒式基础上加了一个全局预算约束:
$$U^{budget} = { \xi : \xi_i^{min} \leq \xi_i \leq \xi_i^{max}, \sum_i \frac{|\xi_i - \xi_i^{nom}|}{\Delta \xi_i} \leq \Gamma }$$
$\Gamma$ 是预算参数,用大白话说就是:虽然每个参数都可能取到最差值,但不允许所有参数同时都取最差值,实操中一般取4到8,具体怎么定我放在第3节讲。
2.3 从max-min到可计算的鲁棒对等模型
有了不确定性集之后,约束就变成“对集合内所有 $\xi$ 都成立”的半无限约束。直接扔给求解器是解不了的,必须把这种带量词的约束转化成有限个确定性约束,这一步叫鲁棒对等转换。
以功率平衡约束为例,如果我考虑的是最坏情况,问题就变成:
$$\forall \xi \in U: \quad P_{G,t} + P_{PV,t}(\xi) + P_{WT,t}(\xi) + P_{ess,t} + P_{buy,t} - P_{sell,t} \geq P_{load,t}(\xi)$$
注意它是“≥”而不是“=”,因为在鲁棒框架下,严格等式很难对所有场景都成立。工程上允许系统在部分极端场景下通过储能削峰填谷来弥补,只要不越界。这一步非常重要,别在建模时写死成等式。
对于盒式不确定集,最坏场景非常好求:如果不确定参数带正号(比如光伏、风电出力增加,对平衡是不利还是有利?要看它出现在哪一侧),直接把它的下界代入约束即可。
我处理这个问题的标准做法是用对偶理论。核心思想是:对每个不确定约束,内层求“关于 $\xi$ 的最坏值”,可以等价化成对偶问题,然后把对偶变量并回到原模型中。对线性约束来说,这个对偶变换是精确的,不会丢解。
以功率平衡约束为例,假设只有光伏出力不确定,令 $\xi \in [\xi^{min}, \xi^{max}]$,且光伏在平衡式中符号为正,那么最坏情况就是 $\xi = \xi^{min}$,所以原约束等价于:
$$P_{G,t} + \xi^{min} + P_{WT,t} + P_{ess,t} + P_{buy,t} - P_{sell,t} \geq P_{load,t}$$
如果光伏符号为负(比如它在等式左边作为负项),就取 $\xi^{max}$。逐个判断符号这种办法很简单,但只适用于所有不确定项最终都能线性化到“各自独立取上下界”的情形。如果加了预算约束 $\Gamma$,就不能每个参数各自跑了,得用排序法或者对偶变量。
2.4 单阶段模型和两阶段模型怎么选
实际工程里,我经常用单阶段鲁棒模型做日前调度。所谓单阶段,指的是所有决策变量在一开始就定好,不考虑“看到不确定值后再调整”的后悔权。这种模型偏保守,但是数学性质简单,解起来很快。
两阶段模型就不一样了,它把决策拆成“这里不可调整的日前决策”和“那里可以基于实时场景调整的再调度决策”,用数学语言写就是:
$$\min_{x} ; c^T x + \max_{\xi \in U} ; \min_{y} ; d^T y$$
这其实是一个三层优化结构,通常用列与约束生成算法(C&CG)或者Benders分解来解。C&CG的思路很朴素:先初始化一个稳定的主问题,然后反复找最坏场景,把对应场景的变量和约束加回主问题,迭代直到收敛。
但我必须提醒你,两阶段模型建起来容易,真正跑通很难。尤其是储能SOC的时序耦合变量和整数变量搅在一起时,子问题要么变成混合整数规划,要么出现对偶不可行,调试周期非常长。所以我的建议是:除非研究需要,工程首版先上单阶段鲁棒,等所有数据分析、汇报展示都跑通了,再考虑两阶段升级。
3. 实战:一台旧笔记本也能跑的微电网鲁棒优化
3.1 案例参数一览
下面这个案例,是我在某园区微电网平台上验证过的版本,参数做了适当脱敏和简化,但逻辑完全一致。时间分辨率取1小时,调度周期24小时。
| 对象 | 参数 | 数值 |
|---|---|---|
| 燃气机组 | 额定功率 | 2 MW |
| 燃气机组 | 出力下限 | 0.2 MW |
| 燃气机组 | 爬坡速率 | 1 MW/h |
| 光伏 | 预测出力区间 | 0~3 MW,具体见曲线 |
| 风电 | 预测出力区间 | 0~1.5 MW |
| 储能 | 容量 | 1 MWh |
| 储能 | 最大充放电功率 | 0.4 MW |
| 储能 | 充放电效率 | 0.95 |
| 联络线 | 最大购电功率 | 1 MW |
| 联络线 | 最大售电功率 | 0.5 MW |
| 负荷 | 预测区间 | 峰月6 MW,谷月2 MW |
光伏和风电的“区间”怎么给?我通常不是凭空拍脑袋,而是取历史同一时刻预测误差的90分位数和10分位数作为上下界。比如过去30天,每天中午12点光伏预测值和实测值误差最大的10%可以算出上界,最小的10%算出下界,这样不确定性集就有了统计数据支撑,而不是主观臆造。
3.2 Python + CVXPY 实现步骤
实现我选的是Python的CVXPY库,求解器用开源免费的HiGHS,做线性规划足够快。如果你有Gurobi或者Cplex授权,直接换也行。
第一步是定义不确定场景。对盒式不确定集来说,最坏场景函数可以这样写:
import numpy as np import cvxpy as cp # 最坏场景构造:根据约束中不确定项前的系数符号决定取上界还是下界 def worst_case_pv(coefficient, pv_low, pv_high): # 如果系数为正,最坏是取下界;系数为负,最坏是取上界 return np.where(coefficient >= 0, pv_low, pv_high)第二步定义变量:
T = 24 P_g = cp.Variable(T) # 燃气机组出力 P_ess = cp.Variable(T) # 储能有正有负,正为放电 SOC = cp.Variable(T + 1) # SOC向量,0时刻初值 P_buy = cp.Variable(T, nonneg=True) P_sell = cp.Variable(T, nonneg=True)第三步是把所有带不确定参数的约束做鲁棒对等。以功率平衡约束为例,如果我把不确定性都归到光伏出力上,那么最坏情况就是光伏取预测区间的下界:
# pv_min 是每个时段光伏出力的最坏情况 constraints = [] for t in range(T): constraints.append( P_g[t] + pv_min[t] + P_ess[t] + P_buy[t] - P_sell[t] >= load_forecast[t] )注意,这里我故意写成了不等式。这样系统在极端情况下可以通过储能放电来填补差额,而不是必须严格相等。
第四步是储能SOC约束和机组爬坡约束:
constraints.append(SOC[0] == 0.5) # 初始SOC 50% for t in range(T): constraints.append(SOC[t+1] == SOC[t] - P_ess[t] * 0.25) # 1小时分辨率,容量1MWh constraints.append(SOC[t+1] >= 0.1) constraints.append(SOC[t+1] <= 0.9) constraints.append(cp.abs(P_ess[t]) <= 0.4) for t in range(1, T): constraints.append(P_g[t] - P_g[t-1] <= 1.0) constraints.append(P_g[t-1] - P_g[t] <= 1.0)第五步是目标函数:
cost = 0 for t in range(T): cost += fuel_cost * P_g[t] cost += buy_price[t] * P_buy[t] cost -= sell_price[t] * P_sell[t] cost += ess_loss_cost * cp.abs(P_ess[t]) problem = cp.Problem(cp.Minimize(cost), constraints) problem.solve(solver=cp.HiGHS, verbose=False)这套代码我跑了无数遍,单次求解时间不超过0.5秒。对于24时段的日前鲁棒调度来说,这个速度完全够用。
3.3 结果对比:确定性模型和鲁棒模型差多少
我用同样的参数分别跑确定性模型和鲁棒模型,最直观的差异在光伏出力偏差较大的时段。
某天中午光伏预测出力2.8MW,鲁棒模型认为最坏情况可能只有1.6MW左右,于是提前安排了燃气机组在11点就开始升出力,同时让储能早早就留了余量。而确定性模型只按2.8MW安排,燃气机组在中午压得很低甚至停机,储能也充满电待命。
结果是:当天下午光伏突然被云遮住,确定性方案的系统出现约0.9MW的缺额,只能紧急购电,而鲁棒方案靠提前预留的机组爬坡空间和储能放电,平稳过渡。
成本对比,我做过一个典型日测试:
| 模型 | 总运行成本 | 是否满足最坏场景 |
|---|---|---|
| 确定性优化 | 约4.6万元 | 否,出现缺额 |
| 鲁棒优化(盒式集) | 约5.1万元 | 是 |
| 鲁棒优化(预算集,Γ=6) | 约4.9万元 | 是,允许部分参数非极端 |
鲁棒方案比确定性方案贵约10%,但避免了切负荷或紧急购电的高额惩罚。很多时候,这10%就是“保险费”。
3.4 不确定性预算Γ怎么定
我认为这是整个鲁棒优化里最有艺术感的参数。Γ太小,模型和确定性优化没什么区别,起不到保护作用;Γ太大,系统过度防御,成本暴涨,储能负荷率低得离谱。
我的做法是画一张“成本-风险曲线”:把Γ从0扫到最大可能值,记录总成本和最坏场景下的失负荷量。拐点附近就是推荐的Γ取值。所谓拐点,就是“再增加一单位Γ,成本上升加速但风险下降已经不明显”的位置。
实际操作中,我还做过一个经验公式参考:设不确定参数的个数为N,建议 Γ 初始取 $\sqrt{N}$ 到 $\sqrt{2N}$ 的区间。比方说有24个光伏时段不确定量,$\sqrt{24}\approx5$,可以先从Γ=5开始扫。
还有一点不能忘:Γ选好之后,在项目交付文档里一定要标清楚“这是基于历史数据90分位误差得到的”,这样即便被质疑保守,也能拿数据说话。
4. 实操中的坑,能救一个是一个
4.1 数值尺度问题,往往最坑
我第一次用全千瓦单位建模,变量动辄几千上万,约束矩阵的条件数很不好。HiGHS直接报数值警告,Gurobi倒是能解,但解的精度让人心虚。
后来我学乖了:功率统一用MW,储能容量用MWh,费用统一用万元或者统一用元,尽量让目标函数和约束的数值量级落在0.01到100之间。如果涉及SOC的递推,注意时间步长带来的系数缩小,比如1小时分辨率下,$P_{ess} \times 1 h / 1 MWh$ 这个系数是1,但如果分辨率改成15分钟,系数就是0.25,别漏掉。
4.2 储能SOC的末端约束别忘
储能SOC如果不加末端约束,优化结果经常是最后几个时段疯狂放电,把SOC放到底,因为这样“看起来省钱”。但现实中第二天还要继续运行,这种解根本不可执行。
我习惯加上 $SOC_T \geq SOC_0$ 这样的循环约束,表示日调度不消耗储能“家底”。代价是成本略有上升,但调度方案更真实。如果你的平台允许跨日调度,可以改成让末端SOC落在一定区间内,比如初始SOC的±10%。
4.3 最坏场景下的不可行问题
鲁棒建模最尴尬的情况是:模型本身不可行,但你又不知道是参数问题、约束冲突,还是不确定性集定义错了,或者对偶转换错了。
排查时有一个好用的调试顺序:
- 先把所有不确定参数全部固定在预测值上,跑一遍确定性模型,确认基础模型可行;
- 再把不确定性集逐个加入,每加一个就检查一次可行性,定位是哪类约束导致冲突;
- 最后检查对偶转换时有没有忘了%+和符号变化,尤其是对偶变量非负约束。
如果第2步发现功率平衡约束不可行,通常不是模型逻辑错,而是你划定的不确定性集范围太大,超出了系统“物理可调能力”。这时候需要回头和气象预测团队聊一下,误差区间是不是取得过于保守,或者适当调低Γ。
4.4 盒式不确定性集太保守怎么办
盒式集最大的问题在于:它假设所有参数同时达到最差。实际中,同一天中风速低谷和光照低谷同时出现的概率并不大。所以纯粹用盒式集,调度方案会显得很笨——燃气机组一直提心吊胆地带高备用,储能也始终不敢满充满放。
预算集是治这个的良药。给不确定参数加上一个总的“异常程度预算”,等效于告诉模型:你允许几个参数同时调皮,但不会全部调皮。偷懒的做法,是把每个时段的预测误差都缩到90%分位,再用Γ=6去约束。
4.5 避免用绝对值函数把线性问题搞复杂
储能损耗成本里我写了 $|P_{ess,t}|$,在CVXPY里写成cp.abs没问题,内部会自动转成等价的线性规划。但如果你在别的框架里手写建模,千万不要把绝对值留在非线性项里,要么拆成两个非负变量,要么引入辅助变量u_t >= P_ess[t]、u_t >= -P_ess[t],把目标改成C_ess * u_t,这才是线性化的正规操作。
5. 汇报与落地:从模型到“智能微电网PPT”的距离
5.1 算法做得再漂亮,最后也要把价值讲清楚
模型跑通只是第一步,现实里还得面对领导、甲方或者评审专家。这时候,平衡公式和对偶变量会瞬间把人劝退。我习惯把所有成果沉淀成一个智能微电网ppt风格的汇报材料,核心只讲四张图。
第一张是典型日调度曲线对比图。把确定性方案和鲁棒方案的机组、储能、联络线曲线画在一起,标注在最坏场景下的差异性,直观表达“鲁棒方案虽然贵一点,但确实更稳”。
第二张是成本-风险帕累托曲线。横轴是Γ大小,纵轴是总成本,再加一条虚线表示最坏失负荷量,用曲线证明你的选择不是拍脑袋,而是有数据支撑的权衡。
第三张是不确定性集的可视化。我经常用一个时间序列误差带状图去解释:蓝色预测曲线,灰色误差带,用红色虚线标出不确定性集边界。对非专业观众来说,这张图远比“预算参数Γ”好懂。
第四张是实时闭环流程图。讲清楚日前鲁棒调度和日内MPC修正的关系,展示你是怎么做滚动更新的,以及鲁棒优化的安全包络如何给日内调整留出空间。
5.2 一份有价值的汇报该放哪些素材
除了上面四张图,我在文件夹里还固定存放三类东西:一是一页“不确定性来源汇总表”,把光伏、风电、负荷的预测误差来源和区间大小列全;二是一页“方案参数表”,包括Γ取值、最坏场景对应的具体时点和数值;三是一页“结论页”,用两三句话给出结论,比如“在光伏出力偏差达35%的极端日,鲁棒方案仍能保持供电可靠,总成本仅增加8%”。
做这类汇报,树状图和表格比大段文字更有说服力。听众最关心的不是你的求解器多高级,而是“这套方案比原来的强在哪,多花多少钱,有没有风险”。
5.3 后续还能往哪扩展
鲁棒优化不是万能药,它和随机优化各有适用边界。如果你们平台历史数据很丰富,而且能够获得相对可靠的预测误差分布,可以考虑随机优化或者分布式鲁棒优化。分布式鲁棒优化是目前学术界和工业界都盯着的方向,思路是“不确定性集合里不是所有概率分布都可信,但我们要保证最坏分布下表现也不差”,这个属于进阶版本,可以在基础鲁棒优化吃透之后再接触。
对工程落地来说,更实际的扩展是:把日前鲁棒调度的结果和日内模型预测控制联动起来,构建“鲁棒优化做边界,MPC做跟踪”的分层框架,既能保证可靠,又不至于因为过度保守损失太多经济性。
我个人实际用下来的体会是,鲁棒优化最打动人的一点,是它把“不确定性”这种抽象的东西,转化成了可以计算、可以调节、可以汇报的参数。你不需要神化它,也不用畏惧它,把它当成调度工具箱里一把专门应对最坏情况的尺子就好。
最后再分享一个小技巧:所有不确定性参数,无论公式里多复杂,第一步永远是用历史数据画区间图。区间画得难看,后面的模型再漂亮也是空中楼阁。