配电网韧性提升的MPS预配置建模与Matlab实现 台风过境那一夜配电网里好几条关键线路同时跳闸城区大片负荷失电。这时候你手里只有三台移动应急电源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}^2x_{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_{i1}^{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}_i0$时这组约束把MPS出力压死为0当$n^{MPS}_i0$时$M$要取得足够大保证不压制真实的出力上限。这其实就是典型的big-M约束写法$M$取$S^{MPS}$就能起到作用。3.3 目标函数的韧性视角预配置模型的目标函数我建议写成最大化所有场景下的期望加权恢复负荷$$ \max \sum_{s1}^{S} \pi_s \sum_{i1}^{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)^2x(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_fleet3台MPS每台容量500 kVA功率因数0.9关键负荷权重设置为普通负荷的10倍。求解之后得到的一组典型预配置位置是节点8、节点18和节点25附近。这个结果其实是很有信息量的不是随便挑出来的三个点。节点18位于馈线末端在故障场景中最容易因上游线路跳闸而失电且它带着不少居民负荷常规网络很难通过联络开关转供放一台MPS能直接兜住末端一大片负荷。节点8靠近一个重要的医疗负荷节点和两条主干支路的分叉点放这里的好处是MPS接入后可以通过下游辐射范围同时支撑多个分支。节点25则处在另一条馈线的中部靠近联络开关这样即使主供电路径断开MPS也能快速配合联络开关形成新的供电回路。我特意把这个位置解读写出来是想说明预配置优化出的结果不是拍脑袋的它本质上是在“末端易失电区域”和“关键负荷附近”以及“拓扑转供枢纽”这三个特征之间做博弈。你做敏感性分析时如果发现MPS配置位置大幅偏移先检查是不是负荷权重或者故障场景设置出了问题。我把基准场景下的恢复效果整理成一个示意表你的算例会因参数不同而有所变化但趋势可以参考MPS台数预配置节点示意加权恢复负荷比例求解时间秒11834.2%3.5218, 2558.7%12.838, 18, 2574.5%47.648, 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}_i0$的节点在大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如何移动、路径如何安排、与修复行动的协同那部分模型比预配置复杂不少但有了预配置的底子你会很快上手。下篇文章我再接着写。