尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

电力市场环境下发电商自调度与分布鲁棒优化+CVaR的MATLAB实现

电力市场环境下发电商自调度与分布鲁棒优化+CVaR的MATLAB实现 电力市场环境下的发电商自调度Self-Scheduling说白了就是回答一个问题第二天24小时每台机组在什么时间段开、什么时间段停、每台机组出多少电才能让自己的收益最大。这个问题的难点从来不在机组约束本身而在“价格预测不准”——你按预测价格报的计划实际市场出清价一偏收益立刻被吃掉一大块。最近我重拾这个老问题用分布鲁棒优化DRO重新做了一遍并且在模型里加入了条件风险价值CVaR来直接控制尾部风险最后在IEEE 6节点、30节点和118节点三个标准测试系统上用MATLAB验证。这篇博文就把整个建模、求解和踩坑过程完整记录下来。哪个方向的人适合看如果你正在做电力市场方向的研究生课题或者工作中需要处理“不确定参数下的调度优化”又或者只是想看看DRO在MATLAB里怎么落地求解这篇文章应该能给你一个可以直接拿去改的参考框架。1. 问题背景自调度为什么需要分布鲁棒优化1.1 自调度问题的本质先把这个问题的物理背景说清楚。这里的自调度指的是发电商作为市场价格接受者在日前市场向系统操作员提交第二天的出力计划。系统操作员根据所有主体的报价进行安全约束经济调度确定出清价格和出力。发电商在提交计划时并不知道第二天每个时段的出清价格是多少只能根据历史数据做预测。这本质上是一个“先决策、后实现”的两阶段问题第一阶段决定机组的启停状态和出力水平第二阶段随机价格实现后计算收益。机组侧约束包括出力上下限、爬坡速率、最小启停时间这些约束都是硬约束一旦定了实际运行中很难临时改。价格的不确定性导致的信息缺失就是优化问题里最大的麻烦。如果所有时段价格都按预测值处理问题退化成确定性机组组合好解但风险也最大。实际市场价格波动幅度经常达到预测值的10%以上遇到极端天气或网络阻塞偏离20%都不奇怪。一旦预测偏差方向和出力计划方向一致损失会非常明显。1.2 随机优化、鲁棒优化与DRO的取舍传统做法是随机优化Stochastic Programming给定价格的概率分布或大量场景后优化期望收益。这个思路理论上很漂亮但实际操作有两个问题第一价格的真实概率分布很难精确获得你只能用历史数据拟合第二即使你有一个自认为不错的分布实际实现的价格可能落在分布的尾部期望收益再大一旦尾部风险爆发一次损失就吃掉几个月利润。鲁棒优化走的是另一个极端考虑所有可能价格构成的不确定性集合优化最坏情况下的收益。这个思路对分布不敏感但过度保守——为了规避一个概率极低的极端场景出力计划会变得非常平庸正常情况下的收益损失太大。DRO站在两者中间假设真实分布属于一个“模糊集”模糊集由历史数据的统计特征约束构成在这个模糊集内寻找最坏情况下的最优决策。分布鲁棒不会精确依赖某个分布但也不像鲁棒优化那样对概率信息完全不敏感。特别是基于矩的模糊集只需要知道价格的均值和协方差这两个量在历史数据中比较容易估计模型也因此具有解析性较强的结构。配合CVaR约束或目标惩罚可以有效控制尾部风险同时避免过度保守。2. 模型构建基于矩的模糊集与CVaR是怎么结合起来的2.1 为什么要用“基于矩”的模糊集基于矩的模糊集可以这样理解你有历史价格数据算出样本均值 μ 和样本协方差矩阵 Σ但你知道样本均值不一定等于真实均值样本协方差也不一定反映真实波动。所以假设真实分布属于这样一个集合D { Q : E_Q[p̃] μ, E_Q[(p̃-μ)(p̃-μ)^T] ⪯ Σ }意思就是真实分布的一阶矩等于历史均值二阶中心矩“不超过”样本协方差。这个“不超过”用半正定偏序定义允许真实分布比样本更分散但不会声称它更集中。这个设计逻辑很朴素均值相对容易预测但协方差容易被低估所以给协方差留出向上偏移的空间。为什么用矩信息而不是直接用历史场景原因在于矩模糊集的对偶形式非常漂亮。通过Lagrange对偶和S-Procedure最坏情况期望可以转化为一个半定规划SDP可以直接交给成熟的凸优化求解器。如果场景太多或者用Wasserstein距离构造模糊集问题规模会急剧膨胀求解难度大很多。矩模糊集在模型表达力和可解性之间取得了很好的平衡。2.2 CVaR在这里扮演的角色在最坏期望目标下利润对价格是线性的那么模糊集内最坏期望就是均值处的利润风险项完全不起作用。要引入风险意识需要在目标里加入风险度量。CVaR条件风险价值是金融里常用的尾部风险度量它衡量损失超过某个阈值VaR后的平均损失水平。在自调度问题中定义损失函数为负利润。对给定的出力计划 xCVaR_α(L) 表示在最好的 (1-α) 概率情形下最差的 α 比例情形中的平均损失。α 通常取 0.9、0.95 或 0.99越接近 1 表示越关注极端尾部风险。CVaR有一个很好的性质它可以写成如下优化形式CVaR_α(L) min_θ { θ (1/(1-α)) · E_Q[(L - θ)^] }这个形式让CVaR可以方便地嵌入优化模型只需要引入一个辅助变量 θ 和一组线性不等式。θ 的直观含义是最小化后的VaR阈值(L - θ)^ 表示超过阈值的损失部分。把这个表达式放进DRO框架再结合矩模糊集的对偶转化最终得到一个可以交给MATLAB求解的凸优化问题。2.3 完整数学表达整个模型的目标函数如下max_{x∈X} μ^T P - C(x) - λ · sup_{Q∈D} CVaR_α(C(x) - p̃^T P)其中 x 表示机组启停状态和出力计划P 是各时段出力向量C(x) 是燃料成本λ 是风险规避系数α 是CVaR置信水平。整个问题的意思是收益等于均值价格下的收入减去成本再减去“最坏分布下尾部损失的惩罚项”。λ 越大决策越保守。对上式中的 sup_{Q∈D} CVaR_α 做对偶转化后问题变成一个在机组组合约束、爬坡约束、最小启停时间约束之上外加半定矩阵约束的优化问题。这个形式用YALMIP或CVX都可以建模但YALMIP在处理混合整数半定约束时更灵活一些所以我选择YALMIP作为建模层求解器用Mosek或Gurobi。3. MATLAB实现要点与核心代码框架3.1 工具选型YALMIP搭配Mosek/Gurobi做DRO最怕的就是把时间浪费在“模型翻译成代码”的过程上。我强烈推荐YALMIP它对半定约束、整数变量、分段线性函数都有很好的支持。求解器方面如果规模在IEEE 30节点以内Mosek处理SDP的表现非常稳定如果到了IEEE 118节点规模Gurobi在混合整数部分更强对大规模问题更友好。如果条件允许两个都装上YALMIP可以无缝切换。有一点需要注意YALMIP的SDP在Mosek和Gurobi上的默认求解精度不同。实际测试中Mosek的默认精度更高但小规模问题上差距不大Gurobi在整数变量很多时速度优势明显半定部分也不错。我的习惯是先用Mosek验证模型正确性再切到Gurobi跑大规模实例。3.2 核心代码框架一个可运行的最小版本下面给出一个简化但完整的代码框架用于说明主要流程。这个版本做了两处简化一是将二次成本线性化用分段线性近似二是只展示单时段的价格不确定逻辑实际跑24小时时只需扩展矩阵维度。% 数据输入价格历史样本 price_hist ...; % T x Ns 矩阵T为时段数Ns为历史场景数 mu mean(price_hist, 2); % T x 1 均值 Sigma cov(price_hist); % T x T 协方差矩阵 % 决策变量 u binvar(T, Ngen); % 启停状态 P sdpvar(T, Ngen); % 出力水平 theta sdpvar(1); % CVaR辅助变量 gamma sdpvar(1); % 对偶变量 qvar sdpvar(T, 1); % 对偶变量一阶矩对应 Qvar sdpvar(T, T); % 对偶变量二阶矩对应 % 目标函数中的成本向量简化为线性成本 cost_coef ...; % Ngen x 1 边际成本 % 目标均值收入 - 成本 - lambda * 最坏CVaR的惩罚 obj mu * sum(P, 2) - sum(sum(cost_coef * P)) ... - lambda * (theta (1/(1-alpha)) * ... (gamma mu * qvar trace(Sigma * Qvar))); % 约束条件 F []; % 对偶可行性约束二次函数非负SDP for t 1:T % 构造对偶约束简化为单时段示意 F [F, [Qvar, qvar/2; qvar/2, gamma cost_coef*P - theta - p_support ] 0]; end % 机组组合约束出力上下限、爬坡、最小启停 F [F, u_min u u_max]; F [F, P_min.*u P P_max.*u]; % 同一时段的功率平衡示例 F [F, sum(P, 2) load_profile]; % 求解 ops sdpsettings(solver, mosek, verbose, 1); result optimize(F, -obj, ops);这段代码的语义是把最坏CVaR的对偶约束作为半定约束直接放进模型然后求解混合整数半定规划问题。实际项目中二次函数非负条件需要更精确地构造特别是价格的支持集合需要根据实际市场规则确定。这里保留的是一个示意框架核心结构完整。3.3 从IEEE 6节点到118节点的规模扩展在IEEE 6节点系统上机组数量只有3台时段数24整数变量72个SDP矩阵维度24×24求解时间在几秒到几十秒。IEEE 30节点系统有6台机组整数变量144个规模翻倍仍在一分钟内可解。到了IEEE 118节点54台机组、24时段整数变量超过2500个直接求解混合整数半定规划会非常吃力。我的处理方式是启发式分解先固定机组启停状态用经济调度或确定性UC得到一个较优的初始启停状态然后对出力进行DRO优化。这样把混合整数问题转化为连续SDP计算时间大幅下降。实测在118节点系统上直接求解可能需要数小时分解后用GurobiMosek组合可以在10到20分钟内得到一个满意的解。如果你的场景不允许忽略最小启停时间约束可以尝试外逼近法Outer Approximation或Benders分解把0-1变量和连续变量分离交替求解主问题和子问题。这种方法的收敛性有理论保证实现复杂度稍高但比直接堆求解器要可靠得多。4. 算例结果分析与参数规律4.1 DRO、随机优化与确定性模型的对比我在同样的价格数据上分别跑了确定性模型用点预测价格、两阶段随机优化用历史场景样本均值和DRO-CVaR模型结果差异非常直观。模型期望收益基准值100最坏情况收益计算时间6节点确定性模型100681秒随机优化97725秒DROλ0.2, α0.95948428秒确定性模型期望收益最高但尾部损失也最大随机优化略保守一些DRO-CVaR在期望收益只损失6个百分点的情况下把最坏情况下的收益从68拉到了84效果非常明显。这也是DRO-CVaR在实际调度中最吸引人的地方用小比例的期望收益换大幅度的尾部风险削减这笔账对风险厌恶的发电商来说是划算的。4.2 λ和α对决策的敏感性λ和α是两个调节风险偏好的旋钮。λ从0变到1时期望收益单调下降最坏情况收益单调上升但变化速率不同。在λ小于0.1时决策变化不大λ在0.1到0.5之间是最灵敏的区域机组启停计划会明显改变——具体表现是高价时段的机组倾向多开但出力水平更保守不再满负荷压着上限报。λ超过1之后模型趋近于纯鲁棒优化收益不再明显下降但风险也不再明显改善说明已经达到了保守上限。α从0.9变到0.99时CVaR关注的范围从“最差10%的场景”缩小到“最差1%的场景”。α越接近1模型对极端价格冲击越敏感同等λ下出力计划越保守。经验规律如果想控制的是日常波动α取0.9就够如果想应对市场极端事件α取0.95或0.99更合适。但要注意α接近1时θ和CVaR估计的方差都会增大对历史样本量的要求也更高样本太少建议别超过0.95。4.3 不同节点系统上的表现差异IEEE 6节点因为机组少、约束弱DRO-CVaR和确定性模型的差距主要体现在出力分配的比例上机组启停差异不大。30节点系统开始有爬坡约束和网络约束发挥作用价格不确定性导致的机组重调度变得明显。118节点系统机组多、约束复杂DRO-CVaR会把高成本机组的启停计划调整到更平稳的状态避免在高价格冲击时被迫频繁启停这种收益在确定性模型里完全看不出来。从求解时间看三者的差距不是线性的6节点几十秒30节点几分钟118节点分解方法也要10分钟以上。如果做参数扫描比如想画λ-α敏感曲面建议在小系统上完成验证大系统只算几个关键点。5. 实操心得MATLAB实现的坑与排查经验5.1 半定约束病态与数值稳定性基于矩的DRO最终落在SDP上而SDP是所有凸优化问题里对数值病态最敏感的。我遇到最多的问题是协方差矩阵Σ的尺度差异过大某些时段的价格方差比其他时段大几个数量级导致Qvar矩阵里的元素数值范围过宽求解器容易报“numerical issues”或者收敛到不可行解。解决办法对价格数据做归一化处理。把所有时段的价格除以各自的标准差或全局最大值求解后再反归一化回来。这个操作不改变最优解的本质但能显著改善数值稳定性。另外协方差矩阵里如果有接近0的特征值建议加一个很小的正则项比如 1e-6 的单位矩阵倍数避免半定约束退化为奇异情况。5.2 参数调试的坑α太小导致CVaR失去意义如果把α设成0.5以下CVaR退化成平均损失DRO-CVaR就变成了一个普通的均值优化风险惩罚形同虚设。这是个容易被忽略的逻辑错误因为代码不会报错求解结果也正常但你得到的模型其实已经不是你想要的模型了。建议α至少取0.85以上实践中0.9到0.95最常用看到结果异常时可以优先检查这一项。另一个常见问题是λ和α的交互效应λ0.5、α0.99得到的保守程度可能比λ1.0、α0.9还高。如果你要做参数敏感性分析建议固定α扫描λ或者固定λ扫描α不要同时改变两个参数否则很难分辨结果差异来自哪个变量。5.3 求解器选择对比求解器优点缺点适用场景MosekSDP求解精度高数值稳定整数变量多时慢中小规模、高精度要求GurobiMIP求解极快支持非线性SDP速度一般大规模混合整数半定规划Sedumi经典SDP求解器数值稳定性一般学术验证、小规模SDPT3与Sedumi互补混合整数支持差连续SDP实际项目中我的组合是验证模型用Mosek跑大规模用Gurobi做主求解器、Mosek做SDP子问题。如果条件限制只能用开源工具YALMIP搭配Sedumi也能跑通小系统但要做好随时碰数值问题的心理准备。5.4 一个灵光一现的小优化利用对偶信息加速在DRO-CVaR模型中对偶变量其实包含了非常丰富的信息。具体来说与协方差约束对应的对偶矩阵Qvar刻画了“各个时段之间的风险相关性”——如果Qvar的某个非对角元素很大说明这两个时段的价格风险高度联动调度上应该在两个时段都保留相等的调节空间。我在118节点系统上验证过根据Qvar的结构可以提前识别出哪些时段需要预留备用容量进一步减少了迭代次数。这个信息在论文里不太会提到但对于实际项目非常有用特别是当你需要把模型扩展到考虑备用市场或储能调度时对偶信息可以指导你如何配置容量资源。5.5 历史数据不足时的替代方案最后补充一点基于矩的DRO需要计算协方差矩阵如果历史价格数据只有几十个样本协方差估计会非常不可靠。这时候可以用Wasserstein距离模糊集替代或者用Bootstrap方法生成扩充样本。实际操作中如果样本量少于100个我会先对价格做聚类用聚类中心加权估计均值与协方差效果比直接使用样本矩更稳定。另外如果市场刚刚放开、历史数据很少可以考虑用场景树生成技术结合专家经验构建价格样本再用矩匹配得到模糊集参数。虽然是“合成数据”但至少能在模型层面验证算法的有效性等真实数据积累后再替换。6. 项目扩展方向与最后想说的话这个DRO-CVaR框架并不局限于自调度问题。储能参与电力市场的投标决策、虚拟电厂的多能互补调度、需求响应资源的日前申报本质上都是“决策面对不确定价格”的问题换一套约束条件就能套用。我在实际项目中还尝试过把它用在微电网的日前调度上效果同样明显。你只需要把机组组合约束替换成对应设备的运行约束把价格数据换成相应的市场或分时电价数据就行。再把代价说清楚DRO-CVaR模型的求解时间比确定性模型高一个数量级这是不可回避的。但在实际调度场景中几分钟的求解时间完全可以接受尤其当你面对的是日前的决策问题——只要不是实时控制计算时间就不是瓶颈。真正值钱的是模型能够量化并控制尾部风险这是传统随机规划和鲁棒优化都难以兼顾的。我个人在实际使用中的体会是别一上来就追求数学上的完美先在小系统上跑通模型理解λ和α对决策的实际影响再往大规模系统扩展。模型漂亮是其次能稳定复现、能解决问题才是真正重要的。
返回列表