ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

电力市场自调度中基于分布鲁棒优化与CVaR的建模和MATLAB实现

电力市场自调度中基于分布鲁棒优化与CVaR的建模和MATLAB实现 做电力市场优化的同行应该都有这种体验你辛辛苦苦把机组约束、网络约束、投标策略都建好模最后发现最不可控的变量是明天的电价。它不给你面子负荷预测偏了它涨新能源大发它跌某条通道检修它直接飙升。最近我把一组分布鲁棒优化DRO模型在IEEE 6、30、118节点系统上完整跑了一遍模型用基于矩的模糊集去刻画电价不确定性并在目标函数里揉入了条件风险价值CVaR用来处理发电商自调度问题。这篇博文把整个建模思路、对偶推导、MATLAB实现细节和踩坑记录一次性讲清楚适合正在做电力市场优化、风险评估或者刚入行想搞懂DRO到底怎么落地的人。1. 为什么自调度问题绕不开价格不确定性这道坎1.1 自调度在电力市场里到底解决什么问题在现货市场环境下发电商需要在日前市场申报第二天的发电曲线系统出清后按市场价结算。所谓自调度就是发电商在给定自身机组物理特性的前提下决定各时段启停和出力使期望收益最大。注意这和经济调度有本质区别调度中心关心的是全系统社会福利发电商关心的只是自己的利润。如果电价是确定常数这就是个混合整数线性规划任何一个商业求解器都能秒解。但现实是电价本身就是随机变量而且它的分布你并不清楚。尤其在新能源渗透率高的系统里价格尖峰、负电价、爬坡段飙价已经成为常态。你提前一天的报价决策可能在一个极端价格场景下就把整个月的利润亏回去。1.2 确定性、随机规划和纯鲁棒优化为什么都不够确定性方法最简单用点预测电价去优化算完再做个敏感分析。问题也很明显点预测误差是必然存在的而自调度问题的收益函数对价格非常敏感一旦实际价格偏离预测要么少赚要么亏损某些极端场景下连启动成本都收不回来。随机规划把电价建模成已知概率的场景树然后求期望利润最大化。思路没问题但有一个致命前提——你必须知道真实分布。现实里你只有历史样本没有那个“真实分布”。如果你假设正态分布而真实电价是重尾分布解出来的方案在真实环境下反而很差这就是分布误差带来的“不合意最优”。纯鲁棒优化走向另一个极端把所有可能的价格都装进一个不确定集合在集合内最坏情形下做决策。好处是很安全代价是过度保守。为了应对1%概率的极端尖峰模型可能让机组在平时也压低出力导致期望收益被砍掉一大截。DRO站在中间我只知道电价分布的均值、协方差这些矩信息真实分布在满足这些矩条件的集合里我就在集合中找最坏情况求最优。它比随机规划抗分布误差又不像鲁棒优化那样把极端场景和常规场景一视同仁。这就是“分布鲁棒”四个字的来历。方法分布假设对极端场景的态度主要代价确定性点预测无保护风险暴露大随机规划已知分布场景按概率加权分布误差导致结果偏优鲁棒优化无全部按最坏情况过度保守收益损耗大DRO-CVaR矩信息对尾部损失按CVaR惩罚求解复杂度上升2. 基于矩的模糊集用均值和协方差把真实分布圈起来2.1 模糊集的数学定义和直觉DRO的核心是模糊集ambiguity set。基于矩的模糊集长这样[ \mathcal{D} \left{ P \in \mathcal{P}(\Xi):\ \mathbb{E}_P[\xi]\mu,\ \mathbb{E}_P[(\xi-\mu)(\xi-\mu)^\top] \preceq \Sigma,\ P(\xi \in \Xi)1 \right} ]这里的 (\xi) 是整个决策周期T个时段的价格向量(\mu) 和 (\Sigma) 从历史样本估计(\Xi) 是价格支持集。协方差用“(\preceq)矩阵半正定意义下的小于”而不是“”意思是只要真实分布的协方差不超过这个矩阵上界就算合格这样做可以把矩估计误差和分布不确定同时包进去。信息量稍微松一点换来的是模型对“分布到底是什么样”不再那么敏感。直觉上可以这么理解你站在市场外面看不清明天电价到底怎么分布但你能统计出过去几百天的均价和波动范围。真实分布虽然未知但总不能偏离这些统计量太远。模糊集就是把所有“统计上和历史数据一致”的分布都圈进来再求一个最坏情况下的方案。只要真实分布确实在这个圈里你的决策就不会翻车。2.2 为什么矩信息是工程上最划算的假设矩信息是所有分布信息里最容易从历史数据里获得的。电价的均值、协方差有明确的工程意义——均价决定基准收益方差刻画波动程度。而高阶矩偏度、峰度估计对样本量非常敏感看着一天的8760个小时数据很多但分时段、分季节之后每个场景的样本数根本不够偏度估计出来噪声很大加了反而坏事。和Wasserstein距离模糊集相比基于矩的集合对偶后结构清晰可以直接提炼成半定约束。Wasserstein模糊集在小样本数据驱动场景下确实更灵活但对偶里会出现带运输项的结构和机组组合这种混合整数模型纠缠在一起时商业求解器很难直接啃下来。实操中我不建议一上来就上Wasserstein先把基于矩的模型跑通、跑稳再根据数据量决定要不要换更精细的模糊集。2.3 矩估计的三个注意点第一用滚动窗口估计不要用全部历史平均。电力市场有明显的季节性和周内结构全历史均值会把夏天和冬天的价差糊在一起均值估计没有代表性。我习惯用过去30到60天、分时段的滑动窗口再叠加一个简单的季节调整项。第二分时段估计。市场电价下午高峰段的方差和凌晨低谷段完全不是一个量级。如果用一个全局协方差矩阵去描述高峰段的风险会被低估低谷段又被高估。分时段处理后协方差矩阵会出现明显的“分段对角”结构这正好和机组运行特性对应。第三协方差矩阵维度和决策时段数相同(T \times T)当T24甚至168时样本协方差很容易病态。后面求解部分我会详细讲正则化处理这里先提个醒别拿到样本就直接算协方差往模型里塞。3. CVaR在DRO框架里的两种嵌法惩罚目标还是风险约束3.1 CVaR和VaR的本质区别很多资料讲CVaR喜欢直接上公式[ \mathrm{CVaR}\alpha(L) \min{\beta} \left{ \beta \frac{1}{1-\alpha} \mathbb{E}[(L-\beta)_] \right} ]其中 ((L-\beta)_ \max{L-\beta, 0})。这个公式被学术界用烂了但工程上真正重要的是它和VaR的区别。VaR说的是“有(\alpha)的概率损失不超过某个值”超过之后怎么分布它完全不关心CVaR说的是“最差那 (1-\alpha) 概率情景下的平均损失”。前者管不住尾部后者直接把尾部期望管住了。对发电商来说CVaR的工程含义非常直观你做了一百次市场仿真把最差的五次结果拿出来平均看平均亏多少钱。把这个值限制住就相当于管住了“黑天鹅”情景下的平均表现。而且CVaR满足次可加性是凸的做优化时能保持问题的可解性——这一点对DRO模型尤其重要因为凸性意味着你可以放心地做对偶变换。3.2 目标函数嵌入和约束嵌入CVaR进入自调度模型有两种常见方式。方式一是均值-CVaR目标[ \max_{x \in X} \ \mathbb{E}[\mathrm{Profit}] - \lambda \cdot \mathrm{CVaR}_\alpha(-\mathrm{Profit}) ](\lambda) 是风险权重越大越保守(\lambda0) 时退化为纯期望利润最大化。方式二是CVaR硬约束[ \max \ \mathbb{E}[\mathrm{Profit}] \quad \text{s.t.} \quad \mathrm{CVaR}\alpha(\mathrm{Loss}) \le V{\text{th}} ]方式一容易调节风险偏好风险权重连续变化可以直接画出“利润—风险前沿”方式二适合企业有明确风险限额的场合。两种方式在DRO下都会形成“最坏分布下的CVaR”但数学结构不同实现难度也不同。我在项目里优先用方式一因为风险前沿曲线对管理层解释模型最直观。3.3 DRO与CVaR叠加出的双层结构在DRO里你已经对真实分布取了外层的最坏情况 (\sup_{P \in \mathcal{D}})CVaR内部又有一个期望算子。所以DRO-CVaR模型实际上是一个双层最坏结构[ \sup_{P \in \mathcal{D}} \ \mathbb{E}P \left[ \mathrm{CVaR}\alpha(-\mathrm{Profit}(x,\xi)) \right] ]这里不能简单地把CVaR样本平均再求最坏因为内层CVaR的最优点 (\beta) 也依赖于分布P。需要在模糊集内部同时优化β和期望这就涉及下一节的minimax交换和对偶化。很多人卡在这一步以为用YALMIP定义一个CVaR就能和DRO直接拼接实际上要先把内层LP结构写出来再做整体对偶。4. 完整模型怎么落地从双层最坏情形到半定规划4.1 机组组合约束不能只写出力上下限自调度模型的决策变量包括机组启停状态 (u_{i,t})、出力 (p_{i,t})以及启动/停机状态变量。约束除了出力上下限还有最小启停时间、爬坡约束、合同电量平衡等。这部分是标准MILP细节不展开但提醒几个容易错的地方启动成本要区分热启动和冷启动否则检修后的机组启动成本会被严重低估爬坡约束要同时写“上一时段到本时段”和“本时段到下一时段”两个方向最小启停时间约束如果写成一连串递推式会引入大量二进制变量建议用文献里经典的紧凑不等式避免重复建模。如果你在118节点上还打算加网络约束那就不是简单的自调度了而是考虑节点电价的博弈问题模型复杂度会指数级上升。这篇项目里默认机组报价和售电量在单节点聚合网络约束留作扩展方向。4.2 目标函数确定性收益减去最坏CVaR把收益拆成确定性部分和随机部分。确定性部分包括燃料成本、启停成本、固定合同收入随机部分主要是现货市场收益它和电价向量 (\xi) 线性相关。目标函数写成[ \max_{x \in X, \beta, z} \quad \text{确定项}(x) - \kappa \cdot V(x) ]其中[ V(x) \sup_{P \in \mathcal{D}} \mathbb{E}P \left[ \min{\beta} \left( \beta \frac{1}{1-\alpha} \mathbb{E}P[(-\mathrm{Profit}(x,\xi) - \beta)] \right) \right] ](\kappa) 就是前面的风险权重(\lambda)这里用(\kappa)是想强调它和CVaR内部(\beta)无关。4.3 对偶化之后为什么变成半定规划把CVaR的LP形式展开外层 (\sup) 对模糊集 (\mathcal{D}) 取拉格朗日对偶minimax交换条件在Slater条件下成立最后会得到一个关于不确定变量(\xi)的二次齐次表达式。这个表达式要求对任意(\xi \in \Xi)都成立等价于一个线性矩阵不等式LMI。最终整个模型变成MISDP混合整数半定规划或者在某些简化场景下退化为MISOCP / MIQP。对偶后的目标函数会出现类似这样的项[ \tau \mu^\top \theta \langle \Sigma, Y \rangle ]其中(\tau, \theta, Y)是对偶变量(Y)是(T \times T)半定矩阵变量(\langle \Sigma, Y \rangle \mathrm{trace}(\Sigma Y))。这个结构是“基于矩”这个选择带来的最大红利换成Wasserstein模糊集这里不会出现整齐的半定项求解器拿它没办法。4.4 求解策略整体求解还是BendersMISDP直接丢给商业求解器是不现实的。Gurobi能解混合整数线性/二次但SDP约束需要MOSEK这类锥规划求解器两者耦合起来很难处理。我实际的做法分两档6节点系统规模小直接用YALMIP把对偶后的SDP约束和机组组合一起建模用MOSEK解根节点再用割平面枚举处理二进制变量整体求解没问题。30节点开始我会固定机组组合后把DRO-CVaR子问题交给MOSEK外层用枚举或者简单的启发式遍历启停组合虽然不保证全局最优但工程上足够。118节点必须上Benders分解或者外逼近主问题是机组组合MILP子问题是给定启停方案下的DRO-CVaR评估SDP子问题返回最坏情形的收益和次梯度作为割不断迭代。这条路我跑通之后118节点168时段的场景下单次迭代SDP大约几十秒总求解时间在几十分钟量级算可以接受。别指望一行YALMIP代码把MISDP整体丢给求解器——内存会先爆炸。5. MATLAB实现路线6节点调通、30节点调参、118节点验规模5.1 三个测试系统的分工IEEE 6节点系统机组少、节点少适合把每个环节跑通和确定性模型逐项对账验证DRO-CVaR代码有没有bug。30节点是标准测试系统机组数和约束复杂度适中做灵敏度分析最方便论文里的“利润—风险前沿”多数是在这个规模上画的。118节点是公认的中大型测试系统机组几十台约束上千用来验证算法在真实规模下的可扩展性。建议严格按这个顺序来不要一上来就跑118SDP和机组组合耦合在一起调试难度会叠加到让人怀疑人生。5.2 环境、求解器和代码结构我的环境是MATLAB R2022b YALMIP Gurobi MOSEK。YALMIP负责建模Gurobi解混合整数部分MOSEK解SDP。只是6节点的话也可以用YALMIP的CUTSDP把SDP割成线性约束交给Gurobi但30节点以上别这么玩割平面层数太多计算量反而失控。项目文件建议按模块分目录data/放IEEE系统参数、价格样本、机组参数models/放四个模型确定性、SP、RO、DRO-CVaRresults/放输出表格和调度曲线utils/放矩估计、协方差正则化、结果后处理函数这样换一个IEEE系统时只需要替换data目录下的数据文件模型代码一行不用改。5.3 核心代码骨架矩估计和协方差正则化% price_samples: T x M 矩阵T个时段M个历史样本 mu mean(price_samples, 2); Sigma cov(price_samples); % 正则化防止协方差矩阵病态 % 1e-4 是经验值数据噪声大时放到 1e-2 Sigma Sigma 1e-4 * diag(diag(Sigma));DRO-CVaR对偶后的YALMIP骨架p sdpvar(T,1); % 机组出力 u binvar(T,1); % 启停状态 beta sdpvar(1,1); % CVaR辅助变量 % 对偶变量 tau sdpvar(1,1); theta sdpvar(T,1); Y sdpvar(T,T,symmetric); % 半定约束和线性约束 Constraints [Y 0, ...]; % 补充线性矩阵不等式的具体项 Constraints [Constraints, ...]; % 机组约束 % 最坏情形CVaR上界手推对偶后得到 worst_cvar tau mu*theta trace(Sigma*Y); % 目标确定性利润 - kappa * 最坏CVaR Objective base_profit - kappa * worst_cvar;注意上面的theta和Y不是随便定义的它们来自对偶推导每一项都必须和原问题的约束一一对应。我建议不要依赖YALMIP的自动对偶手推一遍对偶表达式再写代码否则出错了根本不知道错在哪。求解器配置ops sdpsettings(solver,gurobi,gurobi.MIPGap,0.01,... verbose,2); ops_sdp sdpsettings(solver,mosek,... mosek.SDP.MSK_DPAR_INTPNT_TOL_PFEAS,1e-6);118节点用Benders分解时主问题用Gurobi子问题用MOSEK两个求解器之间通过割传递信息每次迭代都重新构造YALMIP模型不要尝试在同一个模型里同时调两个求解器。5.4 没有真实电价数据时怎么生成样本没有现成现货价格数据时可以用时间序列模型生成样本。我的简单做法ARIMA拟合日内价格趋势GARCH描述波动率聚集再叠加一个尖峰分布做蒙特卡洛抽样。核心目的是让样本具备电价该有的自相关和重尾特征而不是做精确预测。如果样本量太少比如只有20个μ和Σ估计方差很大DRO结果会偏保守。一个处理办法是给矩约束加松弛变量让模糊集自动放大另一个更省事的办法是干脆采集更长时间窗口把样本拉到200个以上。样本充足时基于矩的DRO几乎不会出现“保守到没用的局面”。6. 结果对比与灵敏度风险偏好如何改写机组组合6.1 四种模型在三个节点系统上的结果对比以一台燃煤机组加一台燃气机组为自调度主体基于模拟价格样本对比四个模型的核心指标。数值是相对值但趋势在三个节点系统上完全一致模型期望利润相对值最差5%场景平均利润相对值极端场景亏损概率求解时间确定性100-35高秒级随机规划96-12中秒到分钟鲁棒优化728低分钟级DRO-CVaR91-2低6节点秒级118节点需分解DRO-CVaR牺牲了约9%的期望利润换来的是和鲁棒优化接近的最坏情形保障代价远低于纯鲁棒优化28%的利润牺牲。这个“中间地带”正是DRO的核心价值。在118节点系统上求解时间差异更明显确定性模型秒出DRO-CVaR需要Benders迭代但结果回报是值得的。6.2 风险权重和置信水平的灵敏度把风险权重 (\kappa) 从0慢慢拉到1期望利润单调下降CVaR单调改善。有趣的是调度计划会发生结构性变化(\kappa) 较小时燃气机组在价格高峰时段满发追逐尖峰收益
返回列表