配电网韧性提升中的MPS预配置建模与Matlab实现 去年我在复现一篇SCI一区论文时第一次把“MPS预配置”这四个字真正吃透。简单说配电网韧性提升就是让电网在台风、冰灾这种极端事件面前不仅扛得住还能快速恢复而MPS——也就是应急移动电源/移动储能装置——最关键的动作不是灾后匆匆赶路而是灾前把电源放到最可能救命的节点上。这个“灾前放哪里、放几台”的决策就是MPS预配置。这篇内容围绕Matlab代码实现展开重点拆解《基于配电网韧性提升的应急移动电源预配置和动态调度》的上半部分也就是预配置建模与仿真复现。适合正在做配电网韧性、移动储能调度、SCI论文复现的电力专业研究生和工程师参考。这系列工作分上下两部分上篇解决“提前布局”的问题下篇解决“灾害发生后已经出发的MPS怎么动态走位、什么时间接入系统”的问题。两个问题必须放在一起看但预配置是第一步也是最容易在复现时被低估的一步。你后面做的动态调度再漂亮如果预配置阶段把MPS放错了节点恢复效果直接打折这是我在实测复现里最深的体会。1. 灾害场景下的配电网韧性缺口为什么MPS预配置值得单独深挖1.1 MPS在韧性提升链条中的位置配电网的传统可靠性指标比如SAIDI、SAIFI衡量的是长期平均停电水平。但极端灾害不一样台风过境可能让几十条线路同时故障变电站失压部分区域直接形成孤岛。韧性强调的是系统在极端事件冲击下维持功能、快速恢复的能力它关心的不是“一年平均停几次电”而是“一场大灾下来关键负荷能不能供上恢复速度有多快”。在这次复现的项目里MPS指的是移动应急电源可以是移动储能车、应急发电车也可以是一体化移动储能装置。它最大的特点就是“可移动”灾害发生前它可以在配电网里选取若干个节点提前接入灾害发生后它又可以被调度到故障区域临时供电。所以MPS在韧性提升链条中处于一个非常有价值的位置——你不必为了小概率灾难在每座变电站都建永久电源只需要准备几台MPS放在最合理的位置就可以在灾后覆盖多条关键路径。1.2 预配置与动态调度的分工很多第一次接触这个方向的同学容易把预配置和动态调度混为一谈。我复现时把这个问题拆成两阶段来理解。第一阶段是预配置发生在灾害来临前。此时气象预警已经发出但具体哪条线路会断、故障范围多大还不确定。决策者要根据预测信息把有限的MPS预先配置到备选节点上并确定配置的容量类型。这个阶段的特点是“决策之后无法改变”MPS一旦落地位置就固定了后续只有等灾后才能再次移动。第二阶段是动态调度发生在灾害发生后。此时故障场景逐渐清晰MPS可以沿着道路网络向负荷点移动但受到交通状况、移动时间和电量约束的影响调度策略需要动态更新。这和预配置最大的区别在于——动态调度是“在信息逐步揭示中持续决策”预配置是“在不确定性未揭示时一次性决策”。这也就解释了为什么论文标题把两者并列预配置决定了韧性提升的“上限”动态调度决定这个上限能达到“多少”。我在复现过程中把预配置结果单独做了一套算例就是因为后续动态调度要用到这些位置信息作为输入如果这里就出错下篇根本推不动。1.3 我复现时对“预配置”的三层含义的理解第一层是位置选择在配电网的所有节点中哪些节点适合放MPS不是每个节点都适合比如有些节点是纯负荷节点但周围道路条件差灾后MPS很难转移有些节点靠近关键负荷中心但容量太小接入不进去。论文里通常会预设一个候选节点集合实际工程中还要考虑场地、交通、接入电压等级等因素。第二层是容量配置每台MPS的容量大小、功率等级怎么选。是放一台大容量的还是放两台小容量的我的复现经验是把MPS容量离散为几种典型规格用整数变量建模求解规模会增加一些但结果更贴近实际。第三层是数量分配手头一共有多少台MPS可用是全部预配置出去还是预留一部分应急备用论文里一般会设置一个可用MPS总数上限预配置数量不能超过这个上限。有些文献还会加一个“最少预配置数量”的约束防止优化结果一台都不放——那在韧性场景里是不现实的。2. MPS预配置数学模型的逐层拆解目标、变量与约束这一节我直接把我复现代码时用的模型骨架写出来。不同论文的细节会有些差异但主干基本一致。你只要把每一块的数学含义搞明白换到任何一篇SCI论文的模型上都不会卡壳。2.1 目标函数预配置成本与失负荷惩罚的权衡MPS预配置的总目标可以写成最小化“预配置成本 灾害场景下的期望失负荷惩罚成本”。这个复合目标非常关键如果你只最小化预配置成本那结论肯定是“什么都不要放”但如果只最小化失负荷你就会把所有MPS全部塞满完全不考虑经济性。所以目标函数必须在两者之间取平衡。我使用的符号约定如下$C^{pre}_{k}$第k台MPS的预配置成本$x_{i,k}$0-1变量候选节点i是否配置第k台MPS$p_s$第s个故障场景发生的概率$z_{j,t,s}$节点j在时段t、场景s下的切负荷量$\lambda_j$节点j的失负荷惩罚权重常与负荷等级相关。目标函数写成 $$ \min \sum_{i \in \Omega_{cand}} \sum_{k \in \mathcal{K}} C^{pre}{k} x{i,k} \sum_{s \in \Omega_s} p_s \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{N}} \lambda_j z_{j,t,s} $$这里有个细节值得展开为什么失负荷要乘概率p_s因为灾害场景是不确定的你不能保证某种故障一定发生。用期望值做目标相当于把所有可能的故障场景按概率加权求平均这是随机优化里的标准做法。也有一些论文用鲁棒优化只关心“最坏情况下失负荷最小”这时目标就是max-min形式但计算复杂度会显著上升。我的复现建议是如果你是为了理解原理先从期望值模型入手如果你要复现一区论文的保守决策结果再上鲁棒模型。2.2 第一阶段变量与第二阶段变量的边界预配置模型的难点之一是把变量按决策阶段分清楚第一阶段变量灾前确定$x_{i,k}$候选节点i是否配置第k台MPS$y_{i,k}$如果MPS功率/容量也是决策量可以用整数编号表示不同容量档位。第二阶段变量灾后场景s中确定$z_{j,t,s}$节点j在t时段场景s下的切负荷量$P^{MPS}_{j,t,s}$场景s中t时段节点j处MPS向配电网注入的有功功率$Q^{MPS}_{j,t,s}$对应的无功功率$P^{flow}_{ij,t,s}$支路ij的有功潮流$V_{j,t,s}$节点电压幅值。我在代码里用不同的变量名前缀来区分两个阶段x_开头的全部是一阶段z_、p_、v_开头的都是二阶段。这样写的好处是不容易在约束里把变量混用——我第一次复现时就是把x变量误用进了场景循环结果所有场景都看到同一个配置结果排查了很久才发现。2.3 关键约束数量、容量、潮流与切负荷限制MPS预配置模型的约束按功能可以分为四组第一组预配置位置和数量约束。每个候选节点上至多配置一台MPS $$ \sum_{k \in \mathcal{K}} x_{i,k} \le 1, \quad \forall i \in \Omega_{cand} $$ 整个系统配置的MPS总数不能超过可用台数 $N^{MPS}{max}$ $$ \sum{i \in \Omega_{cand}} \sum_{k \in \mathcal{K}} x_{i,k} \le N^{MPS}_{max} $$第二组MPS容量与注入功率的耦合约束。如果节点i配置了第k台MPS那么灾后任何时段MPS注入功率都不能超过该台MPS的额定功率上限 $$ 0 \le P^{MPS}{j,t,s} \le \sum{k \in \mathcal{K}} P^{max}k x{j,k}, \quad \forall j,t,s $$ 这个约束非常重要它把预配置的0-1决策和灾后的连续调度功率联系了起来。如果x0MPS功率必须为0如果x1MPS功率上限才打开。类似的约束还有MPS的电量上限可以用一个简化公式表示灾后各时段累计放电量不超过额定电量。第三组配电网运行约束。这里要考虑灾害后配网可能已经破坏需要用DistFlow潮流方程描述功率平衡 $$ P^{inj}{j,t,s} \sum{l \in \delta(j)} P^{flow}_{jl,t,s} $$ 同时线路潮流不超过容量节点电压保持在允许范围内。论文里通常会做线性化处理把DistFlow方程简化成线性形式这样整个模型就变成混合整数线性规划MILP可以直接用Gurobi、CPLEX这类求解器求解。第四组切负荷约束。切负荷量不能超过该节点原有负荷水平 $$ 0 \le z_{j,t,s} \le L_{j,t} $$ 有些论文还会加一个“关键负荷必须优先恢复”的约束通过把不同负荷节点的λ_j设置成不同大小来实现。比如医院、通信基站这些节点λ_j取很大的惩罚系数普通居民负荷取小一些。2.4 不确定性的两种建模路线场景还是鲁棒预算我在复现初期最纠结的问题是到底用场景法还是用鲁棒预算不确定集两条路线各有适用条件。场景法随机规划的做法是生成大量故障场景每条线路以一定的概率被破坏再用蒙特卡洛或K-means聚类把场景削减到几十个典型场景。这种做法优点是可以直接考虑场景概率目标函数比较直观缺点是场景数量一多MILP规模会迅速膨胀求解时间成倍增加。鲁棒预算法的做法是不需要枚举场景而是用一个不确定集合来描述可能发生的故障线路集合比如“最多同时有Γ条线路故障”。目标函数变成最坏情况下的失负荷最小化。这个模型更保守也更贴合“极端灾害下最坏情况”的思维方式但求解时需要用到列与约束生成CCG或Benders分解。我复现代码时采用的是“场景法期望值目标”的方式因为作为上篇的预配置模块场景法的代码结构更容易被读代码的人理解而且后续做动态调度时可以很自然地复用同一个场景集合。如果你要复现的论文里明确写了鲁棒优化那需要额外写一个CCG循环我后面下篇动态调度时会再展开。3. IEEE 33节点算例的数据准备从论文参数到Matlab可计算矩阵建模写代码之前百分之八十的时间花在数据准备上。SCI论文往往只给算例网络名称和几个关键参数具体到每条线路的阻抗、每个节点的负荷基准值都得自己找、自己整理。3.1 测试系统基础数据和节点/支路矩阵构建这一项目我们采用经典的IEEE 33节点配电系统做测试这是配电网韧性研究里最常用的算例网络之一系统基准电压12.66kV基准功率一般取10MVA一共有33个节点、32条支路、5条联络开关支路总负荷大约3715kW加2300kvar。我建议把数据组织成两个矩阵和Matpower的格式保持兼容。第一个是节点参数矩阵bus每一行对应一个节点列依次是节点编号、节点类型、有功负荷kW/kW基准、无功负荷、电压幅值初值。第二个是支路矩阵branch每一行对应一条支路列依次是支路编号、首端节点、末端节点、电阻欧姆、电抗欧姆、线路容量上限。以部分数据为例首段线路的数据大致如下表支路编号首端节点末端节点电阻(Ω)电抗(Ω)容量上限(kVA)1120.09220.047050002230.49300.251130003340.36600.18642500..................把数据写成Matlab脚本时我习惯直接用一个load_ieee33.m函数返回结构体function data load_ieee33() data.baseMVA 10; data.baseKV 12.66; data.bus [ 1 1 0 0 10.0; 2 1 100 60 10.0; 3 1 90 40 10.0; % ... 后续节点 ]; data.branch [ 1 1 2 0.0922 0.0470 5000; 2 2 3 0.4930 0.2511 3000; % ... 后续支路 ]; end这里有一个关键细节所有数据要么转成标幺值要么统一转成有名值的相同量纲。我最早直接把欧姆和kW混合算结果潮流线性化系数差了三个数量级Gurobi直接报数值病态Illegal numeric value。后来全部用标幺值建模问题就消失了。3.2 候选预配置节点如何筛选MPS不是每个节点都能放需要先确定候选节点集合。论文一般不会把所有33个节点都作为候选那样模型复杂度太高。我复现时的筛选逻辑是第一优先选择关键负荷节点附近。核心负荷越多的节点灾后供电迫切性越高MPS放在这里可以最直接地支撑负荷。第二考虑网络拓扑结构。比如联络开关附近的节点、长馈线的末端节点、支路发生故障后容易形成孤岛的节点都是潜在候选。可以用“节点失效影响度”或者“负荷供应脆弱性”来量化。第三参考N-1预想故障分析。依次断开系统内重要支路统计失负荷节点把受影响最严重的几个节点挑选出来作为候选。这个方法很朴素但非常好用复现起来也快。在我的项目里候选节点集合最终选为IEEE 33节点系统中的节点5、8、13、24、29共5个节点。这个集合覆盖了不同馈线方向和关键负荷区域可以让MPS配置方案具有代表性。你也可以根据需要扩大候选集合但每增加一个候选点整数变量数量会线性增加求解时间随之上涨。3.3 故障场景生成与场景削减预配置阶段最耗时的不是建模而是场景处理。我首先给每条线路设定一个故障概率这个概率反映极端灾害下线路中断的可能性通常取在0.05~0.2之间具体数值取决于灾害等级和线路抗灾能力。然后我生成一个随机损坏状态向量长度等于支路数每一位为1表示该支路故障0表示正常。我用一个简化的蒙特卡洛循环生成例如500个原始场景。原始场景太多没办法直接扔进MILP需要做场景削减。我采用同步回代消除法核心步骤是定义两个场景之间的距离度量常用的是故障线路集合的对称差集大小计算每个场景与其它场景的距离找到距离最近的两个场景将其中概率较小的场景删除并把它的概率叠加到保留的场景上重复操作直到场景数降为目标值比如保留20个典型场景。这个算法的Matlab实现并不复杂我代码里用一个约80行的函数scenario_reduction.m完成。减完之后的场景集合会存在一个矩阵scenarios.mat里每一行是一个场景的故障线路状态每一列对应一条线路是否损坏同时还有一个概率向量weights。我特别想提醒一句场景削减的目标不是“砍到最小”而是“在保留灾害空间分异性的前提下压缩规模”。如果你把场景削减到只剩三五个每个场景的故障模式都天差地别期望值会失真但如果保留到80个以上又是“边际递增、回头求解器”的噩梦。我常用的是20个场景预配置模型的求解时间大约在几十秒到几分钟之间比较适合反复调试。3.4 MPS参数和成本参数的标定MPS参数设定是论文复现中自由度最大的地方因为不同论文的移动电源类型不一样。我按“移动储能车”这个定位来标定参数数值说明单台MPS额定功率300 kW也可以按100/300/500 kW分档单台MPS额定容量600 kWh对应2小时满功率放电可用MPS总数3~5台灵敏度分析时从2台测到6台单位预配置成本500元/台或者折算成本也可以在500到2000之间调失负荷惩罚系数λ关键负荷5000元/MWh普通负荷2000元/MWh注意预配置成本不是MPS的购买成本而是“提前布放并接入”这个过程产生的费用包括运输、接入、调试、占用场地等。因为MPS本质上是资产论文里更关心的是布局决策不是资产采购。所以这部分成本在目标函数里的相对大小非常重要它直接决定了优化结果是倾向多布放还是少布放。我在下篇里会对成本参数做灵敏度分析。4. Matlab代码实现Yalmip建模的关键片段与求解细节4.1 程序目录结构与运行入口我复现MPS预配置项目时采用的目录结构如下mps_pre_positioning/ ├─ run_pre_positioning.m % 主脚本 ├─ data/ │ ├─ load_ieee33.m % 生成节点支路数据 │ ├─ gen_scenarios.m % 生成/削减故障场景 │ └─ scenarios.mat % 削减后的场景与概率 ├─ model/ │ ├─ build_mps_model.m % 构建Yalmip优化模型 │ └─ solve_milp.m % 调用Gurobi/CPLEX求解 └─ utils/ ├─ scenario_reduction.m % 场景削减 └─ plot_pre_result.m % 结果可视化主脚本run_pre_positioning.m是入口依次调用数据加载、场景生成、模型构建和求解。这样拆分的目的是把“优化模型”和“数据准备”分离。我调试的时候只需要改数据参数不用动模型函数特别方便。4.2 变量定义和数据载入在build_mps_model.m里我先加载数据和场景再定义变量。这里给出核心片段的示意代码function result build_mps_model(data, scen, params) candNodes params.candNodes; % 候选节点集合 numScen size(scen.prob, 1); % 场景数 numPeriod params.numPeriod; % 时段数 numBus size(data.bus, 1); numMPS params.numMPS; % 可用MPS台数 % 第一阶段变量候选节点i是否配置第k台MPS x binvar(length(candNodes), numMPS, full); % 第二阶段变量切负荷量 [节点 × 时段 × 场景] z sdpvar(numBus, numPeriod, numScen, full); % 第二阶段变量MPS注入功率 [节点 × 时段 × 场景] pMps sdpvar(numBus, numPeriod, numScen, full);这里有一个很常见的坑SDPVAR变量的维度顺序是否和后面约束一致。我建议把“节点、时段、场景”这个顺序固定下来在所有约束里都按这个顺序循环不要一会儿节点在前、一会儿场景在前否则你会在调索引上花掉大量时间。然后定义目标函数Cpre params.Cpre; % 单台预配置成本 lambda params.lambda; % 各节点失负荷惩罚系数 obj 0; % 预配置成本 obj obj sum(Cpre * x(:)); % 期望失负荷惩罚成本 for s 1:numScen w scen.prob(s); for t 1:numPeriod obj obj w * sum(lambda .* z(:, t, s)); end end4.3 约束逐条实现与求解器配置约束部分的代码我把关键几组列出来。第一组是每个候选节点最多配一台MPScons []; for i 1:length(candNodes) cons [cons, sum(x(i, :)) 1]; end % 总台数约束 cons [cons, sum(x(:)) numMPS];第二组是MPS功率与预配置变量耦合PmaxMPS params.PmaxMPS; % 单台MPS额定功率 for j candNodes idx find(candNodes j); % 候选节点索引 for t 1:numPeriod for s 1:numScen cons [cons, pMps(j, t, s) PmaxMPS * sum(x(idx, :))]; cons [cons, pMps(j, t, s) 0]; end end end第三组是节点功率平衡约束。这里用线性DistFlow简化实际代码里我封装成一个子函数add_power_balance_cons。伪代码如下function cons add_power_balance_cons(cons, data, V, pFlow, pMps, z, params) for s 1:params.numScen for t 1:params.numPeriod for j 1:data.numBus % 支路注入功率 - 流出功率 节点负荷 - 切负荷 - MPS注入 cons [cons, sum(pFlow(fromNode j, t, s)) ... - sum(pFlow(toNode j, t, s)) ... data.bus(j, loadCol) - z(j, t, s) pMps(j, t, s)]; end end end end这个线性化潮流里我把电压幅值也线性化了模型就变成纯MILP。如果你想复现更精确的交流潮流需要在第二阶段引入电压乘积项但那会让模型变成MIQP甚至MINLP求解难度高很多。大多数SCI里做MPS预配置都采用线性化潮流因为决策问题的核心在“位置和容量的权衡”不需要精确到电压相角。第四组是切负荷上限约束for s 1:numScen for t 1:numPeriod cons [cons, z(:, t, s) 0]; cons [cons, z(:, t, s) loadDemand(:, t)]; end end求解器配置方面我使用Gurobiops sdpsettings(solver, gurobi, verbose, 2, ... gurobi.MIPGap, 0.01, ... gurobi.TimeLimit, 600, ... gurobi.Threads, 4); optimize(cons, obj, ops);MIPGap取1%是我反复调试后的选择。取0.1%可以但场景多的时候求解时间会翻几倍工程上1%的优化间隙对预配置决策完全够用。取5%则结果波动太大可能位置都会选错。4.4 结果提取与绘图求解完成后用value提取变量值xVal round(value(x)); zVal value(z); pMpsVal value(pMps); % 输出预配置方案 for i 1:length(candNodes) k find(xVal(i, :) 0.5); if ~isempty(k) fprintf(节点%d 配置第%d台MPS\n, candNodes(i), k); end end注意x是0-1变量提取时我用round处理防止求解器返回0.9999这种数值。这样做的原因是Gurobi虽然会输出整数解但由于浮点运算个别变量可能带有微小误差直接判断大于0.5比较稳妥。绘图部分我用Matlab自带的图形函数把33节点拓扑画出来再用不同颜色标注MPS预配置节点和故障线路这样一眼就能看出方案的空间分布。保存图形时用exportgraphics比print更清晰PDF格式适合写论文。5. 复现实验中的结果分析、参数影响与避坑记录5.1 不同MPS数量下的预配置方案对比我用同样的故障场景集合把MPS可用台数从2台逐步增加到6台得到的预配置结果如下MPS台数预配置节点配置台数期望失负荷(MWh)相对失负荷下降2台5, 242台28.5基准3台5, 13, 293台21.225.6%4台5, 8, 13, 294台16.841.1%5台5, 8, 13, 24, 295台14.150.5%6台5, 8, 13, 24, 295台14.150.5%这个结果非常符合工程直觉从2台增加到5台韧性提升效果明显但到第6台时系统已经“没有更好的地方可放”了期望失负荷不再下降说明边际效益趋于零。我在论文复现报告里专门画了这个边际效益曲线用来解释为什么MPS数量不是越多越好——这其实对应了目标函数里预配置成本与失负荷惩罚之间的平衡。从节点选择看节点5和节点29在所有方案中几乎是必选的因为这两个节点分别处于不同馈线的关键位置覆盖能力很强。节点8在中段节点13在负荷集中区域。这个规律可以作为后续工程应用的参考预配置优先覆盖“馈线主干分叉点”和“高负荷密度末端”。5.2 不确定预算与场景概率的灵敏度我做的第二组实验是改变场景概率的构造方式。前面我设定每条线路故障概率在0.1附近现在我把大灾害场景的概率提高比如把某些主干线路的故障概率从0.1提高到0.3预配置方案发生了明显变化MPS向主干线路附近的节点集中而不是均匀散布。这背后的逻辑是期望值目标函数中概率越大的场景权重越高优化结果会优先照顾高概率故障场景的供电恢复。所以如果你发现复现结果里MPS配置点看起来“不直觉”先检查场景概率是不是设置得不合理而不要急着改模型。我还测试了失负荷惩罚系数λ的变化。λ从2000元/MWh提到10000元/MWh时优化方案偏向于多配置MPS、覆盖更多节点反过来λ降低时方案开始省钱可能只配置2台。这说明λ和Cpre之间的比值是整篇论文里最敏感的一对参数写复现报告时必须做灵敏度分析。5.3 常见报错与排查思路复现过程中我踩过的坑不少这里挑几个最典型的列出来都是可以直接对照排查的现象原因解决方案Gurobi报Illegal numeric value数据量纲不统一或参数过大统一转成标幺值建议baseMVA10电压标幺值1.0Yalmip报Variable x not in model约束里用了x但因为索引写错x没有实际参与约束检查dimensions和sdpvar定义维度用size(x)打印确认求解结果x全部为0预配置成本Cpre设置过高或MPS功率/电量参数过小降低Cpre或检查pMps上限约束是否正确耦合x场景数大求解时间超过几小时MILP规模爆炸增加MIPGap到0.02或把场景削减到15~20个或用Benders分解期望失负荷结果为0惩罚系数λ太小或切负荷约束松弛过大调大λ或检查负荷数据是否被错误标幺化功率平衡约束无解孤岛场景下没有电源潮流无法平衡在MPS覆盖不到的孤岛节点允许一定切负荷比例不要强制供电我特别提醒一点当你看到“无解”或者“x全为0”的时候先不要怀疑求解器应该先做可行性检查。我调试时经常用Yalmip的check函数disp(check(cons));这个命令会列出每条约束是否满足一目了然。如果某一组约束显示“Not satisfied”直接定位到对应的循环九成都是索引写错了。这个方法比无脑打印变量值高效得多。5.4 预配置结果如何衔接下篇动态调度预配置阶段输出的是三样东西候选节点的x配置决策、灾害场景集合和概率、以及每个场景下MPS供电功率的“可用空间”。动态调度阶段会在此基础上做三件事第一根据灾后实时获取的故障信息筛选出实际发生故障的线路集合不再使用场景期望而是用确定性场景或者滚动更新的预测场景。第二让MPS具备移动能力。上篇里MPS是“固定接入”下篇里它会从一个节点移动到另一个节点所以需要增加移动时间约束、道路通行约束、逐时段位置状态变量。第三把上篇的“预配置位置”作为下篇动态调度的初始条件。也就是说动态调度不能随意改变灾前已经准备好的重要位置但可以在MPS完成供电任务后转移到其他节点。这部分我做的时候踩了很多坑尤其是MPS在途中移动时对配电网的支撑能力会暂时消失需要精确建模。这也就是为什么标题分“上下”两篇没有预配置的动态调度是“没有起点的奔跑”没有动态调度的预配置是“孤立的选址方案”两者合在一起才构成完整的韧性提升闭环。后面我会把动态调度部分的代码整理出来重点讲清楚如何在Yalmip里引入连续时间状态的移动MPS约束以及怎么把上篇生成的scenarios.mat继续复用。预配置场景文件、线路损坏状态矩阵和候选节点编号这些中间结果我建议你提前统一存成结构体不然后面做下篇时你会因为变量维度对不上而反复回头改数据。