在电力系统里,配电侧往往是“规划时省的钱,运行时要还回去”的重灾区。以前做配电网规划,大家盯着单位投资、线损率这些经济指标,可靠性更像是事后核算,很少在方案生成阶段就参与博弈。可分布式电源(光伏、风电)渗透率一上来,电气结构和运行方式全变了,“投多少”、“投在哪”、“可不可靠”这三件事必须放到同一个框架里算,这就是我要在这篇文章里聊的核心内容——基于经济与可靠性双目标的混合配电系统规划及可靠性评估,用Python实现。
文章适合三类人看:一是正在做配电网规划相关课题的电力专业研究生,二是准备上分布式电源改造项目的工程技术人员,三是对Python在电力优化领域落地感兴趣的开发人员。你不会在这里看到把目标函数写成两个加权相加然后跑一次单目标优化的偷懒做法,我会把多目标到底怎么建的、可靠性怎么定义的、NSGA-II和蒙特卡洛模拟怎么衔接的、代码里哪些环节最容易翻车,一项项讲透。全部内容基于我个人的工程实践和常见学术方案整理,项目标题里那个“混合配电系统”,指的就是含常规配电网元件外加分布式电源、储能装置的现代配电网形态。
1. 问题建模:先把“混合配电系统规划”抽成数学语言
1.1 “混合”究竟混在哪
做规划之前先得把对象看明白。传统配电网本质是单向辐射网,电源在上级变电站,负荷在下游,潮流方向几乎固定。而混合配电系统是在这个基础上混入了分布式电源、储能甚至微网,潮流方向不再单一,节点电压的支撑特性也变了。规划的含义因此也从“选导线、选变压器”扩展成了“选什么位置接入分布式电源、装多少容量、要不要配套储能、怎么跟原有网架配合”。
从数学建模的角度看,混合配电系统的规划决策变量是一个混合整数集合,里面包括:线路是否新建或扩容(0-1整数变量)、分布式电源接入的节点位置(整数变量)、接入的容量(连续变量)、储能装置的额定功率与容量(连续变量)。这个变量结构决定了后面求解算法的形态,你不能把它当成普通连续优化来处理,搜索空间是离散与连续交织的。
1.2 经济目标不是“越便宜越好”,而是全寿命成本
经济性目标在学术论文里通常写作全寿命周期成本,英文简称LCC(Life Cycle Cost),它远比“初始投资越小越好”要周全。因为便宜设备可能运维成本高,或者寿命短,算总账反而亏。工程里我建议用如下形式:
其中 C_inv 是初始投资成本,包含分布式电源采购安装和网络改造;C_om 是年运行维护成本;C_loss 是年网损费用;C_ens 是缺电成本,也就是因供电不可靠造成的经济损失。r 是折现率,T 是规划期年数。
需要注意的是,缺电成本这一项很有讲究,它把可靠性和经济性串起来了。可靠性差的地方缺电成本高,规划方案自动会倾向于多投资去改善,这正是双目标模型比传统单目标模型先进的地方——可靠性不再是被事后检验的约束条,而是直接参与目标函数博弈。
1.3 可靠性目标选哪个指标有讲究
可靠性评估领域指标很多,比如系统平均停电频率(SAIFI)、系统平均停电持续时间(SAIDI)、缺供电量期望(EENS)、失负荷概率(LOLP)等。做规划优化时如果直接拿SAIFI或SAIDI当目标,事件归集过程会非常繁琐,因为它们是统计性指标,要和停电事件的用户数、时间点绑定,不适合在进化算法的适应度函数里反复迭代。
实践中最推荐的是EENS(Expected Energy Not Supplied),也就是期望缺供电量,单位是MWh/年或者kWh/年。理由有三条:第一,它是连续型指标,可以直接和缺电成本挂钩,方便和目标函数对接;第二,它的计算过程对蒙特卡洛模拟非常友好,每次采样得到一份系统状态,统计缺供功率再乘以持续时间就行;第三,它的物理意义直观,决策者一眼能看懂“这个方案平均每年少送多少电量”。
1.4 不要忘了约束条件这个“隐形主角”
目标和变量都定了,约束条件往往决定方案是否可行。我遇到过不少新手,算法写得挺顺,跑出来的结果却根本没法用,原因是约束漏了。最基本的四组约束必须写全:
- 功率平衡约束:任意时刻系统注入功率等于负荷功率加网损,这个物理基础不满足,潮流计算直接崩
- 节点电压约束:通常要求电压幅值在0.95到1.05 p.u.之间,分布式电源接入过度会导致电压越限
- 支路容量约束:线路和变压器传输功率不能超过额定值,这个约束约束分布式电源的接入位置和容量
- 分布式电源渗透率约束:常规做法是限制分布式电源总装机不超过系统峰值负荷的一定比例,防止出现严重的倒送潮流问题
许多论文里把约束以罚函数的形式加进目标函数,我在代码里也采用这个方式,但罚函数的权重设置要小心,太大会把Pareto前沿压扁,太小则可行域形同虚设,这一问题在后面的章节会具体说。
2. 求解思路:为什么单目标优化解决不了这个问题
2.1 加权法的致命缺陷
早期很多文献处理双目标的方式是加权求和,比如把经济成本和EENS各乘一个权重系数变成一个标量。这种做法不是完全不能用,但它在工程上有两个毛病:第一,权重系数非常难定,不同电网的可靠性与经济性量纲不同,比例失调就会导致某一项目标被吞掉;第二,加权法对Pareto前沿的凹区段是失效的,也就是某些合理的折中解可能永远搜索不到。
举个我自己遇到过的例子:某规划方案A投资比方案B多大约300万,但EENS每年能少约120MWh,加权法如果权重设置偏向经济成本,A永远不可能入选,可若补贴政策、用电结构发生变化,A其实是更优的选择。所以双目标的价值就在这里——它不替你拍板“哪个更好”,它把所有不互相支配的折中方案都列出来,把决策权交还给规划工程师。
2.2 NSGA-II凭什么成为这一类问题的主力
多目标进化算法里,NSGA-II(Non-dominated Sorting Genetic Algorithm II)是目前学术与工程中最常用的选择,核心优势有三个:非支配排序、拥挤距离、精英保留策略。非支配排序负责把种群划分成若干前沿层,第一层是当前最优解集合,第二层是去掉第一层以后的支配关系,依次类推;拥挤距离保证同一前沿层的个体保持分散,避免解扎堆在一个区域;精英保留策略则将父代与子代合并后统一筛选,保证最优个体不会在进化中被弄丢。
实操层面,NSGA-II的收敛性和种群多样性在配电网规划问题上表现稳定,而且Python生态里已经有成熟实现,比如pymoo库,没必要从头写一遍排序逻辑。但需要注意,pymoo默认的问题接口用的是连续变量优化框架,配电网规划里的0-1变量和整数变量需要自己做映射,这一块我在后面代码设计里会展开。
2.3 决策变量编码是规划问题的“暗坑”
配电网规划里的决策变量类型混杂,NSGA-II本身是实数编码算法,工程上普遍做法是:
- 二进制变量直接映射成实数0或1
- 分布式电源接入节点编号映射成整数实数
- 接入容量、储能容量映射成连续实数
这个映射关系在创建初始种群时就要约定好,并且交叉变异之后必须做边界检查和整数化处理。否则算出来的“最优解”可能在物理上根本不存在。我见过有人直接把节点编号当成连续变量传进去,变异后得到节点3.7,然后跳过了完整性检查,潮流计算直接报错,整个迭代进程就废了。
一个实用的做法是:把分布式电源接入节点做成固定候选集,例如只允许接入系统给定的若干关键节点,那么编码里存放3.7时,就取round后按最近候选节点处理。这样既保证了解空间是离散的,又不会因为四舍五入导致拥挤距离计算失真。
3. 可靠性评估的工程落地:蒙特卡洛模拟怎么和规划优化结合
3.1 解析法 vs. 模拟法,该怎么选
配电网可靠性评估分为解析法和模拟法。解析法基于故障枚举和最小割集,优点是计算快、结果确定,缺点是系统规模一大、故障组合爆炸,而且分布式电源接入后运行方式多变,解析法建模复杂度和错误概率都直线上升。
蒙特卡洛模拟法的思路则朴素很多:对系统中每个元件的运行状态按故障率进行随机抽样,得到大量可能的系统状态;在每个状态下做潮流计算或网络连通性分析,判断是否存在失负荷;最后统计学意义上算出EENS、LOLP等指标。它计算量大,但对系统细节的建模能力最强,尤其适合含分布式电源的混合配电系统。
在双目标规划优化的循环里,每个候选规划方案都要做一次可靠性评估,这就意味着蒙特卡洛模拟会被调用成千上万次。所以重点不是“能不能算”,而是“怎么算得快”。
3.2 非序贯蒙特卡洛采样的实现要点
可靠性评估常用非序贯采样,核心机制是:系统里有 n 个元件,每个元件(线路、变压器、发电机、分布式电源)都有故障率 λ 和修复时间 MTTR,按指数分布或两状态模型抽样,得到一组“哪些元件故障”的系统状态。对每个系统状态,通过失负荷分析确定甩负荷量,记录一次抽样中的缺电功率。
这个过程的代码实现其实不复杂,最要紧的是元件可靠性参数的输入。工程实践里,线路故障率通常按每公里每年多少次故障给,千万别拿裸参数直接套,必须乘上线路长度。这段我在多个案例里帮人排查过,很多人的EENS结果大得离谱,查来查去就是线路故障率忘了乘长度。
3.3 状态分析:不是所有故障状态都要跑潮流
如果每次抽样都跑一次完整的潮流计算,计算代价太高。实际工程里遵循一个分流策略:先做快速连通性分析,如果故障没有导致任何负荷失电,就跳过低效的潮流计算;只有故障割裂了某些区域、或导致潮流严重越限时,才进入详细分析。
在含分布式电源的系统中,还要考虑孤岛运行的可能性。如果故障使得某个区域和主网断开,但区域内部有足够容量的分布式电源,系统可以主动进入孤岛模式,这部分负荷不失电。规划优化时这非常关键,因为接入分布式电源的位置如果选得好,同样的投资能显著改善可靠性指标,而这种改善只有通过详细的偏序分析才能体现出来,单纯的连通性准则会误判。
我建议在代码里把系统状态分析写成两个层次:第一层是快速预筛,判断是否存在隔离负荷;第二层是详细评估,用潮流或线性化叫负荷分配算法给出失负荷量。这样可以在保证精度的前提下缩短接近一半的计算时间。
4. Python工程实践:从算式到可运行的规划优化框架
4.1 工具链选型
Python做这类电力系统规划,常用组合是:
pymoo或deap提供多目标进化算法框架,pymoo更现代,API设计更清晰pandapower或matpower(通过pandapower转换)做潮流计算,pandapower是Python原生,兼容性最好numpy和pandas做数据处理,蒙特卡洛抽样必须向量化,用纯Python循环你会等到怀疑人生matplotlib绘制Pareto前沿可视化结果
需要说明的是,潮流计算在每一次蒙特卡洛状态分析中都会调用,pandapower的函数式API每一轮调用的开销不可小觑。一个加速技巧是用loadflow前的ppc转换并缓存静态拓扑结构,每次只更新故障状态相关的分支和发电出力,这个细节在全寿命周期成本迭代几千次之后差异巨大。
4.2 核心类结构设计
我分享一个经过多个项目验证的类设计思路,不贴全部代码,但会把类和接口定义说清楚。整体分五个类:
NetworkModel:负责构建配电网络拓扑,读取节点、支路、负荷、分布式电源参数OptVariable:负责决策变量编码与边界定义,包括整数变量映射和变异后的检查ObjectiveEvaluator:负责计算全寿命周期成本、EENS以及约束罚函数,是优化循环里最耗时的部分ReliabilityAssessment:封装蒙特卡洛抽样与状态分析,对外提供get_eens()等接口Planner:封装pymoo的Problem接口,把以上模块串成整个优化流程
4.3 罚函数设置的一个可复现方案
约束处理是整个代码能否稳定跑完的命门。工程上我建议不把罚函数写得太狠,而是采用“动态罚函数+可行性优先”策略。在pymoo里,可以让每个个体返回两个F值(经济成本、EENS)和一组G值(约束违背量),然后靠pymoo内部的约束处理机制进行选择。这个方法比手动构造罚函数稳健很多,尤其适合约束类型多样的规划问题。
实际使用时最常见的坑是电压约束写成了“节点电压恒在0.95到1.05之间”,然后分布式电源出力波动场景下就天天触发罚函数,导致算法把候选解全部淘汰。正确做法是按运行场景区分,分布式电源出力大的场景和负荷高峰场景分别做校验,取各场景下最大违背量作为约束输出。
5. 算例分析:IEEE 33节点系统上的双目标规划演示
5.1 算例参数与场景设置
为了验证整套方案,我用经典IEEE 33节点配电网做了测试。该系统的基准电压12.66kV,峰值负荷约5MW,系统包含33个节点、32条支路。规划期取10年,折现率8%。分布式电源候选接入节点取8、16、24、30四个节点,单点最大可接入容量1MW,总容量不超过峰值负荷的25%。每个方案的可靠性评估采样规模设为5000次,通过试算确定该采样量下EENS置信区间可接受。
这个参数规模不算大,但在优化迭代300代、种群数量60的情况下,总评估次数大约18000次,单次可靠性评估耗时约0.8秒,整体运行时间在4小时左右。这在研究阶段是可接受的,如果要缩短时间,可以把蒙特卡洛采样规模降到2000次加方差削减,精度损失不大。
5.2 Pareto前沿解读
运行得到Pareto前沿后,经济成本和EENS之间呈典型的反比关系。投资很少的方案经济成本低,但EENS可能高达150MWh以上;随着分布式电源接入容量增大,EENS逐步下降,但边际效益递减——从200万投资增加到300万,EENS下降明显;从300万增加到400万,下降幅度就小很多。这个转折点,也就是Pareto前沿的“膝盖区”,在工程里往往是最值得选择的折中方案。
还有一个有意思的发现:同样的投资额度,把分布式电源分布在不同节点比集中在单一节点的可靠性提升效果更好,原因是分布式布置能有效减少故障隔离后的失电范围。这说明可靠性目标视角下的规划方案形态,会和单纯经济最优方案有明显区别——这恰恰是双目标规划的意义所在。
5.3 储能的经济性与可靠性角色需要单独看
在这个算例中我们还测试了加装储能的方案。储能对可靠性的改善主要体现在两处:分布式电源出力波动时补平缺口,以及在孤岛运行时提供短时支撑。但储能的全寿命成本较高,单位可靠性的提升成本远高于多装一组分布式电源。所以算例最终Pareto前沿上,带储能的方案往往并不占优。这说明储能接入要结合具体的供电可靠性需求和电价政策,不能盲目上了领导者文章里就照抄。
6. 常见问题与陷阱排查实录
6.1 迭代早期种群崩溃,全是罚函数值
症状是前几代种群就出现大量不可行个体,后续选择压力异常。常见原因有两个:一是电压或容量约束设置过严,随机生成的规划方案几乎必定违背;二是约束值在目标函数里权重过高,导致非支配排序陷入噪声区。
解决办法是给约束评估加“松弛配合”机制——在迭代前中期允许一定程度的约束违背,越到后期越严格。工程上可以设置一个约束阈值,比如电压偏差从初始的0.08降到最终的0.05,这样算法能先探索可行域边缘,再精细搜索。这个方法借鉴了罚函数法里的退火思想,适用于大多数配电网规划问题。
6.2 蒙特卡洛抽样规模设置多少才够
这是初学者问得最多的问题。抽样规模太小,EENS的方差太大,不同规划方案的可靠性差异会被噪声淹没,Pareto前沿乱成一团;抽样规模太大,计算时间不可接受。
我建议做法是:先用500次抽样快速预估EENS量级和方差,然后用公式估算所需采样数,目标让相对误差控制在5%以内。在IEEE 33节点系统上,通常3000-5000次就够;但如果是上百节点的实际配电网,EENS事件比较稀疏,可能需要一两万次,这时就必须考虑重要抽样等方差削减技术了。
6.3 分布式电源的时序出力怎么处理
非序贯蒙特卡洛是“元件状态采样”,但分布式电源出力是时序变量——光伏白天发、晚上停,风机随风速变化。若直接忽略时序,把分布式电源当成恒定出力,可靠性指标会过于乐观,因为它们总是在最需要的时候发电。
代码层面处理不复杂:把运行场景按小时或按典型日风格分类,抽样元件状态后,再按该时段内的分布式电源出力曲线计算可用出力。实际项目中,把8760小时聚合成典型日24个断面即可,精度足够且计算量可控。不少人漏了这步,EENS计算结果偏小30%-50%,这个教训我印象深刻。
6.4 部分程序跑得慢的终极排查思路
如果整个流程跑起来比预期慢很多,我的排查顺序是:先用cProfile统计各函数调用耗时,确认瓶颈在哪一层。绝大多数时候瓶颈在蒙特卡洛状态分析环节,尤其是里面不小心用了Python层循环遍历节点。解决办法是向量化:把所有支路和节点的故障状态放进numpy数组统一运算,对连通性分析用稀疏矩阵的传递闭包计算来代替手动DFS遍历。
还有一个小技巧:把潮流计算放进一个带缓存的函数装饰器中,因为同一系统状态可能在不同场景下重复出现,理论上概率不高,但实际跑下来能省不少时间。缓存可以用lru_cache,注意把状态数据整理成不可变类型。
7. 最后分享几点个人体会
双目标规划这个事,最考验人的不是算法复杂度,而是对电力物理过程和优化算法之间的接口有没有敬畏心。很多代码跑不通,都是忘了一些小环节,比如单位换算、故障率乘以长度、分布式电源的时序出力,这些在论文里都是一行字,在代码里就是几小时甚至几天的排查。做这一块一年多,我的经验是别急于上复杂算法,先把单一规划方案的可靠性评估做得又准又快,再把它嵌套进优化框架里。如果评估函数本身不准,NSGA-II再先进也只是在错误的路线上加速。做优化的人常说“垃圾进,垃圾出”,在配电规划这个问题上,情况比垃圾进还严重——因为错误可能特别隐蔽,比如结果刚好在指标范围内,但方向完全不对。
如果你正在做类似的课题或项目,我建议先把这篇文章里的数学表达和代码结构吃透,动手用一个简单的33节点系统复现一遍双目标优化的完整流程,跑通之后,再往实际系统上叠加复杂度。配电网规划没有万能方案,但一个好的双目标优化框架,能让你在变化的需求面前不慌。