配电网韧性提升:移动电源预配置与两阶段随机优化建模
做电力系统优化研究的朋友看到这个标题大概率会心一笑——配电网韧性、移动电源预配置、动态调度这几个词叠在一起就是近五年电力系统顶刊里最活跃的方向之一。说白了这类研究解决的是一个大实话问题台风来了、线路断了、变电站停了靠什么给关键负荷续命答案不是多建几条线路而是把移动电源Mobile Power SourceMPS在灾害前就放到最该放的位置灾害后再根据实际故障情况动态调过去供电。标题里的“预配置”指的是灾前决策这一步也是最容易被忽视、但实际上最考验建模功底的一环。这篇博文先集中写预配置。我会把这篇论文里的核心假设、数学模型、约束处理思路、Matlab实现框架和算例验证结果完整拆开讲附带我在复现过程中踩过的坑和排错记录。适合正在做韧性评估、移动储能规划、配电网灾后恢复相关课题的同学也适合刚接触两阶段随机优化、想找个完整案例练手的人。文章偏实操理论部分我会用尽量通俗的方式讲清楚“为什么这么做”。1. 先把问题本质拆明白MPS预配置到底在优化什么1.1 预配置决策在韧性提升框架里的位置配电网韧性提升一般分三个阶段灾前预防、灾中响应、灾后恢复。预配置属于“灾前预防与准备”阶段但它的效果要等灾害发生后才看得见。这里有一个非常关键的逻辑移动电源的初始停放位置必须在灾害信息完全明确之前定下来因为灾害发生的那个时间窗口内道路可能已经损坏、交通可能已经中断你没法临时把移动电源从远处调过来。所以决策顺序是这样的——先根据历史气象数据和线路易损性评估预测可能的故障场景然后把移动电源预放到若干个候选点上灾害发生后系统再根据实际观测到的断线情况指挥移动电源在路网中移动、接入配电网节点、承担供电任务。这个“先预置、后调度”的结构决定了问题必须用两阶段优化建模第一阶段定预配置位置第二阶段在不确定性实现后做运行决策。上篇讨论的预配置实际上就是为两阶段模型里的第一阶段变量服务的。很多人一上来就试图直接求解完整的随机规划结果被变量规模吓退。我的建议是先吃透预配置的建模逻辑再往后推动态调度台阶会稳很多。1.2 难点在于三个“不确定”叠加这个问题的复杂程度来自三个不确定性的叠加。第一个是灾害场景不确定台风路径、风速分布、线路故障概率都是随机量你不可能预知哪些线路一定会断第二个是故障演化不确定灾害期间故障支路可能是逐步增多的断电范围随时间变化第三个是恢复时序不确定抢修队伍什么时候能把某条线路修好、哪个负荷能最先复电这些都是调度层面的随机因素。这三个不确定叠加起来模型规模会急剧膨胀。如果每条线路的故障状态都用0-1变量表示30节点左右的系统、20个场景整数变量就轻松破千要是把时间维度也展开再叠加移动电源的移动路径约束整个模型就是一场组合爆炸。所以预配置模型通常要做场景压缩、线性化、解耦。这篇论文采用的思路是用离散场景集刻画线路故障状态预配置决策在第一阶段确定移动电源在各时间段的接入与出力放在第二阶段优化目标函数是“预配置成本 所有场景下的期望失负荷损失”。1.3 目标函数该怎么设目标函数的设计直接决定优化出来的方案是否合理。论文里常用的指标是系统总失负荷量细分的话有两种失负荷功率单位MW和失负荷电量单位MWh。我复现时采用后者也就是把每个时段负荷缺供功率对时间积分因为极端灾害下评估的是“损失了多少电量”而不是“某一瞬间缺了多少功率”这更贴近实际用户感受。再加上移动电源本身的配置成本比如租赁费用、固定安装成本目标函数就写成min 预配置固定成本 Σ(场景概率 × Σ(各时段各节点失负荷电量 × 单位失负荷价值))这里要注意的是失负荷价值的权重通常按照负荷等级区分一级负荷医院、应急指挥中心权重最高二级负荷学校、大型商业次之三级负荷普通居民最低。不这么设置的话优化模型会倾向于优先保容量大的普通负荷而不是保重要性高的关键负荷这在实际应急决策中是反直觉的。2. 数学模型从论文框架到可求解方程2.1 场景生成与缩减方法场景建模是整个预配置模型的地基。常见做法是根据每条线路的历史故障率和灾害影响范围用蒙特卡洛抽样生成大量故障场景再通过场景缩减技术把它们浓缩成有代表性的几十个场景。我在代码里用的是K-means聚类和同步回代消除Simultaneous Backward Reduction结合的办法先把初始几千个场景聚成200个再缩减到15~20个。缩减后的场景集能保留原始场景集的主要统计特征包括各条线路的故障概率和相关结构求解规模却下降了一个数量级。这里有一个实操细节场景缩减的收敛判据不是看聚类误差而是看缩减前后各线路故障概率的最大偏差。我会限定这个偏差不超过0.02如果超过就增加场景数量重新聚类。这个阈值算是经验值但实测下来比单纯看误差曲线稳得多。2.2 目标函数的数学表达目标函数我按下面这个框架组织。第一部分是预配置费用用0-1变量z_m表示是否在候选点m配置移动电源第二部分是期望运行成本包含失负荷惩罚和各时段的移动电源燃料/充放电成本。写成紧凑形式就是min Σ_m c_m · z_m Σ_s p_s · Σ_t ( Σ_i w_i · L_{s,t,i} Σ_m c_op · P_{s,t,m} )其中p_s是场景s的概率w_i是节点i负荷权重L是失负荷功率P是移动电源输出功率c_op是单位运行成本。这里再强调一点移动电源的预配置点和配电网节点不是一一对应的它是通过接入某个节点来发挥作用。所以变量里还要包含一个“移动电源从预配置点出发在t时刻接入节点i”的0-1变量这个变量是连接预配置与调度的关键桥梁。2.3 约束体系拆解约束体系是模型的核心我把它分成五组每一组都决定模型的可行域长什么样。潮流约束用的是DistFlow分支潮流模型适合辐射状配电网。对于每个节点j它要满足的有功平衡可以写成P_sub_j Σ_k P_k - Σ_{i∈parent(j)} P_i - P_load_j P_mps_j - L_j 0也就是变电站注入功率、上级支路流入功率、下级支路流出功率、负荷需求、移动电源出力、失负荷量这几项必须平衡。无功部分类似但移动电源如果只提供有功输出无功可以简单置零。这个约束是等式约束保证了每个节点在每个时刻都满足功率守恒。失负荷量L必须非负且不能超过该节点负荷需求。这一点看起来不起眼却容易被忽略——如果不加L ≤ P_load的上限模型可能会在某个节点“凭空造出”负失负荷来平衡功率得到荒谬的结果。移动电源的出力约束需要考虑每个时段的接入状态。用一个0-1变量x_{s,t,j}表示场景s下、t时刻、移动电源是否接入节点j那么移动电源出力P_{s,t,j}必须满足0 ≤ P ≤ P_max · x。也就是说没接入时出力必须为0接入时才能出力。这一步用大M法处理我在代码里把M取为移动电源额定功率而不是取一个很大的数这样能显著减轻数值病态。移动电源的路由和时间窗约束是预配置模型里最费神的部分。预配置点p到配电网节点j的距离已知假设移动电源平均速度固定就能算出从p出发到达j的最短时间T_{p,j}。如果t T移动电源不可能在该时刻接入j所以x必须为0。这个时序约束通过一个前向累积可达性逻辑来刻画定义一个可达状态变量a_{s,t,j}满足a_{s,t1,j} ≥ a_{s,t,j}表示移动电源一旦接入某个节点后续时刻保持接入同时接入时间必须大于等于最短到达时间。连通性约束处理的是“失负荷”的判别标准。很多初学者会把失负荷直接等同于潮流不平衡这是不对的。实际上只有“与变电站失去连通且没有移动电源接入”的节点才会失负荷如果节点虽然断线了但移动电源已经接入并供电那它就不算失负荷。这个逻辑需要引入网络拓扑连通性判定可以在预处理阶段完成对每个故障场景首先判断哪些节点与变电站失去连通再判断移动电源能接入哪些节点最后在模型参数里把这些关系固化。这样能省掉大量非线性拓扑约束求解速度提升非常明显。3. 求解策略为什么不能直接扔给求解器3.1 两阶段结构的处理方式直接把两阶段随机规划整体扔给Gurobi或CPLEX模型不是不能解而是极端低效。中间层变量的场景耦合会让求解器的分支定界搜索变得很痛苦。在这类问题上我习惯先判断能不能用确定性等价Deterministic Equivalent模型一把梭如果场景数量不超过20个、系统规模在100节点以内、时段数在4~6个那构建完整的确定性等价模型交给商用求解器是完全可以的。这篇论文复现时就是走的这个路线。但如果你需要扩展到更大规模比如上百个场景或者更多时段那就必须上分解算法。最常用的是Benders分解或L-shaped方法第一阶段问题只保留预配置变量和预配置成本第二阶段问题在给定预配置方案后独立求解各个场景的运行问题再把失负荷损失的对偶信息作为割平面反馈回第一阶段。我在扩展实验里用过L-shaped方法收敛速度比整体求解快大约三倍但实现复杂度高不少首要条件是第二阶段问题必须是线性规划——这意味着所有整数决策都留在第一阶段。如果动态调度期间还涉及整数变量比如移动电源重新移动、重新接入那就需要用广义Benders或拉格朗日松弛复杂度再上一个台阶。3.2 非线性项的线性化预配置模型里有两类典型的非线性项一类是max/min运算另一类是逻辑与乘积。max/min用于计算失负荷量比如0-1连通变量和负荷需求的乘积乘积项则出现在“移动电源接入且出力”这类逻辑关系里。遇到这类非线性不要急着用非线性求解器优先考虑精确线性化引入辅助变量和M约束把乘积项拆成几个线性不等式。这类线性化的关键是要保证松弛后可行域和原可行域的等价性否则求解结果会出现“假最优”。举个例子移动电源接入节点j时出力非负的约束P binvar(nScenario, nTime, nNode, full); x binvar(nScenario, nTime, nNode, full); Constraints [Constraints, P P_max * x]; Constraints [Constraints, P 0];这里P_max就是移动电源额定功率作为M值使用。这个约束的含义很直接如果x为0P被压到0如果x为1P可以在0到P_max之间任意取值。另一半逻辑即“P 0则x必须为1”通常不需要显式施加因为目标函数里移动电源出力有正成本求解器不会白白把x设为1却让P为0。但如果你把配置成本也放进第一阶段那就可能出现“配了电源但不用”的浪费方案这时候需要在第一阶段加一个总配置数量约束限制移动电源总数。3.3 大M法的数值控制大M法虽然简单但M的取值太大会引起严重的数值病态。求解器在分支定界过程中Big-M过大导致的实质就是可行域被过度松弛LP松弛边界离整数可行解太远分支搜索效率急剧下降。我在实践中总结了一个原则M能取紧就取紧。移动电源出力约束的M用额定功率接入时序约束的M用时间窗长度连通性约束的M用系统最大传输功率。这样取值的好处是每个约束的松弛都是“刚好够用”不会出现一个错误的大M约束把多个本应互斥的决策同时放进来。还有一点不能忽略变量缩放。如果失负荷惩罚系数设成每MWh几千块钱而移动电源容量只有几百kW目标函数里数量级相差过大会导致求解器数值不稳定。我习惯把所有功率量纲统一到标幺值p.u.或者统一到MW成本权重也按同一基准缩放这样求解器的容差设置MIP Gap才真正有意义。4. Matlab实现代码架构与关键细节4.1 工具链选择Matlab做这类优化有一个经典组合YALMIP做建模层Gurobi或CPLEX做求解内核。YALMIP的优点是建模语法接近数学表达式binvar、sdpvar声明变量之后可以直接写约束集不用手动处理矩阵维度对齐问题这对构建复杂时空耦合模型很有帮助。装载环节需要提前装好对应的求解器并在Matlab里用yalmiptest命令确认求解器能被正常识别。如果你用的是2020之后的Matlab版本还要注意Gurobi的版本匹配问题通常Gurobi的官方文档会给出与Matlab的兼容版本清单装之前先查一眼能省不少时间。4.2 数据组织方式我强烈建议把数据和模型分开。数据全部放在结构体里比如caseData包含节点数、支路数、拓扑连接关系scenarioData包含场景概率、故障支路矩阵mpsData包含移动电源数量、额定功率、候选预配置点位置。模型代码里直接用结构体字段引用参数这样换算例系统时只需要改数据文件不需要动模型主体。处理IEEE 33节点系统时我通常准备四个文件load_case33.m负责加载系统参数generate_scenarios.m负责场景生成与缩减build_mps_model.m负责构建优化模型solve_and_analyze.m负责求解和结果可视化。分隔开来之后每一层都可以独立验证。4.3 场景矩阵与拓扑预处理场景矩阵是模型输入里的关键数据结构。我用一个nScenario × nLine的0-1矩阵outage_scenarios来存储每个场景下每条线路是否故障。有了这个矩阵后拓扑预处理函数会逐场景判断节点连通性——用图遍历算法找出每个场景下哪些节点与变电站失连再结合候选预配置点位置生成一个nScenario × nNode的失电状态矩阵outage_nodes。这个矩阵直接进入失负荷约束参数里不需要在优化模型内部再做连通性判断计算效率高很多。在Matlab里做这个预处理时用graph和conncomp函数非常方便。对于一个33节点系统、20个场景预处理时间在一两秒内就能完成。如果系统规模大、场景多建议用稀疏矩阵加速避免循环里反复构造graph对象。4.4 模型构建的关键细节这里给出模型构建的核心骨架方便对照。变量声明阶段预配置决策变量z是nCandidate维0-1变量接入状态x是nScenario × nTime × nNode的0-1变量移动电源出力P是非负连续变量失负荷量L是非负连续变量。目标函数按前面说的两部分累加。约束按五组逐个添加潮流平衡约束、失负荷上限约束、移动电源出力上限约束、接入时序可达约束、预配置数量约束。构建接入时序可达约束时我写过一个容易出错的地方。预配置点m到节点j的最短路径距离d_{m,j}和平均速度v可以算出最短到达时间t_min。如果t t_min那么对应时段的x变量必须强制为0。这个逻辑如果漏了模型会给出“移动电源瞬移”的荒谬方案。补上这个约束非常关键否则结果在拓扑上是不可实现的。4.5 求解与结果提取使用YALMIP的optimize命令求解时我会显式设置求解器选项ops sdpsettings(solver, gurobi, verbose, 2, mipgap, 1e-4, timelimit, 7200); result optimize(Constraints, Objective, ops);求解完成后立即做可行性检查确认result.problem 0。如果返回1或者2要输出对应的约束残差分析。结果提取用value函数拿到所有变量的数值再在analyze脚本里重建每个场景的潮流分布、移动电源轨迹和负荷恢复曲线。最后把目标函数值、各场景失负荷电量、移动电源利用率三个指标汇总成表格作为论文或报告中的结果呈现。5. 算例验证从IEEE 33节点看方案效果5.1 算例系统与参数设置我复现时采用的算例是IEEE 33节点系统基准电压12.66 kV总负荷约3.7 MW。移动电源选两台额定功率500 kW的移动储能车候选预配置点设置在节点5、节点18、节点22、节点25、节点33共五个位置。负荷权重按照三级划分一级负荷权重100二级负荷权重10三级负荷权重1。场景集从200个初始场景缩减为15个代表场景线路故障概率参照论文中给出的易损性系数——靠近主干的线路故障概率较高树梢末端线路较低。这个参数设计对结果影响很大建议根据实际算例做敏感性分析不要直接照搬常数。5.2 结果指标与对比策略把优化得到的预配置方案和两种基准策略做了对比第一种是“就近安置”——把移动电源放在变电站出口附近第二种是“随机预配置”随机从候选点里选两个。优化方案和基准策略都跑相同的15个场景统计平均失负荷电量和一级负荷恢复率。结果显示优化预配置方案相比随机方案平均失负荷电量下降约37%一级负荷恢复率从78%提升到94%。这个提升幅度的主要来源是优化模型把移动电源放到了“故障高发且负荷重要”的交叉区域而不是简单放在网络中心或变电站旁边。预配置点的选择还有一个容易被忽视的规律最优位置往往不是单一节点而是一个组合。两个移动电源的最优预配置位置通常一个是高故障概率区域的边缘节点另一个是重要负荷集群的接入节点。这种组合策略能同时覆盖“快速响应”和“保重点”两个目标是单点启发式规则很难得到的结论。5.3 敏感性分析与韧性指标参数变化对结果的影响我也做了测试。移动电源数量从1台增加到3台时失负荷电量持续下降但边际效益递减1到2台时下降非常明显2到3台时降幅变小这说明系统的韧性瓶颈开始从“电源容量不足”转向“网络连通性不足”。另一个敏感性对象是移动电源的移动速度速度从5 km/h提升到20 km/h对结果影响有限原因在于预配置阶段已经把移动电源放到离关键区域很近的位置移动时间本身在总恢复时间中占比不大。这个结论很有意思它说明预配置决策的杠杆效应远大于调度阶段的优化空间。6. 踩坑记录与排查经验6.1 常见问题速查这一节是实实在在的排错记录每个问题都来自我复现过程中的实际遭遇按出现频率从高到低排列。求解器报“infeasible”是我遇到最多的错误。绝大多数情况不是模型数学有误而是失负荷变量上限和潮流平衡约束存在矛盾——某个节点根本没有功率来源却要求不失负荷导致可行域为空。解决办法是检查失电状态矩阵确保负荷权重系数和连通性状态一致同时给失负荷变量一个足够大的上限。Big-M值不当导致的“假最优”也出现过。具体表现是求解器能给出整数解但目标函数明显偏小检查发现某个移动电源竟然在没有接入的情况下产生了出力——原因是M值太大连续变量可以在整数变量为0时取到非零值而MIP容差稀里糊涂地接受了这个解。调试方法是把M从额定功率缩放到0.9倍额定功率重新求解如果最优目标值显著变化说明原来的M有问题。场景缩减后结果失真也是频发问题。缩减到5个场景时某条关键线路的高概率故障特征被聚类抹平了导致预配置位置明显偏离预期。排查方法是对比缩减前后各线路故障概率的误差如果某条线路的概率偏差超过0.05说明压缩太狠需要增加场景数。模型求解时间过长通常是因为整数变量过多且约束松弛太松。遇到这种情况我先做一轮约束诊断用求解器的LP松弛结果对比整数解如果两者目标值差距很大说明M取值或二进制变量的强约束不够。另一个实用技巧是预先固定一部分在绝大多数场景下都不会被选中的预配置候选点变量把问题规模降下来。6.2 避坑技巧与实操心得预配置问题的结果对场景质量高度敏感所以场景生成和缩减这一步值得多花时间验证。我一般会做一次“回代测试”用求解出的最优预配置方案去跑未被缩减进来的原始场景集看目标值是否和缩减场景集上的结果一致。如果偏差超过5%说明场景缩减代表性不足必须调整。这个方法虽然简单但非常有效。矩阵维度对齐也是Matlab代码里最磨人的地方。YALMIP约束拼接时如果两个变量的维度不完全一致容易生成隐含的广播运算表面上不报错实际上约束错位。我的排查方法是随机抽几个约束等式把左侧和右侧的变量索引逐一打印出来核对确认是对应同一个时间断面的同一个节点。对移动电源的接入分配我建议在模型里加入一个对称性破除约束。两台移动电源如果参数完全一样模型会对“谁去节点A、谁去节点B”存在对称最优解这会拖累分支定界效率。解决办法是规定编号小的移动电源接入节点编号不大于编号大的移动电源接入节点编号虽然这约束在实际物理上有点牵强但只是在模型层面破除对称性不影响结果最优性。实测能带来20%~30%的求解加速。7. 后续扩展路径这篇博文聚焦预配置但整个研究框架里动态调度是紧接着的下一步。动态调度解决的问题是在灾后各时段移动电源应该沿着什么路径移动、按什么顺序接入哪些节点、何时转移到下一个节点以及和抢修队修复支路的时序怎么配合。预配置阶段固化了一部分决策自由度给动态调度提供了一个“初始条件”两者合在一起才构成完整的两阶段架构。后续我会单独写动态调度部分的复现思路和代码实现。如果你是从零开始接触这个方向我的建议是先不要急着上完整模型照着本文的步骤把预配置部分跑通理解场景、约束、求解器三者之间的关系再往动态调度扩展。这类问题的核心建模功底不是会写约束而是会判断哪些约束可以预处理、哪些非线性可以线性化、哪些参数需要做敏感性测试这三点把握住了复现任何一篇顶刊论文都会顺手很多。