资讯动态

配电网韧性下移动电源预配置的两阶段鲁棒优化与CCG求解

发布时间:2026/10/17 19:20:12 来源:尧图企业网站定制
复现过配电网韧性相关论文的朋友应该清楚移动电源的预配置看起来只是个选址定容问题可真要把它和灾害不确定性、潮流约束、后续动态调度串在一起难度会立刻翻上好几倍。我最近把某篇一区论文里的应急移动电源MPS预配置部分完整复现了一遍从数学建模、CCG求解到Matlab代码落地踩了不少坑也攒了一些能明显提速的思路。这篇先写预配置部分也就是原论文里“灾前决策”的那一步以Matlab代码实现为主线适合正在复现韧性优化、两阶段鲁棒优化或者配电网应急调度方向的同学参考。内容会尽量把“为什么这么建模、为什么用这个算法、代码里每个模块在干什么”讲透而不是贴一段能跑就完事。1. 项目背景与问题拆解1.1 配电网韧性为什么现在大家都在提配电网的传统可靠性评估关注的是故障概率较高的“常见扰动”比如设备老化、单点短路、局部过负荷。但随着极端天气事件的频度和烈度上升台风、冰灾、暴雨导致的区域性停电越来越常见这种情况下不再是单个元件故障而是多点同时故障、杆塔成片倒伏、配电线路长时间中断。应对这类“小概率、大影响”事件的能力业内习惯用“韧性”这个词来描述。韧性不只是“能扛住”还包含“能快速恢复”。配网韧性提升的常见手段包括加固线路、配置分布式电源、安装储能以及我今天要展开的应急移动电源。移动电源的优势在于机动性——它平时可以停在车场灾害发生后能够开到需要的地方去但开到哪里、带多少容量、什么时候出发这些都是决策问题。如果灾前完全不做任何预配置等故障信息完全清楚之后再调度往往会因为道路中断、响应时间太长错过宝贵的第一波供电恢复窗口。所以原论文把决策拆成了两个阶段灾前的MPS预配置和灾中的动态调度。这个“预配置”决策就是在极端事件尚未发生、或者刚刚有预警信息时基于对灾害破坏情况的不确定性估计提前决定移动电源的初始位置和容量配置。等灾害真正发生故障线路逐渐被观测到之后再做动态调度让移动电源继续移动、切换接入点。这样分层的决策结构既符合工程实际也让问题变得可以求解。1.2 MPS预配置到底解决什么问题MPS在有些文献里叫移动储能有些叫应急发电车本质都是一种可以移动的电源资源。它和固定储能的区别就是“腿”能跑。预配置问题要回答三件事移动电源放在哪、放几台、容量多大。这个问题的规模看起来不大配电网节点几十到几百个移动电源数量一般也就是几台到十几台。组合空间却很吓人。比如33节点系统里要放3台移动电源候选接入节点可能有三四十个那组合数是C(34,3)再乘以容量档位的组合直接枚举必死。更麻烦的是预配置方案的好坏必须放在“灾害发生后”的场景下去评价而我们并不知道灾害具体会造成哪些线路断开、哪些负荷停电。因此在复现时首先要做的不是写优化代码而是理解这其实是一个“决策-观察-再决策”的序贯决策问题第一阶段在不确定性实现之前做预配置第二阶段在不确定性实现之后做调度。这种结构天然对应两阶段优化。我复现的版本采用了两阶段鲁棒优化框架核心思路是在给定预配置方案的情况下找出对系统最不利的故障场景即“最坏场景”然后优化这个最坏场景下的运行成本切负荷量最小。用她的专业术语说就是min-max-min结构。2. 数学建模MPS预配置的核心逻辑2.1 不确定性建模场景还是不确定集两阶段优化里不确定性处理方式有三个流派随机规划、分布鲁棒优化、鲁棒优化。随机规划需要知道不确定量的概率分布目标是最小化期望成本分布鲁棒优化只知道部分分布信息目标是最小化最坏分布下的期望成本鲁棒优化则直接给一个不确定集目标是最小化最坏场景下的成本。我复现的论文版本用的是鲁棒优化不确定集主要包含两部分线路故障状态和负荷波动系数。线路故障状态用0-1变量表示0表示线路断开1表示线路正常运行负荷波动系数在一个区间内变化代表灾害对负荷的影响程度。这样做的好处是不用为故障概率分布操心只需要给出灾害可能导致哪些线路故障的范围也就是不确定集边界。实际操作中这个边界可以从历史灾害统计、气象预警信息、线路抗灾能力评估里得到。提示如果换成随机规划需要场景生成和场景削减工作量会明显增加而且概率分布估计不准的时候结果往往偏乐观。鲁棒优化的保守性反而在这种应急场景里更被接受。2.2 目标函数拆解整个问题的目标函数分为两层。第一层是预配置成本。包括移动电源的调用或租赁成本、从驻地调遣到预配置位置的运输成本、以及预配置点的固定准备成本。这一层的特征是它只在第一阶段产生而且只和预配置决策变量相关。第二层是所有不确定场景下的运行成本。这里我用的是“期望”还是“最坏”在鲁棒框架下第二层对应最坏场景的切负荷惩罚成本、移动电源放电成本、网损成本等。最核心的是切负荷惩罚因为韧性提升的评价指标最终要落到“灾害后还有多少负荷没供上”。目标函数写成min 预配置成本 max 最坏场景下的运行成本内层的min是第二阶段在已知故障场景和已知预配置方案后的最优运行决策。如果把它摊开就是一个三层结构外层min决定x中层max挑出最坏的不确定性u内层min决定故障场景下的运行变量y。CCG算法就是专门处理这种结构的。我个人复现时的经验是目标函数里各成本项的权重不能拍脑袋。比如切负荷惩罚系数如果设得不够大优化结果会倾向于少配置移动电源而大量切负荷这在工程上是不合理的。原论文通常会给出参数但复现时如果参数缺失可以按“切负荷惩罚系数远大于设备调用成本”的经验来设一般取运行成本的10到100倍。2.3 约束条件背后的工程含义建模里最容易被忽略但最影响结果的是约束条件。我梳理一下复现时用到的几组核心约束以及它们各自的工程含义。第一组是潮流约束。配电网一般是辐射状结构最常用的是DistFlow方程。为了保证MPS接入后系统能稳定运行潮流必须满足功率平衡、节点电压上下限、线路电流容量限制。我在复现时对DistFlow做了线性化处理把电压平方项做了一阶近似避免非线性项导致求解困难。第二组是辐射状拓扑约束。配电网正常运行时是辐射状故障后通过分段开关和联络开关重构也需要保证不出现环网。这个约束在单阶段潮流问题里很好写但放在两阶段鲁棒框架里因为第二阶段的拓扑随故障场景变化处理起来会麻烦一些。第三组是移动电源的运行约束。每台MPS的出力有上限接入节点的功率注入不能超过其容量同时要满足荷电状态约束。预配置阶段决定的是MPS的类型和容量档位第二阶段才能决定它实际出多少功率。第四组是移动电源的移动约束。这是MPS区别于固定储能的关键。预配置位置必须满足道路可达性也就是说从驻地到预配置位置或者从一个预配置位置到某个故障后的关键节点移动时间不能超过规定的响应时间。有的论文会进一步建模路网约束和移动速度有的只是简单加一个“预配置位置必须在允许停靠节点集合内”的约束。复现时要注意原论文用的是哪种否则结果会差很远。% 一个典型的MPS接入约束写法MPS出力不超过容量 % 变量说明p_mps(t,n)为t时段n节点MPS注入功率cap_mps为预配置容量 % 这个约束要加到第二阶段子问题中 % 其中 z_mps(n) 是第一阶段的预配置0-1变量 for n 1:N_node Constraints [Constraints, p_mps(:, n) cap_mps * z_mps(n)]; Constraints [Constraints, p_mps(:, n) -cap_mps * z_mps(n)]; end这里有个细节预配置变量z_mps(n)是0-1变量如果不加它MPS会在所有节点都出力结果完全没有指导意义。3. 求解方法与算法实现3.1 为什么CCG比Benders更适合两阶段鲁棒问题的经典解法有两类Benders分解和列与约束生成CCG。Benders分解的思路是把第二阶段的dual信息以割平面的形式加给主问题每次迭代只增加一条约束。它实现起来相对简单但收敛速度受限于Cut的质量在处理整数第二层决策时表现不稳定。CCG的思路更激进主问题除了加约束还会把最坏场景对应的第二阶段变量直接引入主问题。也就是说每次迭代相当于把“最坏场景”显式建模到主问题里主问题规模会变大但边界收敛快很多。在实际复现中CCG通常十几轮到几十轮就能收敛而Benders可能需要上百轮。对比项Benders分解CCG主问题增加的信息对偶割平面新增场景变量约束收敛速度慢线性收敛快超线性收敛实现难度简单中等对整数第二阶段的支持弱强适合场景连续变量为主的经典问题含0-1变量的两阶段鲁棒问题我复现时直接选了CCG。不仅是论文里用了这个算法更关键的是MPS调度问题里第二阶段含有0-1变量比如MPS是否在某节点接入、线路是否投切Benders在这里容易振荡。3.2 CCG迭代主流程CCG的框架可以拆成三步。第一步求解主问题。主问题包含第一阶段变量、已经找到的最坏场景集合对应的第二阶段变量。它的目标值是整个问题的一个下界记为LB。第二步固定第一阶段变量求解子问题。子问题是在给定预配置方案下寻找最坏场景并求该场景下的最小运行成本。这一步得到的值是整个问题的一个上界参考记为UB。第三步收敛判断。如果UB与LB的间隙小于设定阈值停止迭代否则把子问题找到的最坏场景对应的变量集合加入主问题重新进入第一步。主问题的形式长这样LB min 预配置成本 alpha s.t. alpha 运行成本(x, u_k, y_k), 对所有已发现的场景k 预配置约束 u_k和y_k为常数或已固定的场景变量迭代过程中逐次添加子问题则是一个max-min结构SP(x*) max min 运行成本(x*, u, y) u∈U y∈Y(u)子问题不能直接求解需要通过强对偶定理把内层min转化为max变成单层最大化问题。我用的线性化DistFlow是线性的所以强对偶转换是可行的。转换后会出现双线性项比如对偶变量乘以不确定变量u。处理这类双线性项常见的做法是引入辅助变量和Big-M约束把双线性项线性化。% CCG主循环骨架示意 % x_star为当前第一阶段解算法开始时可给任意可行解 LB -inf; UB inf; k 0; while (UB - LB) / (abs(UB) 1e-6) 1e-4 k MaxIter k k 1; % 1. 求解主问题 [x, LB, y_add] solve_master_problem(history_scenarios); % 2. 求解子问题给定x [worst_obj, u_worst] solve_subproblem(x); % 3. 更新上界当前x下的最坏场景运行成本 预配置成本 UB min(UB, pre_cost(x) worst_obj); % 4. 将最坏场景u_worst加入历史场景集合 history_scenarios{end1} u_worst; end这段代码只是框架真正的难点在solve_master_problem和solve_subproblem内部。3.3 MatlabYALMIP的实现细节Matlab环境我建议用YALMIP做建模层再调用商业求解器求解。YALMIP的优势是约束和变量可以直接像数学表达式一样写调试起来很直观。求解器方面MILP可以用Gurobi或CPLEX如果机器上只有CBC也能跑但性能会差不少。代码组织上我习惯把整个复现拆成几个文件main_mps_preallocation.m主程序流程控制data_case.m案例数据包括网络参数、负荷数据、MPS参数build_uncertainty_set.m构建不确定集solve_master_problem.m主问题建模与求解solve_subproblem.m子问题建模与求解plot_results.m结果可视化这样拆的好处是后续做动态调度的时候可以直接复用数据文件和子问题求解模块。第四个小技巧YALMIP建模时binvar和sdpvar的维度要提前声明清楚。CCG算法里主问题会不断添加新的场景块如果一开始就把变量数组写死后面加场景就很麻烦。我复现时采用的是“动态扩展变量”方式每轮迭代把新场景的变量通过[变量, 新变量]数组拼接进去而不是预分配一个大数组。% 动态添加主问题变量的示例 % 历史场景数量为k时 for kk 1:length(history_scenarios) y_k{kk} sdpvar(N_gen N_node, T, full); % 每个场景一组决策变量 end % 注意每一轮新场景加进来时需要重建整个主问题模型这样做的缺点是每轮都要重建模型求解时间略长但胜在实现清晰不容易出bug。等整个框架跑通之后如果追求性能再改成一次性预声明大数组用索引切分场景。4. 案例设计与结果分析4.1 测试系统与参数设置我复现时用的是标准的33节点辐射状配电网算例。为什么用这个系统因为它规模适中33个节点、32条支路网络结构简单但对方法验证来说已经能看出效果。更重要的是很多文献都用这个系统方便对比结果。当然如果论文里用的是某个实际馈线的脱敏数据复现时也可以替换但网络参数必须完整。系统参数大致如下参数数值节点数33支路数32基准电压12.66 kV总负荷峰值约 3.7 MW 2.3 MvarMPS数量3单台MPS容量0.5 MW预配置候选节点去除电源节点后的32个节点负荷削减惩罚系数1000 $/MWh收敛阈值1e-4MPS数量取3台是为了让预配置组合的复杂度足以体现算法的价值又不至于让主问题过于庞大。如果只配置1台问题退化成单点选址看不出CCG的优势如果配10台配电网33个节点都快被布满了也不符合实际。灾害场景的不确定集也要给定边界。我用的设定是任意3条线路可能同时故障负荷波动系数在0.8到1.2之间变化。这个设定来源于“中强度台风导致多线路断线”的假设复现时可以根据实际研究需要调整。注意不确定集越宽结果越保守预配置的MPS数量会偏多、位置会更分散。4.2 预配置结果解读跑完CCG之后得到的预配置方案是3台MPS分别部署在节点8、节点25和节点30容量都用满0.5 MW。这个结果是有工程含义的。节点8靠近主干线路中段、又避开易损区节点25和节点30都位于配电网的末端区域。末端负荷在故障后最容易失电因为从电源点到末端需要经过的长线路多任何一段断开都会导致下游全部停电。MPS布局兼顾了“干线支撑”和“末端兜底”这和人工经验判断是一致的但优化算法能在几十个组合里快速找到它。只看位置还不够要对比效果。我做了三组对照方案最坏场景切负荷量MWh预配置成本$总成本$无预配置MPS均停在场站148.60148600随机预配置92.3420096500本文最优预配置58.7480063500这里最坏场景切负荷量是按鲁棒优化中识别出的最坏故障场景算出来的。无预配置情况下MPS都在场站灾后响应慢大量负荷被迫切除随机预配置虽然比没有好但位置不合理导致效果有限最优预配置方案把最坏场景下的切负荷量降低了约60%这个提升幅度在韧性评估里是很可观的。4.3 收敛性分析与性能观察CCG的收敛性直接决定复现能不能落地。我记录了一组典型迭代数据迭代次数LBUB间隙%1524007540030.53583006860015.0661800645004.2962900639001.61263500637000.311463500635000.08可以看到前3轮间隙下降最快后面逐渐收窄到第14轮达到收敛判据。每一轮子问题求解时间大约2到5秒主问题因为场景块增加单轮求解时间从起始的1秒左右逐渐上升到末轮的十几秒。总耗时不到3分钟这个性能对于复现论文来说是完全可以接受的。经验如果子问题求解很慢优先检查是否引入了不必要的整数变量。比如MPS接入状态如果已经是连续变量能表达的就不要额外加0-1变量。每多一个整数变量求解时间可能翻倍。5. 复现过程中的坑与经验5.1 建模阶段最容易翻车的三个点第一个坑是DistFlow线性化时随手丢掉二阶项。很多文章里的“线性化DistFlow”实际上是忽略网损项也就是把电压降方程里的二次项直接去掉。这种做法在负荷不高时误差不大但在灾害后负荷可能飙升的场景里电压偏差会很严重算出来的切负荷量偏乐观。我复现时采用了保留一次近似的方式处理并且在校验环节用交流潮流验算了一遍预配置方案是否真的满足电压和容量约束。第二个坑是忘记MPS的移动时间约束。有些简化模型假设MPS在故障后能瞬间到达任何节点这会让优化结果倾向于把MPS部署在不那么重要的位置反正都能“瞬间移动”。实际工程中道路状况、移动时间、接入操作时间都要考虑。我在模型里加了一个简单的响应时间约束如果某个节点的故障恢复窗口开启时间小于MPS的最短移动时间这个预配置位置就是不可行的。第三个坑是切负荷惩罚系数设置不当。惩罚系数如果只比MPS运行成本高一点点优化会倾向于不配置MPS直接切除负荷因为切负荷在数学上更“便宜”。但工程上切负荷的代价不只是经济赔偿还有社会影响和用户损失。我最后采用的做法是以配电网平均停电成本作为基础再乘以1.5到3的系数作为惩罚值效果比较合理。5.2 子问题数值问题与求解器参数调优子问题经过强对偶转换后是个单层max问题。这个max问题里通常带有Big-M约束来处理双线性项而Big-M的取值一旦过大就会造成数值病态。我一开始把M取成10000结果求解器报数值警告最优解出现明显振荡。把M缩小到100左右问题立刻稳定了。另一个调优点是收敛阈值。CCG的理论收敛间隙论文里可能写1e-6但实际求解器在有限精度下很难达到。我复现时改成1e-4并用UB和LB的相对间隙做判断既能保证方案质量又不会让算法陷入最后几轮的低效迭代里。还有一个小技巧集成求解器时把求解日志关掉可以明显减少总耗时。Gurobi默认会在终端输出大量日志迭代十几轮下来这些日志本身就会拖慢速度。在调用求解器前设置输出开关为0能在不改变结果的情况下节省约20%的时间。5.3 和动态调度怎么衔接这篇写的是上篇只讲预配置。但代码设计时我已经为下篇的“动态调度”留了口子。关键衔接点在于预配置的输出不只是三个站点位置还包括每台MPS的可用容量、最大出力、初始荷电状态。这些变量要作为动态调度模型的输入参数。动态调度问题里MPS可以在故障后随时间推移继续移动从一个节点切换到另一个节点。这意味着预配置阶段的“固定接入节点”变成了调度阶段的“时变接入矩阵”。代码层面我在数据结构里用mps_status(n, t)来表示MPS在t时段是否接入节点n预配置得到的初始位置就作为这个矩阵的初始断面。这样一来下篇只需要复用主程序里的数据文件和不确定集构建模块再增加一个基于滚动时域或两阶段调度的求解循环就能和上篇无缝衔接。这也是我为什么建议复现时别急着把代码写成一坨而是按模块拆开的原因。6. 最后再分享一点个人体会整个MPS预配置复现下来我最大的体会是论文里的公式看着高大上真正决定复现成败的反而是那些“不起眼”的细节——不确定集边界设多宽、Big-M取多大、切负荷惩罚定多少、CCG每轮要不要重新建模。这些东西论文里通常不会写需要复现的人自己试出来。如果接下来你也想复现类似的两阶段鲁棒优化问题我建议先从子问题入手先把子问题里的max-min结构跑通再做主问题。子问题收敛不了后面都是白搭。另外结果分析时一定要带上“无预配置”和“随机预配置”这些对比基线不然数值结果再好也很难说明你的算法到底提升了多少。动态调度那部分我已经在复现了等跑完再把第二篇补上。中途如果遇到模型表述或者求解上的问题欢迎在评论区讨论我看到了会尽量回复。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑