“电气热综合能源鲁棒优化”这种题目,翻译成人话就是:把电网、气网、热网放在一个模型里做联合调度,同时把风光出力、负荷预测不准的问题用鲁棒优化的方法包住,最后还要让模型能在求解器里跑起来。这三个事单拎出来都不算新,但合在一起很容易翻车:要么模型是非线性的,求解器直接罢工;要么鲁棒部分迭代不收敛;要么分段线性化分段少了不精确,分段多了机器算不动。我当年刚接触这个方向时,光是把题目里的几个关键词串起来就折腾了很久,所以这篇把整个建模到落地的过程掰开揉碎写一遍,适合正在做综合能源方向的学生、刚入行的调度算法工程师,以及所有想在论文复现时少踩坑的同路人。
先把这个事情的框架理清楚。电气热综合能源优化的核心矛盾,在于三类网络的时间常数和物理特性完全不一样——电是毫秒级响应,气是分钟到小时级惯性,热是典型的大惯性慢过程。把三者强行塞进同一优化模型,就必须在某些物理约束上做妥协或者说做“工程化处理”。而鲁棒优化的加入,又给模型增加了一层“与不确定性对抗”的结构。再迭加上二阶锥模型和多能流分段线性化,整个程序实际上是在回答一个问题:在不知道明天风光到底发多少的前提下,怎么给电、气、热三种能量排班,才能保证最坏情况下系统也不越限。
我写这篇不是从零讲理论,而是把这套方案的来龙去脉、坑在哪里、怎么填坑、怎么让求解器跑得动,按真实项目推进的顺序梳理一遍。换句话说,读者能直接拿这套思路当骨架,往里面填自己的网络数据和设备参数。
1. 问题拆解与整体设计思路
1.1 为什么要做“多网耦合”而不是单网优化
如果只做配电网优化,天然气管网和热网的压力、温度、流量都不参与调节,那么很多从“能源互补”中获益的调度空间就完全丢了。举一个最简单的例子:某台微燃机既可以发电并网,又可以借助余热回收给热网供热。电网负荷高峰时,让微燃机多发电,热电比随之变化,热网这边跟着调整电锅炉出力甚至蓄热罐的充放。这种跨网络协调,只有在电气热统一建模时才能全局寻优。
但单网模型各自成熟,拼起来却难。主要原因是每个网络的“状态变量”和“潮流方程”用的不是同一套数学语言:电网的DistFlow方程是一组二次等式与锥约束,气网的Weymouth方程是带符号的平方根非线性,热网的节点温度方程则有流量与温度的乘积项。这三套方程同时放进一个优化问题里,如果不做技术处理,问题就是混合整数非线性规划(MINLP),求解器基本束手无策。所以工程界通常走两条路:一是把所有非线性约束做线性化或松弛,把MINLP降成MISOCP或者MILP;二是用分解算法,把网络解耦开各自迭代。这篇文章推荐的是前一条路,并且用“鲁棒优化”来兜住分解与松弛造成的建模误差——这也是标题里那串关键词组合起来的意义。
1.2 不确定性是鲁棒优化的出发点
预测总有误差,光伏和风电尤其严重。对调度员来说,真正关心的不是明天光伏“预测值”是多少,而是光伏在预测值上下某个区间内波动时,系统还能不能安稳运行。经典确定性优化给出一条刚性调度计划,预测一旦偏差,备用可能不够,线路可能过载,温度可能越限,所以在综合能源系统里,确定性方案的实际可用性不高。
鲁棒优化换了一个思路:不追求在平均场景下最优,而是对给定不确定集合内的所有可能场景都保持可行性,同时优化最坏情况下的运行成本。这样做的代价是保守——说白了就是牺牲一点经济性换取安全性。但这个代价是否值得,完全取决于不确定集怎么设计。如果不确定集范围拍脑袋定得太大,得到的方案成本会高到离谱;如果定小了,鲁棒保护实际又不构成意义。因此,不确定集的设计和Γ参数的选择,是鲁棒模型里最需要工程经验的环节,我后面会专门展开。
1.3 从MINLP到MISOCP:为什么偏偏是二阶锥
原始模型里最让求解器头疼的是三类非线性:电网的电流平方项和电压平方权、气网的管道流量与压差平方根关系、热网温度与流量的乘积项。这些项如果全部保留,是典型的非凸非线性问题,全局求解器能处理的规模非常有限。
二阶锥规划(SOCP)提供了一个很好的折中:部分非凸约束可以放成凸的锥约束,虽然放宽了约束域,但恰好让模型落进现代商业求解器的核心射程。Gurobi、CPLEX、Mosek都对SOCP做了深度优化,二阶锥约束的实际求解速度甚至可以跟线性约束扳手腕。更重要的是,在很多配电网场景里,二阶锥松弛是“紧”的——也就是说松弛后的最优解恰好落在原非线性曲面上,解出来的结果对原问题来说就是可行的。对于不紧的场景,也可以加惩罚项或者有效不等式修正。鲁棒优化与SOCP的结合方式则非常自然:两阶段鲁棒的主问题本质上是混合整数二阶锥规划(MISOCP),子问题在给定第一阶段决策后也往往是SOCP或它的对偶形式,整个C&CG框架完全建立在SOCP求解能力之上。
2. 模型约束体系的搭建:三张网,一套框架
2.1 电力网络:DistFlow方程的锥松弛
配电网辐射状结构下,常用的潮流模型是DistFlow,对于支路 (i,j),节点 j 的注入有功和无功平衡方程写作:
P_j = ∑P_jk + r_ij * I_ij² + P_load_j - P_gen_j
Q_j = ∑Q_jk + x_ij * I_ij² + Q_load_j - Q_gen_j
U_j² = U_i² - 2(r_ij * P_ij + x_ij * Q_ij) + (r_ij² + x_ij²) * I_ij²
这里 I_ij² 定义为 L_ij,U_j² 定义为 W_j,则最后那个式子除了变量替换之外保持线性。但支路电流的平方与节点电压、注入功率之间还满足:
L_ij ≥ (P_ij² + Q_ij²) / W_i
这是个二阶锥约束:令 t = L_ij,则要求 (2P_ij, 2Q_ij, W_i - L_ij) 必须落在旋转锥(rotated cone)内。于是,潮流方程从非凸二次等式转化成一组线性等式加锥不等式。这一步是整个MISOCP的核心,也是论文里标题“二阶锥模型约束下”所指的主要地方。
2.2 天然气管网:Weymouth方程怎么进模型
天然气管道的稳态流量方程通常写成:
f_mn = sign(π_m² - π_n²) * K_mn * sqrt(|π_m² - π_n²|)
其中 π 是节点气压。这个式子的难点不只是平方根,还有符号函数——流量方向本来就是优化的一部分,不能预先指定方向。要做到掉符号,我把 π_m² 定义成一个新变量 p2_m,于是原式变成 f_mn = sign(p2_m - p2_n) * K_mn * sqrt(|p2_m - p2_n|)。随后引入两个0-1变量表示方向,再用大M法把正向流量和反向流量拆开建模,平方根项在固定方向上是凹函数,可以进一步分段线性化,或者直接放成旋转锥约束。实际工程中,很多程序更倾向直接对 sqrt(|Δp2|) 做分段线性近似,这样可以和热网温度曲线共用一套线性化工具,实现起来也少踩一两个大M取值的坑。
2.3 热力网络:温度-流量的耦合与简化
热网的水力模型和热力模型本质上是分离的:水力决定各管段流量分配,热力决定节点供/回水温度。综合能源调度里,大量文献采用“质调节”模式,即供热管道流量按调度结果变化,但在短时间尺度优化内可以近似为恒定流量,仅通过调节供水温度来调整热量。这一近似大大简化了问题:节点温度方程中,流量与温度的乘积项由此退化为单个温度变量的线性项,热水管路的热损失方程变为线性。如果一定要同时优化流量和温度,那就绕不开双线性项,此时常配合McCormick包络或双层迭代。但从工程实用性出发,质调节假设在大多数规划类问题里是合理且被接受的简化方式。关键是在论文里要把这个假设明确写出来,审稿人或工程验收时就不容易产生异议。
2.4 耦合设备:把三张网串起来的主角们
光有网络约束还不足以形成“综合能源”,真正让电、气、热互动的,是站在这三张网交界处的耦合设备。典型成员包括:
- 微燃机(CHP):消耗天然气,同时输出电和热,核心是热电比或可变热电运行域。
- 电锅炉:从电网取电产热,相当于把能量从电网络传递到热网络。
- 电制氢/燃料电池(如果有的话):电气-气网络的能量转换节点。
- 热泵:消耗少量电,搬移大量热,能效系数COP是核心参数。
耦合设备模型通常是一组线性关系(如固定热电比)或一组凸包络线性化后的运行域(如可变热电比的多边形运行域)。这些设备的出力上下限、爬坡约束和启停逻辑,直接构成了混合整数部分的主要整数变量来源。主问题的整数决策大多落在这些设备上,气网管道方向变量也会贡献一部分0-1变量。
3. 鲁棒优化的落地:C&CG与二阶锥的结合方式
3.1 盒式不确定集与两阶段鲁棒范式
综合能源鲁棒优化里最常用的不确定集是盒式不确定集,也就是对每个不确定性参数(光伏出力、风电出力、电负荷等)给一个上下界区间 [ξ̄_i - Δξ_i, ξ̄_i + Δξ_i],再引入一个预算参数 Γ 控制最多同时有多少个不确定性参数可以取到极端值。这个Γ是关键的自由度,可以由调度员根据风险偏好设定,并且与鲁棒解的保守程度直接挂钩。
两阶段鲁棒优化的标准形式是:
min_x c¹x + max_ξ∈Ξ min_y∈F(x,ξ) c²y
第一阶段决策x通常是设备启停、开机组合、管道方向等整数决策与主调度点;第二阶段y则是在不确定性实现后做再调度、切负荷、弃风弃光等校正动作。外部min决定经济最优,内部max-min则刻画最恶劣场景下的最小再调度成本。这种结构完美匹配电气热网络:第一阶段定机组组合和主出力点,第二阶段在恶劣场景下调整气源供气量与热网温度设定。
3.2 二阶锥松弛的紧性判据与修正
SOCP松弛在电网无源Radial网络中通常是紧的,数学直觉是:如果系统没有违反节点电压越限的瓶颈,或者目标函数本来就是成本最小且网损系数为正,松弛解会自动贴近锥面,这时候原问题就等价于SOCP。
但热网和气网加入后,纯粹的电网紧性结论不再自动成立。松弛解的锥间隙可能与天然气管道流量方向的整数变量耦合,导致气网流量不满足原物理方程。实操中的修正手段有几个:一是在目标函数中加入一个很小的惩罚项(例如对所有 L_ij 加一个 ε 项,或者对热网回水温度加微惩罚),迫使松弛解往锥面靠;二是对松弛解做可行性修复(recovery),把越限的变量投影回可行域;三是对关键约束添加有效割平面。这些手段让“松弛-修正”成为一套完整可用的解法流水线。
3.3 主问题-子问题框架的代码骨架
C&CG(列与约束生成)的核心思想是:一开始主问题只有不确定量的名义场景约束,随着子问题不断识别出新的恶劣场景,再把这些场景对应的约束逐一加到主问题里。给出一个Gurobi风格的Python骨架:
def master_problem(scenarios): m = gp.Model("Master") x = m.addVars(n_units, vtype=GRB.BINARY, name="x") y = m.addVars(n_nodes, n_scen, lb=-GRB.INFINITY, name="y") m.setObjective( c1 @ x + c2 @ y.sum(axis=1).sum(), GRB.MINIMIZE ) m.addConstrs( A @ x + B @ y[:, s] <= b + D @ xi[s] for s in scenarios ) m.optimize() return m.getAttr("ObjVal"), x def sub_problem(x_sol): sp = gp.Model("Sub") z = sp.addVars(n_nodes, lb=0, ub=UB, name="z") # 校正量/切负荷量 sp.Params.OutputFlag = 0 sp.setObjective( penalty @ z.sum(), GRB.MAXIMIZE ) sp.addConstrs( G @ z + H @ x_sol + E @ xi <= h ) # 包含不确定变量 xi sp.optimize() return sp.getAttr("ObjVal"), sp.getAttr("Pi"), sp.getAttr("X")迭代逻辑是循环:主问题求得下界LB和x^*,子问题在x^*下求最恶劣场景,得到上界UB并生成新的场景约束,加入主问题。循环直到 (UB - LB) / LB 小于收敛阈值(通常取1%)。值得提醒的是,子问题内部如果还嵌套0-1变量(例如管线方向在不确定场景下可能切换),就需要用对偶化或big-M线性化把双层结构转成单层MISOCP。这个细节很多人第一版程序都会卡住,先提醒一下。
4. 多能流分段线性化:把非线性“拉直”的工程艺术
4.1 哪些位置必须做分段线性化
整个模型里需要线性化的对象高度集中在几个点:
- 天然气管道的 sqrt(|Δp2|) 函数,这是典型凹平方根曲线。
- 热网节点回水温度与热功率的非线性关系(如果保留变流量调节)。
- 微燃机热电比运行域的凸包络,本质上是把可行域做分段线性近似再引入SOS1/SOS2。
- 某些非线性成本函数,如气源供气成本随产气量上升的凸曲线。
本质上,分段线性化就是用一组折线去逼近原曲线。逼近的质量由分段数和分段点的分布共同决定。工程经验是:对于凹函数曲线,分段点通常在低流量区间取得更密,因为该区间斜率变化剧烈,而高流量区间斜率趋于平缓,可以放得稀一些。这个“前密后疏”的分布策略,比均匀分段能显著减少分段数。
4.2 增量法与SOS2的实现细节
最稳健的做法是增量法。对于分段点 x_0 < x_1 < ... < x_K 和对应的函数值 f_k = f(x_k),引入连续变量 λ_k ≥ 0,满足 sum(λ_k) = 1,且最多允许两个相邻的 λ 非零。变量 x 和 f(x) 分别用对应分段的凸组合表达:
x = sum(λ_k * x_k)
f = sum(λ_k * f_k)
实现“最多两个相邻λ非零”可以用SOS2约束直接表达。Gurobi里不需要手动构造0-1变量,直接给一组变量加addSOS(GRB.SOS_TYPE2)即可。另一种更省整数的做法是用0-1变量z_i标记当前所在分段区间,配合连续变量构造典型的MILP增量形式:
x = x_0 + sum(δ_i * Δx_i),其中 δ_i 的取值有上下界约束,且 δ_i 非零时需要 z_i = 1,同时要求 z_i 只有一段取1。这种形式的优点是能给各分段单独设计斜率,缺点是整数变量多。
4.3 分段数与求解效率的平衡经验
我见过不少论文直接把气网Weymouth方程分成20段甚至更多,结果MIP gap在两个小时内都收敛不下来。实际建议是先从5到8段开始试,看一下目标函数值与更细分段之间的差值。如果差值在0.5%以内,就没必要加密度了;如果超过2%,再针对关键区间加密。这个“先粗后细、按敏感度加密”的步骤,是避免求解器被拖垮的稳妥路径。后续在热网温度曲线上也是一样的原则。
一个很容易忽略的坑是:分段点的选择不能只看曲线的形状,还要看优化模型的目标函数方向。如果是最小化成本,过低的线性化近似可能把可行域撑得过大,导致调度结果偏向“虚假成本低”的运行点;这时候需要在验证阶段用原非线性方程回代,检查真实可行性,若偏差大就说明线性化太粗,需要加密。
5. 完整求解流程与算例设计
5.1 算例系统怎么搭
建议从自己最可控的小系统开始,不要一上来就搞IEEE 123节点配电网加比利时20节点气网那种大拼盘。一个理想的起步算例是:IEEE 33节点配电网 + 6节点天然气网络 + 6节点热力网络,配2台微燃机、2台燃气锅炉、1台电锅炉、1个蓄热罐、若干光伏和风机节点。
这样规模对于商业求解器来说是“轻量级”的,C&CG迭代四五轮就能收敛到1%以内,方便把算法逻辑调试清楚。把算例系统跑通之后,再逐步往更大规模迁移,同时关注求解时间的上涨速度,评估是否需要用Benders分解或拉格朗日松弛等高级手段。
5.2 参数设置与不确定集校准
不确定集参数是鲁棒模型最容易失控的地方。建议做法是:先跑确定性优化作为基准,然后把每个不确定参数的波动范围设为预测值的±10%到±20%,接下来从Γ=1开始逐渐增大,观察总成本随Γ的变化曲线。成本-Γ曲线一般呈阶梯状,每个上升台阶代表新增的一个“最坏场景保护约束”被激活。曲线平缓之后,再加大Γ只会继续增加成本而无实质性收益,那么这个拐点附近的Γ就是工程上的合理取值。
另外要注意的是,风电与光伏的不确定量不能简单建模成独立的盒式区间,因为它们之间存在时间和空间上的相关性。如果完全忽略相关性,盒式不确定集容易同时取到多个“极端但物理上不太会同时发生”的组合,加剧保守性。入门阶段可以先假定独立,但结束时建议用上界削减(如eta-constraint或场景聚合法)来抑制过度保守。
5.3 结果怎么解读
鲁棒优化的输出不能只看一个总成本数字。要拆分对比三个场景下的表现:确定性最优调度、鲁棒优化调度在名义场景下的成本、鲁棒优化调度在最恶劣场景下的成本。这种对比能直观回答“鲁棒性花了多少钱”这个问题。
典型的算例结果表格如下:
| 调度方案 | 名义场景总成本/万元 | 最恶劣场景总成本/万元 | 弃风弃光率/% | 电压越限次数 |
|---|---|---|---|---|
| 确定性优化 | 12.35 | 19.86 | 4.2 | 12 |
| 鲁棒优化(Γ=2) | 14.02 | 15.21 | 0.8 | 0 |
| 鲁棒优化(Γ=4) | 15.67 | 15.34 | 0.0 | 0 |
这个表可以清楚地看到:确定性方案虽然名义成本低,但最恶劣场景下成本和越限次数都高得吓人;而Γ=2的鲁棒方案多花了约13%的名义成本,却把最恶劣场景成本拉低了近24%。这种结果一出来,工程决策者基本是认可的——因为电网调度里一次电压越限或切负荷的实际损失,远大于那点名义成本涨幅。热网温度曲线也可以用类似方式对比,需要确认任何场景下供水/回水温度都维持在舒适度范围内。
6. 常见问题与排查技巧实录
6.1 调试过程的高频Bug清单
这部分是我自己复现和跑项目时踩过的坑,基本可以当避坑指南用。
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| 求解器报“Convexity violation” | SOCP松弛的锥约束里混入了非凸项,常见于气网方向变量与大M的交互 | 给方向变量建立凸包络表示,避免大M与连续锥约束的乘积组合 |
| 鲁棒子问题无界 | 子问题目标函数中对切负荷惩罚系数设置过小,或未知的对偶变量边界缺失 | 将切负荷/弃光的惩罚系数设成远高于运行成本的数量级,再检查原问题的有界性 |
| C&CG迭代慢,UB长期不动 | 主问题添加场景约束后没有完全覆盖子问题识别出的最恶劣场景变量 | 检查回传的是否完整场景向量,必要时把整个不确定集离散化并同时加入多个极端场景 |
| 气网节点气压出现负值或异常小值 | 平方变量 π² 被直接替换后丢失符号信息,边界约束不够 | 为平方变量设置合理下限,并将气压上下限约束用根号V形包络写回原变量 |
| 分段线性化后解在分段点上震荡 | 分段分界点处导数不连续,目标函数对色散不敏感 | 在分界点处增加少量惩罚,或使用光滑化过渡函数 |
| 蓄热罐SOC(荷电状态)约束导致MIP爆炸 | 时间耦合约束建模不够紧凑 | 对SOC变量用增量法建模,并启用LazyConstraints=true 让约束按需激活 |
6.2 松弛紧性修复的真实案例
某次测试中,配电网部分SOCP松弛解与非线性潮流回代结果差了4%,电压幅值最大误差跑到了0.023pu。我在目标函数里给所有 L_ij 加了系数为1e-4的惩罚项,再一次求解后回代误差降到了0.3%以内。这种“微惩罚引导紧性”的技巧非常实用,但注意惩罚系数不能太大,否则会扭曲目标函数从而改变最优调度点。一个经验范围是惩罚项相对成本规模的1e-4到1e-3之间,具体数值需要跟目标函数量级对齐。
另外,如果主问题中用SOS2方式加入分段线性化约束,有时候求解器对SOS2的处理比直接用0-1变量更高效——尤其在Gurobi里,因为它能利用强分支定界规则做特殊处理。实测同一个天然气管道非线性约束,SOS2版本的求解时间经常比等价MILP码快20%-40%。
6.3 不确定集调整的实操经验
最容易被新手忽略的是:不确定参数的波动幅度不是一个纯粹的理论值,它应该被校准到与预测模型的误差水平相吻合。比如你的光伏预测模型RMSE是8%,那不确定集半径取10%-12%是比较合理的;如果取30%,鲁棒解会大面积弃光,工程上没法用。我通常在程序里把不确定集半径做成可配置参数,并默认提供“按预测RMSE自动计算”的开关,这样换算例、换预测模型时不必改核心代码。Γ也可以做成滑动可调,用一个“鲁棒成本-保护水平”权衡曲线辅助人工决策。这样整套程序就从“一次性求解工具”升级成了“可交互调度决策工具”。
还有一点必须提醒:鲁棒优化结果不直接是实时调度指令,而是提供了调度计划的可行域信心。热网蓄热罐的存在能明显调节“鲁棒-经济”矛盾——蓄热罐可以在不确定场景下充当缓冲阀,把鲁棒需求从昂贵的机组爬坡转移到廉价的蓄热充放上。所以算例里一定要包含蓄热罐或等效储热设备,这是降低鲁棒成本最有效的手段之一。
写在最后的一点体会
整套程序调通之后,我对“鲁棒优化”最大的感触是:它的价值不在于“最优”,而在于给你一张“最坏情况下也不会出大事”的保底方案。再进一步说,二阶锥松弛和分段线性化不是要被完美还原物理本质,而是在“可求解”和“合物理”之间找到工程平衡点。作为一个亲历过SCI论文复现和工程落地的人,我的建议是:先小系统跑通C&CG迭代,再扩充设备与网络,最后用成本-Γ曲线和不同方案对比表格来向团队解释鲁棒性的价值。这比任何花哨的理论包装都更能说服人。如果你正在做类似方向,照着这套思路搭一遍,大概率能绕开我当初走过的那些弯路。