混合配电系统经济与可靠性双目标规划及Python实现

发布时间:2026/10/4 21:52:56
混合配电系统经济与可靠性双目标规划及Python实现 做配电网规划的人都有同一个体会网架方案好不好不能只看初始投资更要看它运行若干年后扛不扛得住故障。尤其是近几年分布式电源、储能、电动汽车充电桩大量接入配电网从传统的“单电源、辐射状、单向潮流”变成了多电源、多运行方式并存的混合配电系统。这种情况下规划一个项目要回答两个很现实的问题这个网在故障时究竟能保多少负荷多花一笔钱下去可靠性又能换来多少提升这两个问题绑在一起就是“经济与可靠性双目标”的规划问题也是我这次想完整拆解的内容。“基于经济与可靠性双目标的混合配电系统规划及可靠性评估研究Python代码实现”这个项目我前后迭代了三轮第一轮只做可靠性评估第二轮补上经济性模型第三轮才把NSGA-II双目标优化完整跑通。这篇文章把我最终的实现思路、参数设置、代码组织和踩过的坑完整整理出来。内容偏工程研究适合正在做配电网规划、分布式电源接入方案设计、可靠性评估的研究生或工程师也适合想搞明白蒙特卡洛法和多目标优化在真实工程问题中怎么落地的Python用户。下面按我实际推进的顺序来讲。1. 项目的定位与核心思路拆解1.1 这个项目到底在解决什么问题把标题拆开看三个关键词构成一条完整的逻辑链混合配电系统是研究对象可靠性评估是核心手段经济与可靠性双目标规划是最终决策口径。先说“混合配电系统”。在工程研究里这个词通常有两种指代一种是交流/直流混合配电系统另一种是传统交流网架与新能源电源、储能、微电网边界并存的系统。这两类都可以做双目标规划但实现难度差别很大。AC/DC混合系统涉及换流器建模、交直流潮流迭代、控制策略切换如果还要套进蒙特卡洛模拟计算量会非常惊人。我这次实现的是第二种也是目前工程可落地性最强的形态保留原有交流辐射网架在若干候选节点上增加分布式电源和储能必要时增设联络线节点性质从纯负荷节点变成含电源的混合节点。这样建模既反映真实改造后的系统形态又不会把复杂度推到无法收敛的程度。可靠性评估要解决的核心问题是系统中任意设备故障后哪些用户会停电、停多久、损失多少电量。这件事涉及故障模式分析、网络连通性判断、转供路径搜索、负荷切除与恢复等一连串操作。常用的做法有两种一种基于N-1准则做确定性校核一种基于蒙特卡洛法做随机模拟。做双目标规划时我建议用后者因为随机模拟能输出期望意义上的可靠性指标比如用户平均停电时间SAIDI、用户平均停电频率SAIFI、电量不足期望值ENS这些指标可以和投资成本一起直接写进目标函数构成一对互相冲突的优化目标。双目标规划的任务则是在候选方案空间中找到Pareto前沿。前沿上的每一个点都代表一种“投资成本-可靠性水平”的权衡结果工程上最终怎么选取决于预算约束和考核指标要求但优化模型能把整个可行边界画出来这就比拍脑袋定一个单方案稳健得多。1.2 为什么把可靠性与经济性放在同一层决策有人会问既然可靠性可以折算成钱停电损失费用等于ENS乘以单位停电损失单价那把“建设成本运维成本停电损失成本”合成一个单目标不就行了吗这种方法确实存在很多工程软件也是这么做的教科书里叫“全寿命周期成本最小化”。但它有一个明显短板单位停电损失这个参数在不同用户类型、不同地区、不同时段差异极大。工业用户停电一分钟的损失可能是居民用户的几十倍同一个城市的不同供电分区也完全不同。把这个参数固定成一个常数等于把决策者的价值判断硬编码进模型。你算出来的最优方案很可能是被这个参数主导的换个停电单价最优网架结构就变了。双目标优化的价值在于不预设两个目标之间的权重而是把经济性和可靠性作为互相矛盾的维度同时交给算法搜索最后返回一组Pareto解由规划人员根据实际偏好在边界上选点。这样既保住了模型的客观性也留存了对不确定性偏好的解释空间。从算法实现角度看双目标并不会显著增加难度。NSGA-II这类算法本身就是为多目标问题设计的把单目标遗传算法改成多目标核心只差两件事一是用Pareto支配关系替代适应度排序二是引入拥挤度距离保证解集分布均匀。后面我会展开说这两点在Python里怎么落。1.3 技术路线和模块边界整个项目我建议按四个模块拆分这也是我反复实现后觉得最清晰的结构系统建模模块读入拓扑数据建立节点、支路、负荷、电源、储能、开关的抽象数据结构可靠性评估模块输入网架和设备参数输出SAIDI、SAIFI、ENS等指标经济性评估模块根据设备选型和容量计算年化投资与运维费用结合可靠性结果给出停电损失多目标优化模块调用NSGA-II对网架结构和设备容量进行搜索输出Pareto前沿及对应方案。分层最大的好处是可独立测试。我强烈建议先把可靠性评估模块单独验证正确再把它作为目标函数嵌入优化循环。实际项目里九成以上的调试时间都花在“评估算得对不对”上如果评估和优化耦合在一起一旦结果不对连是评估错了还是优化收敛失败都分不清楚。2. 配电系统建模与可靠性指标计算口径2.1 网络拓扑怎么建才便于做故障状态枚举可靠性评估最核心的建模对象是网络拓扑。常见测试系统用IEEE 33节点配电网基准电压12.66kV总负荷大约3715kW加2300kvar节点和支路数据都有现成文献可查。Python里建这种图有两个选择直接调networkx或者自建节点和支路类。我的建议是如果后续要做大量蒙特卡洛模拟最好自建轻量级的数据结构因为networkx的图遍历接口虽然方便但节点和边的属性存取在大规模循环里会产生不少开销。以IEEE 33节点为例我会为每个节点保存如下属性dataclass class Bus: idx: int load_kw: float 0.0 load_kvar: float 0.0 dg_kw: float 0.0 # 分布式电源接入容量 storage_kwh: float 0.0 # 储能配置容量 zone: int 0 # 馈线分区故障隔离判断用 is_connected: bool True支路则保存首末端节点、线路长度、故障率、修复时间、是否装开关等。故障率和修复时间是可靠性评估的两个关键输入线路故障率一般按每公里每年0.05到0.1次来设修复时间取2到5小时。这个参数一定要结合自己算例的实际数据做敏感性分析哪怕基准数据相同不同取值对ENS的影响能差出好几倍。拓扑建好后所有后续操作都围绕两个基本算法展开一个是广度优先搜索BFS判断连通性一个是深度优先搜索DFS从故障隔离点往外找负荷节点。很多教材会把这两个算法讲得很复杂实际工程里就是循环加队列的事重点在于节点和支路的数据结构是否支撑快速查询。2.2 核心可靠性指标的计算口径可靠性指标的计算口径必须一开始就定死否则后面所有结果都没法比较。我在这个项目里用了三个最常用的指标SAIFI系统平均停电频率单位次/(户·年)等于用户总停电次数除以用户总数SAIDI系统平均停电持续时间单位小时/(户·年)等于用户总停电时间除以用户总数ENS系统电量不足期望值单位kWh/年等于各负荷点停电电量之和。前两个指标反映的是“停电发生多不多、停多久”第三个指标直接反映经济损失是和经济性目标对接的桥梁。工程研究中有时还会用AENS即ENS除以用户总数用于不同规模系统之间的横向对比。还有一个很容易被忽略的细节用户数怎么定义。有些文献按节点算认为一个节点就是一个用户有些文献按变压器台数折算更精细的做法是考虑节点负荷量和典型用户容量的比值。不同定义直接影响SAIFI和SAIDI的量级所以投稿或出报告时一定要写清楚口径。我这次按“节点即用户集聚点”处理每个节点的用户数用负荷值除以单位用户平均负荷来估算这比简单按节点数计数更贴近实际。2.3 经济性成本模型的组成和参数选择经济性模型在整个项目里承担“投资-运行-损失”三段成本的计算。投资成本包括线路改造费用、开关设备费用、分布式电源单位容量造价、储能单位容量造价。注意一次性投资需要年化不能直接把总造价和目标函数里的年可靠性指标相加。年化的常用方法是等年值法把总造价按折现率和设备寿命摊到每年。运维成本一般按投资的固定比例估算具体比例看设备类型线路通常在1%到2%储能略高可能在2%到3%。停电损失成本等于ENS乘以单位停电损失单价这个单价在不同研究里有不同取值居民负荷和商业负荷要分开设。为了不让单价参数过度左右结论我在第三轮迭代里把停电损失从单目标“加总项”改成了双目标里的可靠性目标载体这样即使单价取不准Pareto前沿的形态依然稳定。下面是一组我在算例里用过的经济性参数参数取值备注线路单位造价25万元/km含电缆与架空线折算分布式电源单位造价4500元/kW光伏典型值储能单位造价1800元/kWh按容量计折现率8%工程经济评价常用设备寿命20年光伏与储能普遍取20年运维费比例1.5%按投资年化额计单位停电损失15元/kWh居民与商业平均值这些参数不一定是你的算例最优值但它们能保证模型跑出来的优化趋势是合理的。实际操作中参数变化会影响Pareto前沿的绝对位置但不会改变“增加投资换来可靠性提升”的基本权衡结构。3. 蒙特卡洛可靠性评估的Python实现3.1 序贯模拟和非序贯抽样怎么选蒙特卡洛法在可靠性评估里有两类主流做法序贯蒙特卡洛和时间无关的非序贯抽样。序贯模拟以小时为步长模拟一整年的运行过程设备的“运行-故障-修复”状态随时间演化能捕捉状态持续时间和时序相关性适合计及储能充放电策略、时序负荷曲线的场景。非序贯抽样则是从状态概率分布中直接抽一个系统状态评估一次重复几万次再聚合统计实现简单、计算快适合求解稳态期望指标。我这次选的是非序贯抽样原因是计算效率。双目标优化要对每一个候选方案反复调用可靠性评估每个方案内部还要做上万次状态抽样如果全部用序贯模拟一轮优化跑下来要几天甚至几周。非序贯抽样在精度足够的前提下计算时间能压缩一个数量级。如果后续需要细化到储能运行策略或时序潮流再在这个框架上改造成序贯枚举也完全可行。非序贯抽样的核心逻辑是每个设备按自身故障概率独立抽样得到一个系统状态然后判断这个状态是否导致负荷失电最后把大量状态的评估结果做期望聚合。这里有个关键点设备故障概率要按“在某个随机时刻处于故障状态的概率”来算而不是按年故障次数直接算。年故障次数除以8760小时得到小时故障概率再与抽样持续时间相乘才是单次抽样中设备处于故障状态的基准概率。3.2 故障区域划分与切负荷量计算在非序贯抽样中一次系统状态评估的流程是这样的先随机确定哪些设备故障然后做故障影响分析。配电系统通常是辐射状或弱环网单个设备故障时故障点上游由变电站电源继续供电故障点下游到最近的开关之间会失电如果故障点下游有联络开关可以合闸转供则合闸后部分下游负荷可以恢复最终剩余的失电负荷就是要切掉的负荷。这个逻辑落到代码里就是一套区域划分规则沿供电路径从变电站出发做遍历遇到故障支路就停下来记录故障点下游的节点集合同时检查是否有联络路径可以从其他馈线反供。注意不是所有下游负荷都能被转供转供容量受联络线和变电站容量限制。如果反供路径过载就要按负荷等级切掉部分负荷直到满足容量约束。切负荷量的计算思路我建议优先级从高到低排列一级负荷优先保二级负荷次之三级负荷最先切。这个部分最容易出bug的地方是环路判断。有些联络开关合闸后系统会短暂变成环网如果遍历逻辑没有处理“已访问节点”标记DFS就会陷入死循环。我习惯在遍历函数的开头维护一个visited集合每次访问节点先检查是否已访问这个细节能省大量调试时间。3.3 代码结构从采样到指标聚合单次状态评估的代码骨架可以写成下面这样def evaluate_system_state(buses, lines, fault_set): # 1. 标记故障支路 for line_id in fault_set: lines[line_id].faulted True # 2. 从变电站节点开始BFS构建上游供电可达集合 upstream bfs(buses, lines, source_bus0, blocked_linesfault_set) # 3. 对每个含联络开关的边界节点判断能否向失电区域反供 restored_nodes set() for tie_line in tie_lines: if tie_line.is_open and tie_line.in_zone(upstream): restored_nodes.update(attempt_restoration(...)) # 4. 计算失电负荷和切负荷量 lost_power 0.0 for bus in buses: if bus.idx not in upstream and bus.idx not in restored_nodes: lost_power bus.load_kw return lost_power # 单位kW外层蒙特卡洛循环就是反复调用这个函数把每次的失电功率累加最后除以抽样次数乘以模拟时长就得到ENS。SAIDI和SAIFI的统计也类似统计每次失电涉及的节点数即可。抽样次数一般取1万到5万次要提前设定随机种子否则每次跑出来的指标都不同后面的优化结果没法复现。我在代码里会刻意把“单次状态评估”和“大批量抽样循环”分开评估函数只做计算不做随机抽样这样既能单测也能并行加速。Python里做并行时最简单的方式是用multiprocessing的Pool把样本分批丢给多个进程再把结果汇总。但要注意并行计算里每个子进程都要重新设置一次随机种子否则并行模式下的抽样序列和串行模式不具可比性。3.4 提速经验和边界条件处理可靠性评估模块是整个项目的性能瓶颈在NSGA-II优化循环里每一代要评估几十上百个候选方案每个方案要跑上万次抽样嵌套循环下来计算量非常大。我在实际代码里用了三个提速手段第一把节点负荷、故障率、修复时间等静态数据预先存成numpy数组评估时用数组索引替代Python对象属性访问速度能快不少。第二把高频复用的BFS和DFS函数做局部变量绑定减少属性查找开销。第三如果条件允许把内层评估逻辑做向量化或者用numba的njit装饰器加速。我在一个场景里测试过numba加速后的评估函数比纯Python版本快大约8到10倍这对优化迭代的收敛速度至关重要。边界条件方面要特别注意故障概率极低时的抽样稳定性。设备故障率通常是每公里每年0.05到0.1次折到小时概率后是非常小的小数普通Python随机数生成器能处理但如果用了不合适的抽样函数在极端条件下可能产生偏差。另外当系统规模变大候选方案数量增多时可靠性评估结果的方差会影响Pareto前沿的平滑度我建议每个方案至少抽样3万次并且在优化结束后对前沿上的每个点再做一次高精度复算。4. 双目标规划与NSGA-II的落地4.1 决策变量网架、容量、位置怎么编码双目标规划的决策变量在工程上通常分两类离散决策变量和连续决策变量。离散变量包括线路是否新建、联络开关是否装设、某节点是否接入分布式电源连续变量包括分布式电源的接入容量、储能的配置容量。不同性质的变量在优化算法里编码方式不同NSGA-II本身支持混合变量编码但实现时要特别注意交叉和变异算子对不同编码类型的处理。我这次选的决策变量组合是二进制变量表示候选线路是否建设候选节点是否配置储能实数变量表示光伏容量和储能容量范围根据节点安装条件设定上限。举个例子IEEE 33节点系统里预设12条候选新建线路、8个候选光伏节点、5个候选储能节点那一个个体的编码长度就是12个二进制位加13个实数总共25维。这个维数不算高NSGA-II的搜索空间完全能支撑。如果线路候选数增加到几十条交叉算子的效果就会下降需要引入局部搜索策略或分阶段优化。决策变量长度直接决定了优化的收敛速度。我建议第一版先把候选方案控制在20到30个变量以内等整个流程跑通再逐步扩大搜索空间。一上来就想做全网大规模混合规划通常连收敛性都很难判断。4.2 NSGA-II的Python实现选型与参数设置Python生态里做NSGA-II有三条路用现成的pymoo库、用deap库、自己写算法框架。我强烈建议用pymoo它内置了NSGA-II、SBX交叉、多项式变异等标准算子而且支持自定义问题类正好适合把可靠性评估函数封装成目标函数。用pymoo定义双目标问题的骨架大概是这样的from pymoo.core.problem import Problem import numpy as np class PlanningProblem(Problem): def __init__(self, n_var, n_ieq_constr1): super().__init__(n_varn_var, n_obj2, n_ieq_constrn_ieq_constr, xl0.0, xu1.0) def _evaluate(self, X, out, *args, **kwargs): cost_list [] ens_list [] for individual in X: cost calc_investment(individual) # 经济性目标 ens calc_reliability(individual) # 可靠性目标用ENS或SAIDI cost_list.append(cost) ens_list.append(ens) out[F] np.column_stack([cost_list, ens_list]) out[G] compute_constraints(X) # 不等式约束这里有个关键点目标1用年化经济成本目标2用ENS或SAIDI两者量纲不同NSGA-II的支配关系直接比较目标向量不受量纲影响这正是双目标比加权单目标方便的地方。参数设置上我推荐种群规模取100到200进化代数取200到500代交叉概率0.9变异概率按变量个数动态调整通常在0.05到0.15之间。实际调试时建议先跑100代观察Pareto前沿是否稳定再逐步加大代数。不要一上来就跑500代万一可靠性评估模块有bug你会在几小时后才发现整个优化逻辑跑偏了。4.3 约束处理和Pareto解集的后处理约束条件是双目标规划里最容易被忽略的环节。常见约束包括节点电压偏移上限、支路容量上限、分布式电源渗透率上限、储能投资总预算等。pymoo里可以将约束写在_evaluate方法的G输出中算法会把违反约束的个体排除在支配关系之外。电压约束和潮流计算绑定这里要注意效率。可靠性评估内部已经做了大量BFS/DFS如果再叠加潮流计算开销非常大。我的做法是在可靠性评估的同一次状态遍历里顺带把支路负载率和节点电压近似计算出来转供后如果出现过载就调整切负荷顺序。这样做虽然牺牲了潮流精度但能保证优化方向正确。对于规划层面的研究这个精度通常足够。优化结束后Pareto前沿上可能有几十个方案还需要做后处理。我会把每个方案还原成可视化网架图并用高精度蒙特卡洛重新评估一次剔除掉那些因优化过程中抽样方差而误判为优秀的点。后处理的另一项工作是检查网络连通性确保所有负荷节点在正常状态和单故障状态下都具备可达性某些优化方案为了省钱会得出岛状运行的结构这在常规配电网规划里是必须修正的。5. 实操中的坑与排查技巧实录5.1 高频问题速查表这轮项目做下来我把最常踩的坑整理成了一张速查表基本覆盖了同类项目调试中的大部分问题症状可能原因排查方法SAIFI/SAIDI结果异常大故障概率计算口径错误把年故障率当成小时故障率核对设备故障概率是否除以8760后作为抽样基准ENS为0故障集合为空或BFS未检测到失电节点打印单次状态的fault_set和上游可达集合手动验算一个简单故障场景优化迭代结果不变决策变量编码范围冲突随机数种子固定导致个体全部相同检查交叉变异算子是否对二进制和实数变量分别处理Pareto前沿全是单点惩罚函数设置过强可行解被全部淘汰放宽约束惩罚系数单独查看约束违反度分布并行计算结果与串行不一致子进程随机种子未初始化在Pool初始化函数中重新设置numpy随机种子电压约束频繁越限约束计算只用了潮流近似忽略了无功分布增加支路导纳参数或改用线性化潮流校验第一行的坑最容易犯。我在第一轮实现时直接把文献里的年故障次数当作单次抽样概率结果ENS偏大了近两个数量级输出结果一眼看过去就不合理。后来把所有故障率先除以8760小时单位再乘以模拟时长结果才正常。这类参数口径错误很难通过代码逻辑层面发现一定要用简单算例手算验证。5.2 参数敏感性与结果校验经验结果校验是我最想强调的部分。很多文章把蒙特卡洛评估结果直接写进优化流程却从不用已知结果去校验这是大忌。我的做法是先在一个简化网络上算理论值再对比程序输出。比如一个三节点单电源辐射网只有一条线路手动推导出该线路故障时的失电负荷和恢复方案然后看程序输出是否一致。只有程序在简单案例上完全正确才能用它去算IEEE 33节点这种复杂系统。参数敏感性分析也值得做。我分别测试了故障率取0.05和0.1次/(km·a)、修复时间取2小时和5小时、单位停电损失取8元和20元/kWh等组合观察Pareto前沿的形态变化。结论是故障率和修复时间主要影响可靠性目标的绝对量级单位停电损失主要影响单目标加总方案的排序但对双目标前沿的整体形状影响较小。这说明双目标框架比单目标框架对参数误差的鲁棒性更强这也是该项目最终坚持双目标的原因之一。5.3 代码组织与工程化建议最后说一点代码组织。这个项目涉及的模块多、计算密度高我建议按包结构组织目录至少包含model、reliability、economic、optimizer、postprocess五个子模块。可靠性评估函数用独立类封装输入输出都用dataclass或命名元组这样后续扩展不同评估方法时接口不用大改。优化模块里把NSGA-II的配置参数集中放在一个配置字典里方便批量跑实验。代码注释也要写清楚参数单位。我吃过一次亏把储能容量的单位在某个函数里写成了kWh另一个函数里又按MW处理结果优化出来的方案储能配置量级完全不对。像这种单位混用问题只用眼读代码很难发现最终靠的就是调试输出里储能曲线的不合理跳变才暴露出来。还有一个实用技巧优化过程要做好中间结果保存。每次进化迭代结束后把当前代的最优个体和目标值写入CSV或npy文件万一程序中途崩溃至少还能接着上次的结果继续跑不用从头再来。我在跑一轮大规模方案时经常要耗时几个小时这个习惯帮我省下了大量重复计算时间。我个人在实际操作中的另一个体会是单目标向双目标切换并没有想象中复杂反而是把“评估”和“优化”两个环节彻底解耦让代码结构更清楚后续换算法、换约束条件的扩展成本都低了很多。这个项目目前已经能稳定输出考虑成本和可靠性的Pareto前沿下一阶段如果要把时序储能策略放进来我会把非序贯抽样改成序贯模拟再把评估结果嵌入到同样的双目标框架里。对正在做同类项目的人来说建议先把可靠性评估做实再谈优化这个顺序几乎不会错。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询