开头部分(约300字)
搞智能电网的朋友应该都有体会,调度问题从来不是一个“把负荷分下去”那么简单的事。以前电网结构相对固定,负荷曲线也比较好预测,靠传统调度经验和经典优化算法基本够用。但这两年新能源装机比例一路走高,风电、光伏的出力波动大,加上电动汽车充电、储能装置这些新型负荷不断接入,电网运行的不确定性一下子拉满。这时候,“智能调度”和“优化算法”这两个词几乎成了行业里躲不开的话题。
这篇东西算是我自己在一线做智能电网调度算法研究的一些经验总结,主要聊三件事:一是智能调度到底要解决什么问题,二是怎么把调度问题建造成一个可求解的数学模型,三是目前主流的优化算法(包括粒子群、多目标优化这些)在实际工程里怎么选、怎么用、怎么落地。内容会穿插一些Python代码和实际踩坑记录,适合刚接触智能电网调度、准备做电力系统优化方向的工程师或研究生参考。已经写了多年调度程序的老手,也可以看看第三部分关于算法工程化的经验,也许能少走点弯路。
1. 智能电网为什么需要智能调度
1.1 传统调度模式面临的真实困境
电力系统的调度,说白了就是要在每一时刻让发电侧的总出力等于用电侧的总负荷,同时满足电压、频率、线路潮流等一系列安全约束。过去火电、水电为主力,机组调节能力强、出力可控,调度员做的是“预测负荷,然后安排机组出力”,一天做一次机组组合,几个小时做一次经济调度,基本就能稳住大局。
但现在不行了。以我一个实际接触过的项目为例,一个区域电网里风电装机占比超过30%之后,出力曲线基本是“看天吃饭”。晴天有风的时候,风电场瞬间满发;无风的时候又几乎零出力。光伏更夸张,早高峰和晚高峰之间的出力曲线跟抛物线一样,中午可能高负荷、傍晚突然断崖式跌落。这个时候如果还按原来的静态调度模型去做,要么出现弃风弃光,要么出现备用容量不足,严重的时候甚至可能触发低频减载。
所以智能调度这个概念被反复强调,本质是:调度系统必须能够感知更多信息(包括新能源预测、实时量测、市场信号),并且在更短的时间尺度内做出优化决策。它不是一个单一算法能解决的问题,而是一整套“感知—预测—优化—控制”的闭环。
1.2 智能调度的核心目标与约束体系
智能调度的目标不是单一个,它通常包含多个相互矛盾的子目标:
- 经济性目标:发电成本最小、购电费用最小、网损最小。
- 环保性目标:碳排放最小化、污染物排放最小化。
- 安全性目标:电压偏移最小、线路负载率均衡、备用容量充足。
这几个目标在大多数场景下是打架的。比如,便宜的煤电机组污染高,昂贵的气电机组响应快但成本高,你要压缩成本就不可能不牺牲一点排放指标。更麻烦的是约束条件:
- 功率平衡约束:所有电源出力之和加上网损,等于总负荷。
- 机组出力上下限约束:每台机组都有最小技术出力和最大出力。
- 爬坡速率约束:机组在相邻时段之间的出力变化不能超过一定速率。
- 最小启停时间约束:机组开起来之后不能马上停机,停了也不能马上启动。
- 网络安全约束:线路潮流、节点电压需要保持在安全范围内。
这些约束堆在一起,再叠加新能源出力的不确定性,整个问题就变成一个大规模、非线性、多约束、多目标的优化问题。经典数学规划方法处理起来相当吃力,因为问题规模一大,计算时间可能指数级增长。这也就是为什么智能优化算法在智能电网调度领域被大量引入的根本原因。
1.3 时间尺度上的调度体系分层
还有一个容易被忽略的点:智能调度不是一个单点问题,而是分时间尺度的。我一开始做研究的时候犯过这个错误,以为把模型建大了、约束全放进去就行,结果程序跑一天都出不来结果。
实际工程里,调度体系通常分三层:
- 日前调度:提前一天做,时间分辨率一般是1小时或15分钟,需要做机组组合和经济调度,安排第二天的开机方式和出力计划。
- 日内滚动调度:每15分钟或1小时滚动一次,基于最新的超短期负荷预测和新能源功率预测,修正日前计划。
- 实时调度/自动发电控制(AGC):秒级到分钟级,由调度自动化系统自动调节机组出力,跟踪实时负荷波动。
不同时间尺度,对算法的要求完全不同。日前调度可以接受几分钟甚至十几分钟的计算时间,日内滚动调度需要在几十秒内给出结果,实时AGC则要求毫秒级响应。所以选算法之前,先搞清楚你的问题属于哪个层级,这比纠结用粒子群还是遗传算法重要得多。
2. 智能调度问题的数学建模与核心难点
2.1 经济调度问题的典型数学表达
先看最经典的电力系统经济调度问题。假设系统里有N台发电机组,每台机组的发电成本通常用一个二次函数来近似:
C_i(P_i) = a_i * P_i² + b_i * P_i + c_i
其中P_i是第i台机组的出力,a_i、b_i、c_i是成本系数。目标函数是让总成本最小:
min ∑ C_i(P_i)
约束条件包括:
∑ P_i = P_D + P_loss(功率平衡,P_D为总负荷,P_loss为网损)
P_i,min ≤ P_i ≤ P_i,max(出力上下限)
还有爬坡约束、备用约束等,如果考虑机组启停,还要加入二进制变量表示启停状态,问题就变成了混合整数规划。
这个模型看着简单,但真正做起来有几个坑。第一个坑是网损P_loss怎么算。稍微精确一点的做法是用B系数法,即P_loss = ∑∑ B_ij * P_i * P_j,但这会把约束变成二次约束,求解难度直接上一个台阶。如果只做简化考虑,可以忽略网损,或者用上一次迭代的结果来近似网损,工程上常见做法是迭代修正。
第二个坑是成本函数的非凸性。实际中有些机组存在阀点效应,成本函数不是简单的光滑二次曲线,而是带有波纹的曲线。这种情况下一阶最优条件可能会找到局部最优,经典拉格朗日乘子法容易失效。这也是为什么很多研究开始转向智能算法——它们对函数形态的要求比较宽松。
2.2 不确定性因素的建模思路
新能源接入之后,调度问题最头疼的数学上的难点就是不确定性怎么建模。目前主流的三条路线:
随机规划:认为风电出力、光伏出力、负荷都是服从某种概率分布的随机变量,通过生成大量场景来逼近真实分布,然后对场景集求期望最优。这条路线的问题是计算量大,场景一多,问题规模直接爆炸。我之前试过用蒙特卡洛抽样生成500个场景跑日前调度,单次求解时间从几秒直接飙到十几分钟。
鲁棒优化:不确定参数只会落在一个给定的集合内,目标是让方案在最坏情况下也不违约。优点是方案保守性强,缺点也是太保守,经济性差。实际项目中如果用户对经济性特别敏感,鲁棒优化的结果往往很难被接受。
分布鲁棒优化:介于两者之间,假设不确定参数的真实分布在一个以经验分布为中心的集合内,优化最坏情况下的期望目标。这是最近几年的学术热点,但在工程落地中还不算成熟。
我个人在实际工程中比较推荐的做法是“场景生成+缩减”的组合拳。先用拉丁超立方抽样生成大量初始场景,再用同步回代缩减(k-means聚类也可以)把场景数量减到几十个,既保留了不确定性信息,又把计算量控制在可接受范围内。
2.3 为什么说它是个棘手的组合优化难题
如果只是纯经济调度,变量全是连续的,那用线性规划或者二次规划就能解决。真正让问题变难的是机组组合(Unit Commitment)里的整数变量——每台机组某个时段开还是不开,这是一个0-1决策问题。
假设系统里有50台机组,调度周期是24个时段,那光是决策变量就是50×24=1200个二进制变量。组合爆炸的意味很浓,穷举法想都别想。即便用商业求解器(比如Gurobi、CPLEX)配合分支定界法,在约束特别复杂的时候也可能需要很长时间。
这就是为什么粒子群算法、遗传算法、差分进化算法这些“启发式”方法在电力系统研究中有那么大的受众。它们不保证找到全局最优解,但能在合理时间内找到一个工程上可用的“足够好”的解。这个“工程上可用”很重要——在调度运行里,你花两小时找到一个只便宜0.3%的方案,远不如花两分钟找到一个接近最优、但能应付突发状况的方案。
3. 优化算法选型:经典算法与智能优化算法怎么选
3.1 经典数学规划算法在什么场景下仍然不可替代
有一段时间,学术界有一种倾向,觉得智能算法就是万能钥匙,什么问题拿过来套一个粒子群就行了。我对此持不同意见。
经典算法在两类场景下依然不可替代:
第一类是求解精度要求极高的小规模问题。比如一个区域配电网里只有十几台分布式电源,用内点法求解二次规划,求解速度快、结果稳定,而且能拿到理论上的最优性证明。这个时候硬用粒子群,属于大炮打蚊子,还得担心收敛精度问题。
第二类是作为“精确算法”的底层引擎。很多智能算法在迭代过程中需要反复求解子问题,这时候内点法、单纯形法这些经典算法作为子问题求解器,反而比纯启发式搜索更高效。比如我在一个配电网重构项目里,外层用遗传算法搜索开关组合,内层用线性规划计算潮流分布和网损,这个组合比纯遗传算法快了三倍不止。
所以我的建议是:不要把经典算法和智能算法放在对立面,它们是互补的关系。经典算法擅长处理“结构好”的问题,智能算法擅长处理“结构差”的问题,而真实工程问题往往是“部分结构好、部分结构差”。
3.2 粒子群优化算法的原理与适用边界
粒子群算法(PSO)应该是搞智能优化的人接触最多的算法之一。它的思想来源是鸟群觅食行为——每只鸟(粒子)在搜索空间里飞行,既参考自己历史上找到的最好位置(个体经验),也参考整个群体找到的最好位置(社会经验),通过不断更新速度和位置来逼近最优解。
核心更新公式就两个:
v_i(t+1) = w * v_i(t) + c_1 * r_1 * (pBest_i - x_i(t)) + c_2 * r_2 * (gBest - x_i(t))
x_i(t+1) = x_i(t) + v_i(t+1)
其中w是惯性权重,控制粒子保持原来速度的程度;c_1和c_2是学习因子,控制粒子向个体极值和全局极值学习的强度;r_1和r_2是[0,1]之间的随机数。
这个算法最大的优点就是实现简单,参数少,不需要求梯度,适合处理非凸、不可导的调度问题。我经常跟人说,一个写代码的新手花一个下午就能把基础PSO跑起来。但它的缺点也明显:
- 容易早熟收敛,陷入局部最优。特别是多峰函数问题,粒子群经常集中在一个局部极值附近“自嗨”。
- 参数太敏感。w、c_1、c_2的取值对结果影响很大,而且不同问题上最优参数还不一样。
- 约束处理能力弱。PSO本身是无约束优化算法,处理电力系统这种强约束问题,必须配合惩罚函数法或者约束修复策略。
给一个经验性的参数建议:惯性权重w从0.9线性递减到0.4(前40%迭代用0.9附近,后期到0.4附近),c_1和c_2通常取2.0,粒子数取问题维度的10到20倍。这些参数不一定是最优的,但作为起点跑一轮,通常能得到一个合理结果。
3.3 多目标优化为什么值得重点关注
实际电网调度几乎从来不是单目标问题。成本、碳排放、网损、电压质量,这些目标往往是互相冲突的。如果强行加权重合成单目标,最大的问题是权重怎么定,而且一次运行只能给出一组权重对应的一个解,无法看到帕累托前沿的完整结构。
多目标优化算法要解决的就是这个问题。NSGA-II是这类算法中最经典的一个,核心思路是用非支配排序把种群分成不同层级(第一层是最优秀的解,第二层次之),再通过拥挤度距离保持解的多样性,保证最终得到的一组解能均匀分布在帕累托前沿上。
我在实际项目中用过NSGA-II来做“成本+碳排放”双目标的经济调度,效果相当不错。跑完之后把帕累托前沿画出来,决策者可以从曲线上直观看到:如果碳排放降低10%,成本大概要增加多少;如果不想增加太多成本,碳排放在哪个区间内是合理的。这种决策支持能力,单目标优化是怎么也给不出来的。
对于多目标算法,还有几个细节值得注意:
- 种群规模不能太小,我一般设100以上,否则帕累托前沿会很难看。
- 变异率不要设太大,否则收敛不了;也不要太小,否则种群很快就同质化了,一般取0.1左右。
- 迭代次数要留够,多目标问题的收敛速度通常比单目标慢,300代以下基本不要期望有好结果。
3.4 其他常用智能算法与混合策略
除了PSO,工程上常用的还有:
- 遗传算法(GA):全局搜索能力强于PSO,但收敛速度慢。适合机组组合这种离散变量占比高的问题。
- 差分进化算法(DE):整体鲁棒性比GA好,尤其是连续优化问题,在我的测试里DE的收敛精度通常优于标准PSO。
- 灰狼优化(GWO):结构简单、收敛速度快,近年在电力系统里也很流行,但同样有早熟收敛问题。
- 野马优化算法(WHO):这是相对新颖的算法,模拟野马群的社会行为,在部分测试函数上表现亮眼,但工程验证还比较少,建议在小规模问题上先试用。
我的实践结论是:没有哪个算法全面碾压其他算法,关键在于用对地方。比如同样是配电网重构问题,如果开关个数不多(少于50个),遗传算法配合枚举局部搜索效果很好;如果是连续变量为主的经济调度,差分进化往往比PSO更稳。
还有一个很实用的策略是混合算法。比如“PSO + 局部搜索”:粒子群先全局粗搜,每一步迭代完了对当前最优解做一次局部精细搜索(比如用模式搜索法),这样既能保持全局搜索能力,又提升了收敛精度。我在多个项目里用这个策略,效果比单用PSO好很多。
4. 实操过程:用Python实现一个智能调度优化示例
4.1 问题定义与数据准备
纸上谈兵没什么意思,我直接用Python写一个完整的调度优化示例,让大家直观感受整个流程。这里以经典的6机组经济调度问题为例,目标是在满足负荷需求的前提下,最小化发电总成本。
机组参数用IEEE标准测试系统里常用的数据,每台机组有出力上下限、成本系数:
| 机组 | P_min (MW) | P_max (MW) | a (元/MW²h) | b (元/MWh) | c (元/h) |
|---|---|---|---|---|---|
| G1 | 100 | 500 | 0.007 | 7 | 240 |
| G2 | 50 | 200 | 0.0095 | 10 | 200 |
| G3 | 80 | 300 | 0.009 | 8.5 | 220 |
| G4 | 50 | 150 | 0.009 | 11 | 200 |
| G5 | 50 | 200 | 0.008 | 10.5 | 220 |
| G6 | 50 | 120 | 0.0075 | 12 | 190 |
总负荷假设是850 MW。先忽略网损和机组爬坡约束,把问题简化为纯经济调度,方便大家看懂核心逻辑。
4.2 粒子群算法实现经济调度的完整代码
我先写一个标准的PSO来求解这个问题,注意点在代码注释里标出来。
import numpy as np # 机组参数 P_min = np.array([100, 50, 80, 50, 50, 50]) P_max = np.array([500, 200, 300, 150, 200, 120]) a = np.array([0.007, 0.0095, 0.009, 0.009, 0.008, 0.0075]) b = np.array([7, 10, 8.5, 11, 10.5, 12]) c = np.array([240, 200, 220, 200, 220, 190]) P_D = 850 # 总负荷(MW) n_gen = len(P_min) def cost_func(P): """计算总发电成本""" return np.sum(a * P**2 + b * P + c) def constraint_penalty(P): """约束处理:功率平衡惩罚项 + 出力越限惩罚项""" penalty = 0.0 # 功率平衡惩罚:偏差越大,惩罚越大 balance_violation = np.abs(np.sum(P) - P_D) penalty += 1000 * balance_violation # 出力上下限惩罚 penalty += 1000 * np.sum(np.maximum(0, P_min - P)**2) penalty += 1000 * np.sum(np.maximum(0, P - P_max)**2) return penalty def fitness(P): return cost_func(P) + constraint_penalty(P) # PSO 参数 n_particles = 60 n_iter = 200 w_max, w_min = 0.9, 0.4 c1, c2 = 2.0, 2.0 # 初始化粒子位置:在上下限之间随机初始化 X = np.random.uniform(P_min, P_max, size=(n_particles, n_gen)) # 修正初始解,使总和接近负荷 for i in range(n_particles): X[i] = P_min + (P_max - P_min) * np.random.rand(n_gen) X[i] *= P_D / np.sum(X[i]) # 缩放使总和等于 P_D V = np.zeros_like(X) pBest = X.copy() pBest_fitness = np.array([fitness(p) for p in pBest]) gBest_idx = np.argmin(pBest_fitness) gBest = pBest[gBest_idx].copy() gBest_fitness = pBest_fitness[gBest_idx] for t in range(n_iter): w = w_max - (w_max - w_min) * t / n_iter r1, r2 = np.random.rand(n_gen), np.random.rand(n_gen) V = w * V + c1 * r1 * (pBest - X) + c2 * r2 * (gBest - X) X = X + V # 反射处理越界:把粒子拉回边界内 X = np.clip(X, P_min, P_max) for i in range(n_particles): # 每次迭代后做一次简单修正,让总和靠近P_D X[i] += (P_D - np.sum(X[i])) / n_gen X[i] = np.clip(X[i], P_min, P_max) fit = fitness(X[i]) if fit < pBest_fitness[i]: pBest[i] = X[i].copy() pBest_fitness[i] = fit gBest_idx = np.argmin(pBest_fitness) if pBest_fitness[gBest_idx] < gBest_fitness: gBest = pBest[gBest_idx].copy() gBest_fitness = pBest_fitness[gBest_idx] print("最优出力方案(MW):", np.round(gBest, 2)) print("总出力(MW):", round(np.sum(gBest), 2)) print("总成本(元/h):", round(cost_func(gBest), 2))这段代码跑完之后,你会看到每台机组的出力分配结果。正常情况下,PSO能找到总出力正好等于850 MW的解,成本大约在8700到8900元/h之间。
4.3 代码背后的关键设计思路
这一段代码虽然短,但里面藏了几个我踩坑之后总结出来的工程技巧:
第一个是初始解构造。很多人初始化粒子时习惯直接在范围内随机撒点,但这样得到的初始种群很多都不满足功率平衡约束,罚函数值巨大,粒子群初期会浪费大量迭代在“纠正方向”而不是“优化成本”。我在这里做了一个缩放修正:先随机生成,然后按比例缩放,让初始解的总和正好等于负荷。这个操作能让初始种群一开始就在可行的超平面附近,收敛速度会快非常非常多。
第二个是爬坡约束的替代处理。上面代码没有显式考虑爬坡约束,但实际工程里这个约束会极大影响可行域形状。如果你要加入爬坡约束,需要把决策变量从一个时刻扩展到多个时刻(比如24时段),这时每个粒子就是一个24×N的矩阵,速度更新要相应改成三维操作。我建议新手先跑通单时段的,再加多时段。
第三个是惩罚系数的掌握。约束惩罚系数设太大,粒子会只顾着满足约束而失去优化动力;设太小,惩罚项根本起不了作用。我的经验是先从1000开始试,如果看到粒子群在迭代中频繁违反约束,就加大;如果看到粒子群稳定在可行域内但成本下不去,就减小。
4.4 扩展到多目标优化:NSGA-II实战要点
如果你做的是多目标调度(比如成本和排放同时优化),NSGA-II会比PSO更合适。这里不贴完整NSGA-II代码(网上现成库很多,比如pymoo),但讲一下用pymoo实现的几个关键点:
from pymoo.algorithms.moo.nsga2 import NSGA2 from pymoo.core.problem import Problem from pymoo.optimize import minimize from pymoo.operators.crossover.sbx import SBX from pymoo.operators.mutation.pm import PM from pymoo.operators.sampling.rnd import FloatRandomSampling class DispatchProblem(Problem): def __init__(self): super().__init__(n_var=6, n_obj=2, xl=P_min, xu=P_max) def _evaluate(self, X, out, *args, **kwargs): # 第一个目标:成本 f1 = np.sum(a * X**2 + b * X + c, axis=1) # 第二个目标:碳排放(排放系数简化为线性) emission_factor = np.array([0.9, 0.6, 0.7, 0.5, 0.7, 0.4]) f2 = np.sum(emission_factor * X, axis=1) # 约束:功率平衡 g1 = np.abs(np.sum(X, axis=1) - P_D) - 5 out["F"] = np.column_stack([f1, f2]) out["G"] = g1.reshape(-1, 1) problem = DispatchProblem() algorithm = NSGA2( pop_size=100, sampling=FloatRandomSampling(), crossover=SBX(prob=0.9, eta=15), mutation=PM(prob=1.0/6, eta=20), ) res = minimize(problem, algorithm, ("n_gen", 300), verbose=True)用pymoo跑多目标优化的好处是,非支配排序、拥挤度计算这些底层逻辑都封装好了,你只需要定义目标和约束。跑完之后,res.F就是一组帕累托前沿上的解。画成散点图,你会看到一条从“低成本高排放”到“高成本低排放”的曲线,这个图直接能给决策者看,非常直观。
5. 常见问题与排查技巧实录
5.1 收敛精度差或收敛到不可行解
这是我被问得最多的问题。粒子群跑完了,结果里有一台机组的出力还在上下限边界附近震荡,或者总出力跟设定负荷差了十几MW,怎么看怎么不对劲。
排查思路先从“问题出在算法还是出在模型”入手。我建议先做一个检测:把用PSO找到的解,代入到约束条件里逐条检查,看看是哪个约束被违反了,被违反了多少。
如果违反的是功率平衡约束,大概率是惩罚系数不够大或者边界修正逻辑有问题。比如有些新手会在每次迭代结束时不加“X[i] += (P_D - np.sum(X[i])) / n_gen”这个修正步骤,那功率平衡只能靠惩罚项拉,很难精确到位。
如果粒子群早熟收敛在某个局部最优解上,试试下面几个方向:
- 增大种群规模,从40增加到80或100。
- 调整惯性权重,不要线性递减,改成自适应(比如用当前种群多样性来衡量,多样性低就加大w)。
- 引入变异机制:随机让一部分粒子重新初始化,模拟遗传算法里的变异操作。
5.2 多目标优化中帕累托前沿分布不均
用NSGA-II跑多目标调度,经常出现帕累托前沿“两头密、中间空”的问题。这通常意味着解的多样性保持出了问题。
一个常见原因是拥挤度距离的计算逻辑在你用的框架里没有覆盖所有个体,导致中间区域的解被错误删掉了。我的建议是:迭代结束后,把得到的非支配解重新做一次拥挤度计算,手动筛选出分布均匀的子集,而不是直接信任算法输出的最后一代表。
另外一个技巧是,可以在每次迭代后把当前代的非支配解记录下来,整个运行结束后合并所有非支配解再做一次筛选。这种做法虽然会多消耗一点内存,但能有效避免中间优秀解的丢失。我做过实验,同样的配置下,记录历史非支配解的方案比只用最后一代的结果,帕累托前沿的覆盖范围能提升15%到20%。
5.3 求解速度太慢,如何加速
调度问题上了规模之后,最头疼的就是运算时间。下面几个加速手段是我实际验证过有效的:
第一,降维。把建模粒度从1小时改成15分钟,决策变量数量直接缩小4倍,速度提升非常明显。当然时间分辨率变粗会损失一些调度精度,要根据工况权衡。
第二,并行化。粒子群和遗传算法这类群体智能算法天然适合并行。每个粒子的适应度计算是相互独立的,可以用Python的multiprocessing或者joblib做并行。我有一次把一个72机的算例,用8核并行把计算时间从20分钟压缩到4分钟,效果极好。
第三,用混合算法做“粗精结合”。简单来说,先用智能算法快速找到一个可行解附近,再用内点法做二次规划精细收敛。因为内点法在用智能算法给出的初始点附近能快速收敛到局部最优,两者结合往往能比纯智能算法快好几倍,精度也不差。
5.4 工程落地中容易被忽视的三个问题
最后分享几个纯数据层面的教训,都是做项目时踩过坑才意识到的:
数据质量问题。智能调度的效果上限,取决于输入数据的质量。风机出力预测误差太大,再好的优化算法也白搭。所以实际项目里我会花大量时间做数据清洗和预测模型调优,有时候算法优化带来的收益,反而不如把预测误差降低2个百分点来得明显。
边界条件意识。调度系统最终是给调度员用的,不是给算法研究者自嗨的。算法跑出来的方案,必须能解释清楚“为什么是这个方案”。有一次我优化出来的方案建议一台大机组在凌晨低谷时段保持运行,从成本上看是优化了,但调度员直接否掉了——因为那个时段该机组所在区域的电网有线路检修,不能运行。从那以后,我养成了把约束条件整理成清单、和业务方逐条确认的习惯。
系统鲁棒性。算法不是跑一次就完事的,实际调度系统是全天候运行的。如果某个时刻数据异常导致算法不收敛,系统必须有fallback机制。我现在做调度算法一定跑两层:第一层是优化算法,第二层是事后校验模块,在算法输出结果之后,重新校验一遍所有约束是否满足,如果不满足,自动切换到预设的安全预案。这套机制看起来笨拙,但在生产环境里能避免大量的故障。
我在实际项目中还有个习惯:每次跑完优化之后,会把解和目标值都存下来做历史对比。过了几个月回看,能很清楚地发现算法参数是否需要调整,负荷结构是否有变化。这种事后的复盘往往比调参本身更有价值。
如果你正准备做智能电网调度方向的研究或者项目,我的建议是:先把基础模型吃透,再玩花活儿。不要一上来就追求复杂的深度强化学习或者分布式优化,把经济调度、机组组合、粒子群这些地基打好,后面遇到真实问题才能举一反三。