配电网N-1扩展规划:基于MILP的Matlab建模与工程实践
2026/9/16 8:47:40 网站建设 项目流程

做配电网规划的工程技术人员,大概率都有过这种经历:花两周时间用最大负荷法把未来五年的网架方案排出来,兴冲冲送去评审,结果专家一句“N-1过了吗”就把方案打回重做。我之前在一个县城配网项目里就吃过这个亏——新建了三条馈线,容量全部按远期负荷选型,结果其中一条馈线出口故障时,下游两个台区的转供通道根本不够,电压直接跌到0.88。后来我换了个思路:把N-1约束从“事后校验”挪进“规划模型”里,用Matlab把配电网N-1扩展规划建成了混合整数线性规划(MILP),让求解器一次性找出既满足投资约束又通过N-1安全校验的网架方案。

这篇内容适合正在做配电网网架规划、可靠性评估或毕业设计里涉及N-1准则的同学,也适合想从“手算潮流校验”过渡到“优化建模规划”的工程师。我会从数学模型、DistFlow线性化、辐射状约束、Matlab代码框架、算例结果和踩坑记录几个角度展开,尽量把每个关键选择背后的“为什么”讲清楚。

1. N-1扩展规划到底在解决什么问题

1.1 传统配电网规划流程的漏洞

传统配电网规划的常规流程是:先做负荷预测,再根据最大负荷选导线截面和变压器容量,接着手拉几条馈线形成一个辐射状网架,最后用潮流软件算一下正常态下是否过载、电压是否越限。这套流程最大的问题在于:N-1校验和网架方案是分开做的。方案是先拍脑袋定下来的,校验只是事后验证。一旦N-1不过,就得靠人工经验去加联络线、加分段开关,改完再验一遍,循环往复,既慢又容易漏。

举个例子,一条10kV馈线上带了8个台区,所有导线都按远期负荷选好了,看上去很稳妥。可一旦这条馈线出口断路器检修或故障跳闸,这8个台区全靠联络线转供。此时联络线的容量够不够、末端电压跌不跌、有没有第二条转供路径,全部要重新算。很多时候算下来发现转供容量不够,只能再砸钱改联络线或者新建通道。这个“规划→校验→整改→再校验”的循环,本质上是把安全约束当成了后验条件。

N-1扩展规划要做的,就是把这个循环倒过来:在优化模型里直接加入N-1安全约束,让求解器在生成网架方案时就把“任意一条支路退出后系统依然安全”作为硬性前提。这样得到的方案不是“先规划再验证”,而是“约束之内求最优”。

1.2 N-1约束进入优化模型后的变化

把N-1从校验变成约束,看似只是措辞变化,模型复杂度却上了一个量级。原因很简单:正常状态只有一套潮流约束,而N-1意味着每一个可能故障的支路都对应一套额外的潮流约束。支路数量十几条时还没什么感觉,到了几十条上百条,变量和约束数量直接翻几十倍,问题性质也变成了含0-1整数变量的混合整数规划。

配电网的N-1和输电网的N-1侧重点不太一样。输电网强调静态安全分析和潮流转移,发电机出力要重新调整;配电网则更关注“断了一条线之后,剩下负荷能不能通过联络开关转带出去”。所以配电网N-1扩展规划里有两件事必须建模清楚:一是故障后的拓扑连通性,二是故障后的潮流可行域。前者靠辐射状拓扑约束和网络连通约束保证,后者靠每个故障场景下的DistFlow潮流约束和容量、电压约束保证。这也是整个模型的核心骨架。

2. 数学模型:从DistFlow到可求解的MILP

2.1 决策变量与目标函数

N-1扩展规划的决策变量分两层。第一层是网架投资变量,也是最核心的0-1整数变量:候选线路建还是不建。第二层是运行变量,包括正常状态下每条支路的有功潮流、无功潮流、节点电压平方值,以及每个N-1故障场景下对应的潮流和电压变量。

目标函数最常见的写法是投资年费用最小化:

[ \min \sum_{e \in C} c_e x_e ]

其中 (c_e) 是候选线路e的投资费用,(x_e \in {0,1}) 表示是否建设。如果想更精细,还可以在目标里加上正常状态下的网损费用、运维费用,甚至把故障场景下的期望缺供电量作为惩罚项。但要注意,网损费用在DistFlow里是二次项,直接加进来会把问题变成MIQP(混合整数二次规划)。我个人的习惯是:第一版先跑纯MILP,只把投资费用放进目标函数,把N-1约束全部作为硬约束;方案跑出来之后,再用确定性潮流去评估这个方案的网损。

这么做的原因很实际:N-1约束已经让问题规模大得离谱了,目标函数里再带二次项,求解时间会成倍增长。如果你做的是几十条支路的小系统,用Gurobi跑MIQP问题不大;如果面向实际馈线组,建议还是先线化处理。

2.2 DistFlow的线性化处理

配电网潮流计算里,DistFlow(支路潮流模型)是特别适合辐射状配网的模型,标准形式是:

[ P_{ij} - r_{ij} l_{ij} = \sum_{k \in c(j)} P_{jk} + P_j^D ]

[ Q_{ij} - x_{ij} l_{ij} = \sum_{k \in c(j)} Q_{jk} + Q_j^D ]

[ u_j = u_i - 2(r_{ij} P_{ij} + x_{ij} Q_{ij}) + (r_{ij}^2 + x_{ij}^2) l_{ij} ]

其中 (u_i = V_i^2),(l_{ij} = I_{ij}^2)。第三项公式里的 ((r_{ij}^2 + x_{ij}^2) l_{ij}) 是网损引起的电压降落,非线性很强。

在N-1扩展规划里,如果保留完整的DistFlow,整个模型高度非凸且非线,绝大多数求解器根本啃不动。工程上常用的是线性化DistFlow,直接忽略网损项,把最后一条方程简化成:

[ u_j = u_i - 2(r_{ij} P_{ij} + x_{ij} Q_{ij}) ]

同时将 (l_{ij}) 相关的式子全部去掉。这样节点功率平衡方程变成线性等式,电压降落方程也变成线性等式,整个网络约束就彻底线性了。

电压幅值约束也要转换一下。因为模型里用的是 (u_i = V_i^2),所以约束 (V_{\min} \le V_i \le V_{\max}) 写作:

[ V_{\min}^2 \le u_i \le V_{\max}^2 ]

容量约束同样可以线性化。视在功率约束 (P_{ij}^2 + Q_{ij}^2 \le S_{ij}^2) 是非线性的,但我们可以用有功和无功分别限界来近似:

[ -P_{\max} x_e \le P_{ij} \le P_{\max} x_e ]

[ -Q_{\max} x_e \le Q_{ij} \le Q_{\max} x_e ]

更精细的做法是用正八边形或正十六边形去逼近交流潮流可行域,但配电网规划阶段的数据精度通常没那么高,有功无功分别限界已经够用了。这条线性化路径也是目前大多数配电网扩展规划论文的实际做法。

2.3 辐射状拓扑约束的等价表达

配电网规划里有个铁律:正常运行状态必须是辐射状。这个约束看起来简单,建模却很讲究。直接检查“任意两节点之间只有一条路径”在数学上没法写成线性表达式,需要用单商品流(single-commodity flow)或者生成树约束来替代。

我常用的是单商品流法。给每个负荷节点定义一个单位虚拟需求,变电站节点是唯一供给源,然后要求:

  • 每条投运走廊上允许流过虚拟流量,候选线路虚拟流量上限和它的建线变量 (x_e) 挂钩;
  • 每个非源节点净流入的虚拟流量恰好等于1;
  • 所有投运走廊数量之和等于节点数减1。

如果投运走廊数是 (N_{\text{bus}} - 1),且每个节点都能收到1单位虚拟流,那么整个网络一定连通且无环,也就是一棵生成树。

注意一个细节:虚拟流量是有方向的,但规划阶段我们并不知道潮流最终方向。所以我在建模时会把每条走廊拆成两个有向弧,分别定义虚拟流变量,两个方向的虚拟流之和不能超过 (N_{\text{bus}} \cdot x_e)。这样既不会限制转供方向,又能保证虚拟流严格受走廊投运状态控制。

这里还有个小坑:有人只在正常状态加辐射状约束,N-1故障场景下不加,结果故障后网络变成孤岛也照样“通过”了约束。实际N-1故障场景下网络也必须是辐射状且连通的,只不过这个辐射状是在“去掉故障支路后”的剩余网络上成立的。我后面会在踩坑部分详细讲。

2.4 N-1场景约束的统一建模

N-1场景的建模是整个模型里最烦的部分,但逻辑其实很简单:对每一条支路,都假设它退出运行,然后要求剩余网络依然满足潮流约束

设支路集合为 (E),对每条支路 (k \in E) 建立一个故障场景。场景 (k) 中支路 (k) 强制断开:

[ P_k^{(k)} = 0, \quad Q_k^{(k)} = 0 ]

其余支路按照正常状态下的投运变量 (x_e) 决定是否可用。如果某条候选线路最终没有建设((x_e=0)),那它在所有场景里都是断开的,不影响可行域。

这里有个容易纠结的点:如果 (x_k = 0),即故障场景k对应的支路本身就没建,那这个场景其实是“一条不存在的线路故障”,听着很蠢。但从建模角度讲,这个场景依然会让变量复制一份、约束复制一套,白白浪费计算资源。我第一版代码就老老实实把每条支路的场景都建了,后来发现系统大了场景数翻倍吃不消。更聪明的做法是只在 (x_k) 被激活时才需要严格建模场景k,可以通过大M约束把 (x_k=0) 时场景k的潮流变量全部置零。不过这会引入额外逻辑,代码复杂度提高不少。对小规模算例,全部枚举反而更省心。

3. Matlab代码实现:场景循环与求解器选型

3.1 核心代码框架

我在Matlab里用的是YALMIP建模,求解器选Gurobi。YALMIP的好处是把“变量声明、约束拼接、目标函数定义”从底层矩阵构造里解放出来,尤其适合这种多故障场景循环建模的需求。如果只是几十条支路的小系统,用MATLAB自带的intlinprog也能跑,但矩阵构造会让你怀疑人生,后面踩坑部分细说。

下面这个代码框架就是我实际跑通N-1扩展规划的骨架,节点1作为变电站节点,其余为负荷节点。数据部分按实际系统填即可。

%% 配电网N-1扩展规划 - YALMIP MILP % 节点1为变电站节点,其余为负荷节点 % line_from, line_to : 支路首末端节点编号 % line_R, line_X : 支路电阻、电抗 % line_cap : 支路容量上限 % line_cost : 候选支路投资费用,已有支路填0 % line_exist : 1-已有支路,0-候选支路 % P_D, Q_D : 各节点有功、无功负荷 N_bus = length(P_D); N_line = length(line_from); %% 决策变量 % 网架投资变量 x = binvar(N_line, 1); Constraints = [Constraints, x(line_exist == 1) == 1]; % 正常状态变量:每条支路两个方向 P_pos = sdpvar(N_line,1); P_neg = sdpvar(N_line,1); Q_pos = sdpvar(N_line,1); Q_neg = sdpvar(N_line,1); u = sdpvar(N_bus,1); % N-1场景变量 Pp = cell(N_line,1); Pn = cell(N_line,1); Qp = cell(N_line,1); Qn = cell(N_line,1); U = cell(N_line,1); for k = 1:N_line Pp{k} = sdpvar(N_line,1); Pn{k} = sdpvar(N_line,1); Qp{k} = sdpvar(N_line,1); Qn{k} = sdpvar(N_line,1); U{k} = sdpvar(N_bus,1); end

3.2 正常状态与N-1场景的变量组织

接下来是约束构造。为避免重复代码,我习惯把“给定一组潮流变量和电压变量时,网络必须满足的运行约束”封装成一个函数,正常状态和每个N-1场景都调用它。这个函数核心包含三件套:节点功率平衡、线路压降、线路容量,外加前面说的辐射状拓扑约束。

%% 网络约束函数的主体逻辑 % 输入:P_pos, P_neg, Q_pos, Q_neg, u, x % 输出:约束集合 % 节点功率平衡(对每个节点j) % 流入 - 流出 = 负荷 Constraints = []; for j = 1:N_bus flow_in = 0; flow_out = 0; for e = 1:N_line if line_to(e) == j flow_in = flow_in + P_pos(e) - P_neg(e); end if line_from(e) == j flow_out = flow_out + P_pos(e) - P_neg(e); end end Constraints = [Constraints, flow_in - flow_out == P_D(j)]; end % 线路压降(线性化DistFlow) for e = 1:N_line i = line_from(e); j = line_to(e); P_net = P_pos(e) - P_neg(e); Q_net = Q_pos(e) - Q_neg(e); Constraints = [Constraints, ... u(j) == u(i) - 2 * (line_R(e) * P_net + line_X(e) * Q_net)]; end % 电压上下限 Constraints = [Constraints, 0.95^2 <= u <= 1.05^2]; % 线路容量约束(两个方向分别限制) for e = 1:N_line Constraints = [Constraints, 0 <= P_pos(e) <= line_cap(e) * x(e)]; Constraints = [Constraints, 0 <= P_neg(e) <= line_cap(e) * x(e)]; Constraints = [Constraints, 0 <= Q_pos(e) <= line_cap(e) * x(e)]; Constraints = [Constraints, 0 <= Q_neg(e) <= line_cap(e) * x(e)]; end

根据支路节点编号判断潮流方向时,如果 (P_{pos}(e) - P_{neg}(e)) 为正,说明功率从 (line_from(e)) 流向 (line_to(e));为负则相反。这样N-1场景下转供路径出现反向潮流也能被线性约束干净地表达出来,不用强行规定“潮汐方向”。

然后就是N-1场景循环。每个场景k里,支路k被强制断开,其余支路仍然由投运变量x控制是否可用:

%% 正常状态约束 Constraints = [Constraints, network_constraints(P_pos,P_neg,Q_pos,Q_neg,u,x)]; %% N-1场景约束 for k = 1:N_line Constraints = [Constraints, network_constraints(Pp{k},Pn{k},Qp{k},Qn{k},U{k},x)]; % 故障支路强制退出 Constraints = [Constraints, ... Pp{k}(k) == 0, Pn{k}(k) == 0, ... Qp{k}(k) == 0, Qn{k}(k) == 0]; end %% 目标函数:投资费用最小 Objective = line_cost' * x; %% 求解 ops = sdpsettings('solver', 'gurobi', 'verbose', 2); sol = optimize(Constraints, Objective, ops); x_opt = value(x);

这里network_constraints是一个自定义函数,除了上面说的功率平衡、压降、容量之外,还需要把辐射状拓扑约束也放进去。辐射状约束我用虚拟流变量实现,为了保持代码简明,这里不展开写具体句法,核心思路就是每个非源节点必须净流入1单位虚拟流量,且虚拟流只能流过 (x_e=1) 的走廊。

3.3 求解器选型建议

求解器选择是很多人会忽略的关键点。我做过一个对比,同一个6节点算例,分别在MATLAB自带的intlinprog、YALMIP+Gurobi、YALMIP+CPLEX下面跑,结论很直接:小算例大家都能秒解,但规模一上来立刻分高下。

方案优点缺点
YALMIP + Gurobi建模快、求解快、支持复杂约束,学术免费商用需授权
YALMIP + CPLEX与Gurobi同级授权管理繁琐
YALMIP + intlinprog无需额外安装求解器节点多时求解慢
纯intlinprog手工建模不依赖YALMIP矩阵构造极其痛苦,极易出错

我的建议很明确:如果你的机器上装了YALMIP,优先选Gurobi;如果没有,intlinprog在小系统上凑合能跑,但一到几十条支路加几十个N-1场景,基本就是“等半天出不了结果”。别把时间浪费在跟求解器较劲上。

4. 一个6节点系统的算例测试

4.1 测试系统参数

为了验证模型逻辑,我搭了一个6节点系统。节点1是10kV变电站母线,两条馈线分别从1号节点引出:左馈线走1-2-3,右馈线走1-4-5。这样截取的好处是,接入同一变电站母线的不同馈线之间做N-1互济,正好是配电网最常见的“站内联络”场景。

系统数据和候选走廊如下:

支路首端末端r(Ω)x(Ω)容量(MVA)状态
1120.110.124.0已有
2230.160.183.0已有
3140.110.124.0已有
4450.160.183.0已有
5340.200.222.5候选
6350.220.242.5候选

节点负荷:

节点有功(MW)无功(MVar)
20.60.3
31.20.6
40.80.4
51.00.5

候选线路投资费用:支路5(3-4)为50万元,支路6(3-5)为60万元。目标是在满足N-1准则的前提下总建设费用最小。

4.2 规划结果与N-1校验对照

模型求解结果非常干净:只建设候选支路6,也就是3号节点和5号节点之间的联络线,总投资60万元。支路5(3-4)不需要建设。

为什么是3-5而不是3-4?我们逐一分析故障场景:

  • 支路1故障(1-2断开):2和3失电,此时需要从右馈线转供。路径是1-4-5-3,这依赖3-5联络线。如果只建3-4,则路径是1-4-3,也能给3供电,但2号节点依然失电——因为2只有1-2这一条上游路径。所以支路1故障时,无论建3-4还是3-5,2号节点都救不回来。这说明这套模型暴露了一个现实问题:如果变电站出线只有两回,且每条馈线首端故障,确实可能无法满足N-1。实际工程里需要上级变电站提供多回出线或母联备自投,这属于变电站级N-1范畴。
  • 支路2故障(2-3断开):3号节点失电,可经1-4-5-3转供,依赖3-5。
  • 支路3故障(1-4断开):4和5失电,可经1-2-3-5转供5,依赖3-5;4号节点则必须通过3-4或5-4转供。如果只建3-5,4号节点只剩5-4一条路,而5可以从2-3-5供电,所以4可以通过5-4带起来。也就是说,只建3-5时4能通过5反送,这条路径依然成立。
  • 支路4故障(4-5断开):5号节点失电,可经1-2-3-5转供,依赖3-5。

对比一下不建任何联络线的原网络:支路2故障时3号节点失电,支路3故障时4、5号节点全部失电,N-1校验直接失败。规划模型选出3-5后,除支路1这类变电站出口故障外,其余支路故障时负荷都能通过联络线转带,这就是N-1扩展规划的价值。

这个算例规模小,但完整呈现了“拓扑连通性约束”和“故障场景潮流约束”的相互作用。一个看似更短的联络线(3-4)反而不是最优,因为3-5能同时覆盖更多故障场景的转供需求。这就是优化模型和人工经验的差异:人容易盯着“就近”原则,模型会穷举所有故障场景找全局最优。

5. 实践中的踩坑与处理

5.1 场景冗余导致计算量虚高

第一次实现时,我把所有支路场景都建了全套变量。当系统里有20条候选线路、20条已有线路时,N-1场景数就是40,每个场景都要复制一套潮流变量和虚拟流变量,模型总变量轻松破万。但仔细想一下:如果某条候选线路 (x_e=0),它根本没投运,给它建N-1场景纯属浪费。

我的改造方案是用大M把场景k的变量和 (x_k) 挂钩:当 (x_k=0) 时,场景k不强制那套变量的可行性;但这样做逻辑约束会绕,容易写错。后来我在工程上是直接分成两段处理:先跑一轮不带“不存在线路故障场景”的松弛模型,识别出哪些候选线路大概率会投运,再针对这些线路建立完整N-1场景做精确求解。这样做虽然理论上有迭代误差,但工程上收敛快,而且规划项目的决策精度要求远没到“需要严格证明最优”的程度。

5.2 辐射状约束与N-1场景冲突

这是我最开始犯的一个经典错误。我只在正常状态加了辐射状约束,N-1场景里没有加,结果某个故障场景下节点3变成了孤岛,但模型依然“满足约束”。后来检查结果才发现,故障场景的功率平衡方程里,孤岛节点的负荷没人供,但因为虚拟流约束缺失,我根本没判断“这个节点通不通电”。

正确做法是:N-1场景k里,故障支路k被强制断开之后,剩余网络依然要满足“全节点连通且无环”的辐射状条件。具体实现上,还是用虚拟流法,只是虚拟流不能流过故障支路k。这样就把“转供路径存在”纳入了优化。如果漏掉这层约束,N-1规划方案很可能是“纸面过校、实际转供失败”。

5.3 电压约束过紧导致无解

我一开始把N-1场景的电压下限也设成0.95,结果多个算例直接infeasible。原因是故障后网络末端电压跌落本来就比正常状态剧烈,0.95的约束对配电网N-1来说过于严格。翻阅一些配电网规划导则和实际工程案例,N-1故障后允许电压短时跌到0.90甚至0.85,再靠有载调压和无功补偿恢复。

所以在模型参数设置上,我最终会把正常状态和N-1场景的电压约束分开处理:正常状态用0.93~1.07(按各地导则),N-1场景放宽到0.88~1.07。这样模型更容易有解,也更符合实际运行规程。不同地区的电压合格标准有差异,但“场景不同、约束不同”这个思路是通用的。

5.4 求解规模与intlinprog的极限

如果你没有Gurobi或CPLEX,硬用intlinprog跑这个模型,会感受到什么叫“组合爆炸”。30条支路、30个N-1场景,每个场景都复制一套潮流变量和虚拟流变量,intlinprog的节点搜索速度会断崖式下降。我在一台i7的笔记本上测过,15条支路以内intlinprog还能几分钟内搞定,超过20条基本要按小时算。

替代方案有两个:一是换Gurobi/CPLEX,二是在模型层面做故障场景削减。场景削减的思路很简单:不是所有支路发生N-1后影响都一样大,末端小分支退出运行和主馈线出口退出运行完全是两个量级。先用灵敏度分析把“关键支路”筛出来,只对关键支路建详细故障场景,其余支路用正常状态的容量裕度粗略校验。这样精度损失不大,但求解时间能降一个数量级。

6. 从N-1扩展规划延伸开去

6.1 分布式电源改变了N-1转供逻辑

传统N-1扩展规划的前提是:故障后负荷只能靠电网侧转供。可一旦配电网里接入了分布式光伏、风电或储能,N-1场景下这些分布式电源能不能作为“孤岛电源”给本地负荷供电,就变成一个有争议但又绕不开的问题。

有的规划人员把分布式电源视为“负负荷”,在故障场景里直接减掉一部分负荷需求,这其实是高估了,因为光伏夜间出力为零,风电波动也大。稳妥的做法是把分布式电源分成两类:具有黑启动能力且能离网运行的,允许在N-1场景中给关键负荷供电;不能离网运行的,则只在正常状态参与潮流平衡。把这个逻辑写进模型,N-1扩展规划就变成了“多状态电源-网架联合优化”,复杂度进一步上升,但也更贴近实际。

6.2 从确定性N-1到N-1-1风险评估

N-1准则的默认假设是“故障只发生一次”,这在单一元件故障概率较低的输电网里成立。配电网设备老旧、外部环境复杂,有时候会出现“检修期间另一条线又跳闸”的双重故障场景,也就是N-1-1。

N-1-1的完整枚举复杂度远高于N-1:支路数量从 (N) 变成 (N^2) 量级,几乎不可能全部建模。实际做法是用概率风险代替确定性准则:给每条支路设定一个故障概率,用机会约束或失负荷期望值约束来筛选“最值得考虑的双重故障组合”,而不是把全部组合都枚举进去。这个方向这几年研究热度很高,也是N-1扩展规划从“安全校核”走向“风险评估”的一条自然路径。

如果你做的是工程规划项目,我建议还是老老实实先把N-1模型跑通跑稳,再琢磨这些进阶方向——确定性N-1做扎实了,加概率、加分布式电源,都只是在这个MILP骨架上添砖加瓦而已。

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

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

立即咨询