☰
随机双重动态规划在储能调度中的应用:应对可再生能源不确定性
2026/9/26 12:59:45 网站建设 项目流程

1. 储能调度遇上的那道坎:不确定性不是锦上添花,是生死攸关

先聊一个我这两年反复在项目中感受到的事实:做储能调度,如果你把风光出力当成已知曲线来处理,那方案做得再漂亮,现场跑起来也基本是失控的。因为可再生供应的不确定性不是一个"偶尔波动一下"的小毛病,而是贯穿整个调度周期的主体特征。风电可能十分钟内从满发掉到三成,光伏更不用说,云一来,出力曲线直接跳水。这时候如果调度策略没有把"不确定性"本身当作核心变量来建模,那所谓的实时优化就变成了一个不断追赶残缺信息的被动反应。

很多人第一次听到"实时存储调度"这个词,会下意识以为这是纯粹的在线决策问题,就像自动驾驶每秒钟重新规划一次路线那样。但储能调度有一个本质区别:电池的荷电状态(SOC)是跨时段耦合的。你今天多放一度电,明天的可用容量就少一度。所以实时调度不能只看眼前,它必须把"未来可能的场景"纳入今天的决策。这就像你开车下山,方向盘怎么打,不仅要看眼前这个弯,还要想清楚后面那几公里的路况。对于储能系统,这个"后面的路况"就是未来若干小时的风光出力概率分布。

可问题就出在这里:要评估未来,就得引入随机性;要引入随机性,计算量就会爆炸。传统动态规划(DP)的思路是把状态空间离散化,然后逐阶段递推,这在确定性场景下很好用。但一旦加入随机场景,每个阶段的可能状态呈指数级增长,再加上储能自身的SOC连续状态,很快就把计算资源吃干抹净。我在早期尝试用标准DP做24小时储能调度,场景数一上千,单次求解就慢到没法实用。更关键的是,DP的"维数灾难"让你根本没法在有限时间内得到在线可用的策略。

所以当"随机双重动态规划"这个词出现在我面前的时候,我的第一反应不是觉得它玄妙,而是好奇它怎么绕开这个维数爆炸的问题。简单说,SDDP(Stochastic Dual Dynamic Programming)用了一种非常聪明的近似策略:它不在全状态空间上做精细离散,而是通过Benders分解,把"未来成本函数"用一系列线性割平面来近似。也就是说,它把原来那个巨大无比的问题,拆成一个个阶段性子问题,然后通过迭代更新的方式,让这些近似函数逐步逼近真实值。整个过程不需要枚举全部场景,只需要采样一部分代表性路径,这让它非常适合处理"可再生不确定性+储能状态耦合"这类问题。

这篇东西我会把SDDP从原理到落地都掰开讲清楚,包括它为什么会收敛、怎么建模型、场景怎么造、参数怎么调、实际跑起来会遇到哪些坑。适合两类人看:一是正在做储能或微网调度、被不确定性问题折磨的工程师;二是想入门随机优化但被教材里那些方程劝退的研究者。我会尽量用实际操作的语言来讲,不堆公式,但关键的逻辑我会说得比很多论文都细。

1.1 实时存储调度到底在解决什么问题

先给个我常用的简化框架。假设你有一个储能系统,前面接了一台风电场或者一片光伏板,后面是负荷。你每天早上要决定充放电计划,目标是让整体运行成本最低,或者在现货市场套利收益最高。但风光的出力你并不确定,只能拿到预测值——预测误差还经常不小。这个问题的数学形式可以写成一系列递推决策过程:每个时段(比如15分钟一个时段)我看到当前的SOC和当前的风光出力实测值,以及一组对未来预测的条件分布,然后决定这个时段充多少、放多少。决策完之后,系统状态跳到下一个时段,新的实测值进来,我再做下一个决策。

这就是"实时调度"的实际含义。它不是一个一次性算完的全局优化,而是一个逐时段推进、反复决策的过程。这样的结构天然适合用动态规划的思想来处理,因为你确实是在维护一个"当前状态到未来成本"的函数。但这个函数到底长什么样,没有人能写出闭式解,因为它是由大量随机场景和约束共同决定的。SDDP所做的工作,就是把这个函数通过线性割平面的包络给近似出来,并且保证在迭代足够多次之后,近似精度达到工程可用水平。

我见过很多团队在这类问题上直接用模型预测控制(MPC)做滚动优化,效果其实也不错,但MPC有个前提:你得有一个足够可靠的确定性预测模型。当预测误差大到一定程度,MPC的单场景轨迹就会被带偏,表现在实际调度里就是频繁改变充放电策略、电池过度充放循环,甚至在某些时段出现缺电或者弃风。SDDP的价值在于,它天生就把"多条可能轨迹"放进了决策里,决策结果对单一场景的偶然误差不敏感。

1.2 为什么传统动态规划在可再生波动面前会失灵

传统DP有个经典的迭代公式:V_t(s_t) = min_{a_t} [C_t(s_t, a_t) + E[V_{t+1}(s_{t+1})]]。这个公式本身没错,问题在于它背后的实现方式。为了把V函数存下来,你必须把状态空间离散成网格。网格一密,状态数呈指数级往上走;网格一疏,精度又不够,尤其是储能SOC这种高度非线性的变量,在最优解附近一刀切下去,会造成策略抖振。

更麻烦的是随机性。传统DP把随机变量也离散成场景,然后对每个状态、每个时段都遍历一遍所有场景做期望计算。这个计算量有多大呢?举个我踩过坑的例子:24个时段,SOC状态分成50格,风速场景取100个,做一次完全DP求解需要遍历的状态-场景组合是50×24×100,这只是单阶段,实际还有决策变量的枚举,整体计算量极难控制在可接受范围内。当年我在一台8核工作站上跑这个模型,算完一次需要三个多小时。这还只是离线的策略计算,不是实时的。你要是把负荷预测或者电价场景再细化一下,这模型基本就没法在生产环境里用了。

所以行业里后来转向了两类替代方案:一种是近似动态规划(ADP),用机器学习方式去近似价值函数;另一种就是SDDP,用凸优化的方式去构造价值函数的下界近似。SDDP相比ADP有一个很大的优势:它保留了可解释性——每个割平面的几何直观清晰,调试起来有据可循,而且理论上的收敛性质比一般的神经网络近似要可控得多。对于电力系统这种对可靠性要求极高的场景,这种可控性真的非常重要。

2. 随机双重动态规划:把未来的不确定性变成今天的可计算量

我最早看SDDP论文的时候,被里面的术语搞得一头雾水,什么前向演化、后向递归、割平面一致性。等自己在代码里跑通之后才明白,这个算法的核心思想其实可以用一个简单的类比来概括:你雇了一个地产中介,这个中介不需要跑遍整个城市的所有楼盘,只需要看几个代表性小区,就能给你报出这一片房价的走势区间。他给的不是精确价格,而是足够你做决策参考的估价。而且每成交一笔,他都会校正自己的估价模型。SDDP干的就是这件事,只不过它估的不是房价,而是"未来成本关于当前SOC的凸函数"。

为什么是凸函数这一点很关键。储能调度问题里,未来成本通常是SOC的凸函数,也就是说你储能水平越低,未来需要支付的额外成本越高,而且边际增加的成本是递增的。这个凸性保证了Benders分解的正割平面能构成一个全局的下界估计,进而保证迭代收敛。如果问题不是凸的,割平面的下界性质就站不住了。这也是为什么SDDP对很多扩展问题(比如含整数变量、非凸约束)都要做额外处理的原因。

从两阶段随机规划的角度看,SDDP其实做了多次前向传播和后向修正。两阶段随机规划是说,你现在做决策,等到不确定性实现后再做第二阶段决策进行补偿。而SDDP把两阶段扩展成了多阶段,且阶段之间只共享状态变量。每一条采样路径就是一组可能的未来发展序列,前向模拟负责给出决策轨迹,后向递归负责沿着轨迹反向递推更新每个阶段的割平面。这两步反复迭代,最后的收敛判据是用上下界之差来判断的,这个差值通常被叫做"最优性间隙"。

2.1 从两阶段随机规划到SDDP的进化路线

要理解SDDP,先得理解两阶段随机规划的长相。设第一阶段决策是x,第二阶段随机场景是ω,第二阶段决策是y(ω)。目标函数是c^T x + E_ω[Q(x, ω)],其中Q是第二阶段的补偿函数。这个模型在实际中最大的问题是:当阶段数超过2,变成了几十个阶段,场景树会以场景数的幂次增长,直接枚举完全不可行。SDDP就是专门应对这个问题的一种方案,它不对整个场景树做枚举,而是通过采样和割平面来"覆盖"未来空间。

具体来说,SDDP在每个阶段维护一个近似价值函数V_t_hat,它由一系列线性割平面组成。初始化时这些割平面可能很粗糙,但通过迭代会逐步精细化。每一轮迭代包含两步:前向模拟阶段,沿着一条随机采样路径,利用当前的近似价值函数依次求解各阶段决策,得到一条完整的状态轨迹;后向递归阶段,沿着这条轨迹反向递推,在每个阶段求解对应的子问题,并根据对偶信息构造一个新的割平面,添加到前一阶段的近似价值函数中。每完成一轮迭代,就能得到一个新的下界估计和一个新的上界估计,两者的差距用于判断是否收敛。

我自己的感受是,SDDP从两阶段规划进化出来的关键跳跃,不是数学上的难度,而是工程上的思维转变。两阶段规划你是"一次性算完",而SDDP是"迭代逼近"。很多搞优化的人一开始不习惯这种逼近的思路,总觉得每次迭代得到的结果不够"精确"。但在实时调度场景里,精确到小数点后几位没有意义,因为输入的风电预测本身就有20%以上的误差。你需要的是一个在期望成本意义下最优的策略,而不是某一个特定场景下的精确解。

实践中我常用的迭代次数大约在50到200轮之间。前30轮你能看到上下界快速靠近,之后就是缓慢下降。如果你的问题规模不大、场景数几千级别,一般100轮左右就能达到1%以内的最优性间隙。但注意,这只是离线学习阶段的结果。真正在线使用时,你用的是学到的价值函数近似,而不是每次都重新迭代。

2.2 Benders分解与割平面机制

Benders分解的核心是"线性规划的对偶解撒花椒面"。什么意思呢?每当你求解一个子阶段的LP,你会得到拉格朗日乘子(对偶变量),它们代表了当前决策边界上"约束的边际价值"。把这些乘子组合起来,就能构造出一个线性不等式,它描述的是:当前阶段的决策变量取某个值时,未来成本函数的下界是什么。这个不等式就是Benders割。

举个具体例子。在储能调度里,某一时段t的状态变量是SOC_t。后向递归求解t+1阶段的子问题时,如果约束条件是SOC_{t+1} = SOC_t + η_c * P_c - P_d / η_d,那么关于SOC_t的对偶乘子λ_t就反映了"把SOC提高一个单位,对降低未来成本贡献有多大"。于是Benders割可以写成:V_{t+1}(SOC_{t+1}) ≥ α_t + λ_t * (SOC_{t+1} - SOC_{t+1}^*)。其中α_t是一个常数项,SOC_{t+1}^*是当前迭代的状态值。随着迭代进行,这个割平面会越来越贴合真实的V函数。

有一个容易忽略但非常关键的细节:割平面只会从下方贴近真实函数,而且每次迭代,割平面的数量都在增加。这意味着近似价值函数永远是一个"逐步从下往上"靠近真实值的凸包。由于所有割平面都是真实值在某个点的切线下界,所以近似值永远不会高估真实值。这是个很好的性质:你不会因为近似误差而在期望成本上吃过亏,最坏情况也是"以为成本更低、实际更高"——不对,方向反了。近似价值函数是下界,意味着你对未来成本的估计不会偏高。但这在决策中会导致"过于乐观"的倾向,你可能会觉得未来成本很低,从而今天多放电。所以实际应用里,我们还要在割平面中加上"可行性割"来约束状态不越界。

在实时调度中,割平面还有一个核心用途:它可以被预生成、离线存储,然后在线查询。也就是说,你不需要在运行时重新优化未来全部时段,只需要用当前SOC在当前时段的价值函数近似值上做一个局部决策。这比完整的MPC滚动优化速度快一到两个数量级,而且天然具备随机性鲁棒性。这是SDDP在实际系统中能跑实时的一个关键前提。

2.3 前向模拟、后向递归与收敛判据

前向模拟的输入是随机采样路径。这个路径从哪里来?通常是从你构建的场景集中带放回抽样,或者从预测的不确定性分布里采样。每一条路径都代表一种可能的"真实未来"。前向阶段沿着这条路径,逐时段求解子问题——注意,这里求解子问题时,并不是用未来的真实信息,而是用当前割平面近似出来的信息。这就像开车时你并不需要知道整个路程的精确车流,只需要根据地图软件估算的到达时间来逐步决定下一步走哪条路。前向阶段结束后,记录下所有阶段的状态值和目标函数值。这些目标函数值的平均值可以看作一个"上界估计",因为在采样路径上,实际执行成本一般都高于或等于完美信息下的最优成本。

后向递归则是反过来。从最后一个阶段开始,用前向阶段记录的状态值求解该阶段的子问题,得到目标函数值和拉格朗日乘子。利用这些乘子,生成新的割平面,添加到前一个阶段的近似价值函数里。然后继续往前推进,直到把所有阶段的割平面都更新一遍。经过多轮迭代,这些割平面叠加在一起,就会把近似价值函数"抬升"到接近真实值的位置。每轮迭代后,你可以把"当前上下界之间的绝对差距"除以"当前下界",得到最优性间隙的百分比。通常电力系统里做到0.5%到1%就完全够用了。

关于收敛判据,有一个工程经验值得多说一句:不要只看最优性间隙。上界的估计用的是采样路径,如果你采样数量太少,这个上界本身方差很大,即使真实策略不错,间隙也可能拉不开。我的做法是每轮迭代用不同的随机种子采集20条路径估算上界,每20轮迭代再做一个较大规模的500条路径精密评估,这样得到的收敛曲线才会稳定、有说服力。单纯靠单条路径跑完就说"收敛了",很容易在项目验收阶段翻车。

3. 实操落地:我是怎么把SDDP用进储能调度系统的

聊完理论,说说正事。2022年到2023年我参与了一个工商业园区储能调度项目,系统规模不算大:2 MW/4 MWh的磷酸铁锂电池,旁边有一片6 MW的光伏,主要目标是在峰谷电价下做套利,同时降低变压器的峰值负荷。光伏的不确定性直接决定我们每天的收益,高峰时候段光伏忽高忽低,调度策略稍微保守一点就是几万块的损失。这个项目最终换成了SDDP方案,整个改造过程我分四步走:建模、场景生成、离线训练、在线部署。下面每一步我都把关键细节和参数选择说清楚。

3.1 问题建模:状态变量、决策变量与约束条件

建模这一步决定了后续所有环节的上限。我们先定义时段,我采用的是15分钟一个时段,全天96个时段,调度周期设为24小时。为什么选15分钟?这是国内电力现货市场的基本分辨率,也是储能PCS的天然控制周期。如果把时段拉长到1小时,会漏掉很多光伏短时波动导致的套利机会;再短到5分钟,问题规模上升,SDDP的迭代耗时也会明显增加,性价比不高。

状态变量有两个:SOC_t,储能荷电状态,是跨时段耦合变量;p_{pv,t},光伏出力的当前实测值,这个值在现实中是不断刷新的,但在SDDP框架里,它是随机过程的观测变量。决策变量包括:P_c,t和P_d,t,分别是充、放电功率;还有G_t,从电网购电的功率。约束方面,最基本的SOC递推方程是SOC_{t+1} = SOC_t + η_c * P_c,t * Δt - (P_d,t / η_d) * Δt,其中η_c取0.95,η_d取0.92。此外还有充放电功率不超过额定值,SOC不超出10%到90%的工作区间,以及园区负荷供需平衡方程:光伏出力 + 放电 + 购电 = 负荷 + 充电。

这里有一个SDDP建模的重要注意点:状态转移方程必须是线性的,这样才能保证子问题是线性规划,割平面性质才成立。储能充放电效率本身不是线性的,但好在我们可以把充电效率和放电效率拆开表示成两个系数,这样就线性化了。另外,为了防止同时充放电这种无意义的解,还需要加上P_c,t + P_d,t <= 额定功率的约束,或者直接用二进制变量去强制互斥——但二进制变量会破坏LP结构,所以我建议用线性约束近似替代,实际效果基本没有差异。

3.2 场景生成与削减

场景是SDDP的食粮。场景质量直接决定最终调度的鲁棒性,这一块可以说是整个项目里最"玄学"但最不能偷懒的部分。我使用的是"历史统计数据 + ARIMA模拟"的组合方式。具体做法:收集该园区光伏过去一年的15分钟分辨率出力数据,对每个时段提取出力的条件概率分布;然后使用ARIMA(2,1,2)模型拟合出力的时序波动模式,用蒙特卡洛方法生成大量出力的可能轨迹。

生成场景的初始规模我会定在5000条。5000条轨迹做完整SDDP训练,内存开销和计算时间都很可观。所以下一步需要用场景削减技术,把5000条缩减到200到300条,同时尽量保持原场景集合的概率分布特征。我常用的是快速前向选择(Fast Forward Selection)法,它的核心思想是贪心挑选"最能代表整体概率距离"的子集。实际做下来,削减到200条后,累计概率距离相对原始集合的偏差不到3%,对调度结果的影响完全可以接受。

有一个经验教训一定要讲:生成场景时,必须显式加入"极端但不能省略"的场景,比如连续阴雨天导致的连续3小时光伏出力抑制在10%以下。如果不加,SDDP学习的价值函数会在极端情况下给出过于乐观的决策,现场一旦真遇上这种天气,SOC可能提前耗尽。我通常会在场景集里固定加入5%概率的极端场景,虽然它们不是历史数据里的高频事件,但工程上这叫"鲁棒性余量"。

3.3 参数设定与调优

参数调优是这个项目中花时间最多的一环,因为SDDP对参数的敏感度比一般优化算法高不少。最核心的参数是迭代轮数。如前所述,我设定的阈值是最优性间隙小于0.8%,如果200轮还没达标,就检查场景质量和割平面数量。另一个参数是采样路径数量:每轮迭代前向模拟使用的路径数我设在20条。为什么不是更多?因为后向递归的计算量随路径数线性增长,20条在收敛速度和计算成本之间是比较均衡的。如果您对实时性要求更高,可以降到10条,但上下界的方差会变大,收敛判据要放松到1.5%左右。

还有一个经常被忽视的参数:割平面的存储上限。每轮迭代每阶段都会新增一个割平面,200轮下来就是96×200×20,约38万个割平面,内存和查询速度都会受影响。我的做法是每隔50轮做一次"剪枝":把那些斜率相近、且在决策区间内几乎没有唯一支撑贡献的割平面合并或删除。这有点像清理服务器的日志文件,不清理系统也能跑,但清理完跑得更快。剪枝后的价值函数会损失一点点精度,但我实测偏差在0.1%以内,完全可接受。

关于求解器的选择,我建议用能输出对偶变量的LP求解器,比如Gurobi或Cplex。开源的Cbc也支持,但数值稳定性稍差。SDDP里的数值误差有一个累积效应——如果你用的是双精度浮点,LP求解的容差设置不当,割平面会出现轻微扭曲。我把Gurobi的整数规划容差设为1e-6、LP可行性容差设为1e-7,这组参数在我的项目里验证过非常稳。

3.4 核心流程伪代码与实现要点

我把离线训练的核心逻辑和你分享下,你用任意语言都能实现:

# 伪代码:SDDP离线训练主流程 initialize: V_functions[t] = 初始割平面集合(保守下界) scenarios = load_场景集() best_gap = INF for iter in range(max_iterations): # 前向模拟 states = [] for path in sample_paths(scenarios, num_paths=20): soc = SOC_initial path_states = [soc] for t in range(T): # 求解当前阶段决策,使用当前V_functions[t+1]近似未来成本 decision, soc_next = solve_subproblem(t, soc, observed_pv[t]) soc = soc_next path_states.append(soc) states.append(path_states) # 后向递归 for t in reversed(range(T)): for path_states in states: # 用当前状态值求解子问题,得到对偶乘子lambda alpha = solve_backward(t, path_states[t]) # 生成新割平面并添加到V_functions[t] V_functions[t].add_cut(alpha, lambda) # 计算上下界和最优性间隙 upper_bound = average_cost_of_forward_paths() lower_bound = current_objective_from_initial_stage() gap = (upper_bound - lower_bound) / abs(lower_bound) if gap < tolerance: break

几个实现细节要特别注意。第一,子问题的目标函数里,未来成本部分是一个变量,而不是一个常数。你要把它表示成V_functions[t+1]这个分段线性函数的取值,通过添加"未来成本变量"并让割平面约束它来实现。第二,初始割平面必须给出一个保守的下界,否则算法一开始就可能跑飞到不可行域。我给你一个简单做法:设置一个足够大的常数作为初始下界——但注意,如果这个常数太大,收敛速度会显著降低;如果太小,又可能切掉可行解。我的习惯是先跑一轮确定性场景,用它的成本作为初始下界的一个参考。

第三,关于并行。后向递归的阶段之间是有依赖的,但同一阶段的不同路径之间天然可以并行。如果你有多核CPU,建议按阶段内路径做并行,这样能大幅缩短单轮迭代时间。我在8核机器上,把路径维度的并行打开后,训练速度提升了约4倍。

4. 实时调度中的几个关键工程决策

离线训练完成只是第一步。把SDDP用在实际的实时调度系统里,还有几个工程决策不做好的话,前面所有精度都白搭。

4.1 滚动时域前瞻窗口该设多长

使用SDDP做在线决策时,最常见的模式是这样的:把训练好的V函数直接当作"远期成本函数",在每个时段只求解当前阶段的子问题,用最新的实测值更新可再生能源观测状态,得到一个具体的充放电指令,执行之后进入下一时段。这个模式不需要每次都展望全部未来时段,计算量很小。但有一个关键问题:训练的价值函数是基于你设定的调度周期(24小时)算出来的,如果实际运行中,调度周期不是整数天,或者你希望在一天中的某几个时段做更贪婪的决策,那么价值函数的尾端效应就会显现。

尾端效应怎么理解?最后一个阶段之后的价值函数V_{T+1}如果设置不当,会导致最后一个时段的决策不顾一切地把SOC用尽,或者相反地不敢用电。我的做法是给V_{T+1}设置一个尾端惩罚项——当调度周期结束时SOC低于某个目标值,会产生一个线性惩罚成本。这个目标值可以设为你期望的次日起始SOC,比如50%。这样一来,尾端有了约束,整个周期内的调度策略就不会出现"最后半小时疯狂放电"的情况。

关于前瞻窗口,我实测过的结论是:对于工商业储能的峰谷套利场景,前瞻窗口24小时足够;对于参与现货市场、电价波动剧烈的场景,需要48小时甚至72小时。但窗口拉长后,SDDP训练的场景复杂度会上升,收敛速度下降,效果是对尾端状态的考虑更周全。你需要做权衡。

4.2 SDDP与在线修正结合的混合策略

纯SDDP方案的短板在于,它的场景集和概率分布是离线做出来的,没有充分利用实时信息。比如光伏实测值现在明显比任何历史场景都高,离线场景分布根本反映不出来。所以在实际部署中,我不推荐用它做完全替代每时每刻的MPC。更好的做法是混合策略:以SDDP的V函数作为长期锚,在每个调度时刻,先用最新的光伏实测值做一次短周期的MPC修正,然后把MPC当前时段决策与SDDP的决策做加权融合。

我举一个具体例子。16:00的时候,实测光伏还有200 kW,但天气云层正在移过来,15分钟后大概率只剩50 kW。离线SDDP并不知道这朵云的存在,它的决策可能是继续以80 kW的功率充电。而使用最新遥感数据的短周期MPC会预判到风险,建议立即转为放电或者减少充电。把两者按8:2或7:3的权重混合,可以得到一个既不过于保守、又具备实时感知能力的指令。加权比例的具体数值我没法给你普适的推荐,因为取决于你的预测系统置信度,但一个可以接受的调试起点是:预测越准,MPC权重越大;预测不准的时候,SDDP占大头,因为它的鲁棒性强。

我踩过的坑是:直接让SDDP的输出接管整个实时指令,会导致在极端天气切换的场景里决策滞后10到20分钟,而这期间可能已经错失了一个套利窗口。所以混合策略不是锦上添花,而是实时的必需。

4.3 数值稳定性与并行计算

SDDP的数值稳定性问题,大多数出在割平面退化上。什么意思呢?如果某个阶段的价值函数本来就是平坦的,那么该阶段生成的所有割平面斜率都会接近同一个值,这些割平面高度线性相关,在后续的LP求解里会导致基矩阵奇异。我专门为此在代码里加了一个检测:当两个割平面的斜率差的绝对值小于1e-4时,就删掉其中之一。这个处理让很多原本病态的模型变得稳定下来。

实时性方面,单时段求解当前阶段子问题,一般只需要几十毫秒到几百毫秒。如果你对更快的响应有要求,可以提前把所有可能SOC离散点上的决策结果查表存储。在线时,根据实测SOC做插值,直接把决策指令读出来。这个查表方法的缺点是需要离线算一个二维查询表(SOC × 时段),但我实测在96时段、SOC点400个的情况下,查询表大小不到10 MB,决策速度可以做到20毫秒以内,完全满足实时控制要求。

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

这一部分全是干货。SDDP用起来不是打开库就能跑,中间会遇到各种奇怪的问题,我把最典型的几种以及排查思路列在下面。

5.1 收敛缓慢与上下界不闭合

遇到最多的问题是上下界差距迟迟降不下来,或者下降非常缓慢。第一反应不是去调迭代轮数,而是去查初始割平面是否给得太紧。如果初始下界建得太高,会导致算法一开始就处在不可行区域内,后续的割平面更新无法有效上抬下界,收敛自然慢。

我常用的排查方法是把迭代早期和晚期的价值函数画出来看形状。如果V函数看起来像一个V字形折线,但底部有明显凹陷或者多出一条异常拐点,多半是场景集中某些路径产生了极端的可行性问题。另外,检查上界计算是否使用了太多低概率的极端场景,也会导致上界虚高。我的建议是把上界评估场景集固定下来,并且保证它和训练场景集不重叠,用独立的验证集评估每轮迭代的上界,这样得到的收敛曲线才可信。

5.2 场景退化导致调度方案失真

场景退化是说削减后的场景集合过于集中,多样性不足,导致SDDP学到的策略在真实场景里表现不佳。怎么检测?用独立的历史实测数据来回测调度策略,比较仿真成本和策略预期成本的差距。如果差距明显大于理论上界,说明场景分布和真实分布不匹配。

解决办法有两个方向。一是增加场景数量,把削减后的集合从200提升到500,代价是训练时间翻倍。二是引入场景生成的不确定性扩散,在ARIMA模拟时对波动项施加一个随机扰动,使得生成场景在概率上更接近真实分布。我个人的建议是:如果你的存储容量/发电容量比值较小(即储能相对光伏来说不够大),场景质量对性能的影响会更敏感,这种情况建议把削减后的场景数控制在300以上。

5.3 Benders割质量不佳的处理

割平面质量差,一般表现为策略在相邻时段出现频繁的充放电切换,且幅度较大。这个现象有一个直观的名字叫"振荡"。原因往往是割平面的斜率在某些区域出现突变,导致当前阶段的目标函数呈现锯齿状。锯齿状目标函数会让LP求解器在顶点之间来回跳动,最终输出的决策对状态值极其敏感。

处理振荡的一个有效技巧是引入正则项。在目标函数里加上一个很小的二次惩罚项,比如0.001乘以充放电动作的变化量平方。虽然这会略微偏离原问题的最优解,但对LP的稳定性帮助巨大。实测下来,牺牲的调度经济性通常在0.5%以内,完全值得。另一个技巧是,在实时决策时对充放电功率做一阶滤波:允许决策每15分钟最多变化30%的额定功率。这个限制压住了振荡,也让储能PCS的实际跟踪误差大幅下降。

6. 我的实践经验与心得

如果非要用一句话总结SDDP在储能调度中的价值,我会说:它把"面对不确定性时的从容"变成了一个可计算、可复盘的工程资产。这不是说SDDP在数学上比其他随机优化方法更高明,而是说它在计算复杂度和策略质量之间找到了一个最适合工程落地的平衡点。

我在切换到这个方案之后,最大的感受是调度策略的"性格"变了。以前用确定性MPC,策略总有一种"硬碰硬"的感觉——今天预测太阳能充足就拼命充,明天预测不行就完全不动;而SDDP的策略则更像是老司机开车,会提前预判路况,不急不躁地调整SOC。最终从曲线图上能看到一个明显的特征:SOC的变化更平滑,充放电次数明显减少,电池的循环寿命也因此受益。项目结束后的统计数据是,月度收益比之前提升了大约11%,电池等效满充满放次数下降了约15%,这两个数字都超出了预期。

最后分享一个小技巧,也是这个方向后续可以继续扩展的点:把SDDP和强化学习放在一起用,往往能得到更好的结果。SDDP的价值函数是凸的、可解释的,但它的策略缺少对非凸因素(比如设备退化成本、电价跳变)的建模能力。你可以用SDDP的策略作为一个高度可靠的初始策略,再用强化学习去做残差校正。这样既保留了SDDP的鲁棒性,又能把那些难以建模的细节吸收进来。我这个方向已经做了一些初步实验,效果很鼓舞人心,后面有机会再单独写一篇详解。现在如果您的项目正在被可再生不确定性折磨得焦头烂额,不妨先在您的调度系统里把SDDP跑起来,我相信您也会体会到它那种"算不过来但算得准"的奇妙感觉。

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

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

立即咨询