配电网N-1扩展规划,这个话题其实很有意思。做过配电网规划项目的人都知道,N-1校验是电网安全运行的红线,而“扩展规划”四个字才是真正考验功力的地方——不是让你验证一个给定的网架能不能满足N-1,而是让你在没有完整网架方案的前提下,决定在哪些位置新增线路、新增多少容量、按什么顺序扩建,才能用最小的投资让整个系统在任意单一元件故障时都不丢负荷。
这篇文章就专门聊聊我自己在Matlab里实现配电网N-1扩展规划的完整思路和踩坑记录。从建模逻辑、场景枚举、求解配置到结果分析,所有内容都基于我实际跑过的算例,代码思路可以直接参考。无论你是刚接触配电网规划的研究生,还是在做电网规划工作的工程师,这篇文章应该都能帮你少走不少弯路。
1. 配电网N-1扩展规划的核心思路
1.1 从“校验思维”到“规划思维”的转变
很多人第一次接触N-1,会下意识觉得这是一个“校核”问题:给定一个网架,把每个元件逐一断开,看系统是否还能稳定运行。这个思路用于安全性评估完全没问题,但放在扩展规划里就行不通了——因为你根本没有一个已经确定的网架可以校验。
扩展规划的本质是“寻优”。你手里有的是现状网架,是未来的负荷预测,是一堆可选的新建线路走廊和变压器扩建方案,你需要做的是从这些选项中挑出一个组合,使得扩建后的网架能够通过任意元件退出运行后的安全校验,同时总建设成本最低。
我印象很深的一次项目经历,某园区配电网现状只有两条10kV馈线,负荷预测显示三年后峰值负荷会翻一倍多。如果只做校验不做规划,你会发现无论怎么调整运行方式,N-1都无法通过——这不是运行问题,这是网架结构问题。只有新增第三条馈线、改变部分负荷的供电路径,才能从根本上满足可靠性要求。这就是扩展规划的价值所在。
1.2 数学模型长什么样
配电网N-1扩展规划说到底是一个混合整数线性规划(MILP)问题。决策变量分两类:一类是整数变量,表示新建线路是否建设、变压器是否增容,另一类是连续变量,表示正常运行方式和N-1场景下的潮流分布。
目标函数通常写成:
$$ \min ;; \sum_{l \in \Omega_{new}} c_l^{line} x_l + \sum_{s \in \Omega_{sub}} c_s^{trans} y_s + \sum_{i \in \Omega_{node}} c_i^{load} z_i $$
其中第一项是新建线路的投资成本,第二项是变电站扩容成本,第三项是切负荷惩罚成本。切负荷罚因子一定要设置得足够大——我的经验是至少比投资成本高一个数量级,否则求解器会倾向于用弃负荷来“偷懒”,得到的方案根本没有实际意义。
约束条件则包括潮流平衡约束、线路容量约束、节点电压约束,以及N-1场景下的拓扑连通性约束。这里面的难点在于如何把“任意元件退出运行后系统仍然连通”这个拓扑要求写成线性约束——我后面会专门展开这个问题。
1.3 为什么选择Matlab实现
说实话,配电网规划并不一定非要Matlab。用Python也完全可以,甚至在某些场景下生态更丰富。但我个人还是更倾向于Matlab,主要出于三点考虑。
第一,Matlab的优化工具箱和YALMIP、CVX等建模工具配合得非常成熟,写MILP模型几乎不需要关心求解器接口细节;第二,Matload的稀疏矩阵运算效率很高,配电网扩展规划往往涉及上千条候选线路和上百个N-1场景,如果不借用稀疏数据结构,光内存占用就能卡死普通机器;第三,很多电力系统专业的教材和公开代码都以Matlab为载体,用它写出来更容易对照、验证、二次开发。
2. 关键元件建模与方法选型
2.1 线路、变压器和负荷的建模细节
配电网扩展规划里的元件建模,和输电网规划完全不是一回事。输电网可以简化成纯交流潮流或者直流潮流,但配电网必须考虑辐射状结构的约束、线路的电阻电抗比高这个特点,还有三相不平衡问题。好在扩展规划阶段我们通常只做单相平衡模型,重点放在结构约束和容量约束上。
线路建模时最关键的是投资决策变量与潮流变量的耦合关系。假设候选线路l连接节点i和节点j,如果投资变量为x_l = 1,则潮流变量P_l允许从0到容量上限之间自由取值;如果x_l = 0,则潮流必须严格为0。这个耦合关系写成大M法约束:
$$ -M x_l \leq P_l \leq M x_l $$
其中M取线路容量的上限。这个大M的取值是有讲究的,取太大了会影响求解器数值稳定性,取太小了可能限制可行域。我在实践中一般取线路热稳极限的1.2倍。
变压器扩容的建模类似,只是把投资变量映射到容量上限的提升。这里要注意配电网变压器往往共用、互为备用,扩容决策对N-1场景下的转供能力影响很大,不能只看单台容量。
2.2 N-1场景枚举的策略
扩展规划的N-1约束不是简单的一组约束,而是针对每一个可能的单一故障场景都要求系统可行。场景怎么选?这是整个建模过程中最需要动脑子的地方。
一种朴素的做法是枚举所有线路和变压器的故障,有多少线路和变压器就建多少套约束。这样做在算例规模不大的时候可行,但现实配电网动辄几千条馈线,完全枚举规模爆炸。
我推荐的做法是“场景剪枝”。先做一次不包含N-1约束的基础规划,然后找出其中最薄弱的几个元件——通常是负载率最高的线路和变压器——只针对这些元件构建N-1校验场景。每轮迭代求解后检查是否还有其他元件不满足N-1,如果有就加入对应场景重新求解,直到所有元件都能通过校验。这种迭代式场景生成逻辑,在工程实践中可以大幅压缩模型规模,实际计算时间往往只需要完整枚举法的十分之一甚至更少。
2.3 辐射状结构约束怎么处理
配电网规划和输电网一个本质区别是:输电网允许环网运行,配电网绝大多数情况下要求辐射状结构。这个约束在数学上很棘手,因为“无环”是一个全局拓扑性质,很难写成简单的线性约束。
工程上我常用的处理办法是引入虚拟潮流变量。具体做法是给每个节点附加一个单位虚拟负荷,然后要求潮流只能从变电站流向负荷节点,且虚拟潮流的路径与潮流路径一致。如果一个候选方案中存在环路,虚拟潮流就会在环路里打转,无法满足节点平衡,从而被约束条件排除。
这种方法的好处是约束都是线性的,可以嵌入MILP框架直接求解。缺点是多了一组变量,模型维度上升。考虑到能换来辐射状的硬性保证,这个代价是可以接受的。
3. Matlab代码实现从数据到求解
3.1 数据准备与算例构造
我先以一个中等规模的配电网算例来说明整体代码流程。假设系统有33个节点,37条可选线路走廊,现状已有线路20条,新增候选线路17条,负荷数据来自某园区实际负荷预测。
在Matlab里的第一步工作是构建节点导纳矩阵和线路参数表。我习惯用结构体数组把线路数据统一管理,字段包括起点、终点、电阻、电抗、容量上限、是否现有线路、投资成本。这样后面建模时可以很方便地通过逻辑索引筛选现有线路和候选线路。
% 示例数据初始化,bus_idx为节点编号 line_data(start_node, end_node, r, x, cap, is_existing, cost)这里要特别注意Matlab的索引习惯。电力系统里节点编号从1开始,但很多数据结构会自动锚定0,转换错了后面全盘皆输。我建议在数据读入后立刻做一次节点重编号,统一从1开始,避免后续调试时被索引错位折磨。
3.2 变量定义与约束构建
用YALMIP定义变量时,我习惯把投资变量定义为binvar,把潮流变量定义为sdpvar。命名规则要清晰:x_line表示候选线路投资变量,p_line_normal表示正常运行工况下的线路潮流,p_line_n1则是一个三维变量,第三维对应故障场景编号。
约束构建的核心代码如下:
% 正常运行方式的潮流约束 Constraints = []; for i = 1:n_bus % 节点功率平衡 Constraints = [Constraints, ... sum(p_line_normal(:, i)) - sum(p_line_normal(i, :)) == ...]; end % 候选线路投资约束 for l = 1:n_candidate Constraints = [Constraints, ... -M * x_line(l) <= p_line_normal(l) <= M * x_line(l)]; end这一段逻辑不复杂,但很容易在节点关联矩阵的索引上翻车。我的建议是先用一个小测试系统验证约束矩阵的形状,比如用5节点系统跑通一遍再上大规模算例。别问我是怎么知道的——直接在大算例上调试索引问题的滋味一点都不好受。
3.3 求解器配置与MILP调优
求解器我默认推荐Gurobi,免费问卷可以用Mosek或者Matlab自带的intlinprog。配电网扩展规划问题规模不大时intlinprog完全够用,但一旦N-1场景多、候选线路多,还是建议上Gurobi,求解速度能拉出两三个数量级的差距。
设置求解器参数时,我最常调整的是相对MIP gap和分支策略。先放开gap到5%跑一轮,看看可行解长什么样,再逐步收紧到0.1%。这样在大规模案例上能节省大量等待时间,同时不影响最终方案质量。
% YALMIP + Gurobi 求解配置示例 options = sdpsettings('solver', 'gurobi', ... 'verbose', 2, ... 'gurobi.MIPGap', 0.001, ... 'gurobi.TimeLimit', 600);时间限制这个参数一定要设置。MILP问题最怕没有任何限制地无止境搜索,设一个10分钟的时间上限,配合gap阈值,可以在工程可接受的时间内拿到高质量的次优解。
3.4 结果提取与方案可视化
求解完成后,我需要检查三样东西:目标函数值、投资方案、N-1校验是否全部通过。投资方案从x_line变量直接提取,哪些线路选中、哪些走廊新建,一目了然。
可视化方面,我通常用Matlab的graph对象画配电网拓扑图,把新建线路用不同颜色标注出来。配电网络规模通常不大,这种图在论文和项目报告里直接能用,比自己画示意图靠谱得多。
% 提取新建线路 selected_lines = find(value(x_line) > 0.5); % 绘制拓扑图 G = graph(from_node, to_node); p = plot(G, 'Layout', 'force'); highlight(p, selected_lines, 'LineWidth', 3, 'NodeColor', 'r');这里的0.5阈值是为了把二进制变量在求解误差范围内的值归整,实际求解中0.001和0.999都是被允许的近似解。
4. 常见问题与排查技巧实录
4.1 求解器报“不可行”怎么办
这是扩展规划里遇到最多的坑。模型构造完扔给求解器,啪一下返回infeasible,第一反应是怀疑约束写错了,但其实绝大多数情况下是可行域本来就空——或者被约束误杀。
我排查不可行问题有固定的三板斧。第一斧,把所有投资变量都设为1(相当于所有候选线路全建),如果这都不行,说明无论怎么投资都无法满足约束,可能是负荷数据错了、容量上限错了,或者N-1场景定义本身有问题。第二斧,把N-1约束全部去掉看是否可行,如果可行,问题出在安全约束上;如果不可行,基础潮流模型就有问题。第三斧,利用YALMIP的诊断工具检查约束类型和变量范围,特别是大M约束里的M取值。
曾经有一次我花了整整半天查一个不可行问题,最后发现是候选线路的起点终点搞反了,导致投资后潮流路径根本走不通。这种低级错误在大规模数据里真的很隐蔽,所以强烈建议每个算例都先画拓扑图肉眼检查一遍。
4.2 求解时间爆炸的常见原因
MILP求解时间爆炸,十个有八个是建模方式的问题。第一个常见原因是把完全相同的约束重复写了N遍。有些初学者在循环里给每个N-1场景单独写约束,其实这些约束共享的结构可以合并成矩阵批量生成,代码简洁不说,求解器处理起来也更快。
第二个常见原因是Big-M取值过大。大M的数值直接影响分支定界算法的松弛质量,M太大时LP松弛的可行域被过度放大,剪枝效率大幅下降。我的原则是M不超过所需的1.2倍,能用线路容量就用线路容量,千万不要图省事统一取1e6。
第三个原因是目标函数中切负荷惩罚系数设置不当。罚因子太大会导致数值病态,太小又会让解偏向切负荷在N-1场景中,我通常设置切负荷单位成本为投资成本的20倍,并通过对数尺度做几次扫描测试,看解是否稳定。
4.3 常见问题速查表
| 现象 | 首要排查方向 | 处理技巧 |
|---|---|---|
| 求解器报infeasible | 约束冲突还是真实不可行 | 全部候选线路都建,逐步释放约束定位 |
| 目标值异常小 | 切负荷惩罚太低 | 提高罚因子到投资成本一个数量级以上 |
| 求解时间过长 | 大M设定、约束冗余 | 收紧M取值,合并重复约束 |
| 结果拓扑成环 | 辐射状约束缺失或失效 | 检查虚拟潮流约束是否覆盖所有节点 |
| N-1校验始终无法通过 | 选择性场景枚举遗漏薄弱点 | 迭代式添加场景,直到全部通过 |
| 整数变量小数化 | 收敛gap偏大 | 提取时用0.5阈值归整,并验证可行性 |
4.4 收敛到“伪最优”的判断技巧
最后聊一个大家容易忽略的细节:如何判断求解器给出的解是真的最优解。
MILP求解器输出的gap是我们最好的判断依据。如果gap在1e-4以下,基本可以认定解质量可靠;如果gap一直在5%以上徘徊,这个解只能作为参考,不能直接拿去写报告。有些场景下,我会故意构造一个略差一点的方案,把目标函数拆开对比,看看是线路投资变贵了还是切负荷变多了,以此判断约束在哪个方向上限制得最紧。
判断解的质量还有一个土办法:把求得的最优网架方案输入到另一个独立编写的交流潮流程序里,逐条线路做N-1开断仿真。如果直流模型里的N-1约束在交流模型下全部满足,那么这个MILP解是经得起推敲的。这种做法虽然多花时间,却是贯穿“仿真-规划”之间鸿沟最有效的保险。
5. 扩展方向与后续工作
5.1 从静态规划到动态规划
上面讨论的扩展规划还是静态的——针对一个确定的目标年份负荷水平做规划。但现实中的配电网扩建是逐年发生的,资金有预算约束,建设顺序有先后逻辑,今年的新增线路可能会影响明年的最优方案。
动态扩展规划把目标函数改成多年投资总和最小,同时加入年度预算和建设时序约束。这会让模型的决策变量从一维变成二维,每个候选走廊在不同年份是否建设都要分别建模。求解难度随之上升,但如果你的项目周期是三到五年,动态规划带来的经济效益非常可观。
5.2 考虑分布式电源和储能
在很多规划场景中,DG(分布式电源)和储能已经成为了绕不开的选项。分布式光伏和风电可以降低线路峰值负载率,储能可以在N-1故障后为部分失电负荷提供短时供电,这两者对N-1校验结果的影响是显著的。
不过把DG引入扩展规划模型也会带来新的挑战:分布式电源的出力具有随机性,N-1校验场景不再是一个确定性的“断开某条线路”,而是“断开线路+光伏出力低+负荷高”这种复合极端场景。需要引入场景法或鲁棒优化来建模不确定性,这一步会对问题规模和算法选择产生不少影响。
5.3 我在一个实际案例里的进一步展望
我曾经处理过一个模拟项目X,那是一个包含微电网接入的配电网规划案例。单纯从N-1安全性约束来看,最优方案是在某个关键分段新增一条联络线,但把微电网的孤岛运行能力算进来之后,那一条联络线就不需要建了——配合微网调节能力,供电可靠性照样达标,省下来一大笔投资。
这是扩展规划最有意思的地方:建模对象每增加一种,最优方案就可能完全改变。N-1扩展规划不是一道固定答案的题,而是一个在可靠性、经济性和新技术应用之间探索平衡的过程。每次求解完毕,看到优化后的网架方案比现状方案在可靠性指标上提升了一个量级,投资成本却只增加了很小比例的时候,那种满足感是其他工作难以替代的。
如果各位在实现中遇到什么有趣的问题,或者有更好的建模思路,欢迎随时交流。配电网规划这个方向,越深入越觉得值得琢磨。