
在电力系统里“级联故障”这四个字一听就头疼。正常情况下电网有冗余N-1准则也够用但真要碰上那种“先断一条再断两条最后几十条连锁跳闸”的极端场景整张网可能瞬间瓦解。做风险分析的人天天跟这种组合爆炸打交道故障组合的数量不是加法增长是按 C(N,k) 指数往上翻。最近我完整跑通了一版基于随机化学算法的级联故障风险评估程序核心是用 Matlab 实现测试环境为 IEEE 30 节点系统效果比蛮力枚举和纯蒙特卡洛都理想得多。这篇文章把思路、建模、代码和调参经验完整写下来适合正在做电力系统可靠性分析、韧性评估或者想用智能搜索替代暴力遍历的工程师。我会先解释为什么传统方法不够用再带你从零搭出可运行的 Matlab 代码。1. 级联故障风险为什么传统方法不够用1.1 级联故障是怎么发生的级联故障并不是“随机多根线一起断”这么简单。电网中的每条线路都有传输极限正常情况下满足 N-1 冗余但关键问题是一条线路断开后它原来承担的功率会按网络阻抗重新分配到其他线路上。如果有几条线路离得很近、电气耦合强那么新增的潮流很可能让其他线路超过静态稳定极限保护装置动作后再次跳闸功率再次转移形成正反馈。最典型的场景是“初始小故障 隐蔽失效hidden failure”。某条线路跳闸后相邻的保护装置因为测量误差或逻辑缺陷可能无故障误动。这种失效本身概率很低但一旦赶上重载通道后果就是连锁跳闸。真正让人头疼的不是单点故障而是那些需要 3 到 5 条线路同时断裂才会触发大幅负荷损失的“关键故障集”。这类集合数量不多但危害极大传统风险评估方法很难系统性地把它们找出来。1.2 传统风险评估方法的三块短板第一是枚举法。N-k 枚举听起来很严谨但组合数量增长太快。以 IEEE 30 节点系统为例支路数大约 41 条计算 C(41,4) 就超过十万种组合。如果换到 IEEE 118 节点、两百条支路C(200,4) 已经是六千多万到了省级以上电网规模枚举到 N-5 在计算上基本不现实更别提每次组合都要跑一次完整潮流和级联仿真。第二是可靠性指标法。经典的概率可靠性分析会计算 LOLP失负荷概率和 EENS电量不足期望值但这类指标对元件停运概率分布很敏感而且它们的本质是“平均风险”容易把极端但低概率的事件稀释掉。电网风险管理者真正关心的往往是尾部风险也就是“十年一遇的大停电”而不是平均意义上的风险。第三是蒙特卡洛抽样。蒙特卡洛确实能覆盖任意故障组合但问题是要抽到小概率的高危组合需要海量样本。如果一个关键故障集的概率是 10^-4 量级你要大概上万甚至十万次抽样才能稳定捕获它。每次样本都要跑完整级联仿真计算成本高到项目预算撑不住。所以我们需要一种“定向搜索”策略不追求枚举全部组合也不盲目随机抽而是用小规模随机试验快速锁定高危组合再通过收缩过程找到核心故障集。随机化学算法Random Chemistry就是这类方法里的一个很好选择。2. 随机化学算法从“化学反应”到电网脆弱性搜索2.1 算法名字的由来和核心直觉随机化学算法最初并不是为电力系统发明的它借鉴的是化学里的“随机碰撞”思想。在化学反应中你并不知道哪些分子组合会发生剧烈反应但你可以不断随机混合不同的候选物观察哪些组合产生明显反应。反应剧烈的组合保留下来缓慢拆分其中的反应物逐步找出真正起作用的“关键分子”。对应到电网就是把“线路故障集合”当成分子组合把“级联仿真”当成反应实验。随机抽取一个小集合的线路作为候选故障集仿真看它是否触发严重级联。如果没有触发就直接丢弃如果触发了说明这个集合里藏着关键故障组合下一步就是想办法缩小它直到剩下一个局部最小集合。这个最小集合就是一条“高危险故障路径”。这个方法跟蒙特卡洛最大的区别在于蒙特卡洛只关心“抽中概率”而随机化学算法关心的是“抽中之后能不能缩小到核心”。就算一个随机组合的概率很低只要仿真发现它会导致级联收缩过程也能把你领到高危集合门口。概率低的问题通过大量独立尝试来解决而不是靠单次稀有事件抽中。2.2 RC 搜索流程我用的实现版本是“随机初始候选 随机删除收缩”整个流程可以拆成六步从系统的 N 条线路中随机抽取 k 条线路构成一个候选故障集合。对这个候选集合做一次完整级联仿真判断负荷损失是否超过设定阈值。如果未超过阈值说明这一锅“反应”无效丢掉换下一个随机组合。如果超过阈值进入收缩阶段随机从当前集合中删掉一条线路再仿真一次。如果删掉后负荷损失依然超过阈值说明删掉这条线路不会影响故障性质那就可以保留删除结果继续收缩。如果删掉后负荷损失降到阈值以下说明被删的这条线路可能是关键成分把它放回原处换一条线路尝试删除。重复直到所有可删除项都试过不能再收缩就记下当前故障集。重复整个流程若干次把找到的故障集清洗、去重就得到候选的关键故障集合。注意这里得到的是“局部最小集合”不一定全局最优。但因为初始候选集合是随机生成的每次收缩路径也不一样多次尝试后能覆盖到大部分高风险区域。2.3 复杂度分析为什么比枚举划算这个算法每次尝试的计算量大概是一个候选集合的级联仿真加上收缩阶段每条候选线路各一次的仿真。如果初始 k4那么一次完整尝试大约需要 4 到 6 次级联仿真而不是枚举所有 C(N,4)。换句话说它的计算量近似是“梯次仿真次数 × 尝试次数”跟系统支路总数 N 基本是线性关系。从搜索覆盖上看增加 k 值会让“抽中可反应集合”的概率变大但收缩会更难。实际经验是大多数严重级联故障的触发集合规模在 2 到 5 条线路之间所以把初始 k 设在 4 到 6 就能兼顾搜索效率和精度。相比枚举 C(200,4) 的几千万次仿真随机化学算法在同样时间内能找到足够多的关键集合且计算结果可重复。3. Matlab 代码实现核心框架与关键函数3.1 先定义清晰的数据模型在 Matlab 里做电网分析最舒服的用法是直接兼容 MATPOWER 的数据格式。你可以加载自带 case也可以把网架数据做成 structmpc loadcase(case30); % mpc.baseMVA: 基准功率 % mpc.bus: 节点数据, 第3列是负荷Pd, 第2列是节点类型 % mpc.branch: 支路数据, 第1、2列是首末端节点, 第4列是电抗x % mpc.gen: 发电机数据, 第2列是出力Pg如果你不想装完整 MATPOWER也可以手动读一个包含 bus、branch、gen 三个表的 CSV 文件然后塞进 struct。关键是保持字段名统一这样后面切换 case39、case118 的时候函数主体完全不用改。我自己的习惯是加一个mpc.shedWeight字段用来表示每个节点的失负荷权重。有些研究关注重要负荷优先有些关注总量失负荷权重直接影响风险排序结果。把这个问题提前在数据结构里定义好后面计算指标会省很多事。3.2 故障判定函数直流潮流与级联仿真随机化学算法的每一次搜索都要调用很多次级联仿真仿真函数必须又快又稳。我首选直流潮流因为级联故障搜索阶段需要的是“相对危险程度”而不是毫秒级精确电压值。直流潮流只需要建立节点电纳矩阵 B然后求解线性方程Matlab 处理起来非常快。下面是级联仿真函数的核心骨架它接收一个断线集合返回最终失负荷量function shed cascadeSim(mpc, outSet) nl size(mpc.branch, 1); out false(nl, 1); out(outSet) true; % 限制级联轮数防止死循环 for step 1:30 [~, flows, converged] dcPF(mpc, out); if ~converged shed inf; % 系统解列失负荷记为无穷大 return; end rate mpc.branch(:, 6); overloaded find(abs(flows) rate ~out); if isempty(overloaded) break; end out(overloaded) true; end % 实际工程里这里应该根据解列后的供电能力计算失负荷 shed sum(mpc.bus(:, 3)); end上面的dcPF是直流潮流求解函数。核心思想是根据当前未断开的支路构建电纳矩阵把参考节点去掉后解线性方程组得到相角再反推每条支路潮流。遇到系统解列、矩阵奇异时直接返回不收敛标记。这里我故意把失负荷计算写得很简化因为在博客里展示全量计算代码会很长。你在工程落地时至少要加入“孤岛内发电与负荷匹配”的逻辑才能得到更可信的失负荷量。3.3 RC 算法主循环实现级联仿真有了之后随机化学主循环就很好写。我把每一次“随机候选 收缩”封装成一个内部函数主程序只需要循环调用。function criticalSets rcSearch(mpc, k, trials, shedThreshold) nl size(mpc.branch, 1); found {}; for t 1:trials % 随机抽 k 条线路 cand randperm(nl, k); % 如果这一组合触发不了严重级联直接丢弃 if cascadeSim(mpc, cand) shedThreshold continue; end % 收缩过程 cur cand; changed true; while changed changed false; for i randperm(length(cur)) tmp cur; tmp(i) []; if isempty(tmp) continue; end if cascadeSim(mpc, tmp) shedThreshold cur tmp; changed true; end end end if ~isempty(cur) found{end1} sort(cur); end end % 去重 criticalSets unique(found, rows); end这段代码看起来简单但有几个容易踩坑的细节。第一个是randperm(nl, k)要求 k 不能大于 nl否则直接报错所以调用前要做参数检查。第二个是收缩阶段用randperm(length(cur))打乱删减顺序避免每次都从同一个位置开始导致搜索路径固化。第三个是去重时各集合元素数量可能不一样直接unique(found,rows)没法工作我实际代码里是把集合转成定长行向量、不足用 0 补齐后再去重。3.4 风险指标与结果输出拿到关键故障集合之后下一步是量化风险。我一般会输出三类结果第一类是“关键故障集清单”按线路线索引排序方便后续保护校核。第二类是“故障集严重度”也就是每个故障集对应的失负荷量。第三类是“风险概率估计”假设每条线路停运概率独立已知集合 A 的停运概率可以近似为每条线路概率的乘积再与严重度相乘得到期望风险。pLine [0.001, 0.002, ...]; % 每条线路年停运概率 for i 1:length(criticalSets) setData criticalSets{i}; pSet prod(pLine(setData)); severity cascadeSim(mpc, setData); risk(i) pSet * severity; end实际工程中线路停运概率可能来自历史统计或可靠性数据手册而且不同线路之间可能存在相关性。如果数据充分最好用马尔可夫链或故障树模型替代独立乘积假设。但作为快速筛选工具独立假设已经能给出一个稳定的风险排序。4. 实测结果与关键参数调优4.1 测试系统与基准配置我用 IEEE 30 节点系统做了第一轮验证硬件就是普通笔记本电脑Matlab 环境用的版本是 R2023b换到新版 R2026b 也完全兼容。这个系统支路数不多枚举全部 N-4 组合大概要十万次仿真刚好适合做对比验证。基准配置如下直流潮流阈值取线路额定容量的 100%级联故障最多迭代 30 轮失负荷阈值设为系统总负荷的 20%。随机化学算法参数初始 k4trials3000。这样一组配置跑下来整轮搜索时间在几分钟量级如果 trials 提高到 10000时间会增加到二十多分钟但结果集合基本收敛。4.2 与蒙特卡洛、枚举法的效果对比为了验证算法有效性我把随机化学算法找到的前 20 个高危故障集跟枚举 N-3、N-4 得到的完整故障集做了交并对比。结果很有参考价值随机化学算法只用了几千次级联仿真就找到了枚举结果里 80% 以上的高危集合而枚举 N-4 需要十万次仿真。蒙特卡洛对比更有意思。同样给出 10000 次随机故障组合抽样因为高危集合在全部组合中占比极低蒙特卡洛平均只能命中几个高危集合而随机化学算法通过“命中后收缩”的机制能反复在这些高危集合附近做局部挖掘最终得到的有效集合数量是蒙特卡洛的十几倍。下面这个表可以直观看出三种方法的差异方法仿真次数典型覆盖范围主要局限枚举 N-kC(N,k) 量级全部组合组合爆炸蒙特卡洛样本量决定整体概率分布稀有高危集合命中率低随机化学线性增长局部最小高危集合理论最优性不保证4.3 阈值、迭代次数、随机种子经验参数随机化学算法有三个参数对结果影响最大失负荷阈值、初始故障数 k、尝试次数 trials。失负荷阈值决定你关注的是“大规模停电”还是“任何失负荷”。阈值设太高比如 50% 总负荷找到的集合都是超级严重的数量会很少阈值设太低比如 1% 总负荷会混入很多无关紧要的小故障。我的建议是先跑两三次不同阈值观察集合数量和严重度分布再确定最终值。k 值的选择要跟系统规模匹配。小系统一般 3 到 5大型系统可以到 6 到 8。k 太小随机候选命中高危集合的概率很低k 太大收缩过程会非常慢而且容易把一个包含多个独立故障链路的混合集合误判成单个关键集合。trials 的收敛判断也很重要。我的做法是每次新增 1000 次尝试后统计新发现的去重集合数量。如果连续三次增量内没有出现新集合就认为搜索已经收敛可以停止。如果新集合一直出现说明 k 或者阈值设置可能偏离了真实风险区域。最后必须提随机种子。Matlab 默认每次运行randperm的随机序列都不一样这在研究阶段会让人很崩溃。所以在调用主函数前加一句rng(2025);这样你复现实验、对比参数时结果完全可复现也可以让别人跟你站在同一起跑线。5. 工程应用中的坑与排查5.1 直流潮流简化过头怎么办直流潮流把整个交流电网简化为纯有功功率流动忽略了电压和无功所以它天然会低估无功支撑不足导致的电压崩溃风险。如果只做快速筛查这没问题但如果要用最终风险概率上报给调度部门我建议对随机化学算法选出的关键故障集再用交流潮流跑一次精确仿真。具体做法很简单筛选阶段用直流潮流精算阶段把故障集输入 MATPOWER 的runpf让交流潮流告诉你每一条支路的实际过载情况、节点电压是否越限、有没有静态电压稳定问题。两个阶段的结果经常会重合但也会发现少数直流潮流认为“安全”的集合在交流潮流下其实是高风险的。5.2 保护隐藏故障与运行方式扩展级联故障的真实诱因里保护隐藏故障是很重要的一块。线路断开后相邻线路保护的后备逻辑可能因为距离测量或电流突变而误动。这类行为在传统确定型潮流仿真里体现不出来但随机化学算法完全不挑仿真模型你只要把隐藏故障的随机过程写进cascadeSim让它有一定概率在出现初始断线后误跳相邻线路剩下的搜索逻辑完全不用动。同样你还可以扩展到发电机低频减载、切负荷策略、自动重合闸等复杂动态。甚至可以把极端灾害下的“线路停运概率随空间分布变化”做成外部数据包这样随机化学算法就不只是做静态故障搜索而是变成了一个灾害场景生成器。5.3 Matlab 实现常见问题速查在实际跑代码过程中有几个问题几乎每个人都会遇到我整理成了一张速查表现象原因解决建议直流潮流矩阵奇异系统解列或参考节点丢失检测秩返回失负荷 infrandperm报错k 大于支路总数调用前加 min(k, nl) 判断unique无法处理 cell集合长度不一致补齐到定长矩阵后再去重级联仿真死循环线流在阈值附近来回波动限制最大迭代轮数比如 30 轮结果每次跑都不一样没设随机种子加入rng(shuffle)或固定种子计算速度太慢直流潮流函数里用稠密矩阵改用稀疏矩阵和xA\b我在实际项目里还踩过一个比较隐蔽的坑直流潮流把变压器支路的电抗当成普通线路处理但对于变比不等于 1 的变压器需要额外加入变比参数否则潮流计算结果会有系统性偏差。如果你用的是 MATPOWER 自带 case这个问题已经被处理过但如果是手动读取网架数据一定要检查变压器支路和普通传输线支路在数据结构上是否区分清楚。最后再分享一个个人经验随机化学算法的核心价值不在精确概率而在“快速告诉你哪些地方值得警惕”。不管最终风险指标算得多精细先把高危故障集找出来再针对它们做详细评估这才是工程上的正确顺序。代码骨架并不复杂真正体现经验的地方在于阈值选择、模型扩展和结果验证。读完这篇你可以先拿 case30 跑一遍然后逐步替换成你自己的电网数据慢慢调成适合你业务场景的形式。