☰
基于NSGA-II的混合配电系统经济与可靠性双目标规划及Python实现
2026/10/5 3:19:03 网站建设 项目流程

做配电网规划的朋友应该都有同感:经济账好算,可靠性账很难算。你算完投资、运维、网损,觉得方案已经很漂亮了,结果领导一句话问回来——"这样改完,用户一年停电几次、停电多久?有没有数据支撑?"如果你拿不出SAIFI、SAIDI、EENS这些可靠性评估结果,那前面的经济性优化做得再精细,说服力也大打折扣。

我最近完整整理了一套基于经济与可靠性双目标的混合配电系统规划及可靠性评估Python代码,从问题建模、可靠性评估方法、双目标优化求解到算例分析,把整条技术链路跑通并沉淀成了可复用的代码框架。这篇文章就把整个项目的思路、建模逻辑、代码结构以及实操中踩过的坑详细写下来。适合正在做混合配电系统规划、分布式电源选址定容、配电可靠性评估课题的研究生,也适合配网规划工程师想用Python快速搭建评估原型的情况。

1. 混合配电系统规划的"双目标"到底在算什么

1.1 混合配电系统的规划问题描述

所谓"混合配电系统",指的是以传统变电站、馈线构成的主干网架为基础,在部分节点接入分布式光伏、风电、储能以及可调度的微型燃气轮机,形成多电源混合供电的配电网形态。这类系统规划的典型问题是:给定一张配电网拓扑图、各节点年时序负荷曲线、一组DG候选安装节点(通常还会给出每个节点的安装容量上限),让我们决定哪些节点装什么类型的电源、装多大容量,使得整个系统在经济性和可靠性之间达到合理平衡。

这个问题的决策变量很直观。假设候选安装节点集合为N,每个节点可选的方案可以写成一组离散容量档位,比如光伏装100kW、200kW、300kW,或者不装;储能系统装200kWh/100kW、400kWh/200kW,或者不装。这样规划方案就可以用整数向量x表示:x[i] = 0表示节点i不装任何电源,x[i] = k表示节点i选择第k种容量配置方案。用整数编码的好处是后续用遗传算法、粒子群这类启发式算法处理起来非常顺手——个体就是一个整数向量,交叉变异操作直接在编码空间上做即可。

单纯从数学形式上看,这个问题可以写成:

  • 目标1:min 系统总费用(含投资、运维、停电损失)
  • 目标2:min 可靠性指标(如EENS或SAIDI)
  • 约束条件:节点电压上下限、支路潮流极限、DG渗透率上限、每个节点安装容量不能超过通道允许值

但"双目标"三个字说起来轻松,真正落地时两个目标之间的冲突关系需要仔细琢磨。

1.2 经济目标:投资、运维、停电损失三层成本结构

经济目标我建议拆成三块来计算,缺一块都不完整。

第一块是投资成本。DG的单位投资成本按类型差异很大,光伏大约每千瓦3000到4500元,风电每千瓦6000到8000元,锂电池储能系统按容量算大约每千瓦时1000到1500元,微型燃气轮机每千瓦4000元左右。投资成本表达式为:

C_inv = ΣΣ c_type × cap(i, type)

其中c_type是单位容量投资成本,cap是节点i上安装的某类电源容量。

第二块是年运行维护成本。光伏的运维成本很低,每千瓦每年大约20到40元;储能稍高一点,要考虑电池循环损耗和日常维护,每千瓦每年80到120元。表达式为:

C_om = ΣΣ om_type × cap(i, type)

第三块是停电损失成本。这也是混合配电系统规划区别于传统电网规划的关键所在——如果不装任何分布式电源,用户停电损失就完全由电网可靠性决定;装了DG和储能之后,部分故障场景下可以通过孤岛运行保住负荷,停电损失会明显下降。停电损失的计算方式比较统一:

C_outage = EENS × IEAR

其中EENS是期望缺供电量(单位MWh/年),IEAR是单位缺电成本(元/kWh),一般取数元到十几元不等,具体看用户类型。

年总费用就是三块之和。这里有个小提醒:投资成本通常是一次性投入,如果直接把它和年运维成本相加,口径是不对的。实际项目中要么用资本回收系数CRF把投资折算到每年,比如用基准折现率6%、设备寿命20年,CRF大约等于0.087。要么就按项目周期内的总费用现值和年费用分开列目标,我建议用年等值费用,也就是C_total = CRF × C_inv + C_om + C_outage,这样同类方案之间可以直接比较。

1.3 可靠性目标:从SAIFI、SAIDI到EENS

可靠性评估指标里,SAIFI、SAIDI、EENS这三个最常用。

SAIFI是系统平均停电频率指标,单位是"次/户·年"。可以通俗理解成每个用户平均一年停电几次。计算公式是:

SAIFI = 系统总停电户次 / 系统总用户数

SAIDI是系统平均停电持续时间指标,单位是"小时/户·年",通俗理解是每个用户平均一年停电多少小时。计算公式是:

SAIDI = 系统总停电户时数 / 系统总用户数

EENS是期望缺供电量,单位是MWh/年,代表一年内因为各类故障导致的少供电量的期望值。公式是:

EENS = Σ (各故障场景发生的概率 × 该场景下的缺供电量)

直觉上,"经济-可靠性"双目标就是:你在配电网上花钱投资DG和储能,可靠性指标会变好(SAIDI下降、EENS下降),但投资和运维成本上升。反过来,如果只想省钱少装设备,可靠性就变差。这两个目标之间的权衡,就是整个规划问题的核心。

我在实际建模中还遇到过一个问题:到底把哪个可靠性指标当第二目标?我的建议是EENS作为优化目标最好,因为EENS以电量的形式出现,可以直接和停电损失成本挂钩,经济目标中的C_outage本身又是EENS乘单位缺电成本,这样两个目标之间有天然的逻辑联系。SAIFI和SAIDI可以作为约束条件来设置,比如要求SAIFI不超过1次/户·年,SAIDI不超过3小时/户·年,这样工程上更有指导意义。

2. 可靠性评估运算效率:解析枚举与蒙特卡洛的取舍

2.1 规划优化嵌套场景下的可靠性评估选型

可靠性评估方法粗略分两大类:解析法和序贯蒙特卡洛法。

序贯蒙特卡洛的思路是模拟系统一年又一年的运行,每次随机生成元件故障时间序列、修复时间序列、负荷时序数据,统计在各年中的停电次数和停电时长。这种方法的优点是建模粒度细——可以考虑天气因素、元件老化、维修策略、负荷波动,结果也容易解释。但缺点非常明显:为了得到一个稳定的期望值,往往需要模拟十万年甚至更多场景。我做过实测,一个33节点系统,模拟5万年大概要跑几十秒到几分钟不等。

这个速度单独做一套评估没问题。可是双目标优化要做的是"优化算法反复调用可靠性评估,根据评估结果决定下一代个体怎么进化",一个种群50个个体,进化200代,意味着要做一万次可靠性评估。如果每次评估都要跑几十秒,那整个优化过程跑完需要好几天,这在实际项目里基本没法接受。

所以我的选择是:规划阶段的优化循环内只用解析式故障枚举,蒙特卡洛留在最终方案出来后做精确校核。解析法的本质是把各个故障场景视为独立事件,逐个枚举计算后果,再用元件故障率作为权重加权求和。对于一个节点数几十个的中压配电网,N-1故障场景数量也就是支路数加变压器数,大概几十到一百多个场景,单次评估开销很小,完全能嵌入优化循环。

2.2 故障场景枚举的工程边界:N-1为主、局部N-2

配电网规划阶段可靠性评估最常见的做法是枚举单一元件故障,也就是N-1准则。对一条馈线支路,取它的年故障率λ(例如0.05次/km·年,乘以支路长度),平均修复时间r(例如4小时)。这个支路故障对下游用户产生的停电影响等于λ乘以该支路覆盖的用户数和停电时长。把所有支路的故障场景影响累加,就得到全系统的可靠性指标。

N-2场景(两个元件同时故障)在规划阶段我不建议全量枚举。原因很简单:组合爆炸。一个60条支路的网络,N-1场景是60个,N-2场景是C(60,2)=1770个,数量级直接跳了一个台阶。而这些N-2事件的概率是两个元件故障率之积,通常小到对EENS的贡献可以忽略。唯一需要关注的是某些关键通道上的双故障,比如同一段电缆沟内的两条并排电缆、同一个变电站母线上的两条出线。这种特殊场景单独拎出来作为约束校核即可,不要混进优化目标里,否则会大幅拖慢速度。

2.3 含DG和储能的孤岛修正:混合配电系统评估的核心差异

如果只是枚举故障场景然后按辐射状网络计算失电用户,那跟传统配电网可靠性评估没区别。混合配电系统的关键差异在于:支路故障断开后,下游区域如果存在足够的分布式电源和储能,可以通过孤岛运行保住一部分负荷不中断。

我在代码实现里处理孤岛效应时,核心逻辑分三步。第一步,把某条支路断开,用连通性分析找出所有失电的连通分量。第二步,对每个失电连通分量,检查它内部有没有DG和储能。第三步,做功率平衡校验——把这个分量内所有DG的可用出力和储能的最大放电功率加起来,看能不能覆盖分量的峰值负荷;如果能覆盖,这个分量的用户就不用纳入停电用户统计,如果只能覆盖一部分,就按比例削减负荷。

这里有个容易被默认掉的点:孤岛能不能成立,不只看功率够不够,还得看电压和频率能不能稳住。规划阶段做快速评估时,我不可能对每个场景都做详细的动态仿真。工程上的简化处理是:先检查功率平衡,功率不够的直接切负荷;功率够的再用潮流计算校验电压,如果电压越限再适当削减负荷。

3. 双目标求解路线:为什么拒绝加权法、选择NSGA-II

3.1 加权法的两个硬伤

很多初学者上手时第一反应是把两个目标加权成一个单目标,比如min F = ω1×C_total + ω2×EENS。这个思路简单,但实际操作相当难受。

硬伤之一是权重系数无法先验确定。"经济优先"和"可靠优先"之间的权重比例是多少?你说0.7比0.3,可0.7对应的是什么经济指标水平、0.3对应的是什么可靠性水平?在没有结果之前,这纯粹是拍脑袋。而且0.7/0.3和0.6/0.4跑出来的方案可能差异巨大,决策者很难从一堆方案里挑出真正符合工程需要的那个。

硬伤之二(更难察觉)是加权法永远找不到非凸Pareto前沿上的解。如果两个目标构成的可行域是非凸的,加权法得到的解始终集中在两端,中间某些更均衡的方案反而会被漏掉。而在配电规划这类具有离散决策变量的整数优化问题中,非凸几乎是一定的。

3.2 NSGA-II的核心流程与规划问题的契合点

NSGA-II(带精英保留策略的非支配排序遗传算法)是处理这类双目标问题的经典选择。它的基本流程是:

第一步,初始化种群。随机生成NIND个个体,每个个体对应一个规划方案。

第二步,非支配排序。把种群中所有个体按Pareto支配关系分层。如果个体A的经济性和可靠性都不差于个体B,且至少一项严格优于B,那么A支配B。不被任何个体支配的那些方案构成了第一前沿,这些方案就是当前种群里的"最优折中集合"。

第三步,拥挤度计算。同一前沿面内,计算每个个体在目标空间中的拥挤距离。拥挤度大的个体代表它周围的解比较稀疏,保留它会维持前沿面的均匀分布。

第四步,选择、交叉、变异。用锦标赛选择法选出父代,对这个规划问题,个体编码是整数向量,交叉用模拟二进制交叉或者简单的均匀交叉都行,变异采用多项式变异,但变异概率要控制在较低水平。

第五步,精英保留。把父代和子代合并,重新做非支配排序和拥挤度计算,保留前NIND个个体进入下一代。

这套流程和配电规划问题匹配度很高。特别是它不要求对两个目标事先赋权重,跑完之后直接得到一整条Pareto前沿,让决策者看到"多花多少钱、能换来多少可靠性提升"的完整图谱。

3.3 在Python里落地NSGA-II的参数设定参考

我经过反复试跑,给出一组适合33节点系统的参考参数:

参数取值备注
种群规模40候选节点5~8个时足够
进化代数100~150单次评估约几十毫秒时可接受
交叉概率0.9保持种群多样性
变异概率0.1~0.2太大容易破坏收敛
容量编码整数档位避免浮点数带来的含意解

另外一定要做存档机制,也就是在优化过程中把每一代产生的非支配个体额外保存下来,防止精英保留策略意外丢掉某些好方案。这个操作看似很小,但在算法快收敛时非常有用。

还有一个经验:约束处理不要做成硬性一票否决。比如节点电压越限,直接判方案不可行会损失太多信息。更好的做法是给越限量算一个惩罚项,加到经济目标里,这样算法能区分"轻微越限"和"严重越限"的方案,引导进化方向。

4. 代码实现:数据结构、评估函数与优化主循环

4.1 用NetworkX把配电网变成可计算的图模型

配电网本质上是图结构。我在代码里用NetworkX来承载拓扑,每个节点node存储负荷峰值、年负荷曲线,每条边edge存储支路电阻、电抗、故障率和长度。这样后面用连通性分析做故障影响域判断,直接调用NetworkX的connected_components函数,能省大量工作。

import networkx as nx class DistributionNetwork: def __init__(self): self.graph = nx.Graph() # 每个节点属性:load_peak, load_profile, user_count # 每条边属性:r, x, length_km, failure_rate, repair_time_h def add_substation_node(self, node_id): # 根节点/变电站节点,电压恒定,不参与故障枚举 self.graph.add_node(node_id, type='substation', load_peak=0) def add_load_node(self, node_id, load_peak, user_count, profile_idx): self.graph.add_node(node_id, type='load', load_peak=load_peak, user_count=user_count, profile_idx=profile_idx) def add_branch(self, node_a, node_b, r_ohm, x_ohm, length_km, failure_rate_per_km, repair_time_h): # 支路故障率 = 单位长度故障率 × 支路长度 self.graph.add_edge(node_a, node_b, r=r_ohm, x=x_ohm, length_km=length_km, failure_rate=failure_rate_per_km * length_km, repair_time=repair_time_h)

这个类的基础就是让后面的可靠性评估函数能自由地对拓扑做各种"破坏性操作"。

4.2 时序负荷与DG出力的协同处理

很多人在初版代码里把负荷当成恒定值、把光伏出力当成额定功率,跑出来的结果误差非常大。光伏出力和负荷高峰往往不在同一时刻——夏天傍晚空调负荷高峰时,光伏出力已经衰减得很厉害;冬季傍晚负荷高峰更是完全靠常规电源支撑。如果在可靠性评估里做孤岛功率校验时用额定功率,会严重高估DG的供电能力。

我的做法是给每个负荷节点绑定一条8760小时(或典型日分段)的负荷标幺曲线,给光伏和风电绑定对应的出力标幺曲线。孤岛功率校验时,把故障发生时刻负荷曲线值和DG出力曲线值对应取出来。规划阶段为了控制计算量,可以不用全年8760小时逐点校核,而是选取几个典型时段:冬季晚峰、夏季晚峰、中午光伏高峰、深夜低谷。每个时段算一遍功率平衡,取最恶劣的结果作为该故障场景的缺供电量估计。

负荷曲线处理代码示意:

def load_at_hour(profile, hour_of_day): # profile是24小时标幺负荷序列,hour_of_day=0~23 return profile[hour_of_day] def pv_output_at_hour(solar_curve, hour_of_day): # 光伏出力按照光照曲线,夜间为0 return solar_curve[hour_of_day]

这样评估EENS时,故障时刻的随机分布通过典型时段的等概率近似来体现。实测下来结果比恒定负荷模型准确得多,而且计算量可以接受。

4.3 核心函数:故障枚举与可靠性指标计算

可靠性评估的函数是整个代码的灵魂,我把逻辑分为两步:先枚举所有单支路故障,算出每条支路故障影响的失电节点集合;再考虑DG孤岛供电修正,最后加权累加得到SAIFI、SAIDI和EENS。

故障影响分析的核心代码:

def reliability_evaluation(net, dg_plan, typical_hours, load_curves, dg_curves): saifi = 0.0 saidi = 0.0 eens = 0.0 total_users = sum(nx.get_node_attributes(net.graph, 'user_count').values()) # 枚举单支路故障(N-1) for branch in net.graph.edges(data=True): node_a, node_b, attrs = branch lam = attrs['failure_rate'] # 支路年故障率 r = attrs['repair_time'] # 平均修复时间(小时) # 断开该支路,寻找失电的连通分量 temp_graph = net.graph.copy() temp_graph.remove_edge(node_a, node_b) # 找到包含变电站根节点的连通分量作为"带电区域" substation_nodes = [n for n, d in net.graph.nodes(data=True) if d.get('type') == 'substation'] energized = set() for sub_node in substation_nodes: energized.update(nx.node_connected_component(temp_graph, sub_node)) # 所有不在带电区域的节点就是失电节点 lost_nodes = [n for n in net.graph.nodes() if n not in energized and n != node_a] # 对每个失电节点,统计受影响的用户数和负荷 affected_users = sum(net.graph.nodes[n].get('user_count', 0) for n in lost_nodes) affected_load = sum(net.graph.nodes[n].get('load_peak', 0) for n in lost_nodes) # 对含DG孤岛分区的失电节点做孤岛供电修正 lost_load = apply_islanding_correction(temp_graph, lost_nodes, dg_plan, typical_hours, load_curves, dg_curves) # 故障年频次 × 停电影响 saifi += lam * affected_users / total_users saidi += lam * r * affected_users / total_users eens += lam * r * lost_load # 按修复时间内平均缺供电量估算 return saifi, saidi, eens

孤岛供电修正函数是关键,我的简化实现逻辑如下:

def apply_islanding_correction(graph_after_outage, lost_nodes, dg_plan, typical_hours, load_curves, dg_curves): if not lost_nodes: return 0.0 # 找出失电区域的连通分量(不含变电站) subgraph = graph_after_outage.subgraph(lost_nodes) components = list(nx.connected_components(subgraph)) total_lost_load = 0.0 for comp in components: # 该分量的总负荷峰值 comp_load = sum(nx.get_node_attributes(graph_after_outage, 'load_peak')[n] for n in comp) # 该分量内DG可用容量(考虑时序出力折减) comp_dg_cap = sum(dg_plan[n]['capacity'] * dg_curves[hour] for n in comp if n in dg_plan) # 储能可放电功率 comp_ess_cap = sum(dg_plan[n]['ess_power'] for n in comp if n in dg_plan and 'ess_power' in dg_plan[n]) # 如果DG+储能能够覆盖负荷,则该分量不停电 if comp_dg_cap + comp_ess_cap >= comp_load: continue else: # 小时级校核:对每个典型时段,统计缺电量 for hour in typical_hours: demand = comp_load * load_curves[hour] supply = comp_dg_cap * dg_curves[hour] + comp_ess_cap total_lost_load += max(0.0, demand - supply) return total_lost_load

这个实现虽然简化,但逻辑是完整的。实际工程中,每个场景还要考虑储能SOC状态,这里我按最不利的初始SOC为50%来估算,保守但稳妥。

4.4 优化主循环:NSGA-II与评估函数的对接

有了评估函数,优化主循环就顺理成章了。如果你不想自己实现NSGA-II,可以用pymoo这类库,只需要定义Problem子类、把两个目标函数返回即可。不同版本的pymoo对算子命名有差异,我这里不锚定具体版本,给一段能表达核心对接逻辑的架子:

from pymoo.core.problem import Problem class DNPPlanningProblem(Problem): def __init__(self, network, dg_candidates, dg_options): super().__init__(n_var=len(dg_candidates), n_obj=2, n_constr=1, xl=0, xu=len(dg_options)-1, type_var=int) self.network = network self.dg_candidates = dg_candidates self.dg_options = dg_options def _evaluate(self, x, out, *args, **kwargs): # x是一个整数向量,表示每个候选节点的容量档位选择 cost = np.zeros(len(x)) reli = np.zeros(len(x)) for i, ind in enumerate(x): dg_plan = decode_solution(self.dg_candidates, self.dg_options, ind) cost[i] = annual_cost(self.network, dg_plan) saifi, saidi, eens = reliability_evaluation(self.network, dg_plan, typical_hours, load_curves, dg_curves) reli[i] = eens # 第二个目标用EENS out["F"] = np.column_stack([cost, reli])

然后在main函数里直接调用pymoo的NSGA2算法和minimize接口跑优化。跑完之后从result中取所有非支配解,再对每个非支配解做一次详细的潮流校验和完整的可靠性指标还原。

如果你的环境里pymoo装得不太顺手,也可以自己实现NSGA-II的核心循环,工作量主要在三块:快速非支配排序、拥挤度计算、锦标赛选择。这三块代码加起来大概一百多行,理解清楚原理后手写并不困难。我个人建议至少手写一遍非支配排序,这对理解"Pareto支配"和"分层"的概念非常有帮助。

4.5 结果可视化与方案后处理

优化跑完,第一件事是画Pareto前沿图。横轴是年总费用,纵轴是EENS,每个散点代表一个非支配解。

import matplotlib.pyplot as plt def plot_pareto(result_cost, result_reliability, highlight_idx=None): plt.figure(figsize=(8, 6)) plt.scatter(result_cost, result_reliability, c='steelblue', s=60, zorder=3) if highlight_idx is not None: plt.scatter([result_cost[highlight_idx]], [result_reliability[highlight_idx]], c='crimson', s=120, marker='*', zorder=4) plt.xlabel('Annual Total Cost (万元)') plt.ylabel('EENS (MWh/年)') plt.title('Pareto Front of Hybrid Distribution Planning') plt.grid(alpha=0.3) plt.show()

还需要把一个典型方案的DG安装位置和容量画到网络拓扑图上,直观展示"钱花在了哪些节点"。这个图在写论文或者给领导汇报时说服力非常强。

5. 算例验证:IEEE 33节点系统上的Pareto前沿长什么样

5.1 算例设置

我用经典的IEEE 33节点配电系统验证模型。基准负荷约3.7MW,候选DG安装节点选了6个,分别是节点8、15、18、22、25、33。每个节点可选装光伏、储能或者两者组合。容量档位如下:

方案编号光伏容量(kW)储能容量(kWh/功率kW)备注
000不装
11000纯光伏
22000纯光伏
33000纯光伏
4200200/100光伏+储能
5300400/200光伏+储能

支路故障率按0.1次/(km·年)取,平均修复时间4小时。单位缺电成本IEAR取8元/kWh。折现率6%,设备寿命20年。

5.2 Pareto前沿形状与拐点解读

优化结果出来后,Pareto前沿呈现出明显的L形,这是非常典型的经济-可靠性格局。左端方案年费用低,EENS高,对应的是只装了少量光伏、没装储能、孤岛支撑能力弱。右端方案年费用大幅上升,EENS降到很低水平,对应的是在多个节点同时安装光伏和大容量储能,故障时能对关键负荷进行长时间的孤岛供电。

最有价值的区间是前沿中段的拐点附近。这个区域有几个方案,年费用比左端方案多大约15%到20%,但EENS下降幅度可达40%到50%。再往右,每多花一万元能换来的可靠性提升明显递减。工程上选方案时,我会优先建议决策者看拐点附近的解,因为边际效益最高。

5.3 两个容易被忽略的算例细节

第一,全装DG会出现容量冗余但可靠性收益递减的现象。原因在于DG只是"电源",故障场景下如果负荷功率超过DG出力,照样要切负荷。变压器容量和馈线容量约束会限制孤岛能带起来的负荷规模,DG装机量超过某个阈值后,EENS改善非常有限。

第二,储能对EENS的改善呈阶梯状,而不是平滑曲线。这是因为储能必须跨越一个容量阈值,才能把孤岛支撑时间从1小时延长到2小时、3小时。如果储能只够支撑1小时,而故障修复时间需要4小时,那么后3小时仍然停电,可靠性指标改善就是有限的。想明白这件事,你就知道为什么算例中"光伏+储能"组合总是出现在可靠性较好的那一端。

6. 实操中的坑和给后来者的工程建议

6.1 潮流不收敛的兜底处理

优化过程中我没有逃避潮流计算。特别是在DG渗透率高的方案里,馈线潮流分布变化剧烈。我在评估函数里加了一个内部潮流校核模块,用前推回代法计算节点电压。前推回代法在辐射状配电网中计算效率很高,一轮迭代只需要沿馈线从末端向前推功率、再从根节点向后回代电压,几十个节点的网络几十次迭代就能收敛。

但总有方案会碰上线损大、末端电压严重越限的情况,迭代可能发散。兜底策略很简单:如果某个方案潮流计算发散,就把它的经济目标设为一个非常大的惩罚值,比如1亿元。这样NSGA-II会自动把这种方案视为劣质方案,慢慢从种群中淘汰出去。这个处理方式比直接废弃个体更温和,算法不会因为某一代全是坏个体而崩溃。

6.2 修复时间参数对结果的影响远超你的想象

平均修复时间r这个参数,我在初版代码里统一取了4小时,结果SAIDI整体偏高,导致优化算法偏好大规模投资储能。后来我意识到自己忽略了自动化开关的作用——如果馈线上安装了馈线自动化装置,故障隔离和转供操作可以在0.5小时内完成,而不是等维修人员到场修完。修正r的取值后,可靠性评估结果和优化方案推荐都发生了明显变化。

这提醒所有做配电规划模拟的朋友:可靠性参数必须和网络的实际自动化水平匹配。你的模型再精细,输入参数不准,输出结果就是错的。规划阶段不确定时,建议用两个r值分别计算——一个取故障隔离时间0.5小时,一个取维修时间4小时,对比结果的敏感性。

6.3 性能优化与可复现性建议

最后说三个工程化建议。

性能方面,故障影响域分析其实不依赖于DG配置方案。每条支路断开后,哪些节点失电、哪些节点在哪个连通分量里,是网络拓扑本身的性质。我建议在优化开始前把每个故障场景的影响域预计算并缓存,这样每次评估只需要做孤岛功率校核和累加,速度能提升一倍以上。我第一次跑的时候没做这个优化,60节点的网络加120代进化,跑完要两个多小时,预计算之后缩减到四十分钟左右。

可复现性方面,所有随机数都要固定种子。NSGA-II的初始化、交叉和变异都用同一套RandomState,保证同一套参数下每次跑出的结果一致。这个细节在写论文时尤其重要,审稿人如果要复核你的结果,种子不固定就得重跑整个实验。

代码组织方面,强烈建议把网络数据、评估函数、优化算法、结果可视化拆成四个独立模块。这样换网络(比如从33节点换成69节点)、换DG候选点、换成本参数,都不需要改动评估和优化部分的代码,只要改数据文件即可。我自己的代码就是data/、evaluation/、optimization/、visual/四个目录,换个算例半个小时内就能完成。

这套代码前前后后改了三四版,最大的体会是:双目标规划本身不难,难的是让两个目标的计算口径都对得上、让可靠性评估的速度能支撑优化算法的迭代、让最终的结果能真正解释给非专业的人听。经济目标算的是钱,可靠性目标算的是停电,这两个东西单位都不一样,但通过EENS和单位缺电成本,它们被自然地统一在了同一个框架里。这也是我认为"经济与可靠性双目标"这个课题最有价值的地方——它不是把两个拼凑起来的指标做数学加权,而是让系统规划回归到"花多少钱、减少多少用户停电"这个最朴素的工程问题上。如果你也正在做类似的研究,希望这篇分享能帮你少走一些弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询