1. 为什么微电网调度绕不开不确定性
1.1 确定性调度的理想世界
先问一个问题:如果你手里有一份完全准确的光伏出力曲线和负荷曲线,调度问题会变成什么样?答案很简单——一个线性规划问题。储能、柴油机、微燃机各自的出力,只要在约束范围内满足功率平衡就行了,求解器几秒钟就能给你最优解。
但真实工程里,这份"完全准确的数据"从来不存在。光伏出力受云层影响能瞬间掉一半,负荷峰值可能比预测高15%,甚至现货电价也会因为网络拥堵而剧烈波动。我早期做微电网能量管理系统(EMS)时就是按确定性模型来的,结果极其惨痛:某天的仿真结果里,调度方案按照"预测光伏出力=90kW"排产,但实际光伏只有60kW,系统频率直接掉出安全范围,备用柴油机强行启动,调度成本比预测值高出将近40%。
这就是确定性调度最大的问题——它把预测当成现实,但对"预测错了怎么办"完全没有兜底机制。
1.2 不确定性从哪来:风光、负荷、现货电价
微电网里的不确定性大致来自三个方向:
第一是风光出力偏差。光伏和风机的出力取决于天气,而天气预报做不到100%准确。风力发电的爬坡率极快,可能十分钟内出力从80kW掉到20kW。这种波动对微电网的功率平衡影响非常大。
第二是负荷的不确定性。用户侧用电行为本身无法精确建模,尤其当微电网带商业综合体或工业园区时,负荷突变是常见现象。负荷预测误差往往在5%到20%之间,而且有一定的规律:早晚高峰时段误差更大,过渡时段相对稳定。
第三是市场电价的不确定性。如果微电网有并网条件,参与市场购售电时,现货电价的波动也会影响调度决策。天然气价格、需求响应信号、甚至相邻区域的价格联动,都会让电价预测模型失效。
这三种不确定性的来源、量级和影响方式各不相同。如果你用一个固定的概率分布去描述它们,工程上往往难以让人信服——你很难说清光伏出力的预测误差到底服从正态分布还是贝塔分布,参数从哪来?历史数据不够怎么办?这正是鲁棒优化的切入点。
1.3 鲁棒优化和随机优化的选择逻辑
行业里处理不确定性的主流方法有两类:随机优化和鲁棒优化。随机优化的思路是"我预测了100个可能的场景,每个场景有各自的概率,求期望成本最小化"。这个思路听起来很美,但它有两个硬伤:
- 概率分布本身的准确性没法保证。你给的分布和真实世界不符,优化出来的解自然也不靠谱。
- 场景数量少了解不出效果,多了计算爆炸。做两阶段随机规划时,1000个场景的MILP问题,求解时间经常以小时计,而且很多场景浪费在极端低概率区间。
鲁棒优化的思路完全相反——我不关心概率,我只要保证你在最坏情况下也不至于崩盘。你告诉我光伏出力波动的区间是[60, 90],我就按照最不利于系统运行的情况来安排调度策略,确保无论光伏实际出力是60还是90,系统都能稳定运行且成本可控。
你说鲁棒优化保守?确实,它比随机优化保守。但它的优势是:不需要精确的概率分布、模型转换后是标准的MILP、计算时间在分钟级可以接受。对一个需要每天滚动优化、甚至日内实时调度的EMS来说,鲁棒优化在工程落地上的友好度远超随机优化。
2. 从物理模型到鲁棒优化模型
2.1 微电网调度的数学描述
先说清楚我们优化的对象是什么。一个典型微电网包含以下设备和约束:
设备模型部分:
柴油机(或微燃机):出力范围限制在[P_min, P_max],爬坡约束限制了相邻时段的出力变化量|P_t - P_{t-1}| ≤ Ramp。燃料成本是出力的二次函数,但工程上常线性化处理为分段线性成本。
储能系统:SOC(荷电状态)随时间更新:SOC_t = SOC_{t-1} + (P_ch·η_ch - P_dis/η_dis)·Δt/Capacity。充放电功率有限制,SOC也在上下限之间。这里有个小坑:充放电功率不能同时为正,否则你的模型会白嫖能量。处理方法要么引入二进制变量,要么用互补约束的线性逼近,后面代码部分会细说。
联络线:如果微电网和主网并网,购售电功率有上限,且购电价和售电价通常不一样(存在价差)。
功率平衡约束:所有发电功率加上购电功率减去用电负荷必须始终等于零,这是每条母线、每个时段都要满足的硬约束。
目标函数:最小化总运行成本,包含燃料成本、购电成本、储能折旧成本(有时可忽略),可能还需要加上弃光、切负荷的惩罚项。
2.2 盒式不确定集与两阶段鲁棒建模思路
所谓鲁棒优化,关键是"不确定量"的描述方式。最常用的不确定集是盒式(box):
光伏出力 P_pv ∈ [P_pv_min, P_pv_max],负荷 P_load ∈ [P_load_min, P_load_max]。
如果直接用这种全区间不确定集,结果通常非常保守——因为它在极端情况下才会出现(光伏同时取最小、负荷同时取最大)。所以工程上会用预算约束(budget of uncertainty)来限制"同时取坏值的变量个数上限"。
例如,一个含24时段、每个时段光伏和负荷各一个不确定量的模型,不确定性变量总数是48个。引入预算参数Γ,要求所有时段内不确定量偏离预测值的归一化总和 ≤ Γ。Γ=0时退化为确定性模型,Γ=48时是全盒式的最保守情形。你可以通过调节Γ在保守度和经济性之间做折中。
建模方式我推荐两阶段形式:第一阶段决定机组开停、储能充放电计划等"现在定下来",第二阶段等不确定量揭露后再做功率调整,确保任何波动下都能通过调整各设备出力维持平衡。两阶段鲁棒问题的标准解法是列与约束生成算法(C&CG),后面展开讲。
2.3 对等转换:如何把Robust变成可求解的MILP
模型里的最坏情况是一个"max-min"或"min-max"结构,不能直接喂给求解器,需要转换。
对于单阶段鲁棒问题,可以通过对偶理论把内层的max问题转为对偶min问题,然后把目标函数合并,最终得到一个标准的MILP。这一路操作的关键是把约束条件里涉及不确定参数的部分拆出来,写成"名义值 + 偏差×扰动量"的形式,再融入不确定集的对偶表达。
对于两阶段问题,C&CG的标准流程是:
- 初始化:假设一个最坏场景(一般是预测值的偏差方向)。
- 主问题:在当前已知场景集合下求解调度方案,得到目标值下界。
- 子问题:固定主问题的决策变量,求解最坏情况下的最小调整成本(或判别可行性),得到目标值上界。
- 收敛判断:若上下界间隙小于阈值退出,否则把子问题产生的场景加回主问题,重复迭代。
这套流程听起来复杂,但MATLAB里用YALMIP加一个通用求解器(如Gurobi或CPLEX)实现下来,核心代码量也就几百行。难的不是代码本身,而是调试过程中那些边界情况和凸性条件问题。
3. MATLAB里怎么把这套模型跑起来
3.1 求解器选型:YALMIP还是不YALMIP
首先明确一个结论:我不推荐直接在MATLAB里手写单纯形法或者对偶转换,那是在重复造轮子。真正该做的是用建模工具把你脑子里的数学问题翻译成求解器能吃的语言。
最常用的选择是YALMIP——一个MATLAB的建模工具箱,本身不求解,但能对接Gurobi、CPLEX、MOSEK等商业求解器。它的好处是把约束写出来特别直观,和你在论文里写的公式几乎一一对应,调试方便。缺点是多了一层抽象,求解大模型时会有额外开销;不过对微电网调度这种规模(几百个变量、上千条约束)来说完全不是问题。
如果你不想装YALMIP,也可以用MATLAB自带的Optimization Toolbox里的intlinprog。但缺点非常明显:你得自己把所有约束写成矩阵形式,变量数量一多,稀疏矩阵的组装错误率极高。我试过一次之后果断放弃,老老实实装了YALMIP加Gurobi。
3.2 数据准备:风光出力场景怎么构造
建模前得先把数据准备好。这一步看起来琐碎,实际上决定了你模型的成败。我一般按以下流程:
- 获取原始数据:光伏出力归一化曲线、负荷实际曲线。如果没有实测数据,可以用预测工具生成,但要清楚标注数据来源和误差水平。
- 计算预测误差:对比历史预测值和实际值,确定每个时段误差的上下界。如果数据不够,工程上常用预测值的10%到20%作为波动范围,并做敏感性分析。
- 构造不确定集:定义每个时段的波动区间和预算参数Γ。建议先用确定性模型跑一版,再逐步增大Γ,观察成本上升趋势。
这里提个经验:如果负荷的波动范围取的太宽,比如±20%,你会发现鲁棒解的成本比确定性解高30%以上,这时候调度的储能往往会预先把SOC充得很高,以便应对负荷高峰——这个行为是符合工程直觉的。
3.3 核心代码骨架与关键函数的实现
下面给一个简化版的两阶段鲁棒调度核心骨架,用YALMIP建模,注释尽量详细,方便你在此基础上扩展。
%% 两阶段鲁棒微电网调度 - C&CG迭代骨架(简化版) % 变量定义 % x: 第一阶段变量,储能充放电、机组出力等 % y: 第二阶段变量,应对不确定性后的调整量 % u: 不确定性变量,光伏/负荷偏差 % 基本参数 P_load_pred = ...; % 负荷预测值,24x1 P_pv_pred = ...; % 光伏预测值,24x1 delta_load = 0.15; % 负荷波动范围比例(假设15%) delta_pv = 0.20; % 光伏波动范围比例(假设20%) Gamma = 8; % 预算参数,调节保守度 % 不确定集:盒式+预算约束 u_lb = -[delta_load*P_load_pred; delta_pv*P_pv_pred]; u_ub = [delta_load*P_load_pred; delta_pv*P_pv_pred]; % 预算约束的归一化累加形式在这里通过循环实现,为简洁不展开 % 第一阶段模型(主问题,MILP) x = sdpvar(...); Constraints = []; Cost = 0; % ... 添加储能、机组、联络线的约束和成本 % C&CG迭代 LB = -inf; UB = inf; worst_cases = {}; % 收集子问题返回的最坏场景 for iter = 1:50 % 1. 求解主问题(含已有的最坏场景集合) optimize(Constraints_with_worst, Cost); LB = value(Cost); % 2. 固定x,求解子问题(max-min结构) % 内层min是线性规划,外层max通过枚举极点求解 [worst_u, sub_obj] = solve_subproblem(value(x)); UB = min(UB, sub_obj + value(Cost)); if (UB - LB) / UB < 0.01 % 间隙小于1%则收敛 break; end worst_cases{end+1} = worst_u; % 把最坏场景加入主问题 end子问题的SDP/线性LP求解在简化版里用双重循环即可,实际工程中会用对偶变换加速。上面的骨架只是说明流程,具体到约束组装需要大量细节,每个人的模型又不一样,这里给的是通用思路。
4. 我踩过的那些坑
4.1 对偶转换时的变量维度炸了
第一次做两阶段鲁棒时,我在子问题的对偶转换上卡了快一周。原因是:子问题内层的min是对所有连续调整量求最小,外层的max是对不确定参数求最大。做对偶时,我先对内层做dual,结果对偶变量个数和约束数量直接翻倍,YALMIP里变量维度对不上,老是报错。
后来才搞清楚,正确的做法是:先分离出和不确定参数相关的项,让它们只出现在目标函数系数里,再对min部分取对偶,把外层max变成内层min的对偶问题。这样整个问题变成单一MILP,维度是可控的。用C&CG替代强对偶转换,可以有效绕开这类维度难题——你不必一次把对偶写对,每次迭代只追加一个场景,调试起来更安全。
4.2 求解器永远在跑、内存爆掉
有段时间我的模型一跑就是三四个小时不出结果,仔细看发现是主问题的二进制变量太多了。储能、机组开停、购售电状态全用二进制变量表示,24时段乘上几个设备,二进制变量轻松上百。对于MILP来说,二进制变量数量直接决定求解难度。
解决办法有三招:
- 优先用内点法先求LP松弛解做良好初始解,喂给分支定界算法。
- 尽量消除多余的二进制变量。比如充放电互斥约束可以通过两个连续变量的线性组合加一个小量M构造,而不必引入额外的状态变量。
- 设置求解器的"MIP间隙"参数,Gurobi的MIPGap可以设为1%甚至更高——工程上1%和0.1%的差距没有你想象的那么大,但求解速度能差一个数量级。
4.3 保守度调参:预算参数到底怎么选
Γ选多少合适?这是每个用鲁棒优化的人都会问的问题。我翻了大量文献,有的推荐Γ取总不确定量的1/3,有的说2/5,但都是经验法则,没有普适答案。
我自己的做法是画一张"帕累托曲线":横轴是Γ从小到大的取值,纵轴是系统总成本。你会发现曲线呈现明显的三段:初始段成本上升缓慢(白赚了很多安全性),中期段成本上升变快(开始真正保守了),末端段成本骤增(过度保守)。然后根据工程需求选择拐点位置——比如成本和可靠性之间权重差不多时,选中期段中间点的Γ。
还有一个技巧:不要把预算约束一股脑全放在全局时段上,可以按关键时段分组设置。比如早晚高峰时段给高预算,深夜低谷时段给低预算。这样比统一Γ更符合实际运行规律。
5. 结果分析:鲁棒解到底值不值
5.1 经济性与可靠性的权衡曲线
做一个具体案例:假设只有光伏和负荷两个不确定源,24时段。确定性调度总成本约4200元。把Γ从0逐步增加到24(48个不确定变量的半数),成本变化大致如下:
| Γ取值 | 总成本(元) | 成本增幅 | 对应的可靠性表现 |
|---|---|---|---|
| 0(确定性) | 4200 | 0% | 光伏偏差10%即需要切负荷 |
| 4 | 4380 | 4.3% | 偏差20%内无需切负荷 |
| 8 | 4520 | 7.6% | 偏差30%内无需切负荷 |
| 16 | 4980 | 18.6% | 极端场景下仍可运行 |
| 24(全盒式) | 5450 | 29.8% | 完全保守,抗所有极端 |
从这个表能清晰看到:前段性价比最高。从Γ=0到Γ=4,只多花了不到200元就扛住了20%的预测偏差,非常划算;但从Γ=16到Γ=24,为了多扛一点极端场景却多花了470元,性价比就很低了。实际项目我一般建议把Γ控制在总不确定量个数的1/4到1/3之间。
分析结果时还有一个值得注意的点:观察最优调度策略中的储能行为变化。随着Γ增大,SOC曲线会呈现出明显的"保底"特征——在光伏出力最差、负荷最高的时段之前,储能会预先充满。这说明鲁棒解确实在学习"最坏场景"的结构,而不仅仅是无脑加安全裕度。
5.2 如何验证鲁棒解的可行性
鲁棒优化的结果不是算完就完,一定要做事后验证,否则你根本不知道模型有没有建模错误。
标准做法是蒙特卡洛模拟:根据历史数据拟合(或直接设定)真实的不确定性分布,随机采样10000个场景,把调度方案代入每个场景,检查功率平衡约束、储能SOC约束、联络线功率上限是否全部满足。理论上,只要场景在不确定集范围内,鲁棒解都应该是可行的。如果发现大量场景违反约束,多半是你的不确定集建模有bug,比如预算约束写错了方向。
我还做过一件比较笨但有效的事:直接把最坏场景提取出来逐时段手动推演。选一个光伏最低、负荷最高的场景,把每一时段的功率流手算一遍,看是否满足平衡。这个过程虽然花时间,但能帮你发现很多代码里隐蔽的问题——比如储能充放电同变量的边界处理是否正确。
5.3 后续可以怎么扩展
鲁棒优化的框架定型后,扩展方向很多:
- 多时段耦合的储能容量规划:把调度模型嵌入容量优化的外层迭代中,可以用于微电网的长期规划计算。
- 与需求响应结合:把可平移负荷作为第二阶段的可调变量,系统在面对不确定性时会更从容。
- 市场决策的鲁棒化:在购售电策略中考虑电价不确定集,把买卖决策优化和系统调度放在同一个框架里做。
- 分布式求解:如果微电网节点变多,可以考虑用交替方向乘子法(ADMM)把调度问题分解成各子网独立求解,配合鲁棒化处理内部不确定性。
这些扩展的共同点都是:以鲁棒模型为内核,外面套一层规划或市场决策的循环。所以你只要把内核对偶、迭代求解这套基本功打好,后面做各种衍生模型都会顺畅很多。
6. 给新手的几条实操建议
如果这篇文章只能留下三句话,我会留这三条。
第一,先跑通确定性模型,再谈鲁棒。很多人一上来就想直接上最先进的方法,结果模型有问题都排查不出来。确定性模型是对照组和调试基准,先把这套基础做扎实,你才有资格判断鲁棒优化带来的是真实收益还是模型的bug。
第二,不要迷信精确解。微电网调度本质上服务于工程决策,鲁棒优化是帮你找到一个"在不确定环境下依然可靠且成本可控"的方案。求解器的最优性间隙设到1%就完全够用,多出的算力不如拿去多做几轮蒙特卡洛验证。
第三,模型要能解释,不能当盲盒。不要做完优化就输出一个数字。一定要分析为什么储能这样充、为什么这个时段买电、为什么Γ增大后成本上升来自哪个约束——这才是一个能写进报告、能过专家评审的成果,也才是你真正理解了系统运行规律的表现。