news 2026/10/20 14:34:17

微电网两阶段鲁棒优化调度:CCG算法应对风光不确定性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微电网两阶段鲁棒优化调度:CCG算法应对风光不确定性

1. 微电网优化调度为什么要考虑不确定性

做园区级微电网调度的人应该都有过这种体会:今天光伏预测曲线明明很漂亮,上午十点突然飘来一片云,出力直接砍半;或者风电场那边预报微风,结果下午风速爬升,风机满发。这时候如果还按着早上做的计划走,储能该充电的时候没充上,该放电的时候又早早放空了,最后只能靠向上级电网买高价电来兜底——一算账,白白多花不少钱。

这就引出了微电网最优运行里的一个核心问题:可再生能源和负荷的不确定性到底该怎么处理?

传统做法是确定性优化,把光伏出力、风速、负荷都当成已知参数,求解一个单层线性规划或者混合整数规划,得到一条最优调度曲线。这个方法简单、清晰、求解快,但短板也很明显——它本质上是在赌预测值准。一旦实际和预测偏差稍大,最优解就变成了“次优解”甚至“不可行解”。实际运行中,微电网里往往有储能、柴油机、燃料电池这些可控资源,它们的响应速度远快于日前调度的周期,完全有能力在实时阶段做二次调整。所以理想的做法是:在做日前计划时,就给实时调整留出余量,并且这个余量要能覆盖最坏情况下的不确定性。

在这个背景下,学界和工程界逐渐形成了两条技术路线。一条是随机优化(Stochastic Optimization),用蒙特卡洛采样生成大量场景,用场景的期望值作为目标函数的一部分。随机优化的优点是经济性好,缺点是你得知道不确定量的概率分布,而且当场景数量多到一定程度时,模型规模和求解时间会急剧膨胀。另一条就是我们今天要重点聊的鲁棒优化(Robust Optimization)。

鲁棒优化的思路和随机优化完全不同。它不去猜测概率分布,而是把所有可能的不确定性范围画一个集合——比如“光伏出力在预测值的±20%以内波动”,然后把目标函数改成最小化“最坏情况下”的运行成本。换言之,我不赌哪个场景会出现,我只保证:不管不确定性怎么变,我都能扛住,而且代价是可控的。

我最初接触这个概念时,也被“最坏情况”这个思路吸引住了。因为微电网调度本质上是一个保守的行业——供电可靠性永远排在经济性前面。与其把希望寄托在预测模型的精度上,不如在制定计划时就让方案本身具备对抗不确定性的能力。这正是鲁棒优化在微电网领域越来越受重视的原因。

本文要聊的这个项目——“具有可再生能源和储能的区域微电网的最优运行:针对不确定性的鲁棒性和非预测性解决方案”,做的就是这么一件事:用两阶段鲁棒优化(Two-Stage Robust Optimization)来求解微电网日前-实时两阶段调度问题,兼顾了鲁棒性和非预测性(Non-Anticipativity),并且给出了完整的Matlab实现。下面我会从建模思路、数学推导、求解算法、代码实现到避坑经验,一条线拉通讲清楚。

2. 从确定性模型到两阶段鲁棒优化

2.1 先回顾确定性调度模型的骨架

要理解鲁棒优化,得先把确定性调度模型装进脑子里。一个典型的含可再生能源和储能的微电网,日前调度模型通常包含这么几个部分:

目标函数是最小化总运行成本,一般包括向上级电网购电费用、柴油机或燃气轮机的燃料成本、储能充放电损耗成本,如果允许切负荷还可以加上惩罚项。写成数学形式就是:

min sum( C_grid * P_grid + C_fuel * P_engine + ... )

功率平衡约束是这个模型的心脏:任意时刻,光伏出力、风电出力、储能放电、购电功率、机组出力之和,要等于负荷需求加上储能充电功率。这是等式约束,也意味着鲁棒优化中最难啃的一块——等式约束包含不确定参数时,怎么保证对任意实现都可行。

储能约束包括荷电状态(SOC)递推式、充放电功率上下限、SOC上下限、以及“不能同时充放”的逻辑约束。这是微电网调度里最容易出数值问题的部分,尤其是SOC递推式和充放电0/1变量放在一起时,等价类很多,稍不注意就出现死循环或无解。

机组出力约束包括发电功率上下限和爬坡约束。如果考虑机组启停,还要加启停逻辑约束,这时候模型就从线性规划升级到混合整数线性规划(MILP)。

2.2 不确定性该加在哪里

确定性模型全部参数都是常量。一旦引入不确定性,我们需要明确:哪些参数是不确定的?

在微电网场景中,不确定性主要来自三类:光伏出力、风电出力、负荷需求。对于电价,在电力现货市场背景下也可能存在不确定性,但很多研究把它当作确定性参数处理,因为电价属于市场出清结果,微电网运营者大概率是价格接受者。这个项目的标题里直接点出了“可再生能源”和“储能”,所以核心不确定性集中在光伏和风电出力上。

把不确定性参数单独抽出来,用符号ξ表示。那么约束条件大致可以写成两类:

  • 不含ξ的约束,对任何不确定性实现都必须满足;
  • 含ξ的约束,这类约束在鲁棒优化里又分两种处理方式:要么要求在ξ的任意取值下都满足,要么在ξ实际值观测后再做调整。

这就是“两阶段”的由来。

2.3 两阶段鲁棒优化的数学结构

两阶段鲁棒优化的通用形式是:

min_x c'x + max_ξ∈U min_y d'y s.t. Ax ≥ b Bx + Cξ + Dy ≥ h

这里的x是第一阶段决策变量,通常代表日前计划量,比如储能各时段的充放电基准功率、机组启停状态、购电计划。这些决策必须在不确定性揭示之前确定下来,也就是“非预测性”约束的核心含义——你不能在制定日前计划时,就假设你已经知道了明天光伏出力的实际值。

第二阶段决策变量y则是实时调整量,比如实际运行时根据当前光伏出力偏差对储能出力的微调、对机组出力的修正、紧急购电量的变化等。y可以在看到ξ的实现后做出响应,所以它是“预测性”的。

整个模型的求解思路可以理解为:在不确定性集合U中找到一个最坏的ξ实现(外层max),使得对应的最优调整成本(内层min_y)加上日前成本总和最大——我们要把这个最大的总成本最小化。

注意:这里的“非预测性”(Non-Anticipativity)在随机优化中更常用,指决策只能基于当前已知信息,不能预知未来场景。在鲁棒优化中对应的就是第一阶段决策不能依赖ξ的具体取值。

3. 不确定性集合怎么构造

3.1 盒式不确定集与预算约束

鲁棒优化和随机优化最大的差别之一,就是不确定性的描述方式。随机优化给每个场景分配一个概率;鲁棒优化给每个不确定参数画一个取值范围。

最基础的是盒式不确定集:

ξ ∈ [ξ_hat - Δξ, ξ_hat + Δξ]

这里的ξ_hat是预测值,Δξ是最大偏差。盒式集的优点是简单直观,缺点是过于保守——它允许所有不确定参数同时取到最坏值,这在现实的微电网中几乎不可能发生。光伏出力偏低的同时风电出力也偏低,负荷又飙到最大值,这种“三重极端同时出现”的场景虽然理论上存在,但概率极低。如果把所有不确定参数都设成盒式集最坏点,最后得到的调度方案会非常保守,储能整天处于“戒备状态”,经济性损失巨大。

为了解决这个问题,工程上引入了预算参数(Budget of Uncertainty)。预算约束的思想是:虽然在极端情况下所有参数都可能偏离预测值,但同一时刻总共偏离的参数个数(或总偏离量)是有限的。数学上可以写成:

sum( |ξ_i - ξ_hat_i| / Δξ_i ) ≤ Γ

Γ就是预算参数。当Γ=0时,模型退化为确定性模型;当Γ等于不确定参数总数时,等价于最保守的盒式集合。通过调节Γ,我们可以在鲁棒性和经济性之间连续调节。这个参数在实际工程项目中非常好用——业主方如果问“你这方案太保守了吧,多花这么多钱”,你直接把Γ调小一点;如果问“可靠性有没有保证”,你就把Γ调大。

3.2 我常用的不确定集设计方式

在实践里,我不建议把光伏和风电放在同一个预算约束里,因为它们的预测误差特征差别很大。光伏出力误差有明显的时段性——中午高、早晚低,而风电出力误差相对连续且带有相关性。我会把不确定集拆成多个子集,例如光伏一组带预算约束,风电单独一组带预算约束,负荷如果也视为不确定量则单独一组。这样可以避免“光伏取最坏值的同时风电也取最坏值”这种不合理的组合。

这种拆分在Matlab实现中也很方便。用YALMIP建模时,只需要对每个不确定变量组单独定义约束,C&CG算法内部处理时分别投影就好。

4. 求解算法:C&CG(列约束生成)实战

4.1 核心思想

两阶段鲁棒优化模型是一个min-max-min三层结构,直接求解根本不可能。C&CG算法(Column-and-Constraint Generation)是目前处理这类问题的主流方法之一,核心思路是:把原问题拆成一个主问题和一个子问题,通过迭代,让主问题不断加入子问题生成的新场景约束,直到上下界收敛。

**主问题(MP)**是原问题的一个松弛版本,它只考虑一个有限的场景集合(最开始通常是预测值场景):

min c'x + α s.t. Ax ≥ b Bx + Cξ^k + Dy^k ≥ h (k = 0,1,...,K) α ≥ d'y^k (k = 0,1,...,K)

这里的ξ^k是第k轮迭代时子问题找出来的最坏场景,y^k是对应场景下的第二阶段决策变量。注意,主问题每加入一个场景,就会增加一组y变量和对应的约束。

**子问题(SP)*的职责是:给定第一阶段解x,找到当前最坏的不确定性场景ξ。形式上就是:

max_ξ∈U min_y d'y s.t. Cξ + Dy ≥ h - Bx*

这是一个max-min双层问题,内层是线性规划,外层是max问题。处理它的思路一般是:先把内层取对偶,将max-min转化为max-max形式,也就是:

max_ξ∈U, λ≥0 λ'(h - Bx* - Cξ) s.t. D'λ = d

这样内外层都是max了,可以合并成一个单层优化问题。对偶变量λ是连续变量,外层ξ在不确定集U内取值,如果U是盒式集加预算约束,这个单层问题本质上是一个带线性约束的连续优化问题,可以用标准求解器(CPLEX/Gurobi)直接求解。

4.2 子问题要小心的地方

子问题求解是这个算法里最容易翻车的地方。我列几个常见坑:

**坑一:内层问题的不可行性。**在C&CG迭代早期,主问题的约束还不全,可能对某个ξ来说,第二阶段y不存在可行解。这时候子问题的对偶问题可能是无界的,模型直接报错“Unbounded”。解决办法是在主问题中加入人工松弛变量,并给予足够大的惩罚系数,保证任意ξ下第二阶段问题都有“软约束”可行解。

**坑二:对偶转换后求解器判性。**当内层包含0/1变量(比如机组启停变量在第二阶段),强对偶就不成立了。这种情况要么把0/1变量放到第一阶段,要么用KKT条件把内层问题转成平衡约束,要么引入大M法和辅助变量线性化。我建议在建模时就把0/1变量全部放到第一阶段,第二阶段只保留连续变量,对偶才干净。这不仅是代码方便的问题,也是模型本身符合实际:机组启停是日前决定好的,实时运行中不可能突然启停机组。

**坑三:数值范围差异导致对偶变量尺度失衡。**储能容量的数值可能是几百kWh,购电功率的数值是几十kW,两者差了一个数量级,对偶问题中λ的值分布会很畸形。建议在所有约束中用统一单位(比如全部用kW和kWh),并在必要时做归一化处理。

4.3 Benders分解和C&CG怎么选

很多文章会把Benders分解和C&CG放在一起比较。我的主观感受是:针对微电网调度这类问题,C&CG通常比Benders收敛更快。原因是C&CG每次迭代会往主问题里加一整套第二阶段变量和约束,而Benders只加一条割平面(一个不等式)。C&CG的割平面信息量更大,虽然单次迭代的求解时间变长,但总迭代次数明显减少。如果你发现你的C&CG迭代了二三十轮还不收敛,先别急着换算法,多半是子问题的对偶写错了。

4.4 收敛判据怎么定

一般用主问题目标值(下界LB)和子问题目标值(上界UB)之间的gap来判断:

gap = |UB - LB| / |LB| ≤ ε

工程上我一般设定ε=0.5%,太小的ε(比如0.01%)会让迭代次数成倍增加,而调度结果的经济性改善微乎其微。做工程要懂得在精度和效率之间找平衡,0.5%-1%是非常合适的区间。

基于C&CG的整体流程,可以梳理出如下完整步骤:

  1. 初始化:设定当前场景集合只包含预测值场景(ξ=ξ_hat),LB=-∞,UB=+∞,迭代计数k=0。
  2. 求解主问题(MILP),得到最优解(x*, α*),更新LB = c'x* + α*。
  3. 固定x=x*,求解子问题(SP),得到最坏场景ξ和第二阶段目标值Q(ξ)。
  4. 更新UB = min(UB, c'x* + Q(ξ*))。
  5. 计算gap = |UB-LB|/|LB|。如果gap < ε,停止迭代,输出当前主问题解。
  6. 否则,把ξ*作为新场景加入主问题场景集,增加对应的y变量和约束,k=k+1,回到步骤2。

5. Matlab代码实现要点

5.1 代码总览与模块划分

这个项目的完整代码我建议按下面这个结构组织,逻辑清晰且方便后期扩展:

main.m % 主脚本:参数设置、模型构建、C&CG主循环 data_define.m % 所有输入数据:负荷曲线、光伏预测、电价等 uncertainty_set.m % 不确定集参数设置:偏差幅度、预算Γ build_mp.m % 构建主问题(YALMIP模型) solve_sp.m % 求解子问题(对偶转化) update_mp.m % 向主问题添加新场景约束 plot_results.m % 结果可视化

5.2 YALMIP还是CVX?建模工具怎么选

在Matlab环境下做两阶段鲁棒优化,我强烈推荐YALMIP。原因有三:第一,YALMIP对MILP/MIQCP的支持比CVX更成熟,尤其在离散变量处理上更稳定;第二,YALMIP的constraint对象可以非常方便地在循环里增删约束,这对C&CG迭代来说太重要了;第三,YALMIP能直接调用CPLEX、Gurobi、MOSEK等求解器,且与优化模型耦合度低,方便切换。

如果你只用Matlab自带的linprog/intlinprog,能用但麻烦,尤其是子问题对偶后的双线性项(λ'Cξ)处理起来比较痛苦。预算约束本身是线性约束,但某些不确定集设计(如椭球不确定集)会引入二次项,自带求解器处理不了。Gurobi或CPLEX是必须的。

5.3 一个关键细节:不确定性变量的实现方式

在主问题里,ξ值固定为当前场景的已知值,所以直接用常数数组即可。核心挑战在子问题。子问题对偶化之后,ξ作为变量出现在目标函数中(包含双线性项λ'Cξ)和约束中,这时需要额外引入辅助变量来线性化双线性项。

以盒式不确定集(带预算约束)为例,假设单时段只有一个不确定参数(比如光伏),不确定集为:

U = { ξ | ξ_hat - Δξ ≤ ξ ≤ ξ_hat + Δξ, |ξ - ξ_hat|/Δξ ≤ Γ }

由于只有一个不确定参数,这里的预算约束其实是冗余的——单参数取到上下界的任何一个都“用完了”整个预算。这种情况直接向量化写约束,子问题是一个简单的线性规划。真正的复杂度在于多时段、多类型不确定参数同时存在时,预算约束需要引入0-1辅助变量来描述“哪些参数偏离了预测值”,这时候子问题从LP变成了MILP,求解时间会立刻上升。

常见的线性化技巧是引入连续变量z_i和0-1变量u_i,令:

  • z_i ≥ 0 表示不确定参数i的相对偏离幅度
  • z_i ≤ u_i(u_i=1表示该参数偏离,取0则为0)
  • 预算约束 sum(z_i) ≤ Γ
  • ξ_i = ξ_hat_i + Δξ_i * z_i(如果允许正负偏离,则再引入正负两部分变量)

这样处理之后,子问题就是一个标准的MILP,Gurobi求解非常快。

5.4 储能SOC约束的实现细节

储能的约束是微电网调度模型里的“麻烦制造者”,代码层面有几个点必须注意:

**SOC递推式的初始化。**SOC(1) = SOC_init + η_ch * P_ch(1) - P_dis(1)/η_dis,其中η_ch、η_dis分别是充放电效率。很多初学者容易忘记考虑采样间隔Δt,直接把功率当能量用了。kWh和kW之间差了Δt倍,这个错误在数值上表现为SOC越界,而且往往在鲁棒优化的某些极端场景中才会触发,排查起来非常隐蔽。

**充放电功率上限的耦合。**P_ch(t)和P_dis(t)之间不能同时为正,除了用0/1变量外,也可以用互补约束实现,但在MILP框架里0/1变量是标准做法。我见过的很多简化模型直接把充放电两个变量合成为一个变量P_ess(正为充、负为放),然后在约束里对正负分别限制。这样虽然少了一个0/1变量的维度,但损失了充放电效率不对称的建模能力——因为充电效率和放电效率不一样,合成单变量时无法区分。实际项目中储能效率不对称的影响很大,不建议贪图建模方便而牺牲这个精度。

**SOC的鲁棒性处理。**在两阶段模型里,SOC递推式可以放在第二阶段——因为SOC的变化取决于实际的充放电功率,而这些功率在第二阶段才能完全确定。但这样会使得主问题无法预先知道SOC的可行域,也就无法提前约束第一阶段的充放电计划。我的做法是:把SOC递推式放在第二阶段,但在第一阶段加入储能各时段的SOC上下限约束,确保即使第二阶段在最坏场景下,SOC仍有调整空间。

5.5 子问题目标函数的“运输”问题

第二阶段子问题的目标函数一般包含实时购电成本、储能调整惩罚、弃风弃光惩罚。这里要特别注意:实时购电成本不能用日前电价直接乘,因为实时市场电价和日前电价往往不同。如果项目里没有区分,也要单独设一个系数,标明这是实时能量市场购电的成本系数。

另外,子问题目标里要加一个对第一阶段决策偏离的惩罚项。这个惩罚项有两个作用:一是避免第二阶段解决方案偏离第一阶段计划太远,这样调度的可执行性更强;二是它的存在削弱了子问题目标对第一阶段决策的敏感性,让C&CG迭代更平稳。惩罚系数不宜太大,否则第二阶段失去了调整自由度;也不宜太小,否则子问题纯粹找最坏场景,第一阶段调度曲线会显得毛躁。经验做法是惩罚系数取购电成本系数的0.1到0.3倍。

6. 标准测试案例:结果对鲁棒参数的敏感性

6.1 测试场景设定

我设计了一个典型日验证模型性能,时间粒度为1小时、共24个时段。负荷预测曲线模拟了一个小型工业园区的典型日——白天两个峰、中午略微回落;光伏预测曲线是一个冬季晴天——8点开始爬升,12-14点达到峰值,17点后归零。储能容量为2MWh,最大充放电功率为0.5MW,充放电效率均为0.9。上级电网购电价格按峰谷电价设置。作为对比基准,我分别求解了确定性模型(Γ=0)和鲁棒模型(Γ取不同值)。

6.2 调度结果对比

确定性模型的调度策略很“激进”:它认为光伏预测完美无缺,所以中午时段几乎满负荷给储能充电,同时大量削减购电功率;到了晚间负荷高峰,储能放电支撑,购电功率维持在低谷时段水平。整体成本最低,但光伏出力一旦达不到预测值,储能可能无法完成充电目标,晚高峰就得高价购电。

而鲁棒模型(Γ=4)的调度策略明显更“留有余地”。它把储能充电时段拉长,充电功率降低,以保证即使光伏出力偏小,储能也大概率能充到目标SOC;同时购电功率的峰谷差缩小,不再完全依赖中午的光伏高发来支撑储能充电。最终的日前成本比确定性模型高出不少,但最坏情况下的总成本显著更低。

从鲁棒优化的角度来说,这就是典型的价格换取可靠性——多花一点日前购电成本,避免最坏情况下的高额实时购电罚单。

6.3 预算参数Γ的敏感性

我扫了一遍Γ从0到6(光伏和风电各3个不确定参数)的变化趋势:

  • Γ=0:等价于确定性模型,成本最低,但最坏场景下成本剧增。
  • Γ=1到2:成本缓步上升,最坏场景成本快速下降——性价比最高的区间。
  • Γ=3到4:成本继续上升,但最坏场景成本下降趋势放缓。
  • Γ=5到6:成本几乎不再变化,因为此时不确定集已经接近盒式集合的最保守情况,调度方案的“鲁棒边际”已经饱和。

在设计项目方案时,我一般会根据历史预测误差数据来标定Γ:统计过去90天中,实际光伏出力偏离预测值超过±15%的小时数占比,如果这个比例低于5%,就说明Γ取2-3足够覆盖绝大多数风险。通过历史数据来标定模型参数,比拍脑袋选Γ要靠谱得多。

6.4 为什么两阶段解优于单阶段鲁棒解

单阶段鲁棒优化把所有决策都放在不确定性揭示之前,所以对储能、机组、购电功率全部都要求“对所有可能的ξ都可行”。这相当于要求调度方案在每一种不确定性实现下都不能触碰任何约束边界,自然非常保守。

两阶段则不同:日前只决定第一阶段的“基准计划”,实时阶段可以根据实际ξ自由调整储能出力、机组出力和购电计划。这给了调度方案更大的可行域,也意味着成本更低。举个直观的例子:单阶段鲁棒优化里,储能容量必须大得足以覆盖光伏最大偏差时的全部调整需求;而两阶段模型里,储能只需要覆盖光伏偏差中“实时调整后仍然需要储能额外承担”的部分,这个量往往小很多。

7. 常见问题排查与避坑指南

7.1 子问题对偶不可行或目标无界

C&CG调试中最常见的问题。如果你看到子问题求解返回“Infeasible”或者“Unbounded”,大概率是内层原始问题在某个ξ下无可行解。这时候可以先固定一个简单的ξ(比如ξ=ξ_hat)去求解内层问题,确认第二阶段模型本身是不是有缺陷(约束冲突、边界条件错误)。如果固定ξ下内层问题可行,再检查对偶代码的维度匹配问题——对偶变量λ的维度必须与原始约束个数完全一致,差一个都对不上。

我自己习惯的做法是:在C&CG迭代循环外加一层“validator”——每轮子问题求解之前,先固定ξ=当前最优场景去跑一遍内层min_y,确保内层问题有界可行,再去跑max-min对偶版本。虽然多花一点时间,但能快速定位问题出在“原始问题不可行”还是“对偶转换出错”。

7.2 迭代收敛慢或震荡

如果gap在某个值附近来回抖动,不往下走,最常见的原因是第一阶段的整数变量(机组启停、储能充放电模式)切换引起的子问题目标值非凸跳跃。解决方案有两个:一是给第一阶段整数变量加上“小范围禁带”,比如禁止机组在相邻时段反复启停(最小启停时间约束);二是在子问题目标中加入一个很小的正则化项,比如对ξ的偏离量加一次项惩罚——正则项的系数要足够小,小到不影响最坏场景的识别,但足以平滑收敛曲线。

7.3 YALMIP建模中的性能陷阱

YALMIP建模时会自动做模型预处理,但如果你把整个两阶段模型一次性堆给YALMIP,让它处理max-min结构(YALMIP支持bilevel优化),在微电网规模的模型下性能会非常差。YALMIP的bilevel求解器内置的迭代算法远不如你自己实现的C&CG,遇到稍微大一点的模型就容易内存爆炸。我的经验是用YALMIP构建MP和SP的标准形式,然后手动控制C&CG循环,YALMIP只负责每一轮里MP和SP的建模与求解,不涉及其跨层级优化功能。这样既保留了YALMIP建模的便利性,又掌控了算法核心逻辑。

还有一个隐蔽但极其常见的问题:在循环里不断往YALMIP的constraint对象里“追加”约束时,如果直接写Constraints = [Constraints; new_constraint],代码执行效率会随着约束数量增加而大幅下降。我自己在项目中被这个卡过不少次——到第15轮迭代时,主问题的变量和约束数量上来了,单轮求解时间翻了两三倍,差点以为是模型本身的问题。后来改用元胞数组暂存所有约束,最后一轮一次性用vertcat拼起来,效果立竿见影。如果你的代码在迭代中越跑越慢,先看看是不是这个问题。

7.4 数值稳定性问题

鲁棒优化的数值问题通常比确定性优化更严重,因为对偶问题的系数矩阵包含了原问题的对偶乘子,而乘子的量级差异很容易让求解器产生病态矩阵。一个有效的措施是统一模型中的单位体系,不要同一个模型中同时出现MW和kW、MWh和kWh。再加上量级归一化,把所有数值控制在0.01到100之间,求解速度会好很多。

Gurobi的参数设置也值得花时间调。我一般会把MIPGap设到0.01%、MIPFocus设为1(偏重可行性搜索),这两个参数在C&CG迭代中能明显加速收敛。如果子问题是纯LP,那直接调用linprog或Gurobi的连续求解器就好,没必要让MILP的MIP初始化逻辑拖后腿。

7.5 鲁棒解一定有经济性价值吗

这是个好问题,也是很多人在用过鲁棒优化后产生的疑惑。

如果预测模型已经非常准,不确定性范围很小,那么鲁棒优化的价值就很有限——它只是把预测误差的尾部风险抹平了,但为此付出的鲁棒代价(Robust Price)会显得不划算。反过来说,如果预测误差大,那么确定性模型的调度结果几乎天天偏离最优工况,两阶段鲁棒优化的优势就会非常明显。所以,在项目落地前先做一次预测误差统计,看看历史数据里实际出力和预测出力的偏差到底有多大。如果偏差超过15%的时段占比不到3%,那大概率不需要上鲁棒优化,用滚动优化控制(MPC)更合适;如果偏差超过15%的时段占比超过10%,鲁棒优化几乎是必选项。

8. 个人实操中的几点体会

代码跑通只是第一步,真正让鲁棒优化从论文走向工程,还需要在模型细节上反复打磨。我在实际项目中体会最深的一点是:不要盲目追求最坏情况下的绝对最优,而是在鲁棒性和经济性之间找一个对运营者来说“心理可接受”的点。这并不是一个纯数学问题,而是一个决策问题。我会把不同Γ取值下的调度结果和成本做成表格,让业主方直观看到“多花多少钱、规避多少风险”,让业务人员参与参数标定,而不是自己在办公室里拍定。

另外,两阶段鲁棒优化的求解规模对模型细节非常敏感。储能SOC用线性递推式时,24时段的问题非常轻松;一旦加上最小启停时间约束、爬坡约束的完整表述,MILP规模和求解时间会急剧上涨。这时候可以考虑缩减时间粒度(从15分钟改成1小时),或者采用滚动求解策略——先求解24小时模型,然后只取前4小时的结果作为执行计划,后续重新求解。虽然理论上是次优的,但工程上完全够用。

最后再分享一个小技巧:C&CG迭代收敛后,把每一轮迭代的主问题下界和子问题上界画成迭代曲线,不仅能在论文中展示算法的收敛性,也能在调试时快速发现振荡和异常。我习惯在每个迭代循环中记录 LB、UB、Gap、迭代耗时、场景数量,在调试和汇报时都很有用。比如某轮迭代gap一直卡在2%不下来,那就去查是不是某个场景没有真正加入主问题;如果子问题求解时长突然翻倍,那就去查是不是新增的0-1辅助变量让子问题从LP变成了MILP——这些问题在迭代曲线上一眼就能锁定位置,不需要逐行翻代码。

两阶段鲁棒优化是一个“入门容易、精通难”的方向,但一旦把C&CG的主线逻辑和不确定性集合的设计理解透了,后续延伸到多微网协同、参与电力市场的竞价策略、分布式鲁棒优化等场景,都只是在这个骨架上做扩展。希望这篇文章能把你的第一道坎迈过去。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 14:34:05

SQL Server数据库处于RESTORING状态无法删除?完整排查与解决指南

数据库状态死死卡在“正在恢复”&#xff0c;执行DROP DATABASE直接报错&#xff0c;管理工具里删除按钮也是灰色的——碰上这种情况的运维应该不少。不管你是备份还原到一半手滑取消了&#xff0c;还是日志传送、镜像同步出问题之后想把那个副本彻底清掉&#xff0c;最后都会撞…

作者头像 李华
网站建设 2026/10/20 14:32:56

Linux与实时控制如何兼得?三种方案选型与延迟优化实践

前阵子朋友的项目做方案评审&#xff0c;甲方提了一个很典型的要求&#xff1a;控制器既要跑视觉检测、网络上报、人机界面这些Linux生态的东西&#xff0c;又要保证伺服位置环的响应延迟控制在1毫秒以内&#xff0c;而且不允许偶发超时。会议室里做软件的同事说Linux没问题&am…

作者头像 李华
网站建设 2026/10/20 14:32:52

TSX如何击穿KASLR:硬件侧信道下的内核地址随机化破解探秘

第一次看到这个标题的时候&#xff0c;我的第一反应是&#xff1a;KASLR 又又又被击穿了。在 2020 年前后那批“瞬态执行类漏洞”研究里&#xff0c;Intel TSX 几乎成了绕过内核地址随机化的标配放大器&#xff0c;每次出现都让人觉得“哦&#xff0c;居然还能这样玩”。Kernel…

作者头像 李华
网站建设 2026/10/20 14:32:51

OpenClaw本地部署实战:用WSL2和Docker打造私有AI助理

1. 先搞清楚 OpenClaw 到底是什么 1.1 它不是又一个聊天机器人 最近总有人问我 OpenClaw 是不是类似智能助手客户端&#xff0c;或者是不是某个新出的开源对话项目。其实都不太准确。OpenClaw 是一个定位很清楚的个人 AI 助理框架&#xff0c;名字致敬了经典游戏《黑与白》里那…

作者头像 李华
网站建设 2026/10/20 14:32:46

微电网日前经济调度:风光储与需求响应的MILP建模实战

做微电网调度的同行应该都有同感&#xff1a;光伏风电一接入&#xff0c;原来那套“负荷多大就发多少”的思路直接失灵。白天光伏出力上来&#xff0c;电价反而低&#xff1b;晚上负荷高峰&#xff0c;风电出力又往下掉。这个“错位”不是靠人拍脑袋能解决的&#xff0c;尤其当…

作者头像 李华