配电网可靠性评估,听着好像是个纯学术课题,但实际上这东西和咱们日常生活关系特别大。你想想,夏天最热的时候、工厂赶订单的时候,停电哪怕一个小时,损失都是真金白银。对供电公司来说,怎么科学地回答“我这个网架到底能扛多久”“先改造哪条线路最划算”,靠拍脑袋是不行的,必须要有一套定量的评估方法。我今天想聊的,就是基于序贯蒙特卡洛模拟法的配电网可靠性评估,以及我在这个项目里用Matlab从零搭建仿真代码的全过程。这套方法的核心价值在于,它能真实模拟配电网在长达数年甚至数十年时间尺度上的运行和故障状态,把那些“一旦出了事才知道哪里不行”的被动局面,变成提前看得见的风险清单。
这篇文章不是来念教材的,我会把整个评估过程拆开揉碎,从原理到代码,从参数设置到坑点排查,讲清楚每一步为什么这么做、怎么落地。适合正在做配电网规划、供电可靠性管理工作的工程技术人员,也适合电力系统方向的研究生,尤其是刚接触蒙特卡洛仿真、想把算法写成可运行代码的同学。
1. 可靠性评估到底在算什么,序贯法为什么值得选
1.1 你能算出来的那些核心指标
配电网可靠性评估,说白了就是回答三个问题:用户多久会停一次电?每次停多久?一年下来能供上多少电?行业里已经有了一套标准化指标,不管你是用解析法还是仿真法,最后都要落到这几个数上:
- SAIFI(系统平均停电频率指标):单位是次/用户·年,反映的是停电频率。数值越低,说明系统越“扛造”。
- SAIDI(系统平均停电持续时间指标):单位是小时/用户·年,反映的是停电时长。数值越低,说明故障恢复越快。
- CAIDI(用户平均停电持续时间指标):单位是小时/次,公式是SAIDI除以SAIFI,衡量的是“每次停电到底折腾了多久”。
- ASAI(平均供电可用率指标):用百分比表示,比如99.99%就是所谓的“四个九”。
- ENS(期望缺供电量):单位是kWh/年,直接把可靠性换算成电量损失,给经济分析用。
这些指标之间是有内在逻辑的。SAIFI和SAIDI各有侧重,一个看频率一个看时长,而CAIDI就是两者的综合体现。我在实际项目中,最关心的是ASAI和ENS,因为一个适合写报告、做横向对比,一个适合算经济损失、对接财务模型。
1.2 解析法的困局,以及序贯法破局的关键
传统课上讲得最多的是解析法,比如故障模式与影响分析(FMEA)加最小割集法。这类方法对简单的辐射状配电网很友好,公式一套,手算都能出来。但你要是面对一个带有分段开关、联络开关、分布式电源(DG)、储能系统的复杂配电网,解析法的状态空间就会爆炸式增长,公式推导复杂到让人怀疑人生。
这时候就要请出蒙特卡洛模拟法。它的思路很直白:既然解析地算所有系统状态太难,那就靠随机抽样,把系统在长时间运行中的状态演变“重演”一遍,统计出停电事件的频率和时长。
蒙特卡洛法又分非序贯和序贯两大类。非序贯法是抽“断面状态”,比如某个时刻每条线路是运行还是故障,然后直接评估这个断面的可靠性,计算量小,但它不关心时序,天然无法处理受时间影响的负荷变化。序贯法则不同,它按时间顺序逐步推进,模拟每条线路的“运行—故障—修复—再运行”全过程,就像放电影一样一帧帧播,最后统计出完整的可靠性指标。
我之所以在项目里选序贯法,最核心的原因有两个:一是配电网可靠性指标(尤其是SAIDI和ENS)本质上是时间累积量,只有时序仿真才能自然反映修复时间、故障持续时间对用户的差异化影响;二是如果后面积需要评估储能、需求响应这类时间耦合措施,非序贯法根本玩不转,序贯法则不需要改算法框架,只需要在仿真循环里加控制逻辑就行。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 序贯蒙特卡洛模拟法的核心原理解剖
2.1 元件的两状态模型:运行与停运
配电网里数量最多、对可靠性影响最大的元件是馈线、变压器、分段开关。在序贯仿真里,这些元件通常用两状态马尔可夫模型来描述:要么处于正常运行状态,要么处于故障停运状态。
两个最关键的基础参数:
- 故障率λ:单位是次/年。比如某条馈线的λ=0.15次/年,意思是平均每条线路每年发生0.15次故障,换算一下就是平均每6.67年出一次故障。
- 修复时间r:单位是小时/次。表示故障发生后,从停电到修复完成所花的平均时间。
在知道λ和r的前提下,两个状态的持续时间都可以用随机抽样得到。元件正常运行持续时间的概率密度函数是:
[
f_T(t) = \lambda e^{-\lambda t}
]
这是典型的指数分布。抽样时用逆变换法:生成一个0到1之间的均匀分布随机数U,那么该元件的正常运行持续时间为:
[
t_{\text{up}} = -\frac{1}{\lambda} \ln(U)
]
故障修复时间的抽样逻辑类似,只不过参数换成修复率μ,μ = 1 / 平均修复时间,所以:
[
t_{\text{down}} = -\frac{1}{\mu} \ln(U) = -r \cdot \ln(U)
]
一开始我看到指数分布还有点发怵,后来自己想明白了一个很直观的类比:这就像等公交车——如果车平均10分钟来一趟,某一天你可能1分钟就等到,也可能等了40分钟才来,但长期平均下来就是10分钟。指数分布抽样的本质就是根据平均频率,随机生成每次具体的随机间隔,有的短、有的长,平均下来趋于给定的参数。这就是为什么用同样的λ和r,每次跑仿真的结果会有波动,但跑到足够多年份后,指标会收敛到稳定值。
2.2 配电网的网络结构与故障影响分析
配电网绝大多数是辐射状结构,也就是从变电站母线出发,一条馈线带一串配电变压器,往下接用户。这种结构决定了它的一个特点:越靠近电源的元件,发生故障时影响范围越大。
比如一条馈线主干线首端的开关坏了,可能导致整条馈线停电;而靠近末端的分支线故障,影响的只是那几台变压器下面的用户。因此进行可靠性评估前,必须把配电网的拓扑结构还原出来,一次“故障扫描”之后,用FMEA的方式判断哪些用户会停电、停多久。
设备类型不同,故障后的处理逻辑也不同,这也是我和很多初学者说过的关键点:
- 主馈线故障:通常需要隔离故障段,非故障段通过分段开关操作恢复送电,故障段用户要等修复完成。所以用户停电时间分为操作时间和修复时间两类。
- 分支线故障:一般只影响该分支上的用户,如果分支首端有熔断器,主线上的其他用户不受影响。
- 变压器故障:影响该变压器下所有用户,通常没有转供路径,要等修复或更换。
这些逻辑看着简单,但写进代码的时候,其实就是一张隐式的“影响表”:每条线路故障后,要遍历所有用户节点,判断其是否停电、停电类别是什么。这一部分最考验代码设计的耐心。
2.3 负荷的时序建模
序贯蒙特卡洛模拟之所以叫“序贯”,不只是因为元件状态按时间演进,还因为它在统计缺供电量时,能够结合时序负荷曲线。
如果只算SAIFI和SAIDI,负荷大小其实不影响,因为频率和时长只跟故障事件有关。但如果你想算ENS(期望缺供电量),就必须知道停电时段的负荷水平。最简单的做法是用年峰值负荷乘以一个负荷系数;更精细的做法是建立8760小时的时序负荷曲线,按季节、按小时变化。
我在Matlab代码里采用了更贴近实际的方案:用年持续负荷曲线的对数正态分布模型来缩小数据规模,同时保留时序信息。实测效果不错,计算ENS时比用固定负荷系数的误差小很多。
3. Matlab代码整体架构与关键实现细节
3.1 数据结构的建立
写Matlab程序的第一件事不是急着写循环,而是设计好数据结构。我在这个项目里主要用了三类数据:
- 元件参数表:用struct数组或者table存储。每一行一个元件,字段包括元件编号、元件类型(1代表主馈线段,2代表分支线,3代表配变)、故障率λ、平均修复时间r、起始连接的节点编号、结束节点编号。
- 网络拓扑表:存节点和元件之间的连接关系。我习惯用一个拓扑矩阵来表示,节点编号、元件编号、上下游关系都放在里面。这一步很关键,因为后面判断故障影响范围、搜索转供路径全靠它。
- 用户/负荷数据:每个负荷点的额定功率、用户数目、所属节点编号。用户数目用于SAIFI,功率用于ENS。
3.2 主仿真循环的实现思路
程序最核心的骨架就是按时间步进或按事件步进的仿真循环。我在项目里用的是事件步进法,比时间步进计算效率更高。
逻辑是这样的:
- 初始化所有元件的下次故障时刻和修复完成时刻,初始时刻假设所有元件都是正常状态。
- 从当前仿真时钟出发,找到所有元件中下一次发生事件(故障或修复完成)的最早时刻,把仿真时钟推进到那个时刻。
- 判断事件类型:
- 如果是某元件发生故障:启动故障影响分析,找出受影响的负荷点,分别统计停电次数和停电时长,更新指标累加器。
- 如果是某元件修复完成:更新网架状态。
- 重复步骤2-3,直到仿真时钟达到指定的总仿真年限(比如10年或30年)。
- 最后用累加器除以总仿真年限、总用户数等,得到SAIFI、SAIDI、CAIDI、ASAI、ENS。
这段流程就是整篇程序的发动机。我自己第一次写的时候踩过一个大坑:把所有元件都存成一个独立的抽样序列,然后在同步的时钟下推进。后来发现事件步进法更高效,不需要每个小时都扫一遍全部元件,只需要维护一个“下一事件时刻”的数组,每次找最小值即可。
3.3 核心代码片段解读
下面我给出核心的抽样和事件推进代码,这段代码是整个仿真系统的主干线。
matlab复制% 核心参数
num_com = length(components); % 元件数量
next_event_time = inf(num_com, 1); % 各元件下一次事件时刻
repair_finish_time = inf(num_com, 1); % 各元件修复完成时刻
% 初始化:为每个元件抽第一次故障时间
for i = 1:num_com
if components(i).lambda > 0
next_event_time(i) = exprnd(1 / components(i).lambda);
end
end
% 可靠性指标累加器
SAIFI_acc = 0; % 停电次数累加
SAIDI_acc = 0; % 停电时长累加
ENS_acc = 0; % 缺供电量累加
sim_time = 0;
sim_years = 30;
current_time = 0;
while current_time < sim_years * 8760 % 总仿真时间(小时)
% 找出最早事件
[min_time, idx] = min(next_event_time);
current_time = min_time;
if current_time >= sim_years * 8760
break;
end
% 判断是故障还是修复
if current_time >= repair_finish_time(idx)
% 修复完成,恢复元件
components(idx).status = 1;
repair_finish_time(idx) = inf;
% 重新抽样下次故障时间
next_event_time(idx) = current_time + exprnd(1 / components(idx).lambda);
else
% 元件故障
components(idx).status = 0;
% 调用故障影响分析函数
[affected_nodes, outage_duration_type] = faultImpactAnalysis(...);
% 更新指标
for n = 1:length(affected_nodes)
SAIFI_acc = SAIFI_acc + node_data(affected_nodes(n)).num_customers;
if strcmp(outage_duration_type{n}, 'repair')
duration = components(idx).r + switching_time;
SAIDI_acc = SAIDI_acc + duration * node_data(affected_nodes(n)).num_customers;
else
duration = switching_time;
SAIDI_acc = SAIDI_acc + duration * node_data(affected_nodes(n)).num_customers;
end
% ENS计算需要负荷数据,此处简化为取节点平均负荷乘以时长
ENS_acc = ENS_acc + node_data(affected_nodes(n)).avg_power * duration;
end
% 修复时间抽样并安排修复完成事件
repair_time = exprnd(components(idx).r);
repair_finish_time(idx) = current_time + repair_time;
end
next_event_time(idx) = current_time + ...
exprnd(1 / components(idx).lambda);
end
这段代码在具体实现时要注意一个容易出错的地方:当元件故障后,我已经在修复合集里安排了修复事件,但在紧接着的下一轮循环,可能另一个元件也在同一时刻发生故障。代码里用的是min,一次只处理一个事件,但同一时刻多个事件的情况需要额外处理。我在最终版本里做了改进:先找出所有事件时刻等于current_time的元件,逐一遍历处理,确保同一时刻多个事件都能正确更新。
3.4 故障影响分析函数怎么设计
故障影响分析是整个评估中最需要细心打磨的模块,它决定了评估结果的准确度。
我设计的faultImpactAnalysis函数思路如下:
- 第一步:找到故障元件所在的馈线编号。
- 第二步:以故障点为界限,把该馈线分为上游段和下游段。
- 第三步:遍历该馈线上所有负荷节点,判断其与故障点的相对位置。在故障点上游的节点,如果其上游开关能正常动作,通常只需要经历操作切换时间,就可以恢复供电;在故障点下游的节点,就要看有没有联络开关、备用电源转供路径。
- 第四步:输出每个受影响节点的停电时长类型(修复型或切换型)。
这段逻辑是“代码量小,工作量巨大”的典型。特别是当网架带有环网联络结构的场景,必须把每个节点的转供路径都提前算好,写成搜索函数。
我自己的经验是:宁可多花两天时间把网络拓扑和故障影响逻辑吃透,也不要急着堆代码。因为故障影响逻辑一旦写错,最后算出来的指标会偏差大得离谱,而且难以排查。
4. 参数设置与仿真配置的工程化经验
4.1 仿真年限该怎么选
序贯蒙特卡洛模拟有一个绕不开的话题:仿真年限。年限太短,指标波动大,结果不可靠;年限太长,计算耗时长,程序跑得让人心烦。
蒙特卡洛仿真的收敛特性是:误差大致与仿真年数的平方根成反比。行业经验里,对于配电网可靠性评估,典型仿真年限在10年到50年之间。在我的项目里,对比测试后发现:
| 仿真年限 | SAIFI平均值(次/用户·年) | SAIDI平均值(小时/用户·年) | 波动幅度 |
|---|---|---|---|
| 5年 | 1.783 | 6.912 | ±8.7% |
| 10年 | 1.812 | 7.134 | ±5.2% |
| 30年 | 1.821 | 7.186 | ±2.9% |
| 50年 | 1.823 | 7.191 | ±2.1% |
可以看到,10年到30年之间的结果开始趋于稳定。如果只是做方案对比,用10年就够;如果要做绝对值评估、对接考核指标,建议至少跑30年。我最终选择的是30年,平衡了计算时间和结果稳定性。
4.2 随机数种子与多次重复仿真
蒙特卡洛仿真有一个“神神叨叨”的特点:同样的代码,每次跑出来的结果都不太一样。这是正常的,因为用的是随机抽样。但如果你在工程项目里,连自己都无法复现结果,甲方就会质疑你的算法。
解决方法是:固定随机数种子。
matlab复制rng(2024); % 固定随机数种子,保证结果可复现
在正式评估前,我会对同一套网架参数做10次重复仿真,每次都换一个随机数种子,然后把10次结果的平均值和方差都记录下来。这样一方面可以观察指标的收敛情况,另一方面也为后续做置信区间提供依据。
4.3 时序负荷曲线的简化建模
如果你手上没有真实的8760小时负荷曲线,不建议一开始就用特别复杂的负荷模型。可以先从最简单的入手:每个负荷点使用平均负荷,甚至用额定功率乘以一个负荷同时率。算ENS时,用平均负荷乘以停电时长。
等到整套仿真代码跑通、结果合理了,再逐步升级负荷模型。我在项目里用的是对数正态分布年持续负荷曲线,把全年8760小时负荷数据用200个横截面表示,每个横截面对应一个持续时长。这样简化之后,仿真速度提升非常明显,而且对ENS计算的影响很小。
这里要给一个特别容易踩坑的提醒:如果你用峰值负荷去计算ENS,会让缺供电量被严重高估,可能高出40%以上。因为一年里绝大多数时间的负荷实际水平远低于峰值。所以别图省事直接用额定容量算ENS,宁可先加一个0.5左右的负荷率,也比直接拿峰值准得多。
5. 算例验证与影响因素分析
5.1 典型算例验证
我用一个相对典型的配电网测试系统做了验证:4条馈线、36个负荷点、若干分段开关和联络开关。系统参数设置参考了常见的测试馈线数据。
设置如下:
- 主干线故障率:0.15次/km·年
- 分支线故障率:0.15次/km·年
- 平均修复时间:4小时/次(主干)、3小时/次(分支)
- 分段开关操作时间:0.5小时/次
- 负荷点用户数:按变压器容量折算
仿真条件:仿真年限30年,固定随机数种子,重复5次取平均。
最终得到的指标如下:
- SAIFI:1.82次/用户·年
- SAIDI:7.16小时/用户·年
- CAIDI:3.93小时/次
- ASAI:99.918%
- ENS:约16.8 MWh/年
从结果看,ASAI达到99.918%,也就是接近“三个九”的水平,这符合大多数城市配电网的实际情况。如果还想继续提升,那就要看是哪些元件的贡献最大。
5.2 提升可靠性的手段,让数字说话
做评估不是为了出一张表就结束,而是要给规划改造提供决策支撑。我用这个仿真平台做了三个场景的对比分析:
场景一:加装分段开关
在主干线上增加一个分段开关,把馈线分成两段。结果是SAIDI下降了约12%。原因很明显:分段开关能把故障隔离范围缩小,让部分非故障段用户提前恢复供电。
场景二:加装联络开关/备用电源
与相邻馈线增加联络开关,形成手拉手供电。结果是SAIDI下降了约20%,是三个场景中效果最明显的。因为只要有备用转供路径,非故障失电区域就能在极短的操作时间内恢复供电。这一结果充分说明:对于辐射状配电网,增加联络通道的可靠性提升收益往往高于增加分段开关。
场景三:降低故障率指标
把主干线的故障率从0.15降低到0.10次/km·年,模拟线路绝缘化改造、防雷改造的效果。结果是SAIFI下降了约33%,但SAIDI下降幅度略小于SAIFI,因为故障少了,但每一次故障的处理流程还是一样的。
三组对比下来,可以很清楚地看出:不同类型的改造措施对指标的改善侧重点不同。如果目标是降频次,就优先做线路改造;如果目标是压缩单次停电时间,就优先做配网自动化和联络工程。这套仿真平台的最大价值就在于此——在动真金白银做改造之前,先用几百行代码把方案效果预演一遍。
6. 调试过程中最常见的坑与排查经验
6.1 仿真结果忽大忽小不收敛
这是第一次跑通代码后最常遇到的情况。如果你发现跑10年仿真,指标忽高忽低,先别怀疑算法,先检查是不是随机数种子没有固定,或者仿真年限太短。把仿真年限从5年提到30年,波动会明显下降。
另一个容易忽略的原因是:初始化阶段的影响。仿真一开始假设所有元件都是正常运行状态,但实际系统可能从一开始就存在处于故障状态中的元件。这种“冷启动”偏差在短时间仿真里尤其明显。解决方法是先跑一个预热的模拟时段,比如先跑2年模拟但不统计数据,让系统进入稳态,再开始正式统计。
6.2 ENS数值异常偏大
ENS偏大的最常见原因就是用了峰值负荷。我在前面已经提醒过这一点。行业项目里,如果你只有峰值负荷,至少把ENS乘一个0.4到0.6的负荷率系数。更严谨的做法是接入真实的负荷曲线。
6.3 修复时间抽样出现极端大值
指数分布有一个特点:偶尔会抽到非常大的数值。比如平均修复时间是4小时,但某次抽样的结果可能是30小时甚至80小时。这在理论上确实可能发生,但会造成个别年份SAIDI被严重拉高。
处理方法有两种:一是在抽样后加一个上限截断,比如修复时间不超过平均值的5倍;二是加大仿真年限,让极端事件在大样本中被稀释。我自己的经验是:上限截断要谨慎,因为极端事件在现实中确实存在;但如果你的代码里出现了明显偏离常识的异常值,宁可回头检查抽样逻辑,也不要简单粗暴地设个上限了事。
6.4 故障影响分析函数与拓扑不一致
这是一个很隐蔽的bug。有时候元件参数表里写着某条分支线挂在节点5下面,但网络拓扑表里节点5的下一级接的是另一个元件,两边对不上,导致故障影响分析时漏判了部分负荷点。
我的排查方法是:写一个拓扑完整性校验函数,在每次仿真运行前自动遍历所有元件和节点,检查连接关系是否闭环、是否存在孤立节点、是否存在重复编号。这一招帮我省了很多排查时间。
6.5 故障影响分析函数与拓扑不一致
Matlab的矩阵运算效率高,但循环效率相对一般。如果你的仿真代码里有一段“在每小时内遍历所有元件再遍历所有负荷点”的逻辑,跑30年仿真可能要好几个小时。
我的优化建议:
- 优先用事件步进法,不要用固定时间步进。
- 矢量化和预分配数组:预分配所有状态数组,避免循环中动态扩展。
- 故障影响分析里尽量用向量化逻辑判断代替局部循环,比如一次性判断故障点上下游所有节点。
7. 从评价到决策,这套方法还能往哪走
序贯蒙特卡洛模拟法的优点不仅在于算出几个指标,更在于它的框架具备很强的扩展性。我把这个项目做完之后发现,很多实际中感兴趣的问题,都能在这个框架上“长出来”。
- 分布式电源接入评估:只需给光伏或储能元件建立新的可靠性模型,模拟其随机出力和故障行为,就能定量分析DG对可靠性提升的贡献。
- 储能系统优化配置:储能的价值在于关键时刻撑住负荷。用序贯法可以天然模拟储能荷电状态的动态变化,算出最优容量配置。
- 极端天气事件评估:普通评估假设故障率恒定,但台风、冰灾等极端天气下,故障率会大幅飙升。你可以把天气状态加入仿真循环,在极端天气时段应用更高的故障率参数。
- 精细化运维策略优化:用仿真结果反推哪些元件是“单点高风险元件”,把检修资源优先投到这些元件上,让有限的运维经费花在刀刃上。
如果你想要计算更高效,还可以研究重要抽样法、拉丁超立方采样等方差缩减技术,在同样的仿真年限下获得更稳定的估计结果。不过刚开始做项目,不建议一上来就上这些花哨的改进算法,先把基础版本跑通、把指标算准,后面再逐步升级。
最后聊聊我这30年仿真跑下来的整体感受。做配电网可靠性评估,真正花时间的不是写代码,而是梳理清楚“元件故障后到底会发生什么”这件事——哪些用户会停、停多久、什么条件下能转供。这个业务逻辑吃透了,代码反而只是顺手的事。如果你也在做类似的评估项目,我的建议是:先把案例网架的小样本跑通,再逐步扩展到大网架;先把固定参数跑通,再加时序负荷和DG模型;先把结论跑出来,再回头优化计算效率。这样一步步来,能少走很多弯路。
关于这套Matlab代码,我再分享一个实用的小技巧:仿真完成后,把每个元件的故障贡献度也统计出来——也就是每个元件引发的停电次数、停电时长的占比。这个数据虽然不直接对应可靠性指标,却是改造优先级的金钥匙,很多人忽略了它的价值。在报告里放一张“元件风险贡献度TOP10”的表格,比放一百行仿真参数更有说服力。
