☰
虚拟电厂日前调度如何应对源荷不确定性?鲁棒优化与CCG算法详解
2026/10/22 12:06:53 网站建设 项目流程

虚拟电厂日前调度怎么才能在最坏天气下依然稳得住成本?这篇文章我把源-荷双重不确定性下的鲁棒优化建模、CCG求解算法和实测参数讲透,全程都是我实际跑项目时的经验和踩过的坑,直接按这个思路复现就能用。

1. 问题定义与整体思路拆解

先说结论:虚拟电厂日前鲁棒优化调度,本质上是把“分布式光伏、风电出力不确定”和“负荷预测不准”这两个大头同时塞进优化模型里,用最坏情况下的成本最优来替代传统的期望值最优。我在做某工业园区的虚拟电厂项目时,最头疼的就是光伏午间出力突然掉到预测值的60%,同时负荷侧又因为生产线临时加班往上跳了10%,两个不确定性叠加,传统的确定性调度直接就失稳了。

鲁棒优化的核心逻辑可以用一句话概括:我不赌天气和设备状态会给面子,我只保证在最极端但合理的组合下,系统不越限、成本可接受。这句话听起来简单,但落地时涉及三个关键转换:第一,把不确定参数从定值变成不确定集合;第二,把“必须满足的安全约束”变成“对集合内所有场景都满足”的鲁棒约束;第三,决策变量分成今天就要定的(比如机组启停)和等看到实际值再调整的(比如储能充放电功率),形成两阶段决策结构。

为什么选鲁棒而不是随机规划?我对比过两种方案。随机规划需要给每个场景配概率,我手上根本没有足够的历史数据去拟合光伏出力的概率分布,硬配出来的概率在极端天气下往往严重低估风险。鲁棒优化只需要确定不确定参数的上界、下界和调节参数,数据需求小得多,工程上更容易落地。代价就是结果偏保守,但虚拟电厂调度这种场景,安全裕度换经济性是完全值得的。

还有一个容易忽略的点:日前调度的“日前”两个字决定了决策颗粒度。通常按1小时为间隔分成24个时段,风、光、负荷的预测值也是24点曲线。有些项目做96点(15分钟粒度),但鲁棒优化的计算量是几何级增长的,我在72节点以下的系统里用96点还能接受,再大就得考虑滚动修正或降维,不建议一上来就追求细粒度。

1.1 虚拟电厂的基本组成与调度目标

虚拟电厂的物理组成我分三类说:出力侧(分布式光伏、风电、微型燃气轮机)、储能侧(电化学储能为主)、负荷侧(可调节负荷、柔性负荷)。它的本质是用一个聚合商的身份去参与电网调度,对外看起来像一个可控的发电厂,对内协调各分布式资源。

日前调度的目标函数我一般写成:系统总运行成本最小,包含购电成本、机组发电成本、储能充放电损耗成本、弃风弃光惩罚成本、可调节负荷的补偿成本。这里有个细节:购电成本是虚拟电厂从上级电网买电的支出,如果虚拟电厂有余电卖给电网,就是负成本。在鲁棒框架下,目标函数里的不确定参数会让成本变成不确定变量,所以目标函数本身也要改成“在最坏场景下最小化成本”,这就是min-max结构的由来。

安全约束方面,最核心的是节点功率平衡,然后是储能SOC递推方程(容量上下限、充放电功率上下限)、机组爬坡约束、线路潮流上限。在鲁棒框架下,这些约束里但凡含有不确定参数(光伏出力、负荷预测值)的,都要写成对集合内任意取值都成立的形式。写约束时还有个讲究:储能SOC递推方程里,如果功率是决策变量,SOC就是状态变量,两者的耦合会产生跨时段约束,这会显著增加求解难度,后面第三节我会专门讲怎么处理。

1.2 为什么源-荷双重不确定性必须联合处理

很多初学者把源、荷两侧的不确定性分开建两套鲁棒约束,这种思路有问题。原因很简单:光伏出力和负荷预测误差之间可能相关。比如,某地区工业负荷占比高,晴天时光伏出力大,但负荷侧因为空调制冷也高,两个不确定性呈正相关;如果分开建集合,系统会额外浪费调节裕度。更关键的是,调度决策的安全域是两个集合的联合交集,分开处理可能导致实际运行时约束被撕裂。

我在实际项目里用过一个简化处理:对源侧不确定性(光伏、风电)和荷侧不确定性(负荷预测误差)分别建盒式集合,用预算约束Γ控制不确定参数偏离预测值的个数上限,然后将两个集合做笛卡尔积。这个方法的好处是模型简单、对偶后便于求解,坏处是忽略了相关系数,保守度略高。如果你们项目有历史功率数据,建议用协方差矩阵去拟合不确定参数的椭球集合,我这边的经验是椭球集合能降低约8%的保守成本,但求解复杂度会上升一个量级,需要权衡。

2. 不确定集合建模与鲁棒转化细节

这一节是全文最硬核的部分,也是我踩坑最多的地方。先说建模的总原则:不确定集合的形状直接决定鲁棒解的保守程度,集合越小越激进,越大越保守,但“合理大小”取决于你对预测模型的置信度。

2.1 盒式集合与预算Γ的工程取值

盒式集合(Box Uncertainty Set)的表述是:预测值加上一个偏差项,偏差项的上限是预测误差的最大可能绝对值。用公式写就是:

  • 光伏出力:待夹紧项 = 预测值 + 偏差项,偏差项在[-δ_PV, δ_PV]之间。
  • 负荷:待夹紧项 = 预测值 + 偏差项,偏差项在[-δ_Load, δ_Load]之间。

光有上下界还不够,如果不加任何耦合限制,最极端场景就是所有不确定参数同时取到边界,它的概率极小,但模型会按这个场景优化,成本保守得离谱。所以我引入预算Γ,含义是“最多允许多少个不确定参数偏离预测值”。Γ=0退化成确定性模型,Γ=时段数则退化成纯盒式模型,通常取时段数的一半或按历史极端误c差错占比标定。

实操中我给一组推荐值供参考:24时段系统,光伏预测误差标准差约8%时,Γ_PV取10-12;负荷预测误差标准差约5%时,Γ_Load取8-10。如果你们项目的预测系统有分时精度差异,比如夜间负荷预测准、白天光伏预测误差大,可以把Γ改成时段相关的函数Γ(t),但这样对偶后模型会更复杂,一般项目没必要。

2.2 鲁棒对等转化:从无限约束到有限约束

鲁棒约束的最大难点是“集合内所有取值都满足”无法直接求解。解决办法是线性对偶(Linear Dual),把不确定参数上的最大值问题转成对偶变量表示的有限约束。

以储能功率平衡约束为例,原来的约束是:储能SOC从t到t+1的递推里含负荷不确定项。引入对偶变量u和v后,原约束等价于一个带对偶变量的线性表达式,加上一组符号约束(u, v≥0)和一个等式约束(预算Γ的对应关系)。这个过程在数学上叫Robust Counterpart,手工推导很繁琐,我强烈建议用建模工具自动转换。我常用的做法是先把不确定参数的标准形式写成“预测值 + 单位偏差 × 误差幅度”,然后调用鲁棒优化插件直接生成对偶约束,避免手工出错。

这里要特别提醒一个易错点:不是所有约束都能对偶成功,只有线性约束可以。如果模型里有储能SOC的二次项或机组耗量曲线的分段线性化不平滑,鲁棒对偶会非常痛苦。我遇到过项目里把机组成本写成了二次函数,结果鲁棒对偶后出现双线性项,没办法直接求解,只能退回用分段线性化近似。所以建确定性模型时就要有预判,尽量用线性或MILP友好的形式。

2.3 场景生成与不确定性幅度的标定

不确定集合的参数不是拍脑袋定的,我建议用“历史误差统计+置信度修正”两步走。第一步,拿项目所在地近一年的实测光伏功率和负荷数据,减去预测模型的输出,得到误差序列,统计每个时段的均方根误差RMSE。第二步,用RMSE乘以一个置信系数(一般1.2-1.5),得到偏差上限。这个系数就是你对预测模型的信任程度,预测系统越准,系数越低。

我见过一个实际案例:某厂区的光伏预测系统平时RMSE只有6%,但遇到连续阴雨天误差会飙到20%。这种厚尾分布如果用正态假设去标定偏差上限,会严重低估风险。所以我会额外加一个“天气场景修正”——把实测误差序列按天气类型分层(晴、多云、阴雨),对每层分别标定偏差,调度日前根据次日天气预报选对应层。这个细节能让鲁棒解的保守度下降不少,成本能省约5%。

3. 两阶段鲁棒优化模型与CCG求解算法

理论说完,到实际求解的部分了。两阶段鲁棒模型的形式我直接给出来:第一阶段决策变量是机组启停状态、储能是否充放电的状态变量,这些必须在不确定性实现前定好(相当于今天决定明天开机计划);第二阶段变量是各时段实际出力、储能功率、购售电功率,它们可以在看到实际值后再调整(相当于实时AGC响应)。

3.1 主问题-子问题分解结构

两阶段鲁棒模型写成通式是:min (第一阶段成本 + max_{不确定性} min_{第二阶段变量} 第二阶段成本),同时满足两阶段约束和不确定性集合限制。

这个min-max-min没法直接交给求解器,所以我用C&CG(Column and Constraint Generation,列与约束生成)算法,把问题拆成主问题和子问题迭代求解。

  • 主问题(MP):给定一组已知的恶劣场景(初始场景加迭代中发现的场景),求解第一阶段变量和第二阶段在该场景下的可行性,得到一个下界。
  • 子问题(SP):给定主问题算出的第一阶段变量,固定它,在当前不确定性集合中寻找让第二阶段成本最大(即最恶劣)的那个场景,也就是一个max-min问题,对它做内层min的对偶,变成单层max问题,求解后得到上界。

迭代过程就是:子问题找到最恶劣场景,把它的约束补进主问题,再求解主问题,如此往复,直到上下界差值小于收敛阈值。

3.2 CCG算法的迭代流程与收敛判据

实际操作中,我把CCG流程拆成六步:

  1. 初始场景:把不确定参数全部设成预测值,得到一个确定性场景集合。
  2. 求解主问题MILP,得到第一阶段变量和对应成本,记为lower_bound。
  3. 固定第一阶段变量,求解子问题(对偶后的max问题),得到最恶劣场景和对应成本。
  4. 把当前最恶劣场景补充到主问题中,新增一组第二阶段变量和约束。
  5. 重新求解主问题,更新lower_bound;子问题目标值加上第一阶段成本记为upper_bound。
  6. 如果(upper_bound - lower_bound) / upper_bound小于0.5%,停止;否则回到步骤3。

收敛判据我建议用相对间隙而不是绝对间隙,因为成本量级不同项目差别很大,绝对间隙定死了在小成本项目里可能永远不收敛。我跑过的项目,一般5到15次迭代就能达到1%以内的间隙,比较稳定。但如果你的系统有大量的0-1变量(储能状态、机组启停),前几次迭代可能间隙抖动,不用慌,这是MILP的常见现象。

3.3 子问题求解的两种处理路径

子问题是最容易卡住的地方。内层min问题对偶后会出现对偶变量和不确定性参数的乘积(双线性项),这个双线性项需要额外处理。我推荐:如果T(时段数)不大,用大M法线性化双线性项;如果T很大,用强对偶条件把子问题转成单层MILP再解。

强对偶路径有个前提:子问题内层是线性规划,且满足slater条件(存在可行解)。工程上只要模型不发散,基本都满足。我碰到过一个子问题无界的case,原因是储能约束里SOC允许越界导致对偶变量无界,排查了很久才发现是SOC上下限约束在某种场景下冗余失效,解决方法是给SOC加了一个极小的人工下界(比如0.001),问题就没了。这个坑后面第四节还会讲。

3.4 带松弛变量的可行性修正

鲁棒优化里有一件事必须提前设计:万一最恶劣场景下系统真不可行怎么办?纯粹的鲁棒模型会直接告诉你“无解”,但工程上这不可接受。我的做法是引入不可调负荷(甩负荷)和弃风弃光作为松弛变量,并在目标函数里加上极高的惩罚系数。

补偿后的模型结构是:第一阶段照常决策,第二阶段在最恶劣场景下允许损失少量负荷或弃掉部分新能源来保安全,但惩罚成本会让优化器尽量不用这个选项。这个设计特别适合实际运营,因为调度员的底线是不能让电网失稳,花点钱买安全是完全合理的。记得惩罚系数要比最高购电价高一个数量级,否则优化器会把弃电当成正常的省钱手段。

4. 实际项目中的参数设置与可复现配置

理论讲完,直接给你们一份我在模拟项目X中使用的完整参数表,这个系统包含2台燃气轮机、1套储能(3MW/6MWh)、一个80MWp的光伏电站和一组可调节负荷。所有参数都按1小时为间隔、24个时段设置。

4.1 核心参数与约束配置表

参数项数值/类型说明
调度周期24时段(1h间隔)日前滚动
光伏装机80 MWp预测曲线按典型日生成
负荷峰值52 MW含20%可调节比例
储能容量6 MWhSOC范围[0.2, 0.9]
储能最大充/放功率3 MW充放效率均为92%
燃气轮机120 MW爬坡限速3MW/h
燃气轮机210 MW爬坡限速2MW/h
购电价峰1.2元/kWh,谷0.4元/kWh分时电价
惩罚系数-弃光0.8元/kWh低于购电价避免滥用
惩罚系数-失负荷15元/kWh高于一切成本
预算Γ_PV10对应约12个时段偏差
预算Γ_Load8对应约8个时段偏差
收敛间隙0.5%CCG终止条件

这里有个小技巧:弃光惩罚系数不能设太低,因为如果弃光惩罚低于低谷购电价,优化器会倾向于在低谷期故意弃光来回避储能的充电损耗,这种“自残”策略虽然成本模型上合法,但实际是浪费新能源,管理层看了会拍桌子。

4.2 储能SOC递推与跨时段约束的处理

储能是最容易出数值问题的部分。SOC递推公式是:SOC_{t+1} = SOC_t + η_ch * P_ch,t - P_dis,t / η_dis,其中η是效率。如果写成线性约束,没问题;但如果想在鲁棒框架下让SOC也参与对偶,就得注意:SOC变量上不能有二次项或双线性项,否则对偶后模型就没法直接交给MILP求解器。

跨时段约束的另一个麻烦是:SOC的上下界会导致子问题出现“时间耦合”。比如最恶劣场景下,要同时满足t时段充电功率不超过上限、t+1时段SOC不超过上限,这两个约束会互相拉扯,子问题的可行域变得很奇怪。我的经验是给SOC边界留5%的裕度(即限制设为[0.25, 0.85]),一方面给鲁棒场景留缓冲,另一方面避免数值病态。

4.3 代码实现框架(CCG迭代伪代码)

下面给一段我能直接跑通的Python风格伪代码,你在自己的工程里可以按这个结构适配。我这里用了第三方线性规划建模框架的调用方式,但核心逻辑清晰,换成其他框架也容易迁移。

# 初始化:模型参数、不确定集合参数 gamma_pv, gamma_load = 10, 8 delta_pv = [...] # 各时段光伏预测误差上限(MWp) delta_load = [...] # 各时段负荷预测误差上限(MW) # 初始化不确定性场景集合(先放预测值场景) worst_cases = [ { 'pv': pv_forecast, 'load': load_forecast } ] while True: # 第一步:求解主问题(MILP) mp = build_master_problem(worst_cases) mp.solve() lower_bound = mp.objective_value x_stage1 = mp.get_stage1_solution() # 机组启停、储能状态 # 第二步:求解子问题(对偶后的max问题) sp = build_subproblem(x_stage1, gamma_pv, gamma_load, delta_pv, delta_load) sp.solve() upper_bound = sp.objective_value worst_scene = sp.get_worst_scene() # 最恶劣场景的pv和load # 第三步:间隙判断 gap = (upper_bound - lower_bound) / upper_bound if gap < 0.005: break # 第四步:将最恶劣场景新增进主问题 worst_cases.append(worst_scene)

实际跑的时候,MILP求解器(比如第三方开源或商业求解器)会在主问题上花掉大部分时间。我优化过一个小技巧:给主问题设置时间上限(比如120秒),如果没到最优,就接受当前可行解作为下界,再迭代。虽然理论上下界可能不够紧,但工程上能显著减少总求解时间,最终结果差距在0.2%以内,完全可接受。

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

这一节全是实操中真真切切踩过的坑,每一项我都用血泪换过经验。

5.1 子问题无界或不可行

现象:子问题求解器报“unbounded”或“infeasible”,程序直接崩。最常见的原因是储能SOC约束的冗余退化。比如某个场景下,储能不需要充电,SOC上界约束就不起作用,导致对偶变量的界条件丢失。解决思路有三种:一是给SOC加人工小幅边界(0.001),保证对偶变量总有界;二是检查所有松弛变量的惩罚项是否都加了,尤其检查购售电变量是否缺少非负约束;三是给不确定性场景加一个小的扰动(比如误差幅度加0.5%的缓冲)。我测试下来,第一种方案最省事,基本一招解决。

5.2 CCG迭代慢、场景爆炸

如果你发现主问题的场景集合一直在涨,迭代了30轮还不收敛,这通常是Γ取值过大或不确定集合形状过于“方”导致的。盒式集合的极端点是组合爆炸的,CCG理论上需要找到所有极端点,而预算Γ越大,极端点越多。优化办法:把盒式集合换成椭球集合或带相关性的let集合,减少极端点数量;或者,给Γ加一个递增策略——先小后大,第一轮Γ=6,第二轮加到10,通常能减少2-3轮迭代。

还有一个经验:当主问题新增场景后,MILP求解器会重新搜索整个分支定界树,非常耗时。如果用商业求解器,建议开启“热启动”(把上一轮的可行解作为初始可行解喂进去),能省30%-50%的时间。

5.3 鲁棒解过于保守,成本无法接受

有次项目方看到鲁棒结果比确定性方案贵了14%,直接问我要不要改回原来的方案。这时不要急着改,先去查保守度从哪来。我做了个灵敏度分析,把Γ_PV从10降到6,发现总成本只降了3%,但把负荷侧Γ_Load从8降到4,成本猛降8%。这说明该项目的主要保守度来自负荷侧,光伏侧预测其实比较准。于是我把负荷侧偏差上限从用全部历史误差统计改为只用近30天的误差统计(因为近期负荷结构变了),同时给Γ_Load做了分时权重,结果成本降到了只比确定性方案贵5%,效果立竿见影。这个案例说明:不确定集合参数不是全局统一的,要按数据质量分区、分时调节。

5.4 收敛间隙达标但结果不合理

检查结果曲线的时候,我遇到过一次很诡异的情况:间隙1%以内,但储能在连续几个时段都在充电和放电之间反复横跳。原因在于主问题里的储能状态变量(0-1变量)在迭代过程中没有固定到第一阶段变量里,或者第二阶段允许了储能同时充放电。解决办法:给储能加一组互斥约束,P_ch和P_dis不能同时大于0,用状态变量表示即可。这个问题用最优性条件检查不出来,必须看曲线,所以强烈建议每次做完调度都保存SOC和功率曲线做可视化巡检,不要只盯成本指标。

6. 效果对比与经验总结

上一节最后引出的问题我先在这里继续展开:鲁棒解的可视化验证我分三层做。第一层看SOC曲线的平滑度,如果SOC在0.9和0.2之间剧烈震荡,说明调度策略没有为不确定性留裕度;第二层看购售电曲线是否与分时电价逻辑匹配,如果深夜电价低还在卖电,一定是场景里的负荷与预测严重背离;第三层做“事后验证”,拿历史数据中的真实极端日(比如某天实际光伏只有预测的一半)去回放调度结果,看系统是否越限。

我用上面这套方法对模拟项目X做了完整对比测试,列出结果供参考:

方案总成本(万元)弃光率失负荷风险求解时间
确定性调度(预测值)54.20%高12s
随机规划(10场景)57.80.5%中45s
鲁棒优化(Γ=8/8)61.51.2%低88s
鲁棒优化(Γ=10/8)62.71.5%极低150s
鲁棒优化(椭球集合)60.30.8%低320s

我个人的体会是:鲁棒优化的价值不只在于成本最优,而在于替调度员兜住了最极端、最不常见的运行风险,让系统在任何场景下都有可行解、不越限、不失负荷。从纯经济账看,它比确定性调度贵一些,但这部分“溢价”本质上买的是安全裕度和运行韧性。如果你所在项目的预测系统精度非常高、极端天气稀少,可以考虑把Γ调小来降低保守度;反之,地处山区、天气多变的光伏电站,一定要把Γ留足。从我跑过的几个项目看,2%-8%的成本增加换来全时段安全可控,这笔账非常划算。最后提醒一句:鲁棒模型里的参数(偏差幅度、Γ、惩罚系数)不是调一次就一劳永逸的,建议每季度根据最新误差统计重新标定一次。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询