做微网优化调度的人,十有八九都绕不开一个让人头疼的问题:光伏、风电出力根本没法精准预测,今天看是晴天,下午一片云飘过来,光伏出力瞬间暴跌。你要是按一个固定的预测值去做调度计划,真到了运行时刻,不是切负荷就是弃光弃风。今天要聊的这个项目,就是针对这个问题给出了一套完整解法——用基于关键场景辨别算法的两阶段鲁棒优化来做微网调度。核心是先把不确定性建模进优化里,再用关键场景辨别算法从海量场景里挑出最有威胁的那几个,以此驱动两阶段鲁棒模型的迭代求解,最终得到一套“在最坏情况下也扛得住”的调度方案。整个实现基于Matlab代码完成,主问题、子问题、场景筛选、CCG主循环都在同一套代码框架里衔接。这篇文章我会把模型的数学逻辑、算法的筛选思路、Matlab的代码架构和调试中踩过的坑全部摊开讲,适合正在做微网调度、主动配电网优化,或者想研究鲁棒优化怎么落地的研究生和工程师们。
1. 微网调度为什么要用“两阶段+鲁棒”这套组合拳
1.1 不确定性到底从哪来,传统方法为什么扛不住
微网里的不确定源比想象中多。风电出力和光伏出力是最大的两头,它们受天气、温度、云层、风速曲线影响,短期预测误差经常能到20%以上。除了电源侧,负荷侧也有波动,用户用电行为没有严格规律,尤其居民负荷,夏天傍晚空调一开,晚高峰负荷曲线直接抬头。另外,电价信号在日前市场和实时市场之间也存在偏差,属于市场侧的不确定性。这些因素叠加在一起,如果调度模型里只用一个确定性的预测值,得到的机组组合和储能计划在真实场景里往往不是次优,而是直接不可行。
传统做法里,最典型的是场景法。你把历史数据拿来,生成1000个可能的风光出力场景,然后把每个场景对应的约束都塞进同一个优化模型里,试图让方案在所有场景下都可行。这个方法在小规模系统里勉强能跑,场景一多,约束和变量的规模成倍膨胀,求解时间直接崩。而且场景法最大的问题在于:它把所有场景都当成“平等的”,但实际上很多场景对调度结果的影响很小,比如风电出力处于中位水平、且与预测值接近的那些场景,根本不会让系统逼近安全边界。真正决定方案鲁棒性的,是那些“小概率、大影响”的极端场景。
1.2 两阶段鲁棒优化的本质:先决策,后校核
两阶段鲁棒优化解决问题的思路很巧妙。它把调度问题拆成两个阶段:第一阶段是“这里现在就要做”的决策,对应微网里的日前调度,包括机组启停、储能充放电计划、与大电网的购售电计划,这些决策必须在不确定性实现之前就要定下来,属于“看到天气前就要决定”的部分。第二阶段是“等真实场景出来之后再做”的调整决策,对应实时调度,比如机组实际出力调整、储能实时充放电功率微调、切负荷量等,属于“看到天气后再补救”的部分。
这个思想说白了就是“先拍板,再校核”。第一阶段做决策时,并不假设不确定性一定是某个固定值,而是假设它落在某个不确定集合内,然后在集合里挑一个“最坏情况”,看第一阶段方案在最坏情况下能不能通过第二阶段的调整来保证可行。如果最坏情况都能兜住,那其他场景自然没问题。这就是鲁棒优化和确定性优化、随机优化最本质的差别:随机优化追求期望最优,鲁棒优化追求最坏情况兜底。
1.3 关键场景辨别算法在整个框架里的位置
刚才讲了,两阶段鲁棒的核心是“挑最坏场景”。那问题来了:不确定性集合里的场景有无数个,你总不能把每个场景都拿来算一遍吧?这时候就需要一个工具来快速锁定那些真正可能导致系统越限、成本激增、甚至无解的“关键场景”。关键场景辨别算法干的就是这件事——它从候选场景集合中,用一套评分和筛选机制,挑出少数几个“最坏”场景,作为第二阶段的校核标准。
这样设计的好处是显而易见的。一方面,两阶段鲁棒模型不必显式枚举所有场景,避免了组合爆炸;另一方面,算法迭代过程中会不断补充新的关键场景到主问题中,像滚雪球一样,每轮都让方案更稳健,直到达到收敛条件。整个求解框架就变成了一个“主问题-子问题”交替迭代的过程,这也就是国内文献里常说的列与约束生成算法(C&CG)。关键场景辨别算法是子问题输出端的一个滤波器,它决定哪些场景值得被升级为约束。
2. 关键场景辨别算法的原理与设计思路
2.1 从“遍历所有场景”到“只挑关键场景”:省的不只是时间
我刚接触鲁棒优化时,第一反应就是枚举:把所有可能的波动场景列出来,逐一检验方案是否可行,不可行就把约束补进去。这个思路本身没问题,但实际操作中会撞上两堵墙。第一堵墙是维度灾难,不确定源一多,场景数量成指数增长,微网里至少有三个不确定源(风电、光伏、负荷),每个取10个离散水平,组合就是1000个场景,第二阶段的子问题就得求解1000次min问题,每次还嵌套max,基本算不动。第二堵墙是大量无效约束,绝大多数场景对应的约束是冗余的,把它们加进主问题,除了拖慢求解速度,没有任何收益。
关键场景辨别算法的价值在于:它把“全部场景”压缩为“少量关键场景”,而且这些场景在几何上覆盖了不确定集合的极端边界。通俗点说,不需要把每一个可能的天气都试一遍,只需要试最晒、最阴、风最大、风最小这些极端组合,再从中挑选几个代表性场景即可。这个思路有点像做可靠性分析时的最劣状态搜索,也有点像全局优化里的主动约束识别,都是为了用最小的代价逼近问题的本质边界。
2.2 候选生成、评分筛选、迭代收敛:三步走流程
在实际代码里,关键场景辨别算法可以拆成三个模块。第一步是候选场景生成,这一步产生一个规模适中的初始场景池,可以基于历史数据的抽样、拉丁超立方采样,也可以在不确定性集合的极值点附近取点。生成方式直接影响了算法的覆盖质量,我建议用拉丁超立方或者Sobol序列,比纯随机抽样更均匀。第二步是场景评价,对于当前第一阶段方案,逐一求解每个候选场景对应的第二阶段最小化问题,得到一个“最坏损失值”,再按损失值降序排列。第三步是筛选与更新,把排在前面的场景加入主问题约束,同时用场景之间的欧氏距离做去冗余处理,保证新增场景和已有场景有足够差异度,避免加入一堆几乎重叠的约束。
整个过程被嵌在C&CG主循环里,每轮迭代后重新生成候选场景、重新评价,直到主问题上界和子问题下界的差小于给定阈值,就判定收敛。实际算例中,这个算法通常只需要4到5次迭代就能达到不错的收敛精度,而如果直接枚举全部场景,主问题的规模可能会膨胀到无法求解的地步。
2.3 场景评价指标怎么设计:目标增量、最坏程度与差异度
评价指标是整个算法的灵魂。用得最多的一种方式是目标增量指标:给定一个场景,把它代入当前方案的第二阶段优化问题,求出在该场景下系统的最小运行成本,这个成本与“场景为预测值”时的基准成本之差,就是该场景带来的额外代价。差值越大,说明这个场景越“凶险”,越应该被选为关键场景。这一点很容易理解,如果某一天风突然停了,光伏也只有两成出力,整个微网得全靠储能和从大电网购电撑住,成本自然飙升,这种场景就是最能检验方案成色的试金石。
差异度指标则是为了防止选了太多的“相似场景”而导致约束冗余。两个场景如果各节点出力偏差都很接近,那么它们对应生成的约束本质上是同一条,根本没必要都加进主问题。我在代码里一般用归一化后的欧氏距离来度量场景差异,只有当新增场景与现有关键场景集合中每个场景的距离都超过一定阈值时,才把它加进去。这个阈值调得太小,场景会很多,求解变慢;调得太大,又可能漏掉真正有威胁的场景,需要在实验里多试几组值对比。
2.4 收敛性判据与参数敏感性
收敛判据用的是经典的上下界间隙。主问题求解得到一个目标函数值作为下界,因为主问题是在有限个场景下求最优,随着关键场景不断加入,下界只会不断增大;子问题求解得到的是第一阶段方案在最坏场景下的真实成本,作为上界。两者之差除以初始下界的绝对值,小于比如1e-3,就视为收敛。这里有个细节需要注意:如果第一阶段决策是整数变量,比如机组启停,那么两次迭代之间这个间隙可能出现振荡,解决办法是给整数变量设置一个热启动初值,把上一轮的最优解传给下一轮主问题,能明显加速收敛。
参数敏感性方面,最值得关注的是不确定性预算Γ。Γ代表不确定源中“最多有几个能同时达到最坏水平”,Γ越大,不确定集合范围越大,方案越保守,成本越高。实际工程里Γ不是越大越好,应该根据预测精度和运行风险容忍度来折中。这个参数在关键场景辨别算法中直接决定了候选场景的极值点分布范围,所以算例分析时一定要做Γ的灵敏度测试,给决策者提供一个投入产出的曲线。
3. Matlab代码实现:架构、建模与核心模块拆解
3.1 代码总体架构:六个模块各司其职
这个项目我用Matlab写完整实现,整体分为六个模块。主入口脚本负责加载基础数据、设置全局参数、启动CCG主循环;数据预处理模块读取负荷曲线、可再生能源出力预测及误差区间,生成不确定性集合;主问题模块用YALMIP或直接调用Cplex接口构建混合整数线性规划,求解第一阶段决策;子问题模块把第二阶段的内层min问题通过对偶或者KKT条件转化为单层优化问题,再和不确定性集合结合成max-min问题;关键场景辨别模块接收子问题的场景集,执行评分排序和去冗余;最后是结果输出模块,把调度曲线和迭代过程绘图保存。这样的分层架构在调试时特别好用,哪里出了问题,直接定位到对应的函数就行,不用在一大坨脚本里翻来翻去。
模块之间的数据流我简单梳理一下。主入口把系统参数传给数据预处理模块,得到不确定集合的上下界和基准场景;然后进入CCG迭代,每一轮主问题模块输出第一阶段方案,传给子问题模块;子问题模块在当前方案下搜索最坏场景,输出候选场景集合;关键场景辨别模块筛选出关键场景并反馈给主问题模块作为新增约束;主问题重新求解,循环往复。这种清晰的单向依赖关系,也让后面做并行加速变得容易——子问题对各个候选场景的求解天然是并行的,可以开parfor同时跑。
3.2 数据准备与不确定性集合建模
数据准备是建模的地基。负荷曲线和风光出力预测值,我建议直接读入真实的微网历史数据,没有的话可以用Matlab自带的一些标准测试系统数据,比如IEEE 33节点配电网数据改造出来的微网数据也行。每条曲线至少取一天24个时段的功率值。除了预测值,还需要给出误差范围,这里我用的是百分比的上下波动区间,比如光伏出力预测误差为±20%,风电为±30%,负荷为±15%。在此基础上,不确定性变量用一个盒式集合描述:每个时段每个不确定源的真实值等于预测值加一个扰动,扰动的绝对值上界由预测误差决定。
不确定预算Γ在代码里是个标量参数,代表所有时段里允许同时达到最坏情况的“不确定源-时段”组合数上限。这个参数很关键,它直接控制了鲁棒优化模型的保守程度。Γ=0时模型退化为确定性模型;Γ越大,算法考虑的最坏情况越极端。初始调试时建议先设Γ=1或者2跑通,再去逐步增大测试。这里我用了一个24×3的参数矩阵UncertaintyRange和标量Gamma,方便后续做敏感性分析。
3.3 主问题建模:第一阶段决策怎么变成MILP
主问题是整个模型中规模最大的部分。目标函数由三个成本构成:机组发电成本、储能运行成本(包括充放电老化成本)、与大电网的购售电成本。其中机组发电成本我用分段线性函数近似,储能成本简化为充放电功率的线性成本,购售电则分峰谷时段取不同电价。决策变量包括机组启停状态(0-1变量)、机组出力、储能充放电状态(0-1变量)和功率、购售电功率等连续变量。
约束条件里最核心的是功率平衡约束、机组出力上下限约束、爬坡约束、储能容量约束和充放电功率约束。注意,第一阶段决策下发的机组启停和储能充放电状态,在第二阶段子问题里是给定的,不能再改变,这就是两阶段鲁棒“先决策、后校核”的体现。如果在第一阶段就把储能充放电功率也完全定死,第二阶段就没有调整手段了,模型的鲁棒性会大打折扣。所以正确做法是:第一阶段只定储能充放电状态和机组启停,具体的出力值留给第二阶段去优化调整。
3.4 子问题建模:max-min双层问题怎么求解
子问题的数学形式是一个max-min双层问题,外层的max在不确定性集合里寻找最坏场景,内层的min是在给定场景和第一阶段决策下求最小运行成本。直接求解这个双层问题很困难,常规思路是内层min先写出拉格朗日函数,利用强对偶条件把min转化为max,这样内外层就统一成了一个max问题。如果内层约束比较复杂,也可以引入KKT条件,把内层问题转成一组带互补松弛条件的约束,再用Big-M法做线性化。我在这个项目里用的是强对偶转化,因为子问题内层是个线性规划,没有整数变量,强对偶成立的条件比较干净。
转化完成后,子问题变成了一个单层的max问题,目标函数里出现了对偶变量与不确定性变量的乘积项。由于不确定变量是一个有界的连续变量,这个双线性项会导致问题变成非凸的,直接求解很棘手。处理办法是对不确定变量引入0-1辅助变量,表示该不确定源是否偏离预测值到边界,再用Big-M线性化处理乘积项。这一步是模型求解的关键,代码里涉及不少对偶变量和Big-M参数的书写,最容易出错,后面我会专门讲调试经验。
3.5 关键场景辨别模块的Matlab实现
关键场景辨别模块虽然核心逻辑不长,但它是整个代码里最能体现算法设计思想的部分。我给出一个典型框架:
function [keyScen, keyVal] = key_scene_select(worstSceneMat, baseCost, ... thresholdDist, maxKeepNum) % worstSceneMat: 候选场景矩阵,每列是一个场景 % baseCost: 基准场景下的第二阶段最小成本 % thresholdDist: 场景差异度阈值 [~, nScene] = size(worstSceneMat); deltaCost = zeros(1, nScene); for i = 1:nScene cost_i = sub_problem_fixed_scene(worstSceneMat(:, i)); deltaCost(i) = cost_i - baseCost; % 目标增量 end [~, idx] = sort(deltaCost, 'descend'); keyScen = []; for j = idx if length(keyScen) >= maxKeepNum break; end % 去冗余:新增场景必须与已有场景差异够大 if isempty(keyScen) || min(pdist2(...)) > thresholdDist keyScen = [keyScen, worstSceneMat(:, j)]; end end keyVal = deltaCost(idx); end在真实代码里,我还会把这个函数的候选场景数量动态调整,第一轮迭代时候选场景多生成一些,比如2000个,后续迭代可以减到500个,因为随着方案趋于稳定,极端场景往往就在那少数的几个位置反复出现。一度我以为关键场景辨别模块只是一个性能优化手段,后来跑多了才发现,它其实还承担着约束管理的作用——如果不加筛选,CCG迭代到第三轮之后主问题里就会堆积大量几乎相同的约束,求解速度会肉眼可见地退化。
3.6 CCG主循环:迭代求解整体节奏
主循环的框架我之前在项目里总结成了一个标准结构,分五个步骤。第一步,初始化:给定一个初始场景(通常是预测场景),添加到主问题的关键场景集合中。第二步,求解主问题,得到第一阶段决策和下界目标值。第三步,固定第一阶段决策,求解子问题,得到最坏场景和上界目标值。第四步,调用关键场景辨别模块,筛选新的关键场景并加入主问题。第五步,检查上下界间隙,如果小于容差就退出,否则回到第二步继续迭代。如果只想看一个整体雏形,可以对照下面的代码骨架来理解:
for k = 1:maxIter [x1, objMP] = solve_master(keyScenes); LB = objMP; [worstScen, objSP] = solve_sub(x1); UB = objSP; fprintf('Iter %d: LB=%.2f, UB=%.2f, gap=%.4f\n', ... k, LB, UB, abs(UB-LB)/abs(LB)); if abs(UB - LB) / abs(LB) < tol break; end keyScenes = [keyScenes, key_scene_select(worstScen)]; end实际运行中还要注意几个坑。第一个是子问题求解失败时上界会缺失,不能直接跳过,否则收敛判据会出错,我的处理方式是设置一个很大的惩罚上界,强制继续迭代。第二个是主问题和子问题目标函数的常数项要保持一致,比如储能初始容量、系统固定成本这类不变量,两边都要加上,否则上下界永远有系统性偏差。第三个是诊断信息要多打印,每轮迭代的上下界、关键场景个数、求解耗时,都要记录在案,这样分析收敛曲线时才能看出问题。
4. 算例测试与结果分析:算法到底能省多少
4.1 测试系统与参数设置
为了验证这套两阶段鲁棒微网调度方案的性能,我搭了一个典型的小型微网测试系统,包含一台燃气轮机、一台柴油发电机、一个储能系统、一个光伏电站、一个风电场,外网联络线可以双向购售电。负荷曲线取夏季典型日,光伏出力曲线按晴天设定,风速数据取某风电场实测数据的聚合值,整个系统按24个时段建模。光伏预测误差设为±20%,风电预测误差设为±30%,负荷预测误差设为±15%,不确定性预算Γ分别测试0、1、3、6四组。
求解硬件就是普通的台式机,Intel i5处理器,16GB内存,求解器用的Gurobi,通过YALMIP在Matlab里完成建模与传递。迭代容差设为1e-3,最大迭代次数设为50次。为了公平对比,我还实现了一个把所有候选场景显式加入主问题的枚举场景法作为基准,场景数量取100、500、1000三档。
4.2 结果解读:成本变化与迭代过程
先看Γ=3的典型结果。枚举1000个场景时,主问题约束数量爆炸,单次求解耗时接近150秒,而且因为整数变量太多,求解器内存占用峰值到7GB以上,有几轮迭代几乎卡死。而关键场景辨别算法在同一测试条件下,每轮只保留不超过20个关键场景,单次主问题求解耗时大约10到15秒,整体迭代5轮收敛,总耗时约70秒。两相对比,求解时间下降了50%以上,同时内存占用大幅降低。这个差距在只有3个不确定源、24个时段的模型里就已经这么明显,放到节点数更多、不确定源更多的系统里,差距只会进一步拉大。
调度方案本身的鲁棒性也值得说。在Γ=3的保守水平下,系统的总运行成本为9625元,而Γ=0的确定性模型算出来是8933元,成本增加了约7.7%。这多出来的成本就是“买保险”的代价,换来了在最坏场景下系统依然能保持功率平衡、储能不越限、电压不越界的能力。如果决策者觉得7.7%的成本增幅可以接受,那这个方案就可以直接落地;如果想更激进一些,把Γ降为1,成本增幅只有2.3%,保守程度也相应降低。这里面的权衡是鲁棒优化最实际的一个问题,多做几组Γ的对比,给决策者的参考价值远大于单点最优解。
4.3 关键场景的时间分布特征
还有一个有意思的观察:算法筛出来的关键场景并不是随机分布的,而是集中在晚高峰和光伏出力骤降的时段。比如在Γ=3设置下,算法识别出的最坏场景往往是“午后光伏出力仅为预测值的60%、同时晚高峰负荷比预测值高15%”的组合。这个结果其实揭示了不确定性对调度方案的真实威胁路径,光伏骤减导致晚高峰前储能无法存满电量,晚高峰负荷又高于预期,机组爬坡能力不够,只能高价购电。在调度方案的呈现上,储能系统会在午间提前加大充电功率,燃气轮机在下午就提高出力下限,这些防御性动作都是鲁棒方案自动学出来的,而不是人工预设的规则。做鲁棒优化,很多时候跑完结果,你对系统薄弱点的理解会比以前深刻得多。
4.4 参数敏感性:偏差范围和关键场景数量的影响
我再提一组敏感性测试的结论。固定Γ=3,把光伏预测误差从±20%调整到±30%,关键场景数量上限从10增加到30,系统成本变化并不明显,说明增加一定数量的关键场景并不会显著提高保守度,约束冗余的情况被差异度阈值控制得很好。相比之下,把差异度阈值降到原来的一半,关键场景数量直接从平均12个涨到28个,主问题求解时间翻倍,但上下界间隙并没有明显改善。这个现象说明,阈值设置太小时算法会把相似的边界场景重复纳入,纯属浪费算力。我最终的推荐是:差异度阈值取基准场景波动幅度的10%到20%,关键场景数量上限取10到20个,是一个比较划算的区间。
5. 调试经验与常见问题实录
5.1 主问题不可行:八成是约束漏了
调试过程中最容易遇到的是主问题直接报infeasible。第一次遇到时,我先怀疑是参数写错了,后来一点点排查,发现是储能约束出了问题。储能在一个时段内的能量状态变化,既要满足充放电功率约束,又要满足容量上下限,如果第一阶段初始的储能电量设置得太低,同时第二阶段又不允许切负荷,功率平衡约束就会被顶穿,主问题自然不可行。解决办法有两个方向:要么把初始储能电量设置在一个合理水平,比如总容量的50%;要么在第二阶段加入失负荷和弃风弃光变量,并赋予很高的惩罚成本,这样即便在最坏场景下,系统也不会因为“完全无解”而直接崩溃,而是以极高代价做最后的兜底。
还有一个细节:加入关键场景生成的约束时,如果多个关键场景对应的第二阶段决策变量不同,那么它们在主问题里生成的约束是独立的,不能直接合并。曾经我图省事,想用一组变量代表所有场景的第二阶段调整,结果主问题规模是降下来了,但解出来的第一阶段方案在子问题里怎么都验证不通过,上下界差距一直在40%以上。原因是不同场景里储能和机组的调整动作完全不同,强行共用变量等于砍掉了第二阶段的适应能力。
5.2 Gurobi接口报错:YALMIP参数类型要统一
YALMIP和Gurobi联用的时候,最常见的报错是“Unable to convert expression into a linear constraint”之类的类型不匹配错误。这种情况经常出现在Big-M线性化的代码里。比如要表达一个对偶变量乘以不确定变量的项,如果M取的是一个大常数,比如1e6,而其他变量是double类型,YALMIP在构建约束时可能会因为变量的属性推断问题抛出异常。我的经验是,所有涉及Big-M的辅助变量都要显式声明为二元变量,M的值不要超过模型量纲的100倍,太大了会引发数值稳定性问题。
另外,Gurobi的多线程参数和YALMIP的求解设置要匹配。我试过在子问题里使用并行求解,也就是开parfor同时算多个场景的子问题,结果每个worker都会自动开满线程,导致CPU超卖,整体速度反而下降。后面我统一在模型求解前关闭Gurobi的线程重用,或者干脆串行求解子问题,反而更稳定。真要并行,建议直接对主问题用Gurobi自带的并发求解器,效果更好。
5.3 上下界长期不收敛:检查不确定性集合的边界
我在一次测试中发现,上下界迭代到第10轮还没有收敛趋势,UB一直在某个水平附近小幅波动,LB却增长得很慢。排查后发现,不确定性集合的边界设置有问题。光伏出力偏差我用了±20%,但这个偏差是相对预测值而言的,而预测值在某些时段本身很低,比如夜里光伏预测值几乎为零,±20%的上界还是接近零,导致这些时段的极端场景根本没有威胁性,关键场景搜索空间被浪费了。正确的做法是对偏差设置一个绝对下限,比如偏差绝对值不得小于额定容量的5%,这样即便预测值很低,极端场景也有足够的差异化能力。
另一个常见的坑是预算Γ的实现方式。Γ表示整个调度周期内最多允许多少个“时段-不确定源”组合达到最坏情况,但这个约束应该在子问题里实现,而不是在不确定集合的边界上直接体现。如果代码里把Γ错误地写成了每个时段都要满足的独立约束,那么模型会自动把所有时段都推向最坏,极端保守,成本会比预期高出20%以上。调试时可以通过收敛后的关键场景总数来反推,正常情况关键场景总数不会超过Γ乘以不确定源数量,如果超过了,说明Γ约束写错了。
5.4 场景差异度阈值怎么调:从成本-鲁棒性曲线里找答案
差异度阈值这个参数,很多人第一次做时容易忽略,觉得只是性能优化,随便设一个就行。实际上它对算法稳定性影响很大。阈值太大,关键场景太少,主问题过早收敛,子问题复核后却可能发现方案在某个没被覆盖到的边界场景下不可行,上界跳变,导致已经收敛的迭代必须回退。阈值太小,关键场景太多,主问题庞大,算力浪费。我的经验是先把阈值设为0跑通基准,记录关键场景的总数、上下界的历史曲线,然后逐步增大阈值,观察上下界间隙是否会变差。当间隙在容忍范围以内、关键场景数量明显减少时,这个阈值就是当前系统的最优配置。
最后说一个个人体会。做这个项目时,我最初也想直接抄一个成熟的C&CG框架,然后把关键场景辨别算法塞进去就完事。后来几次调参跑崩溃才发现,鲁棒优化这类模型,真正的难点不在算法本身,而在对模型物理意义的把握。你越理解微网里储能的充放电时序、机组的爬坡瓶颈、峰谷电价的博弈关系,就越能判断代码里的哪个变量、哪个约束不对劲。两阶段鲁棒也不是银弹,它只是把不确定性留给第二阶段去适应,第一阶段的保守是显式的、可控的。调试中还有个小技巧:把Γ设为0跑一遍确定性模型,再把所有极端场景全部放进枚举模型里跑一遍,这两个结果就是算法的上下界参考点,无论怎么调参,两阶段鲁棒的结果都应该落在它们之间。如果不在,模型哪里写错了,一查一个准。