ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

虚拟电厂日前调度:源荷双重不确定性的随机优化策略实战

虚拟电厂日前调度:源荷双重不确定性的随机优化策略实战

做 VPP 虚拟电厂日前调度的人,基本都被同一个问题折磨过:光伏出力今天和明天完全是两个脾气,负荷侧更是一会儿一个样。你拿着一份预测曲线去做确定性调度,遇到晴天少云的中午,可能大量弃光;遇到突然阴雨,又得高价从电网补电。这份项目标题里提到的“源荷双重不确定性”随机优化调度策略,其实就是把这两种不确定性的“脾气”一起放进模型里量化,用蒙特卡洛模拟生成海量可能场景,再配合场景削减技术提取典型场景,最后求解出兼顾经济性和可靠性的日前计划。这篇文章我想把我们实际搭建这套策略的过程完整拆一遍,适合正在做虚拟电厂、微电网日前调度、想从确定性优化转向随机优化的朋友参考,不管你是刚接触场景法还是已经有点基础,照着这个思路复现都不会太痛苦。

1. 项目拆解:源荷双重不确定性到底难在哪里

1.1 先想清楚:虚拟电厂日前调度到底要干什么

虚拟电厂不是单个电厂,它是把分散的屋顶光伏、储能、可控负荷、甚至柴油机组聚合成一个整体参与电网互动的协调系统。日前调度的核心任务很简单:在当天下午或晚上,根据第二天的预测信息,决定未来 24 个小时里每一时刻的买卖电计划、储能充放电计划、柴油机启停和出力曲线。调度目标通常是园区型或运营商型 VPP 的成本最小化——尽量多用廉价的分布式光伏,少从电网买高价电,储能则在低价时段充电、高价时段放电来赚价差。

但问题在于,这种计划是提前一天做的,第二天光伏到底发多少、负荷到底涨跌多少,谁都说不准。传统的做法是把预测值当成真值塞进模型里,求一组唯一的调度方案。这在历史数据稳定、天气不太恶劣的场景下勉强能用,但只要哪天光伏预测误差超过 20%,结果就可能让储能在一整天里做了错误决策,该充的时候没充满,该放的时候全放光了,最终经济性差一大截,甚至出现功率越限这类安全问题。

所以这个项目里要做的,不是“预测得更准”,而是“在预测不准的前提下,仍然能做出一个不会出大错、且期望成本足够低的调度计划”。这正是随机优化解决的问题,也是标题里“随机优化调度策略”这六个字存在的意义。

1.2 为什么双重不确定性不能简单叠加处理

源侧不确定性主要指光伏出力的随机波动,受光照、云层遮挡、温度影响;荷侧不确定性指负荷曲线与预测值的偏差,涉及用户行为习惯、温度敏感性设备启停等因素。很多人第一反应是:我不把两种不确定性一起建模,而是分别留足备用不就行了吗?听起来合理,实际做起来问题很大。

两个随机变量叠加,不代表它们的方差相加就完事了。光伏出力和负荷在某些时段存在关联,比如中午光伏大发的时刻往往也是空调负荷爬升的时刻,傍晚光伏骤降的时刻负荷可能还在高位。如果只按最坏情况保守叠加,会导致备用容量过度配置,储能的大幅充电在凌晨、大幅放电在傍晚,经济性全面恶化;如果完全忽略相关性,又可能在某些场景下出现调节能力不足。

随机优化场景法的好处在于,它把所有可能的组合情况都“枚举”出来了:光伏高、负荷低是一种场景;光伏高、负荷高是另一种;光伏低、负荷高又是一种。每一个场景都有自己的发生概率,模型在期望值意义上做决策。这样就不需要人为去定义“最坏情况有多坏”,而是让概率说话。双重不确定性在这套框架里不是两个孤立的误差项,而是一个多维联合分布的采样问题。

1.3 方案选型:随机优化、鲁棒优化还是区间优化

做日前调度时,针对不确定性问题的建模方法主要有三条路线:鲁棒优化、区间优化、随机优化。我在项目初期把这三种方法都对比过,心里很清楚它们的边界。

鲁棒优化的思路是假设不确定性落在某个集合内,求最坏场景下仍然可行的方案。好处是方案非常安全,但代价是成本偏高,因为真实场景中那种所有条件同时恶劣到极致的情况几乎不会发生,你等于每天都在为小概率灾难买单。区间优化更简单,给每个变量一个上下界,求解时保证任意取值都在区间内可行,但同样存在过度保守的问题,而且区间模型往往丢失了概率信息,无法比较哪个方案在经济性上更优。

随机优化则是把不确定性用场景的概率分布来描述,目标函数是所有场景下的期望成本,约束条件是每个场景下都要满足功率平衡和运行上下限。它在经济性和鲁棒性之间取得了一个合理的折中。你可以通过控制场景数量和削减水平来调节保守程度,比鲁棒优化更细腻。

方法对不确定性的处理结果倾向计算复杂度适用场景
确定性优化用单一预测值经济性最好,风险最高低数据波动小、短时间尺度
鲁棒优化不确定集合安全性优先,成本偏高中极端天气、安全要求极高
区间优化上下界约束保守折中中低无概率数据的初步评估
随机优化概率场景集合期望成本最优高光伏/负荷随机性明显的VPP

最终我选的是随机优化路线,原因很简单:虚拟电厂的调度问题有大量历史数据可以拟合分布,场景法能把概率信息充分利用起来;同时商用求解器成熟的今天,哪怕生成几百个场景的混合整数规划问题也能在合理时间内解完。这个项目标题里强调了“蒙特卡洛模拟”和“快...”(大概率说的是场景削减),正好对应了随机优化最核心的两个技术步骤。

2. 场景生成与削减:蒙特卡洛只是第一步

2.1 光伏出力建模:不能只靠随手画几条正弦曲线

光伏出力的随机性根源是太阳辐照度。在实际数据拟合时,我发现直接用正态分布描述辐照度效果很一般,因为光照强度在晴天和阴天呈现明显的双峰特性。更常用的是 Beta 分布拟合每个时段的光照强度,然后根据光伏板的物理模型折算成出力。

辐照度转换为光伏出力的公式我建议直接用工程上通用的简化模型:发电量与辐照度近似线性,但需要考虑温度修正和环境效率。实际操作中我的做法是,拉出过去一年的光伏出力历史数据,按天气类型分档,然后针对每个时段用 Beta 分布拟合,再用转换公式反向生成出力序列。这样生成的场景和真实数据的分布特性很接近,不会出现那种“理论模型很漂亮、实际场景对不上”的尴尬。

如果历史测光数据不足,也可以用正太分布加偏差校正的方式快速生成初始场景集,但误差会偏大,最终通过场景削减筛选出来的典型场景可能仍然覆盖不到真实运行边界。所以在项目里我通常将历史数据分季节、分天气类型处理,宁可多花一点时间做数据清洗和分布检验,也不要省这一步功夫。

2.2 负荷侧不确定性建模:它的“随机”比光伏更难缠

负荷预测误差的分布并不是简单的高斯白噪声,它有时间自相关性,而且不同时段误差的方差差别很大。中午和傍晚负荷波动大,凌晨负荷平稳、误差很小。如果我们把负荷误差建模为恒定的正态分布,误差会严重偏离真实情况。

我采用的是“基础负荷曲线 + 误差叠加”的方式:先用历史数据做典型日负荷曲线,然后对每个时段分别拟合误差分布,误差项用一阶自回归模型(AR(1))来引入时间关联性,避免出现相邻时段误差完全独立的突兀现象。在场景生成时,AR 模型的随机项再用蒙特卡洛抽样。

这一步的细节很影响最终调度质量。自制一个简单的 AR(1):令负荷预测残差满足 e(t+1)=φ·e(t)+ε(t),其中 φ 是自回归系数,ε 是抽样噪声。这样生成出来的负荷场景在时间轴上看起来是平滑延续的,不会出现那种“8:00 还是低谷、9:00 突然跳变到峰值”的失真场景。

2.3 蒙特卡洛模拟怎么用在场景生成上

理解了分布模型之后,蒙特卡洛模拟其实就是个规模扩大的抽样问题。具体流程是:对每个时段抽样一批光伏辐照度随机数和负荷误差随机数,然后将它们装配成一条完整的日运行曲线,重复几千次,得到几千个可能的今日或明日场景。

在实际采样时,要特别注意光伏与负荷之间的相关性处理。如果光伏采样和负荷采样完全独立,生成的场景会出现“晴天+负荷极低”“阴天+负荷极高”这类不太协调的组合,放大不必要的工况。我用的是从历史样本计算光伏与负荷的相关系数矩阵,再通过 Cholesky 分解生成相关的正态样本,最后映射回 Beta 和 AR 模型,这样场景内的源荷组合更贴近真实耦合关系。

同样类型的操作也可以直接用拉丁超立方采样替代纯随机抽样。拉丁超立方比普通蒙特卡洛抽样的分层特性更好,能用较小样本量覆盖整个分布区间,对后续削减和求解都友好。如果项目规模不大,我建议直接上拉丁超立方,效果稳定又不容易踩坑。

2.4 场景削减:为什么不能直接留上万个场景

蒙特卡洛生成的场景集通常有几千甚至上万条曲线,直接丢进优化模型求解会面临严重的计算负担,因为每个场景都对应一套约束条件,场景数量直接影响模型规模。这个项目标题里后半段很可能就是在讲“快速场景削减”——用聚类或后向削减算法,把大规模场景集浓缩成几十个代表性场景,同时保留主要概率特征。

我实际用的算法是两步:先用 K-means 或改进的 K-medoids 对场景集做粗聚类,然后用后向削减策略从每个聚类中挑出最能代表该簇中心形状和离差范围的场景,最后把这类簇内场景数量占比设为该代表场景的概率权重。这样原始场景集的期望值特性几乎不会损失,但模型求解速度能提升一个数量级。

场景削减的质量检验很简单:比较削减前后场景集的均值曲线和方差曲线。均值曲线差得越小,说明代表性场景越能还原整体期望行为;方差曲线保持越完整,说明尾部场景没有被抹掉。我通常要求削减前后的均值偏差控制在 3% 以内,置信区间形状基本重合,这样随机优化的结果才有说服力。

3. 随机优化调度模型怎么搭才完整

3.1 两阶段决策框架:哪些决策要提前定,哪些要等场景实现

随机优化里的两阶段框架是理解整个模型的核心。第一阶段决策在场景实现之前就要确定,也就是日前计划部分:向电网购售电的功率曲线、储能的充放电计划、柴油机的启停状态,这些必须在每天开始前就定好,因为交易合同、设备启停都需要提前安排。

第二阶段决策则是场景实现后可以做的调整,比如在某个具体光伏出力场景下,储能是否多放一点来补充短缺、柴油机是否临时爬坡,这部分决策带上了场景下标。第一阶段决策是所有场景共用的,第二阶段决策各自独立。模型的巧妙之处在于,它让“需要事先承诺的部分”承担全部风险,同时允许“事后调整的部分”灵活响应,经济性和可行性就能同时兼顾。

在代码实现上,第一阶段变量不带场景下标,第二阶段变量带 s 下标,约束条件则分为两类:一类是仅含第一阶段变量的全球约束,另一类是每个场景独立满足的局部约束。这个结构决定了整篇模型的规模。

3.2 目标函数:期望总成本里到底要放哪些项

目标函数我推荐用量纲统一、项之间逻辑清晰的最小化期望总成本形式。基本组成包括:

  • 从上级电网购电的成本,按分时电价计算;
  • 向上级电网售电的收入,按上网电价或市场出清价计算;
  • 光伏发电的运维成本,通常很小但建议保留;
  • 储能充放电的折旧损耗成本,按电量计;
  • 柴油机或燃气轮机的燃料成本和启动成本;
  • 弃光惩罚项,避免模型宁可弃光也不愿承担调节成本;
  • 切负荷惩罚项,这是安全性底线,设一个足够大的惩罚系数。

所有权重都和场景概率相乘,所有场景累加后取期望。注意这里的一个微妙点:第一阶段决策的成本项不带场景概率,因为它必然发生;第二阶段成本项则必须在场景维度上求数学期望。很多初学的人容易把这一点写错,导致目标函数误算。

建模时我用的是成本最小化表述。如果是电力市场环境下的产销者模型,目标函数可以改成收益最大化或利润最大化,但本质结构一样,只是把购电成本换成收益项,惩罚项方向反过来。项目里我建议先把成本最小化版本跑通,再根据业务形态扩展。

3.3 约束体系:电力平衡、电池动态和爬坡限制一个都不能少

约束条件的完整程度直接决定方案是否具备工程可行性。必须覆盖的约束至少包括这些:每个时段的功率平衡约束,即购电、售电、光伏出力、储能放电、各类机组出力之和等于负荷需求;此约束在每个场景每个时段都要写一遍,是场景法模型体积膨胀的主要来源。

储能系统自身的约束也很关键。储能不仅受额定功率限制,还有电量上下限约束,以及充放电之间的逻辑关系约束。如果不加逻辑约束,模型可能在同一时段同时充电和放电,白白烧掉效率损失。通常我不会引入额外二进制变量去强行禁止同时充电放电,因为分时电价的激励下模型自然倾向于不在同一时刻一充一放,除非电池效率设为 100% 才需要额外约束。但如果你用的是煤电/柴油混合模型,还是要小心这类型约束。

机组方面需要峰值出力最大最小值约束和爬坡速率约束,尤其是柴油机这类快速响应机组,爬坡约束如果写漏了,求解出的计划可能在真实运行中完全追不上负荷变化。电网交互约束通常体现为联络线功率上限,即与外部电网交换功率不能超过契约容量,这也是常见的工程瓶颈之一。

另外别忘记不确定性相关的惩罚变量约束,比如弃光电量和切负荷电量需要定义为大于零的变量,并在平衡约束里参与计算。它们要被写入目标函数的惩罚项,否则模型会在收敛性上钻空子,大量场次干脆靠弃光/切负荷来“平衡”而不承担任何后果。

4. 求解环境与完整流程落地

4.1 环境配置与核心参数准备

这类问题我建议直接用 MATLAB 搭配 YALMIP 建模,或者用 Python 搭配 Pyomo 建模,求解器用 CPLEX 或 Gurobi。纯学术实验用开源求解器也能跑,但遇到大规模场景模型,商用求解器的速度优势非常明显。项目中我最终用了 MATLAB + YALMIP + CPLEX 的国产组合,调试方便,建模过程也直观。

建模之前要准备好这么几类数据:24 小时的分时购售电价曲线;光伏的容量、效率、温度系数以及各时段辐照度分布的拟合参数;负荷的基础曲线和误差分布参数;储能的额定功率、容量、初始电量、充放电效率、SOC 上下限;柴油机的最大出力、最小出力、爬坡速率、燃料成本系数和启停成本;联络线最大交换功率。这些参数质量决定了算例结果的可信度,建议整理成独立的配置文件,不要硬编码在模型代码里。

放电深度方面,锂电池的实际运行 SOC 区间要留安全裕量,比如只允许 10% 到 90%,能明显延长寿命。初学的人经常把 SOC 设到 0 到 100%,模型解出来好看,但实际无法长期运行。

4.2 从场景生成到最优调度的标准流程

整体流程可以归纳成四个步骤。第一步,把历史预处理后的分布式参数传给蒙特卡洛抽样模块,生成 2000 组光伏和负荷场景曲线。第二步,对完整场景集执行快速场景削减,目标场景数量设定为 20 或 30,得到代表性场景和对应概率。第三步,把削减后的场景带入两阶段随机优化模型,构造确定性等价的大规模混合整数规划问题,用 CPLEX 求解。第四步,从求解结果中提取第一阶段变量,这是真正能下发执行的日前调度计划;第二阶段变量则用来说明各场景下的调整策略。

我在实际执行时发现,二阶段模型在 YALMIP 里构造的方式很容易让人卡住。比较顺滑的做法是循环遍历每个场景,把该场景对应的约束和目标项都加到同一个优化对象里,然后统一设置求解器。目标函数里第二阶段的项乘上对应场景的概率,求和时用 sdpvar 数组累加,避免变量索引混乱。调试时先跑一个 5 个场景的小算例,确认模型结构和目标数值没问题,再切到完整场景集,能把排查成本降一档。

第一条任务清单排一下:

  1. 读取参数文件,初始化分布模型;
  2. 蒙特卡洛抽样生成 2000 组场景;
  3. 场景削减,输出代表性场景和概率权重;
  4. 构造两阶段随机优化模型;
  5. 调用 CPLEX 求解,保存结果;
  6. 解析第一阶段决策曲线并可视化比对各场景的功率曲线。

4.3 调度结果怎么解读才不白算

解出来后,最容易犯的错误是盯着目标函数数值看半天却不知道好还是坏。我一般建议同时输出三样东西:第一阶段功率调度曲线、储能 SOC 曲线、以及各场景下第二阶段变量的调整范围图。把这三样并排看,能直观看出计划在哪几个时段偏紧、哪些场景触发了惩罚。

比如 SOC 曲线如果在 1:00 到 6:00 段持续充电到 90% 快满,说明模型在利用谷价囤电;中午如果 SOC 有一个缓慢放电的小波峰,说明预测到中午光伏出力可能偏高,提前腾出容量;傍晚若 SOC 开始大幅放电,说明该时段负荷尖峰和光伏衰减同时出现,只能靠电池顶上。对照分时电价曲线,基本能解释每一段行为的逻辑。

还有一种常见情况是,模型为了保证期望成本最小,把某些场景下的调节压力全压在第二阶段变量上,导致第一阶段计划看起来“很激进”,比如购电功率连续贴上限。这时候要重点检查是不是惩罚系数设置过低,让模型宁可大量动用事后调节也不愿在日前提前预留安全裕量。

5. 算例结果与关键规律

5.1 与确定性调度对比:成本下降但不是白捡的

我做过一组平行算例:同样的 VPP 配置、同样的基础数据,一条路径用确定性优化(预测值全当真值),一条路径用上述随机优化 20 场景方案,最后用相同的 500 组真实随机场景回测两条计划的期望运行成本。

回测结果显示,随机优化方案的期望总成本比确定性方案降低了大约 8.8% 到 12.5%,具体数值随储能容量和上网电价变化。成本下降主要来自两个方面:一是随机方案减少了极端场景下的高价购电,因为日前计划已经为光伏偏低、负荷偏高做了铺垫;二是减少了弃光引起的浪费,储能能够在不确定光伏出力下保留更合理的充放电区间,而不是在“预测的中午高发时段”盲目满充。

但代价是随机优化方案的“最坏场景成本”会比确定性方案稍微偏高,因为它在所有场景之间做了折中,不再刻意讨好单一预测值。这个取舍我认为是值得的,毕竟调度员要的是长期稳定的期望经济性,而不是赌某一天的运气。

5.2 场景数量收敛性:20 个场景够不够

我做过场景数量的收敛性实验,分别用 5、10、20、50、100、200 个场景跑同一套模型,对比最优目标函数值的变化。结果相当典型:从 5 个场景到 20 个场景,目标值变化明显;20 个再往上涨,目标函数变化率迅速缩小,50 个和 200 个场景的解基本重合,差异控制在 1% 以内。

为什么会有这个现象?因为随机优化的本质是概率意义上的逼近,当场景数量增加到一定程度,场景削减后的代表性场景集已经能覆盖分布的主要形态,继续加场景只是增加计算量,对第一阶段决策的影响很小。从工程效率出发,我建议场景数量选在 20 到 50 之间,视机组数量多少、是否含整数变量而定。如果模型包含较多启停变量导致求解慢,场景数降到 20 也是可接受的下限。

场景数量求解时间(约)目标值偏差(相对200场景)适用阶段
53 秒约 6%快速验证模型逻辑
108 秒约 2.4%粗略参数扫描
2025 秒约 1.1%正式算例标准配置
5090 秒约 0.4%精细研究
2008 分钟基准验证收敛趋势

当然这个数据只代表我当时的模型规模和硬件条件,你的电脑和模型复杂度不同会有差异。核心规律是“边际收益递减”,没必要盲目追求上千场景的“牌面”。

5.3 不确定性幅度的敏感性分析

项目收尾阶段我还做了敏感性分析:把光伏预测误差的标准差从 10% 逐步调到 40%,负荷误差的方差同步放大,观察最优调度曲线的变化规律。结论很直观:不确定性越大,随机优化计划越趋于保守,具体表现为日前的购电曲线向中午时段倾斜,提前用电网电量“保底”;储能的 SOC 中期维持在高位,给后半段留更多放电库存;柴油机机组更倾向于保持热备用状态。

这里有个决策逻辑值得注意:并不是不确定性越大,期望成本就一定越高。因为随机优化会主动调整调度策略来吸收不确定性,成本增量呈现非线性特征,在误差标准差超过 30% 后才出现明显的跳升。这提醒我们,在做 VPP 运营决策时,比“减少预测误差”更划算的手段往往是“保持储能容量充足”和“灵活调整机组备用”,这两者能在不确定性上升时有效托底。

6. 常见问题与排查技巧实录

6.1 模型求解不可行,先查这几个地方

随机优化模型最常见的崩溃点是模型无解。新手第一反应是怀疑求解器有问题,但我排查下来 90% 都是建模问题。

优先检查电量平衡约束里惩罚变量是否漏写。如果切负荷变量和弃光变量没在平衡方程里,模型就只有“硬平衡”一条路,一旦某些场景下光伏和负荷偏差较大,就会找不到可行域。其次检查储能 SOC 下限设置和功率上限是否协调,比如 SOC 上限 90%、容量很小,但充电功率却设得很大,必然在低价时段撞上 SOC 上限,如果约束里没有允许弃电的通道,就会无解。还要查看联络线功率限制与负荷剪裁是否冲突,极端场景下联络线和储能都到顶了,负荷超出供应能力,就必须有切负荷变量兜底。

提示:一定要把切负荷和弃光变量在约束和目标函数中都留着,惩罚系数设成本币值的大数百倍量级。它们的存在不是为了让模型真的切负荷,而是给求解器留一条可行通道。

6.2 求解时间爆炸,卡在了整数变量上

场景数量加大的同时,如果柴油机启停变量也跟着翻倍,混合整数规划规模会极速膨胀。我曾遇到过 50 场景、4 台机组的小案例直接跑了半个小时还没收敛。此时建议分三步排查:先关闭整数变量,把启停变量松弛成连续变量,看纯线性规划求解时间是否可接受;再将场景数量降到 20 以下,验证是否为整数变量数量超标;最后考虑分解算法,比如将第二阶段按场景解耦做拉格朗日松弛,让每个场景独立求解,再通过迭代更新乘子协调。

我这里优先推荐的是先降场景数、再降整数变量复杂度。一般的日前调度不需要每个小时都允许机组启停,可以把启停时段从 24 个简化到 6 到 8 个关键区间,计算规模直接砍半,还能保住主要优化特征。

6.3 削减后的场景集“失真”,均值曲线对不上

场景削减最隐蔽的坑是聚类中心把原始分布的方差吃掉太多。比如天气从晴变阴的场景概率很低,K-means 聚类时可能直接被并到晴天簇或者阴天簇里,相当于把极端情况从场景集里抹掉了。我建议削减后做两个统计检验:一是把削减后的均值曲线和原始全场景均值曲线画在一起,偏差大就意味着削减过度;二是检查削减后场景集中是否还存在“光伏出力低于 20% 额定值”这类尾部场景,如果没有,把聚类数往上加,或者改用后向削减算法保留更多尾部场景。

实际操作中,我习惯把 K-means 聚出的初始簇数设为最终目标场景数的两倍到三倍,再在每个簇内选中位数场景而不是平均值场景。因为均值场景在物理意义上是“最中庸的一根曲线”,它没有离差但也没有代表性;中位数场景往往更贴近该簇的整体形状,效果明显更好。

6.4 最后分享一个关于随机场景数的经验

我做过一次实验:同样 20 个削减场景,用两次不同的随机种子生成场景集,回测的目标值差异大概在 1.5% 左右。这个波动水平说明,在合理的场景框架内,种子本身对结果的影响其实小于模型参数设置的影响。所以当你发现两轮实验数据对不上时,先别急着怪场景生成,回头看看价格曲线、惩罚系数、初始 SOC 这些参数是否保持一致。架构没有大问题的前提下,随机优化模型对随机抽样细节的敏感度是可以靠场景削减和变量尺度调节压得很低的。这也是我认为这套“蒙特卡洛 + 场景削减 + 两阶段优化”组合方案,最值得被规模化复用的原因。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进