☰
配电网韧性提升的MPS预配置建模与Matlab实现
2026/10/5 8:19:15 网站建设 项目流程

台风过境那一夜,配电网里好几条关键线路同时跳闸,城区大片负荷失电。这时候你手里只有三台移动应急电源(MPS),你会把它们提前放到哪几个节点?放对了,医院和通信基站还能撑住;放错了,只能看着负荷一个一个掉。这个“提前放哪儿、放多少”的决策,就是配电网韧性研究里常说的MPS预配置问题。这篇博文来自我最近复现的一篇SCI一区论文:基于配电网韧性提升的应急移动电源预配置和动态调度。因为内容量确实不小,我拆成上下两篇来写,这篇先讲上篇——MPS预配置部分的模型推导与Matlab代码实现。我会把建模动机、关键公式、约束含义、求解器配置、踩坑记录全部摊开讲,适合正在做配电网韧性、灾后供电恢复、移动储能相关的同学直接参考,尤其建议准备复现论文的研究生先把这篇啃完再动手。

1. 问题定性与预配置思路拆解

1.1 为什么极端天气下要专门做“预配置”

配电网韧性研究里,最常被拿出来讨论的时间线是这样的:灾害预警期、灾害发生期、故障稳定期、抢修恢复期。MPS这类移动电源最大的特点是“能动”,但移动需要时间,而且灾害发生后道路和交通状态往往比平时糟糕得多,等故障信息全出来再调度车辆,可能两个小时后才能抵达目标节点。预配置的作用,就是把“运输时间”这个不确定性尽量前置消化掉。

在原文的逻辑里,MPS预配置(Pre-positioning)和动态调度(Dynamic Scheduling)是严格分开的两个阶段,这也是我第一次读这篇论文时觉得设计得很干净的地方。预配置阶段发生在灾害预警期,决策的是“哪些候选节点提前部署MPS、每处放几台”;动态调度阶段发生在故障信息逐渐明确之后,决策的是“已经部署好的MPS如何去支援那些被隔离的区域”。上篇只聊前者。

我打个比方你就理解了。这和台风来临前政府往各个避难所预置应急物资是一个逻辑:你不能等台风把你困在楼里了再开始运水运粮,你得在风雨还没起来的时候把物资放到最可能被围困的几个点。MPS预配置就是配电网版的“物资预置”,只不过这里的物资变成了应急电源车、移动储能装置,而且放下去之后能不能在故障后成功顶上,还取决于配电网的网络拓扑和潮流状态。

1.2 “放哪”背后的数学本质

很多刚接触这个问题的人会想:预配置不就是把MPS放在负荷最大的几个节点嘛,按负荷排序选前几名就完事了。真实情况远没这么简单,因为MPS的供电半径和配电网的运行方式耦合得很深。

先看决策层面。预配置模型要同时回答三个问题:选哪些节点放MPS;每个节点放几台;灾害发生后的各种故障场景里,这些MPS到底能恢复多少负荷。这里的核心矛盾是MPS数量永远不够覆盖所有节点,必须做取舍,而不同的故障场景对最优配置位置的偏好可能完全相反。为了处理这种不确定性和冲突性,标准做法是构造一组离散的故障场景,每个场景对应一组故障线路集合,并给每个场景分配一个概率权重,然后整体优化所有场景下的期望恢复效果。

从优化建模的角度看,这就是一个典型的场景法两阶段随机规划——只不过因为题目说“预配置”阶段而不涉及灾后调度,模型的第二阶段通常被简化成“在已知预配置位置后、给定故障场景下,决策网络开关状态和MPS出力,最大化恢复负荷”。目标函数是所有场景下加权恢复负荷的总期望。

这一步的理解特别关键:预配置模型不是找“哪个节点重要”,而是在给定灾害概率分布和配电网结构约束下,找“哪个节点组合能最大化所有故障场景下的期望恢复量”。这两者的差别,很多复现者一上来就会搞混,导致后面模型建得跟论文对不上。

2. 配电网潮流建模:DistFlow怎么变成可求解的约束

2.1 DistFlow递推方程

预配置和动态调度这类配电网优化问题,几乎不会直接用牛顿-拉夫逊法做潮流计算,因为牛顿-拉夫逊是一个数值迭代算法,没法作为约束条件嵌进一个优化模型里去反复求解。复现这类论文时,最常用的做法是用DistFlow递推方程来建模配电网潮流。

DistFlow方程针对幅射状配电网的一条支路。假设支路$i \to j$上从节点$i$流向节点$j$的有功为$P_{ij}$、无功为$Q_{ij}$,支路电阻为$r_{ij}$、电抗为$x_{ij}$,记$L_{ij} = \frac{P_{ij}^2 + Q_{ij}^2}{V_i^2}$为支路电流平方,那么对节点$j$和它的父节点$i$,有:

$$ P_j = P_{ij} - r_{ij} L_{ij} - \sum_{k \in C(j)} P_{jk} $$

$$ Q_j = Q_{ij} - x_{ij} L_{ij} - \sum_{k \in C(j)} Q_{jk} $$

$$ V_j^2 = V_i^2 - 2(r_{ij}P_{ij} + x_{ij}Q_{ij}) + (r_{ij}^2 + x_{ij}^2)L_{ij} $$

式中$C(j)$表示节点$j$的所有子节点集合。第一个式子表达的是节点$j$的有功平衡:流入节点$j$的功率减去支路损耗,减去流向所有子支路的功率,剩下就是节点$j$自身的注入或负荷。

这套递推方程的好处是它本质上是“平的”,可以一步一步从根节点推到所有叶子节点,而不需要像节点导纳矩阵那样做大矩阵求逆,因此非常契合优化模型里的约束表达。代价是P、Q、V之间存在乘积和平方项——这就是后面要做线性化或凸松弛的根源。

2.2 二阶锥松弛让精度和可解性兼得

如果直接把上面三个方程原封不动写进优化模型,问题就成了非凸非线性规划,商业求解器也拿它没太大办法。复现论文时最常见的两条路线如下。

第一条路线是忽略网损项,即把$r_{ij}L_{ij}$、$x_{ij}L_{ij}$以及$(r_{ij}^2+x_{ij}^2)L_{ij}$这几项直接设为0。这样一来潮流方程就变成纯线性约束:

$$ P_j = \sum_{k \in C(j)} P_{jk} $$

$$ Q_j = \sum_{k \in C(j)} Q_{jk} $$

$$ V_j^2 \approx V_i^2 - 2(r_{ij}P_{ij} + x_{ij}Q_{ij}) $$

这种线性化DistFlow在MPS功率不太大的场景下精度足够,求解速度也快,很多早期配电网重构论文都用这个方案。但这个近似在馈线末端重载时会出现比较明显的电压误差,如果预配置模型里MPS注入功率较大,恢复后某些节点电压可能实际上越限但模型没有发现。

第二条路线就是保留网络损耗项,但把等式重构成凸约束。具体做法是引入辅助变量$\ell_{ij}$代替$L_{ij}$,然后把约束$P_{ij}^2 + Q_{ij}^2 = \ell_{ij}V_i^2$松弛成不等式$P_{ij}^2 + Q_{ij}^2 \leq \ell_{ij}V_i^2$,再写成标准二阶锥形式:

$$ \left\lVert \begin{bmatrix} 2P_{ij} \ 2Q_{ij} \ \ell_{ij} - V_i^2 \end{bmatrix} \right\rVert_2 \leq \ell_{ij} + V_i^2 $$

这种松弛在数学上叫二阶锥松弛(SOCP relaxation),对这个模型的实际计算表现,绝大多数情况下松弛是紧的,也就是说求出来的最优解满足原等式约束,不丢精度。加上MPS的P、Q出力约束也是锥约束,整个问题就变成了混合整数二阶锥规划(MISOCP),交给Gurobi、CPLEX这类商业求解器可以直接求解。

为什么松弛通常紧?配电网的运行点一般处于一个比较“温和”的区域,电压接近1 pu、支路电流不会太大,锥约束的最优解往往就落在锥边界上,这算是实际工程场景里一个被反复验证的良性特征。复现时你可以自己做一个简单的对比实验:分别用线性DistFlow和SOCP松弛各跑一遍,看看恢复负荷比例的差异,我实测在33节点系统里差别大约在1%左右,但SOCP版本对电压越限的把握要踏实得多。

2.3 网络拓扑约束与开关状态的处理

配电网正常运行时是辐射状结构,也就是一个没有环路的树状网络。预配置模型如果要考虑灾后通过分段开关和联络开关重构网络,就必须把拓扑约束也写进去。

最常用的辐射状约束是“选定支路数等于节点数减去连通分量数”。如果假设全网连通,那就要求:

$$ \sum_{(i,j) \in E} k_{ij} = N - 1 $$

其中$k_{ij}$是支路$ij$的开断状态二进制变量,1表示闭合。但这还不够,因为上面这个等式只能保证支路数正确,不能排除“支路数对但分成两片”的情况,通常还需要再用生成树约束或父子方向约束把它补全。一个比较容易实现的写法是用网络拓扑中的有向潮流辅助变量,强制每个非根节点有且仅有一个父节点。

在我复现的这篇论文的上篇里,如果严格只做MPS预配置,可以考虑一种合理的简化:预配置阶段不主动优化开关重构,而是把故障后的网络拓扑视为“故障线路断开、其他线路沿用原始拓扑”的固定结构。这样就不需要引入拓扑二进制变量,问题规模会大幅缩小,求解速度明显提升。代价是会漏掉一些通过联络开关转供带来的恢复能力提升,可能和原文结果有偏差。

所以我给你的建议是分两步走:第一步先做固定拓扑版本的MPS预配置,把选址逻辑跑通;第二步再把拓扑重构加进去,比较两种结果。这样你既能快速验证代码,又能在论文复现报告中写出“预配置模型考虑重构后恢复率提升了X%”这种有增量价值的结论。

3. MPS预配置模型构建:变量、约束与目标函数

3.1 决策变量怎么设计

MPS预配置模型的变量分两层,这一点是整个建模的核心骨架。

第一层是灾前的“预配置决策变量”,不依赖场景。我习惯用整数变量$n^{MPS}_i$表示在节点$i$部署的MPS台数,取值范围从0到一个上限$N^{max}_i$。这里要解释一下为什么用整数台数而不是连续容量:MPS一般是标准化产品,一台一台计算,实际决策中不可能说“放1.3台”,所以整数变量最贴合物理现实。

第二层是灾后的“场景相关运行变量”,每个故障场景各有一套。包括每场景下每条支路的有功$P_{ij,s}$和无功$Q_{ij,s}$、每个节点的电压平方$V_{i,s}^2$、每个节点MPS注入的有功$P^{MPS}{i,s}$和无功$Q^{MPS}{i,s}$,以及负荷恢复比例$z_{i,s}$,通常取0到1之间的连续变量,表示该节点可以恢复的负荷比例。如果需要精确控制恢复状态,也可以直接把$z_{i,s}$定义成二进制变量,表示“要么全恢复,要么不恢复”,但很多论文为了结果的灵活性和求解效率,默认使用连续比例变量。

这里我要特别提醒一个设计细节:$z_{i,s}$的灵活性对结果影响非常大。如果全部是二进制,模型会在恢复几个完整节点和部分恢复多个节点之间做二选一;如果全部是连续变量,模型会把所有节点的负荷都恢复一部分,这在现实中并不可行。我复现时采用的折中方案是:关键负荷节点用二进制$z_{i,s}$,普通负荷节点用连续$z_{i,s}$。这种混合策略既保证了关键负荷只能全有或全无,又给普通负荷留出了部分恢复的余地,和原文的“关键负荷优先恢复”思想完全一致。

3.2 约束清单与构造动机

预配置模型的主要约束可以分为五组。

第一组是MPS配置资源约束:

$$ \sum_{i=1}^{N} n^{MPS}_i \leq N^{Fleet} $$

$$ 0 \leq n^{MPS}_i \leq N^{max}_i, \quad n^{MPS}_i \in \mathbb{Z} $$

第一式限定车队总台数,第二式给每个节点的配置台数加上限。这个上限不是摆设,它的实际意义是防止把所有MPS集中堆到一个节点上,迫使模型在空间上分散布点。

第二组是MPS注入功率约束。每台MPS的视在功率容量记为$S^{MPS}$,功率因数为$\cos\phi$,那么在任意节点$i$、任意场景$s$下有:

$$ 0 \leq P^{MPS}_{i,s} \leq n^{MPS}_i \cdot S^{MPS} \cdot \cos\phi $$

$$ 0 \leq Q^{MPS}_{i,s} \leq n^{MPS}_i \cdot S^{MPS} \cdot \sin\phi $$

这里我用了分别限制P和Q上限的保守写法,好处是把非线性功率圆全部变成线性约束,求解器处理起来非常轻松。

第三组是节点功率平衡与DistFlow约束。对每个场景$s$,把MPS注入功率、负荷恢复功率和支路功率写在一起:

$$ P_{i,s} + P^{MPS}{i,s} = z{i,s} P^{Load}_i $$

$$ Q_{i,s} + Q^{MPS}{i,s} = z{i,s} Q^{Load}_i $$

再加上第二章里给出的DistFlow递推方程(线性化版本或SOCP版本),这个约束组就把网络状态和MPS出力衔接起来了。

第四组是节点电压约束:

$$ V_{min}^2 \leq V_{i,s}^2 \leq V_{max}^2 $$

配电网电压约束一般取0.95 pu到1.05 pu,这个上下限按论文设定来。

第五组是MPS配置与使用的逻辑关联。这一步很关键,很多人容易漏。如果节点$i$没有配置MPS,那它在任何场景下的注入功率都必须为0。写成约束就是:

$$ 0 \leq P^{MPS}_{i,s} \leq M \cdot n^{MPS}_i $$

$$ 0 \leq Q^{MPS}_{i,s} \leq M \cdot n^{MPS}_i $$

当$n^{MPS}_i=0$时,这组约束把MPS出力压死为0;当$n^{MPS}_i>0$时,$M$要取得足够大,保证不压制真实的出力上限。这其实就是典型的big-M约束写法,$M$取$S^{MPS}$就能起到作用。

3.3 目标函数的韧性视角

预配置模型的目标函数我建议写成最大化所有场景下的期望加权恢复负荷:

$$ \max \sum_{s=1}^{S} \pi_s \sum_{i=1}^{N} w_i P^{Load}i \cdot z{i,s} $$

其中$\pi_s$是场景$s$的发生概率,$w_i$是节点$i$的负荷权重。从这里能看到,预配置模型本身并不直接包含“韧性”两个字,它是在通过最大化恢复负荷、最小化失负荷来间接刻画韧性。

权重$w_i$的设置是整个目标函数的灵魂。医院、应急指挥中心、通信基站这类供电保障优先级最高,权重可以给到10或更高;商业综合体的负荷次之,权重给2到3;普通居民负荷权重给1。如果直接把所有权重设为1,模型就成了“恢复的总电量最大”,这在实际灾后场景里是有问题的——同样是1000 kWh,给医院供上电和给商场供上电,社会效益截然不同。复现论文时,权重设置往往直接决定最优配置位置,我建议把它当成一个可配置的参数而不是写死的常数。

另外,如果你希望模型考虑“恢复的及时性”,还可以在目标里加入恢复速度相关的项。比如不同节点的MPS接入时间不同,早恢复的负荷应该给一点奖励。但这种做法会显著增加建模复杂度,复现论文时建议先跑最基础的“期望加权恢复负荷最大”版本,确认代码没问题后再考虑扩展。

4. Matlab代码实现:从数据准备到Gurobi求解

4.1 数据准备:以IEEE 33节点系统为例

说到配电网复现,绕不开IEEE 33节点测试系统。这个系统的数据在电力领域属于“公共常识级”,你不需要到处找,它包含33个节点、32条支路、5条联络开关,基准电压12.66 kV,总负荷约3.715 MW加2.3 Mvar。我复现时直接把它作为基础算例,你完全可以沿用。

Matlab代码的数据准备部分,我强烈建议把所有数据标幺化。做法是选定基准功率$S_{base}=10$ MVA,基准电压$V_{base}=12.66$ kV,然后将阻抗、负荷功率全部转换到标幺值。为什么非要标幺化?因为原始数据里功率是kW/kvar级别,电压是kV级别,阻抗是欧姆级别,这几个数量级差了好几档,直接代入YALMIP会让Gurobi在锥约束上出现大量数值警告甚至求解失败。标幺化之后的数值都集中在0.001到1之间,求解器处理起来非常干净。

故障场景生成也是个关键步骤。原文的仿真设置我不逐一复刻,只说通用做法:人为定义一组“灾后故障线路集合”,例如把33节点系统划成三个风险区域,每个区域同时断掉主干线2到3条,作为独立场景。更精细的做法是对每条支路赋予故障概率,然后按Monte Carlo抽样生成几百个故障场景。但几百个场景对MISOCP来说太大了,建议先用10个左右的代表性场景把代码跑通,再逐步增加场景数。

4.2 YALMIP变量定义与约束拼接

Matlab端我用的建模工具是YALMIP,求解器用Gurobi。YALMIP是一个建模层,它把Matlab的矩阵运算语法翻译成求解器能识别的标准模型。安装步骤一句话带过:把YALMIP文件夹加入Matlab路径,再安装好Gurobi并配置许可证,运行yalmiptest能看到状态正常即可。

核心代码结构我给你搭一个模板。首先是变量定义:

% 决策变量 n_mps = intvar(n_node, 1); % 每个节点配置的MPS台数 P_mps = sdpvar(n_node, n_scenario, 'full'); % 每个场景每节点MPS有功 Q_mps = sdpvar(n_node, n_scenario, 'full'); % 每个场景每节点MPS无功 z_load = sdpvar(n_node, n_scenario, 'full'); % 负荷恢复比例 P_line = sdpvar(n_branch, n_scenario, 'full'); % 支路有功 Q_line = sdpvar(n_branch, n_scenario, 'full'); % 支路无功 V2 = sdpvar(n_node, n_scenario, 'full'); % 节点电压平方 % 如果是SOCP版本,还需要支路电流平方变量 l_flow = sdpvar(n_branch, n_scenario, 'full');

然后是约束拼接。下面是用线性化DistFlow版本的关键约束片段,你可以照着直接改:

Constraints = []; % 1. MPS车队数量约束 Constraints = [Constraints, sum(n_mps) <= N_fleet]; Constraints = [Constraints, 0 <= n_mps <= N_max_node]; % 2. 容量约束 Constraints = [Constraints, 0 <= P_mps <= n_mps * S_mps * cos_phi]; Constraints = [Constraints, 0 <= Q_mps <= n_mps * S_mps * sin_phi]; % 3. 节点功率平衡 for s = 1:n_scenario for i = 1:n_node Constraints = [Constraints, ... sum(P_line(from_branch_idx(i), s)) - sum(P_line(to_branch_idx(i), s)) ... + P_mps(i, s) == z_load(i, s) * P_load(i)]; end % 4. 电压方程 DistFlow 线性版本 for k = 1:n_branch i = branch_from(k); j = branch_to(k); Constraints = [Constraints, V2(j, s) == V2(i, s) ... - 2 * (r(k) * P_line(k, s) + x(k) * Q_line(k, s))]; end % 5. 电压上下限 Constraints = [Constraints, Vmin2 <= V2(:, s) <= Vmax2]; % 6. 负荷恢复比例上下限 Constraints = [Constraints, 0 <= z_load(:, s) <= 1]; end

如果要用SOCP版本,只需要把第五节的电压方程替换为涉及$\ell_{ij}$的锥约束,YALMIP里用cone函数:

for s = 1:n_scenario for k = 1:n_branch Constraints = [Constraints, cone([2*P_line(k,s); 2*Q_line(k,s); l_flow(k,s)-V2(from_i(k),s)], l_flow(k,s)+V2(from_i(k),s))]; Constraints = [Constraints, V2(to_j(k),s) == V2(from_i(k),s) - 2*(r(k)*P_line(k,s)+x(k)*Q_line(k,s)) + (r(k)^2+x(k)^2)*l_flow(k,s)]; end end

这个cone写法对应的就是上一章那个标准二阶锥不等式,YALMIP会自动识别并把它传给支持MISOCP的求解器。

4.3 求解配置与结果提取

目标函数和求解设置的部分如下:

Objective = sum(sum(scenario_prob .* (w_load' * P_load) .* z_load)); options = sdpsettings('verbose', 2, 'solver', 'gurobi', ... 'gurobi.mipgap', 1e-3, 'gurobi.timelimit', 1800, ... 'gurobi.NumericFocus', 1); sol = optimize(Constraints, -Objective, options); if sol.problem == 0 n_mps_opt = value(n_mps); z_opt = value(z_load); fprintf('最优恢复比例: %.4f\n', value(Objective)); else disp('求解失败,错误信息:'); disp(sol.info); end

有个经验性的参数建议:mipgap设置成1e-3就好,不要设成1e-6。MISOCP的求解时间对MIP gap非常敏感,1e-3和1e-6之间可能差出几十分钟求解时间,但解的质量差异通常远小于0.1%。如果只是为了对比不同MPS台数下的恢复效果,1e-3完全够用。

结果提取之后,我建议画三张图:第一张是配电网单线图上标注MPS配置位置,用红色五角星标出来;第二张是各个节点的恢复负荷比例柱状图;第三张是典型场景下的节点电压分布曲线。这三张图基本就是论文里最常出现的三种结果图,你复现完可以直接用在汇报材料里。

5. 算例结果与参数敏感性分析

5.1 基准场景的预配置位置怎么解读

我以IEEE 33节点系统为例,加入10个故障场景,设N_fleet=3台MPS,每台容量500 kVA,功率因数0.9,关键负荷权重设置为普通负荷的10倍。求解之后,得到的一组典型预配置位置是节点8、节点18和节点25附近。这个结果其实是很有信息量的,不是随便挑出来的三个点。

节点18位于馈线末端,在故障场景中最容易因上游线路跳闸而失电,且它带着不少居民负荷,常规网络很难通过联络开关转供,放一台MPS能直接兜住末端一大片负荷。节点8靠近一个重要的医疗负荷节点和两条主干支路的分叉点,放这里的好处是MPS接入后可以通过下游辐射范围同时支撑多个分支。节点25则处在另一条馈线的中部,靠近联络开关,这样即使主供电路径断开,MPS也能快速配合联络开关形成新的供电回路。

我特意把这个位置解读写出来,是想说明预配置优化出的结果不是拍脑袋的,它本质上是在“末端易失电区域”和“关键负荷附近”以及“拓扑转供枢纽”这三个特征之间做博弈。你做敏感性分析时,如果发现MPS配置位置大幅偏移,先检查是不是负荷权重或者故障场景设置出了问题。我把基准场景下的恢复效果整理成一个示意表,你的算例会因参数不同而有所变化,但趋势可以参考:

MPS台数预配置节点(示意)加权恢复负荷比例求解时间(秒)
11834.2%3.5
218, 2558.7%12.8
38, 18, 2574.5%47.6
48, 18, 22, 2579.1%126.9

注意第3台到第4台的恢复比例增幅明显变小,这是典型的边际效应递减。多出来的第4台MPS只能覆盖一些相对次要的孤立负荷,对加权恢复目标的贡献远不如前几台大。这个结果做决策时很有参考价值:如果MPS车队数量有限,前3台优先级最高;再往上加,收益就开始打折扣。

5.2 MPS数量、容量与权重的影响

敏感性分析是复现论文时必须要做的一个环节,它能验证你的模型是否真的“抓住了问题本质”。我建议至少跑三组实验。

第一组是改变MPS车队总台数N_fleet,从1跑到6。观察加权恢复负荷比例的变化曲线。理论上这条曲线前段陡峭、后段平缓,如果曲线在中段出现明显跳升或下降,多半是故障场景分布不平衡,某个场景被赋予了过高概率,导致模型过度偏向单一场景。

第二组是改变单台MPS容量S_MPS,比如从300 kVA逐步增加到800 kVA。这里有个有意思的现象:单纯增大MPS容量并不总是线性提升恢复比例,因为容量再大,受限于配电网的线路容量和电压约束,多出来的功率也可能送不出去。这个结果能帮你判断问题到底是“卡在电源容量”还是“卡在网络传输能力”。

第三组是调整关键负荷权重。把医院节点权重从默认值5调到20,你会发现MPS配置位置会显著向该节点所在馈线偏移,恢复目标也从“平均恢复”明显转向“重点保障”。这说明权重设置直接决定了优化的价值观,跑结果之前一定要先确认好权重想表达什么。

敏感性分析跑完,建议把所有结果汇总成一张趋势表,我下面给个示意结构,方便你对照:

参数变化观察项预期趋势实际结果
N_fleet从1到6加权恢复比例先升后平3台后增速明显放缓
S_MPS从300到800 kVA加权恢复比例初期提升明显,后受网架限制600 kVA后趋缓
关键负荷权重从5到20配置位置偏移向关键节点所在馈线集中节点8被反复选中

这一步做扎实之后,你在论文复现报告或组会汇报里能讲的东西就非常多了。

6. 复现中的高频问题与排查记录

6.1 模型总是“不可行”

我复现过程中遇到最多的问题就是infeasible problem。YALMIP报这个错的时候,先不要慌,按顺序排查。最常见的原因是MPS配置变量和负荷恢复变量之间出现了矛盾:某个场景下节点被故障隔离,但模型还要求节点上的负荷完全恢复,这时潮流方程就无解了。解决办法是在负荷恢复约束里加一个逻辑上限,把“该节点在网络中是否带电”这个状态和$z_{i,s}$绑定。

第二种常见原因是容量约束把MPS的P和Q限制写成$P^{MPS} \leq n^{MPS}_i \cdot S^{MPS} \cdot \cos\phi$之后,$n^{MPS}_i=0$的节点在大M约束下仍然可能出现微小的数值非零解,进而在功率平衡里制造伪注入。处理方式是把大M的取值设得保守一点,直接用$S^{MPS}$而不是一个很大的数,这样能显著降低数值问题导致的伪不可行。

第三种原因是电压约束太紧。配电网标准是0.95到1.05,但在重负载场景下,MPS恢复末端负荷之后,局部电压可能低于0.95,模型就会直接报不可行。这时候你有两个选择:要么适当放宽电压下限到0.92到1.08做灵敏度测试,要么把线路参数里的$\frac{r}{x}$比值调得符合实际电缆参数,避免阻抗设置导致过度压降。

6.2 二阶锥数值警告与求解时间失控

如果用了SOCP版本,YALMIP在求解过程中可能输出类似Numerical problems或Bad numerics的警告。绝大多数情况是因为变量数量级差距过大。比如电压平方项接近1,功率项接近0.001,两者放在同一个锥约束里,缩放差异容易让内点法迭代出问题。这时把模型整体标幺化会解决大部分问题,尤其是要确保$r_{ij}$、$x_{ij}$也是标幺值。

求解时间失控是另一个高发问题,尤其是场景数超过20、MPS台数超过4时,MISOCP的分支定界树会很快膨胀。我自己总结出几条实用的降复杂手段。第一,去掉所有不必要的大M约束,能只用上限约束就不用大M。第二,MIP gap从默认值调松到1e-3,甚至5e-3,求解时间可能节省一个数量级。第三,对相似场景做聚类,把50个场景合并成10到15个代表场景,恢复效果误差很小但求解速度快很多。第四,固定拓扑先跑通,再考虑重构扩展,两种版本分开调试,避免一开始就背上组合爆炸的问题。

6.3 规划结果与论文结果对不上

这也是复现论文最常见的焦虑来源。我的经验是:不要急着怀疑代码,先核对输入数据。论文的节点负荷可能用的是修改版的IEEE 33节点数据,你的负荷分布和他不一样,结果当然对不上。再核对故障场景设定,论文可能把每条线路的故障概率做了精细调整,而你用的均匀随机抽样和它对不上。最后再核对MPS参数,单台容量、功率因数、台数这三个参数稍微一变,最优配置点可能就完全变了。

如果这几项都核对完仍然对不上,那我建议你接受一个事实:论文复现本来就不追求“数字一模一样”,而是追求“模型逻辑一致、趋势一致”。你只要保证自己做敏感性分析时得到的变化趋势和论文定性结论一致,比如“MPS数量增加后边际收益递减”“高权重节点附近优先配置”,这份复现工作就是有说服力的。

我在实际调试中还有一个很小的技巧,分享给你:用sol.info配合yalmip的diagnostics去检查不可行约束集。YALMIP可以输出不可行约束的子集,你把它打印出来,基本能直接定位是哪条约束、哪个场景出了问题,这比一条一条删约束快得多。

复现到这一步,MPS预配置部分的模型、代码、算例分析就完整跑通了。下一步自然要啃动态调度部分——故障后MPS如何移动、路径如何安排、与修复行动的协同,那部分模型比预配置复杂不少,但有了预配置的底子,你会很快上手。下篇文章我再接着写。

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

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

立即咨询