ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

考虑风光不确定性和双向备用的电力系统鲁棒优化调度

2026/9/9 17:01:11 拓冰建站 浏览量
考虑风光不确定性和双向备用的电力系统鲁棒优化调度 1. 项目概述与问题背景搞过电力系统优化调度的人应该都有同感风光出力预测数据永远是“看起来很美”实际运行起来总会被现实打脸。今天要聊的这个问题针对的就是这个痛点——风光负荷不同鲁棒性对系统总成本的影响同时把系统向上、向下备用容量约束一起纳入优化模型。这是个非常典型的两阶段鲁棒优化/单层鲁棒优化在电力调度中的应用场景。先把这个题目拆开看。风光负荷三者的预测值都存在误差传统确定性调度只按预测值安排出力一旦实际值与预测值偏差较大就可能出现功率失衡、切负荷或弃风弃光。鲁棒优化的思路是不再假设预测值一定准确而是假设不确定参数风光出力、负荷会在一个预先设定的不确定集合内波动调度方案必须对集合内的所有可能场景都可行。这里的“不同鲁棒性”指的是不确定集合的大小或鲁棒调节参数比如预算参数、保守度系数的变化。当鲁棒性增强时系统预留的备用容量增加调度方案变得更保守总成本大概率上升但代价是系统应对不确定性的能力变强。这个“成本-鲁棒性”的权衡关系就是这个项目要搞清楚的核心问题。为什么要把向上、向下备用容量单独考虑进来因为风光的波动是双向的实际出力低于预测值时系统需要向上备用来补功率缺口实际出力高于预测值时系统需要向下备用或调峰能力来消纳多余电量。只考虑单向备用在现实中是行不通的。把两个方向的备用需求都建模为与鲁棒性参数相关的约束才能真实反映系统成本随鲁棒性变化的规律。这个项目适合谁正在做电力系统优化调度方向的研究生、做新能源并网规划的工程师、以及想学习如何用MatlabYALMIP求解器CPLEX或Gurobi求解鲁棒优化问题的入门者。看完这篇文章你能得到一套可以直接跑的Matlab代码框架以及关于鲁棒性参数选取、备用约束建模、结果分析的一整套实践经验。2. 鲁棒优化建模思路与关键设计2.1 不确定集合怎么选盒式集合与预算约束鲁棒优化的第一步是定义不确定参数的波动范围。最常见的做法是盒式不确定集合每个不确定参数在预测值上下浮动一个区间。以光伏出力为例如果预测值是100 MW预测误差比例是20%那么光伏实际出力p_pv就在[80, 120] MW之间任意取值。只做盒式集合有个问题它假设所有不确定参数同时达到最坏情况这太保守了。实际中所有风电、光伏、负荷同时偏差到极值的概率非常低。所以工程上更常用的是带预算约束budget的不确定集合也叫做Bertsimas-Sim方法。核心做法是限制所有不确定参数偏离预测值的总“数量”不能超过一个预算参数Γ。这样做的好处是可以通过调节Γ连续地控制方案的保守程度Γ0退化为确定性调度Γ取最大值时等价于最保守的盒式鲁棒。在Matlab代码里我是这样处理的把风电、光伏、负荷的预测误差都归一到各自预测值的百分比区间比如风电误差±20%光伏误差±15%负荷误差±5%然后引入统一的预算参数Γ它表示所有节点不确定参数偏离预测值之和的上限。实际代码中用0到N不确定参数总数之间的整数或连续值来扫描观察总成本随Γ的变化曲线。注意Γ到底取整数还是连续值取决于你的不确定参数建模方式。如果每个不确定参数的偏差是一个0-1乘上最大偏差的连续变量那Γ可以是连续值如果只允许出现/不出现偏差Γ就是整数。两种方式YALMIP都能处理但整数形式的求解速度更快。2.2 目标函数总成本都包含哪些项系统总成本不是只算发电成本。在这个模型里我考虑了以下四部分常规机组火电/燃气的发电成本用二次函数或分段线性函数表示工程中常用二次函数 ai * P_i^2 bi * P_i ci常规机组的启停成本单位时间示例中为简化可暂不考虑启停状态变量但更完整的模型需要加入系统向上备用的成本由提供向上备用的机组按备用报价结算可以按各自机组备用容量乘以备用价格系数计算系统向下备用的成本同理由参与下调的机组提供为什么备用要单独计算成本因为备用容量占用的是机组可调容量机组需要预留这部分能力而不能全出力发电这相当于一种机会成本必须体现在经济信号里。另外向上备用的价格通常高于向下备用因为向上备用需要机组在较低出力点运行并具备快速加出力能力对机组性能要求更高。对于风光和负荷侧模型里不需要为它们单独加成本项但通过弃风弃光约束和切负荷约束来保证不出现不合理的调度结果。如果想更精细可以在目标函数里加入弃风弃光和切负荷的惩罚项这样求解器在可行与不可行之间会自动权衡。本项目基础版不加惩罚项而是严格保证所有不确定场景下都满足功率平衡和备用约束这样鲁棒性含义更纯粹。2.3 备用约束怎么转化为数学表达式这是整个模型最核心也最容易写错的地方。先定义符号P_g(t)常规机组g在时刻t的计划出力决策变量P_w(t)、P_pv(t)、P_L(t)风电、光伏、负荷的预测值ΔP_w、ΔP_pv、ΔP_L对应的不确定偏差属于不确定集合UR_up(t)系统向上备用需求决策变量或由不确定集合推导R_down(t)系统向下备用需求功率平衡约束的原始形式是sum(P_g(t)) P_w(t) ΔP_w P_pv(t) ΔP_pv P_L(t) ΔP_L这里ΔP_w、ΔP_pv、ΔP_L是变量这就导致约束是不确定的。鲁棒优化的核心就是求一个不依赖于Δ取值的调度方案使上式对所有Δ∈U都成立。把约束重新整理成最坏情况形式。对向上备用来说最坏情况是风电、光伏出力最小ΔP_w、ΔP_pv取下界负值而负荷最大ΔP_L取上界正值此时需要的向上备用容量为R_up(t) max_{Δ∈U} [ ΔP_L - ΔP_w - ΔP_pv ]对向下备用来说最坏情况是风电、光伏出力最大、负荷最小此时需要向下备用容量为R_down(t) max_{Δ∈U} [ ΔP_w ΔP_pv - ΔP_L ]于是机组的调节能力约束变为sum( P_g,max - P_g(t) ) ≥ R_up(t) // 机组上调能力 sum( P_g(t) - P_g,min ) ≥ R_down(t) // 机组下调能力这两个约束的物理含义很直观所有常规机组剩余可加出力之和必须能覆盖最坏情况下的功率缺口所有常规机组剩余可减出力之和必须能消纳最坏情况下的超额功率。3. 不确定性与备用的耦合处理3.1 对偶变换把max问题变成线性约束上面的R_up(t)和R_down(t)是max问题不能直接嵌进线性规划里。标准的处理办法是把它转化成对偶问题或者直接用线性规划的对偶理论。具体来说风电预测偏差表示为ΔP_w ξ_w * ε_w * P_w,base其中ξ_w是0到1之间的不确定水平系数ε_w是最大偏差比例。如果每个不确定参数都可以独立地在其区间内取最大偏差那么 R_up(t) 的最大值可以通过对偶变换转化为一组线性约束。以预算约束Γ为例R_up(t)的max问题可以写成max Σ_i ( -ε_i * P_i,base * ξ_i ) // 对同向偏差符号做归一化 s.t. Σ_i ξ_i ≤ Γ 0 ≤ ξ_i ≤ 1其中i遍历风电、光伏、负荷三个不确定源。由于目标函数是线性的、约束是线性的这个max问题本质上是一个线性规划。把它的对偶问题写出来对偶变量是α对应预算约束和β_i对应0≤ξ_i≤1然后让原调度约束里带上这些对偶变量和α、β就能得到一个等价的可解的线性约束系统。这样处理的巧妙之处在于原问题max的每个解都对应对偶问题的一个可行解两者的目标函数值相等强对偶成立因为原问题是线性规划所以对偶问题加进原模型后不会改变最优解但把不确定约束变成了确定线性约束。在YALMPI求解器环境下你甚至不需要手动推导对偶形式因为代码里通常会直接用YALMIP的鲁棒优化模块uncertain和uncertainty声明。但如果你想自己手推上面这个过程就是标准推导。3.2 为什么向上/向下备用要一起考虑很多人做鲁棒调度时容易忽略向下备用。实际项目里遇到的情况是光伏在午间大发时系统净负荷可能变成负值如果只考虑向上备用调度方案会在光伏大发时段大量弃光或者让常规机组压低出力但机组有个最小技术出力往下调的空间有限。如果这个有限的下调空间还不够用系统就需要额外的向下备用来源比如储能充电、可中断负荷等。所以完整的备用约束必须同时考虑两个方向。从模型结构上看这两个约束会共同制约机组出力区间。举个例子某台机组容量300 MW最小出力150 MW如果系统需要200 MW向上备用和100 MW向下备用这台机组的出力必须同时满足300 - P_g ≥ 200 → P_g ≤ 100 P_g - 150 ≥ 100 → P_g ≥ 250单个约束都成立但组合起来显示这个机组自身无法同时满足两种备用需求。这就是为什么备用约束必须放到多机组的系统层面来看而不是单台机组算完就完事。从数学上看向上备用约束和向下备用约束叠加在一起定义了常规机组群的可行出力区间。鲁棒性增强时两者都变紧可行域收缩系统不得不让更多机组在线运行或增加高成本机组出力总成本随之上升。3.3 鲁棒性参数的扫描策略“不同鲁棒性”在代码里通常体现为对Γ或ε做参数扫描。我的经验是分两个维度看固定不确定区间大小如风电±20%扫描预算参数Γ从0到最大值的等间距点观察总成本和备用需求的变化曲线。这回答的是“系统对同时发生多个偏差的容忍度成本”。固定Γ扫描不确定区间宽度如风电误差从±5%到±30%观察系统总成本的变化。这回答的是“预测精度提高能带来多少经济效益”。两种扫描都很实用论文里也常用。实际计算时为节省时间可以用50个或100个扫描点线性插值画出平滑曲线。Matlab里用for循环包住求解过程就行每个扫描点单独调一次求解器求解完成把结果存到数组里最后统一画图。4. Matlab代码实现与核心环节4.1 系统数据设计我在做这个项目时参考了标准IEEE 6节点/30节点系统的数据风格搭建了一个含6台常规机组、1个风电场、1个光伏电站和一组负荷节点的简化系统。为了让你能快速上手下面给出一个可直接用于小规模测试的数据设计表机组编号容量(MW)最小出力(MW)煤耗系数a(元/MW²h)煤耗系数b(元/MWh)煤耗系数c(元/h)上调备用价格(元/MWh)下调备用价格(元/MWh)G1300800.0015356005030G2200600.0020384505532G3200500.0025424005532G4150400.0030453506035G5150300.0035503006035G6100200.0040552506538风电场装机200 MW预测出力按日曲线变化最大预测误差设为±20%。光伏电站装机150 MW预测出力按日曲线变化最大预测误差设为±15%。负荷侧峰值1500 MW预测误差设为±5%。这一组数据不是实际电网数据但用来做机理研究和算法演示足够了。你在用自己的数据时只需要替换矩阵里的数值代码框架不需要大改。4.2 求解器与YALMIP设置代码实现用的是YALMIP加外部求解器。求解器选CPLEX或Gurobi都可以我在本机实测两者都能快速求解这个规模的优化问题6台机组、24时段几百个变量和约束秒级求解。安装YALMIP很简单去GitHub Releases下载把文件夹放到Matlab路径下然后addpath(genpath(yalmip路径))。求解器需要单独安装CPLEX或Gurobi都提供免费学术授权。YALMIP里声明决策变量的方式如下P sdpvar(6, 24, full); % 6台机组24时段出力 R_up sdpvar(6, 24, full); % 向上备用 R_down sdpvar(6, 24, full); % 向下备用目标函数用sum和quad2lin处理二次成本函数或者直接使用二次目标函数让求解器自行处理如果用的是Gurobi/CPLEX都能直接求解二次规划。为了线性化方便也可以把二次成本分段线性化。我的建议是先用二次函数跑通再去尝试分段线性化两个结果应该非常接近。4.3 核心约束代码对照下面是一段简化但可运行的核心约束伪代码展示功率平衡、向上/向下备用约束的实现思路% 不确定参数最大值修正 for t 1:24 % 功率平衡约束不确定形式用鲁棒对偶后的确定等价形式 Constraints [Constraints, sum(P(:,t)) P_w_base(t) P_pv_base(t) P_L_base(t)]; % 向上备用需求不等式最坏情况风光低、负荷高 % 这里用R_up_total表示所有机组提供的向上备用总和 Constraints [Constraints, sum(R_up(:,t)) Gamma_scale * (delta_PL_max(t) delta_Pw_max(t) delta_Ppv_max(t))]; % 机组出力与备用能力约束 Constraints [Constraints, P(:,t) R_up(:,t) P_max(:)]; Constraints [Constraints, P(:,t) - R_down(:,t) P_min(:)]; % 向下备用需求不等式最坏情况风光高、负荷低 Constraints [Constraints, sum(R_down(:,t)) Gamma_scale * (delta_Pw_max(t) delta_Ppv_max(t) delta_PL_min(t))]; end上面代码中Gamma_scale是归一化后的鲁棒性参数取值0到1之间。delta_Pw_max(t)表示t时刻风电预测偏差的最大值用预测值乘以误差比例得到。这样写虽然不完全等同于Bertsimas-Sim的标准形式那个需要引入对偶变量但在不确定参数只有三个源、且你主要想观察趋势的场景下这个简化形式已经够用且非常直观。如果你要严格推导预算约束下的对偶形式推荐参考Bertsimas-Sim 2004年的论文代码实现上可以用YALMIP的uncertain接口但新手容易踩坑建议先跑通简化版再升级。4.4 结果展示与成本曲线绘制求解完成后的标准画图动作包括常规机组各时段最优出力堆叠图面积图系统总成本随鲁棒性参数变化曲线向上/向下备用需求随鲁棒性参数变化曲线不同鲁棒性场景下的功率平衡校验图验证方案在最坏偏差下是否依然可行画图用Matlab基础函数plot和area就行注意设置FontSize和LineWidth保证放到论文里清晰可读。以下是一个画成本曲线的示例Gamma_range 0:0.1:1; cost_list zeros(size(Gamma_range)); for k 1:length(Gamma_range) % 在这里设置当前Gamma并求解 % ... cost_list(k) value(Objective); end figure; plot(Gamma_range, cost_list, -o, LineWidth, 1.8); xlabel(鲁棒性参数 \Gamma); ylabel(系统总成本元); grid on;5. 实验结果与分析要点以我搭建的6机系统为例跑出来的典型结果是总成本随着鲁棒性参数Γ从0到1增大而单调上升但曲线形态往往是先缓后陡。Γ从0到0.4时成本上升约3%-5%从0.4到1时成本上升幅度明显加大可能到15%以上。原因是低鲁棒性时备用需求增量主要由效率较高、成本较低的机组承担边际成本上升不明显高鲁棒性时低成本机组的备用能力被用尽必须调用高成本机组或增加高成本机组出力边际成本迅速上升。向上备用和向下备用的变化规律不完全同步。风资源好的夜间时段向下备用需求增幅更大光伏大发的中午时段向下备用需求也显著增加。这说明鲁棒性对两个方向备用需求的影响存在时段差异在分析结果时要把时段因素考虑进去不能只给一个全天平均值。另一个值得注意的现象随着鲁棒性增强某些时段的机组组合会发生质变。比如从只开4台机组变成必须开5台甚至6台机组导致固定成本跳升总成本曲线出现不连续的跳跃点。这种跳跃在真实系统里很常见论文呈现时不需要刻意平滑。如果画功率平衡校验图你会发现在最坏偏差场景下风光取最低、负荷取最高常规机组出力加上备用总量刚好等于负荷上限说明模型正确保证了鲁棒可行性。这是判断你的模型写对没写对的标志性检验。6. 常见问题与排查技巧实录6.1 求解器报“Infeasible Problem”怎么处理这个项目最容易遇到的坑就是模型不可行。我调试时遇到过的情形和解决办法电源总容量不足以覆盖最大负荷加上向上备用需求。检查发电机总容量与负荷峰值的关系至少要留出备用裕度。如果不可行把某些机组最小出力调低或增加机组数量。向下备用约束过紧导致机组出力区间冲突。典型场景是光伏大发时段系统要求大量向下备用但所有机组出力已经压到最低出力附近没有下调空间了。解决办法是允许弃风弃光或者增加储能装置。鲁棒性参数取到最大值时任何方案都不可行。这是正常现象说明在给定不确定集合最大值下系统无法保证所有场景可行。分析时把Γ限制在可解区间内即可不必强求覆盖整个0-1区间。排查顺序建议是先把Γ设为0跑确定性调度确认模型基础没问题再逐步增大Γ观察哪个约束最先被触发把对应的约束松弛掉或用对偶形式替换。6.2 YALMIP报错“No suitable solver”出现这个错误通常是因为没装求解器或者YALMIP没找到求解器路径。检查方法是在Matlab里运行yalmiptest它会列出所有已安装求解器的状态。我实际用过CPLEX 12.10、Gurobi 9.5和Gurobi 10.0配合YALMIP R2021版本都能正常用。如果你的问题里有二次目标函数确保求解器支持二次规划。Gurobi和CPLEX都支持但如果用的是免费的linprog只支持线性规划就需要先把二次成本分段线性化。具体做法是把机组出力区间切成几段每段内成本按线性函数近似再引入0-1变量选择段。切5段左右精度就很高了不用太贪多。6.3 结果不随鲁棒性变化或变化异常大多数情况是因为鲁棒性参数没有真正进入约束。比如代码里用了全局变量但求解循环里忘了更新或者对偶变换后有简化处理导致约束变成了定值。调试方法很简单把不同Γ值对应的备用需求值打印出来如果完全一致说明模型里鲁棒性参数和备用约束之间的连接断开。还有一种可能是误差分配方式不对。如果所有误差都归到一个“总偏差”变量上Γ的变化会被线性稀释导致结果变化非常平缓。正确的做法是每个不确定源有独立的偏差变量Γ通过预算约束来限制偏差的总量。6.4 求解时间过长怎么办6机24时段这个规模正常求解时间应该在几秒到几十秒之间。如果求解时间超过几分钟大概率是二元变量太多或者约束写得不够紧凑。优化建议机组组合启停变量是主要耗时点如果只是研究备用与鲁棒性关系可以先把启停变量固定为确定性调度结果只优化出力与备用这能大幅加速。用sdpvar声明变量时指定维度不要用动态扩展比如循环里不停把变量拼接进约束数组预先分配好约束数组能提速不少。如果用了YALMIP的uncertain接口可以手动写出对偶等价形式替代手工对偶虽然推导繁琐但求解器处理起来更高效。7. 扩展方向与实际应用建议这个基础模型本身就能回答很多工程问题。比如当风电预测误差从20%降到10%时系统总成本能节省多少这个“预测精度的经济价值”是新能源并网评估里很有说服力的数据。再比如增加储能系统后相同鲁棒性水平下系统总成本能降低多少这些扩展只需要调整约束和决策变量代码框架不用推翻重来。如果你是做毕业设计或者发小论文建议在这个框架上叠加更复杂的场景多时段耦合的机组爬坡约束、储能充放电模型、需求响应资源、市场出清机制。这些扩展会显著增加模型的现实意义。我个人在实际操作中的一个习惯是每次调整模型后都保留一个“验证场景”——固定Γ0.3把最坏偏差场景的功率平衡情况打印出来确认所有等式约束在误差范围内成立。这个习惯帮我避免了很多因为约束写错而导致的隐性错误也能在答辩或汇报时作为模型正确性的有力佐证。最后再分享一个小技巧跑完扫描后把每个Γ值下各时段的备用需求和机组出力存成Excel表格。后面写报告或做敏感性分析时不需要重新求解直接用表格数据就能做二次分析省时省力。