资讯动态

分布鲁棒优化与线性决策规则的机组组合建模与求解

发布时间:2026/10/7 3:45:38 来源:尧图企业网站定制
从论文复现到工程落地机组组合问题一直是电力系统调度里的硬骨头。以前做确定性模型把风电当成一个固定的预测值算出来的开停机方案在晴雨天都一个样实际调度时经常被打脸。后来试过随机规划但前提是得知道风电出力的真实概率分布这在工程上根本没戏手里只有一堆历史预测误差数据分布长什么样根本说不清。所以这次我把目光转向了分布鲁棒优化配合线性决策规则用Matlab把整套机组组合模型跑通效果比预期稳得多。这个项目适合两类人看一类是做电力系统优化调度的研究生另一类是已经在用YALMIP、Gurobi这类工具写优化模型的工程师。如果你正在为风电、光伏这类间歇性电源的调度建模发愁这篇内容可以给你一条清晰的技术路线——从不确定性建模到模型转化再到代码实现每一步都按实际踩过的坑来写不是教科书式的照搬。1. 项目概述与整体思路1.1 为什么弃用随机规划改用分布鲁棒优化传统随机规划要求我们给风电出力设定一个确定的概率分布比如假设预测误差服从正态分布然后基于这个分布去求期望成本最小的调度方案。问题在于真实的风电预测误差和正态分布差得很远尾部更厚、还有明显的偏态。你拍脑袋定一个分布算出来的方案对真实分布的抵抗力就很差极端场景下一来就是大麻烦。分布鲁棒优化的思路完全不同我不需要知道精确分布只需要知道分布所属的一个集合这个集合就叫做模糊集。它把所有可能与真实分布兼容的分布都装进去决策的目标是让最坏情况下的期望成本最小。这样算出来的调度方案对分布的不确定性天然就有免疫力。说白了这是在我不知道真实分布但我知道它大概在某个范围内这个前提下找一个最保险的决策。1.2 线性决策规则在分布鲁棒机组组合中的角色两阶段机组组合里第一阶段决定机组启停第二阶段根据风电的实际出力做经济调度。风电出力是随机的第二阶段的决策变量自然也是随机变量的函数。这个函数可以非常复杂导致问题根本没法直接求解。线性决策规则也叫线性准则做了一个关键简化把第二阶段的可调变量设成随机变量的仿射函数。比如机组 i 的出力调整量写成 ( p_i(\xi) p_{i0} \alpha_i \xi )其中 \xi 是风电预测误差\alpha_i 是待优化的线性系数。这样就把一个无限维的函数优化问题降维成了有限维的系数优化问题原来的 min-max-min 三段问题也就能转化成常规的数学规划问题。这是整套模型能落地求解的核心。提示线性决策规则相当于在灵活性和可解性之间做了取舍。完全最优的二阶段决策是非线性函数线性近似不一定达到全局最优但在实际风电预测误差范围内效果已经足够好而且换来的是求解速度的大幅提升。工程上这个交换非常值得。1.3 项目整体技术路线整套技术路线分四步第一步基于历史风电预测误差数据构造模糊集确定均值、协方差和支撑集第二步建立两阶段分布鲁棒机组组合模型第一阶段0-1变量管启停第二阶段用线性决策规则表达调整量第三步通过拉格朗日对偶把内层最坏情况期望问题转化为可求解的凸优化问题第四步在Matlab中用YALMIP建模调用Gurobi或者CPLEX求解。这个路线的好处是每一个环节都有现成的工具支撑不需要自己从零写求解器。Matlab负责数据预处理和结果可视化YALMIP负责模型描述求解器负责真正算数。2. 风力发电不确定性的特征与模糊集构造2.1 风电预测误差的统计特征风电预测误差不是白噪声它有明显的规律第一误差大小和预测风速区间有关一般中速区间误差最大满发和零出力时反而小第二误差分布有偏态尤其在风速快速变化时段负误差实际出力低于预测的尾部更厚第三相邻时段误差之间存在正相关体现为时间上的连续性第四不同风电场之间的误差存在空间相关性。这些特征决定了模糊集不能拍脑袋随便定。只约束均值和方差不够还要把协方差和支撑集加进去否则模糊集太大算出来的方案过于保守运营成本高得离谱。2.2 基于矩信息的模糊集构造我采用的是最常见的矩信息模糊集形式如下[ \mathcal{F} \left{ P \middle| P(\xi \in \Xi) 1,\ \mathbb{E}_P[\xi] \mu,\ \mathbb{E}_P[\xi\xi^\top] \Sigma \right} ]这里 \xi 是风电预测误差向量\Xi 是误差的支撑集\mu 和 \Sigma 从历史数据里估计。支撑集通常设置为盒式约束 ( {\xi : \underline{\xi} \le \xi \le \overline{\xi}} )上下界取历史误差的最大最小值或者预测容量的百分比。这样定义模糊集既保留了不确定性的大致形状信息又不需要精确分布。实际估计 \mu 和 \Sigma 时要注意一点直接用样本均值、样本协方差会偏大尤其在样本量不足的情况下。我一般会做收缩估计把样本协方差向对角矩阵方向收缩数值稳定性好很多模型结果也更稳健。2.3 模糊集参数对调度结果的直接影响模糊集的大小直接决定了方案的保守程度。把协方差矩阵放大两倍最坏情况下的期望成本会明显上升因为模型在防御一个更大的最坏情况集合。反过来模糊集太小和真实分布偏差太大鲁棒性就没了。实操中我一般用交叉验证法选取模糊集尺寸把历史数据分成训练集和验证集用训练集构造模糊集在验证集上评估调度方案的实际成本选成本最低的那组参数。还有一个更工程化的做法——直接设定95%置信水平的误差界简单粗暴但效果不差。3. 机组组合问题的数学模型与转化3.1 两阶段决策框架先明确一下决策顺序。第一阶段是日前决策在风电实际出力还不知道的时候决定每台机组在24小时内每个时段的启停状态 ( u_{it} \in {0,1} ) 和基点出力 ( p_{it} )。第二阶段是实时调整风电出力被观测到之后各机组围绕基点出力做微调 ( \Delta p_{it}(\xi) )补上预测误差产生的功率缺口。这个两阶段结构和电力系统实际的日前-实时市场运行逻辑是完全吻合的。第一阶段定启停是要给明天的系统留出足够的调节能力第二阶段做调整是应对实际风电和预测不一致的情况。模型贴近实际结果才有工程参考价值。3.2 目标函数与约束条件目标函数是总成本期望最小包括三块机组燃料成本用二次函数近似或分段线性化、启停成本、弃风和切负荷惩罚。在分布鲁棒框架下目标写成一个 min-max-min 三层结构[ \min_{x} \left{ c^\top x \sup_{P \in \mathcal{F}} \mathbb{E}P\left[ \min{y(\xi)} d^\top y(\xi) \right] \right} ]约束条件按阶段分开。第一阶段的约束包括功率平衡约束、机组出力上下限、最小启停时间、爬坡约束、旋转备用约束。第二阶段的约束包括调整后的出力必须在机组出力范围内调整量自身不能超过爬坡能力系统功率平衡必须实时满足。最小启停时间是机组组合模型里最让人头疼的约束之一它让整数变量之间产生复杂的耦合关系直接用 YALMIP 建模时容易写错。我的经验是把每个机组每个时段的启动状态和停机状态分别用变量表示通过逻辑约束把它们和启停状态变量关联起来这样模型清晰也不容易出bug。3.3 线性决策规则下的问题转化如果没有线性决策规则第二阶段决策 ( y(\xi) ) 是 \xi 的任意函数内层 min 问题没法直接处理。引入仿射形式之后原本不可解的分布鲁棒问题就变成了一个有限维凸优化问题。转化过程用的核心工具是拉格朗日对偶把内层 sup 部分对偶成包含矩约束和支撑集约束的极小化问题。具体操作是构造拉格朗日函数引入对偶变量利用已知的矩信息 \mu 和 \Sigma 把不确定参数分离出来最终得到一组线性矩阵不等式或者线性约束。这一步是整个模型的灵魂。对偶转化做对了原问题就变成一个标准的二阶锥规划或者半定规划问题可以直接交给求解器做错了问题要么无界要么根本解不出。我得提醒一句对偶推导一定要在草稿纸上一步一步推别跳步尤其是支撑集的极值点分析一马虎就出大问题。注意最终求解问题的规模取决于三个维度机组数、时段数、风电场景的随机变量维度。10台机组24个时段的算例转化后的约束数量可能上万条这是正常现象不代表模型有问题。4. Matlab代码实现与关键细节4.1 代码架构与工具选型Matlab写优化模型我推荐用 YALMIP 作为建模层后面接 Gurobi 或 CPLEX。YALMIP 对二阶段分布鲁棒优化的支持比较友好特别是对半定约束和二阶锥约束的描述语法简洁出bug的概率比手动写矩阵小一个数量级。代码结构上我按数据、模型、求解、结果四个模块拆load_data.m加载负荷、风电预测值、历史误差数据计算模糊集参数build_ambiguity.m构造模糊集的均值、协方差、支撑集build_ucmodel.m定义机组参数构建第一阶段确定性约束build_dro.m建立第二阶段分布鲁棒部分引入线性决策规则solve_uc.m统一装配模型调用求解器plot_results.m输出机组启停方案、出力曲线、成本分析4.2 模糊集构造的Matlab实现模糊集参数估计的代码不复杂但细节很关键。样本协方差的收缩估计要自己写小函数处理直接用cov()函数的结果在样本量小的时候问题很多。以下是我实际用过的代码骨架% 从历史预测误差数据构造模糊集参数 errors load(wind_error_history.mat); % 每行一个历史样本每列一个时段 mu mean(errors, 1); % 误差均值 Sigma cov(errors); % 样本协方差 % 收缩估计在小样本下提高稳定性 delta 0.2; % 收缩系数 Sigma_shrink (1 - delta) * Sigma delta * diag(diag(Sigma)); % 支撑集取历史误差的90%分位数作为上下界 lower_bound prctile(errors, 5, 1); upper_bound prctile(errors, 95, 1);支撑集这里用的分位数是保守取值。工程实践里上下界设在误差的5%和95%分位数比最大最小值更稳因为最大最小值容易被极端离群点带偏。如果你的数据里确实有硬件故障导致的异常值建议先做清洗再估计参数。4.3 机组组合模型建模代码机组参数用结构体数组保存方便后面批量访问。10台机组24个时段每台机组定义容量、爬坡率、最小启停时间、成本系数。下面是我常用的机组参数定义方式% 定义机组参数 G 10; % 机组数量 T 24; % 调度时段数 gen.pmax [200; 180; 160; 150; 120; 100; 80; 80; 60; 40]; % 最大出力(MW) gen.pmin [80; 60; 50; 40; 30; 25; 20; 15; 10; 10]; % 最小出力(MW) gen.a [240; 210; 190; 170; 150; 130; 110; 90; 70; 50]; % 燃料成本常数项 gen.b [30; 28; 26; 24; 22; 20; 18; 16; 14; 12]; % 燃料成本一次项 gen.SU [100; 90; 80; 70; 60; 50; 40; 30; 20; 10]; % 启动成本 gen.RU [50; 45; 40; 35; 30; 25; 20; 15; 10; 10]; % 爬坡上限(MW/h)构建模型时第一阶段变量用binvar定义启停变量用sdpvar定义基点出力第二阶段变量用sdpvar定义线性决策规则的系数矩阵% 第一阶段变量 u binvar(G, T, full); % 启停状态 p sdpvar(G, T, full); % 基点出力 % 第二阶段线性决策规则系数 alpha sdpvar(G, T, full); % 出力调整对误差的线性系数 p_adjust alpha * xi; % 实际出力调整量xi是误差随机变量 % 约束装配 Constraints []; for t 1:T Constraints [Constraints, sum(p(:, t)) xi load(t)]; % 功率平衡 for g 1:G Constraints [Constraints, ... p(g, t) gen.pmin(g) * u(g, t), ... p(g, t) gen.pmax(g) * u(g, t), ... p(g, t) p_adjust(g, t) gen.pmin(g) * u(g, t), ... p(g, t) p_adjust(g, t) gen.pmax(g) * u(g, t)]; end end这里的xi不是具体的数而是代表不确定参数的符号对象YALMIP 会处理它。真正的分布鲁棒部分通过uncertain()函数和矩约束来描述这部分代码要单独处理不能直接写进上面这个循环里。4.4 求解器调用与参数设置模型装配完成后调用求解器。Gurobi 对这类大规模 MILP 表现很稳定但要设置一个合理的 MIP 间隙不然求解时间会很离谱% 设置求解器参数 ops sdpsettings(solver, gurobi, ... gurobi.mipgap, 1e-3, ... gurobi.timelimit, 3600, ... verbose, 2); % 求解 optimize(Constraints, Objective, ops); % 提取结果 u_star value(u); p_star value(p); alpha_star value(alpha);提示mipgap设到1e-3一般够用。工程上追求过小的间隙没有实际意义因为输入数据本身就带误差。我见过有同学为了一个0.01%的间隙跑通宵真没必要省下来的那点成本在误差面前可以忽略。5. 实操过程与关键环节复盘5.1 数据准备与处理首先说数据来源。我用的是公开的IEEE 30节点系统数据负荷曲线是典型夏季工作日曲线风电数据取自某个风电场的历史预测和实测出力记录。数据格式统一为15分钟一个点聚合成小时级后输入模型。数据处理有个容易踩的坑风电预测数据和实际数据的时间戳要对齐否则算出来的误差序列里全是错位数据。我拿到原始数据的第一件事就是检查时间戳对齐把缺失时段的处理逻辑前置。要么删掉要么用前后时刻插值千万不能用零填充零会破坏误差分布的形状。模糊集参数估计好之后我跑了一个验证把模糊集预测的误差分布和实际出力的经验分布画在一起对比确认均值、方差大致吻合。这一步虽然简单但能提早发现数据质量问题避免后面模型算出离谱结果才发现是数据错位。5.2 模型调优与方案对比模型建好后我对比了三种方案确定性模型把风电当成确定值、随机规划模型假设误差服从正态分布、分布鲁棒模型用本文方法。结果如下表方案总成本万元启停次数最坏场景失负荷MW确定性486.2845.7随机规划501.81021.3分布鲁棒518.6124.2确定性方案成本表面上看最低但真实运行遇到预测误差时失负荷风险最高。随机规划比确定性稍好但对极端情况的保护仍然不足。分布鲁棒方案成本只高出3%左右但最坏场景失负荷从45.7MW降到4.2MW这个代价换来的可靠性提升非常值得。启停次数变多是分布鲁棒方案的一个典型特征因为它需要在预测误差不确定的情况下保持更多的旋转备用自然会频繁调整部分小机组的启停状态。如果你的系统对频繁启停特别敏感可以在模型里加上启停次数惩罚项略微牺牲经济性换取运行平稳性。5.3 结果图表与解读Matlab画图部分我输出两个核心结果机组组合的Gantt图和24小时的出力构成堆叠图。Gantt图能直观看到哪些机组全天都开着哪些机组在高峰时段才启动这个信息对运行人员最有价值。出力构成图则展示每个时段风电、火电、以及备用调整的比例关系能验证功率平衡约束是否满足。还要额外画一张误差灵敏度曲线改变模糊集的协方差尺度观察总成本和失负荷风险的变化趋势。这张图一方面能证明模型的鲁棒性另一方面也能帮运行人员理解对风电不确定性有多保守带来的成本代价。6. 常见问题与排查技巧实录6.1 模型求解时间过长怎么办最常遇到的问题是求解器跑了几个小时都出不来结果。我的排查顺序是先看约束数量有没有爆炸性增长再看整数变量规模。10台机组24个时段的启停变量就有240个0-1变量加上时间耦合约束MIP的搜索树非常大。解决思路之一是做对称性削减。很多机组参数相近启停方案存在对称性Gurobi在搜索时会浪费大量时间在对称分支上。用gurobi.symmetry参数开启对称性检测或者手动加一些对称破缺约束比如按成本排序限制启动顺序能把求解时间缩短到原来的1/3。另一个实用技巧是先求一个可行解作为MIP的初始上界。用确定性模型的结果作为热启动解再喂给分布鲁棒模型Gurobi的MIP收敛会快很多。代码实现是用assign函数给变量赋初值再调用optimizeassign(u, u_deterministic_result); assign(p, p_deterministic_result); optimize(Constraints, Objective, ops);6.2 模型显示不可行模型不可行的原因十有八九在约束自相矛盾。最常见的两个坑一是第二阶段调整量同时受爬坡约束和机组出力范围约束在极端误差下可能找不出满足所有约束的调整量二是旋转备用需求和机组爬坡能力之间冲突高峰时段备用要求过严但机组根本爬不了那么快。排查方法是先用确定性模型跑一遍去掉不确定性相关约束确认基础约束是可行的。然后逐步加上模糊集约束每加一组就运行一次定位是哪组约束导致不可行。这一步虽然笨但非常有效。还可以用YALMIP的check函数逐个约束检查残差找到具体是哪条约束的上下界冲突。6.3 数值病态与求解精度问题分布鲁棒模型里面有大量协方差矩阵相关的约束矩阵条件数不好时求解器会报数值警告结果也不稳定。解决手段包括对变量做无量纲化处理把功率单位从MW换成p.u.基准功率让数值在一个数量级内对协方差矩阵做正则化加一个很小的单位矩阵倍数比如1e-6。还有一个很容易被忽视的点YALMIP底层要调用BLAS库做矩阵运算尽量不要让模型里出现几千阶的大矩阵直接参与运算。把约束拆分成小块循环虽然代码看起来啰嗦一点但数值稳定性会好很多。6.4 线性决策规则系数异常波动如果我画出 alpha 的曲线发现某些时段的系数值出现正负交替的剧烈波动这说明模型在利用线性规则过度拟合极端场景调度方案反而失去意义。此时需要在目标函数里加一个对 alpha 的惩罚项限制调整量的幅度让决策规则保持平滑。惩罚项系数我一般从1e-3开始试逐步增大直到 alpha 曲线变得平滑且总成本没有明显升高为止。这个技巧在实用中很有用能让调度方案在极端分布下更可操作而不是理论最优但现场无法执行。7. 最后再聊几句实操心得这套模型跑了几个算例之后我最大的体会是分布鲁棒优化不是把问题复杂化而是把工程里本来就存在的不确定性用一个可控的方式兜底。线性决策规则的引入让原本没法算的三层问题降到普通MILP的复杂度效果在实际数据上也很扎实。关键还是要对模糊集的参数选择上心它比模型本身更影响最终方案的质量。如果你准备复现这套代码我的建议是先跑一个2台机组、4时段的小算例把对偶转化的每一行代码都核对清楚确认结果和解析解一致再放大到完整规模。否则一上来就刷大规模算例出bug时你连原因都找不到。代码层面不要贪图快宁可矩阵拆细一点也要保证数值稳定。后续如果想把模型变得更实用可以考虑往里面加碳排放约束、储能系统、以及多风电场之间的相关性建模。风电不确定性这部分把时空相关性加进模糊集之后模型会复杂不少但更贴近真实系统的运行逻辑。这套框架的扩展性很强值得花时间深耕。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑