资讯详情

资讯详情

配电网韧性提升:移动储能预布局与动态调度策略全复现

配电网韧性resilience这事做配电方向研究的这几年应该都有体感台风、暴雨、冰冻这类极端天气导致的故障往往不是常规N-1校核里能提前建模的而是大范围多点故障、长时间停电搅在一起。修复时间越长社会影响越大这就要求调度系统在故障发生前和故障发生中都得有“预案加实时动作”的能力。移动储能MES恰恰是这两端都能发力的装备——灾害前它可以开到关键负荷节点附近原地待命灾害后它可以跟着故障隔离的进程在网架上跑位充当临时电源。这篇博客要完整复现的就是一套面向配电网韧性提升的移动储能预布局与动态调度策略算例用经典的IEEE33节点系统全部代码在MATLAB环境实现。如果你正在做韧性评估、应急调度、移动储能规划这类的课题或者手头有论文需要快速验证思路这篇内容会特别适合你。我会把整个框架拆开讲模型怎么建、指标怎么定、代码怎么组织、图怎么复现、坑怎么避。内容偏工程实操但也把原理讲透保证拿到手能直接跑、能改配置、能换场景。1. 项目背景与整体设计思路1.1 配电网韧性到底是什么和传统可靠性有什么差别传统配电网可靠性关心的是“平均”意义下的指标比如系统平均停电时间SAIDI、系统平均停电频率SAIFI。这类指标基于长期统计针对的是单个或少数元件故障所以配电网规划里常见的安全准则是N-1校核失去一条馈线或一台变压器后网络还能不能通过联络转供把负荷带起来。极端灾害事件完全不同。台风过境时可能十几条馈线同时跳闸变电站出口保护动作配电网被切成若干个孤岛。这时N-1校核没有意义因为N-kk很大的事件已经发生。韧性resilience正是衡量系统在这样的小概率高损失事件下能否“扛得住冲击、快速恢复”的能力。学术上一般用性能函数F(t)来描述正常运行时期F(t)1灾害冲击后F(t)急剧下降随后随着故障修复和应急措施逐步回升。系统韧性就可以理解为性能曲线与时间轴包围的面积或者说负荷供应率在整个事件周期内的期望值。我接触不少刚开始做这个方向的同学最容易犯的错误是把“可靠性优化”和“韧性优化”混为一谈。其实核心区别就一句话可靠性关心的是长期平均失负荷韧性关心的是极端事件下性能跌到什么程度、多久能拉回来。因此韧性提升策略往往需要“事前预防事中响应”配合也就是你会在标题里看到“预布局与动态调度”两个动作的原因。1.2 移动储能既是“充电宝”又是“移动电源”移动储能Mobile Energy Storage System, MES说白了就是把电池组、PCS和控制系统集成在运输车辆上。和固定式储能电站相比它的优势不是效率或度电成本而是“可移动”这个自由度。在配电网韧性场景里这个自由度能解决固定储能解决不了的两类问题。第一类是故障隔离后的孤岛供电。配电网灾害后的失电区域往往被隔离在故障段之外固定储能如果正好装在被隔离的节点上整个灾害过程中它只能在原地放电放完就没了而MES可以在故障发生前通过预测的灾害影响范围被预判性地部署到最可能失电的高优先级负荷附近。第二类是恢复期内的“再生”能力。MES电量放完后它可以沿未故障的线路开到还有电的区域从网上充电再开回孤岛放电。说句大白话固定储能是“一次性充电宝”MES是“能自己跑回去补电的移动电源”。当然MES也有代价移动需要时间移动路径受道路和配网拓扑约束电池在移动过程中不能参与充放电这些约束在动态调度模型里都得老老实实写进去否则解出来的方案在工程上根本不可行。后面第2.3节会详细讲这块的建模。1.3 预布局与动态调度如何衔接这套策略的总体思想是“两条腿走路”。在灾害来临之前通常提前24到48小时我们只有天气预报和故障概率没有确定性故障信息此时要做的是把有限数量的MES预先布置到若干候选节点——这是第一阶段“预布局”对应英文里的Pre-positioning。在灾害发生过程中随着继电保护动作、故障隔离区域逐步明确系统会获得越来越多的实测信息。这时候需要在一个滚动时域上重新决策各台MES当前停留在哪个节点、下一时刻要不要转移到别的节点、在某个节点是充电还是放电、放给哪些负荷——这是第二阶段“动态调度”对应Dynamic Scheduling/Re-dispatch。两阶段的衔接点是状态变量。预布局阶段解出的初始位置作为动态调度阶段t0时刻的已知条件动态调度的每一轮滚动求解又会把上一轮最优解的前几个时间步结果固定下来形成“预布局定起点、动态调度定路径”的闭环。我在实际复现里会额外加一个步骤把所有故障场景按概率加权预布局目标函数直接写成期望韧性最大而不是某个单场景最优。这样能保证最终方案在全场景平均意义下不差同时又留出了动态调度在实时信息下修正的余地。1.4 为什么选IEEE33节点作为复现算例IEEE33节点是配电网研究中出镜率最高的放射状测试系统33个节点、32条支路、5条联络开关系统基准电压12.66kV基准容量10MVA总有功负荷约3715kW、无功负荷约2300kvar。系统参数在大量文献里都能查到拓扑图也是一看就懂的那种。选择它做复现算例有三个实在的好处。第一是规模适中33节点的MILP模型商业求解器一般几秒到几十秒就能出全局最优不需要上高性能计算第二是结构代表性强它包含多条主干馈线和分支馈线可以构造出多种故障隔离场景能体现“故障上游有电、下游失电”的典型韧性困境第三是便于画图验证节点和支路的关系简单拓扑图、电压剖面、孤岛划分图可以直接用MATLAB的绘图命令画出来结果是否和论文一致很容易肉眼检查。我自己做扩展实验的时候还会在IEEE33节点基础上多接几个分布式光伏电源或者在部分节点把负荷替换成重要用户比如医院、数据中心用来检验策略对不同负荷等级的区分度。这套框架改动起来很灵活后面代码部分会提到对应的参数入口。2. 核心数学模型与关键公式拆解2.1 韧性评估指标怎么定义复现任何一篇韧性提升论文第一步都是把它的韧性指标复刻出来否则后面所有结果都无法对比。这套策略用的指标是“系统负荷供应率曲线”和“期望失负荷电量”的组合形式。性能函数F(t)可以定义为t时段所有负荷节点的加权供电比例F(t) (Σ_i w_i x_i(t) P_i_load) / (Σ_i w_i P_i_load)其中i是负荷节点w_i是权重系数x_i(t)是0-1变量1表示负荷由电网或MES供电P_i_load是正常时的有功功率需求。韧性综合指标一般写成事件周期[0,T]内F(t)曲线下面积的期望或与理想面积的比值即R E[Σ_t F(t) Δt] / (T × 1)本质上就是“整个灾害过程里实际供上电的能量占总需求的期望比例”。也有些版本用加权失负荷量来表示目标函数越小越好数学上两者等价。做复现时建议把指标做成独立函数输入运行结果输出韧性数值。这样不同方案无MES、固定储能、MES预布局动态调度之间的对比就变成一个干净的表格审稿人和导师都能一眼看懂。2.2 预布局阶段的优化模型预布局发生在灾前决策的核心问题是若有M台MES、S个候选站址应该把M台MES分别放到哪里模型输入是灾害场景集合每个场景包含故障线路集合、修复时间、时段负荷修正系数输出是MES的初始布点方案。目标函数通常写成最小化期望失负荷量min Σ_s p_s × Σ_t Σ_i (1 - x_i,t^(s)) w_i P_i_load Δt其中p_s是场景s的出现概率x_i,t^(s)是在场景s下采用某种调度规则后负荷是否恢复供电。约束主要包括预布局数量约束每个候选站址最多放一台MES总共放的台数等于M候选站址约束通常限定在重要负荷节点或配电站附近的特定节点与动态调度的耦合约束预布局位置必须等于动态调度初始时刻MES所在位置。注意预布局本身并不直接决定负荷如何恢复它给出的只是“初始条件”最终负荷恢复由动态调度的最优解决定。因此严格来说两阶段应该用主问题-子问题迭代甚至Benders分解来整体求解但工程复现里很多实现会采用“先场景平均求解预布局再用确定性滚动调度仿真每个场景”的简化方式。我在复现中采用的是后者好处是代码简单、运行快坏处是预布局可能不是理论最优但韧性指标提升依然明显作为工程分析完全够用。2.3 动态调度阶段的滚动优化模型动态调度是代码实现里最重的部分。在每个时间步t_0给定当前故障隔离信息、MES当前位置和SOC求解一个有限时域T_s的优化问题决策未来各时段每台MES在哪位置变量每台MES是充电、放电还是待机P_ch、P_dis每个负荷节点是否恢复供电x_i。目标函数是未来T_s时域内的加权失负荷量最小同时可以考虑MES移动代价和电池损耗不过多数复现版本为了突出韧性只保留失负荷项和很小的移动惩罚项。约束数量较多挑三个关键的说。节点功率平衡用线性DistFlow方程辐射状网络的线性近似对每个节点jP_j_in P_j_DG P_j_dis - P_j_ch - P_j_load × x_j Σ_km P_km电压约束表示为父节点电压与支路潮流的关系V_j V_i - 2(r_ij P_ij x_ij Q_ij) / V_base支路潮流功率设置上下限。这个线性化忽略了支路损耗平方项在12.66kV的33节点系统里精度足够常用于韧性恢复类问题。MES的荷电状态SOC递推E_t1 E_t η_ch × P_ch × Δt - P_dis × Δt / η_dis同时要求同一时间不能既充电又放电P_ch × P_dis 0实际用二进制变量或大M做线性化充电功率不超过额定值SOC不超过上下限。MES的移动过程用“时空网络”建模。节点i在时段t的位置变量是0-1的如果上一时段在i、本时段要赶到j且两者间行驶时间τ_ij大于等于1个时段则中间时段该MES不能在任何节点充放电。这个约束是动态调度容易写错的地方我在第2.4节和第5.3节会专门给一个正确写法。2.4 约束条件的线性化处理技巧移动储能相关的模型几乎所有的难点都来自二进制变量。把二次、逻辑、非凸约束线性化是代码能不能跑通的关键。分享三个常用技巧。第一个技巧是“充放电互斥”。P_ch和P_dis之间用Big-M法0 ≤ P_ch ≤ b_ch × P_rated0 ≤ P_dis ≤ b_dis × P_ratedb_ch b_dis ≤ 1b为0-1变量。这样就不需要写非线性乘积。第二个技巧是“预布局位置与调度初值的耦合”。如果预布局变量是u_i0-1表示MES初始在i动态调度初始位置变量是z_i(0)0-1那么加约束z_i(0) ≥ u_i如果预布局在i初始位置必须也在i。注意如果M台MES可区分要加台数下标。第三个技巧是“交通转移弧约束”。设δ_i,j(t)是0-1变量表示MES在t时刻从节点i转移到j则每个时段每个MES只能在一个位置且“该时段”与“上一时段位置”之间通过转移弧衔接。若τ_ij2个时段则t时刻出发到达j的MES在t1和t2时刻不能放电只能处于“行驶中”状态在模型里就是所有时段的功率变量强制为0。这一条如果不写求解器会给出“瞬移充电”这种物理上不可能的方案这是我在评审论文时经常看到的模型缺陷。3. 基于MATLAB的代码实现方案3.1 环境准备工具箱与求解器配置复现这套策略MATLAB环境里必须有三个东西MATLAB本体建议2020a及以上主要是兼容Yalmip和绘图函数、Yalmip优化建模工具箱、以及一个能解MILP的求解器推荐Gurobi其次CPLEX。Yalmip的安装非常简单下载压缩包后解压到任意目录然后在MATLAB里执行addpath(genpath(你的Yalmip目录)); savepath;就完成了。注意Yalmip不一定自带求解器必须单独装Gurobi或CPLEX。Gurobi对学术用户提供免费许可证安装完成后在MATLAB命令行执行gurobi_setup然后用yalmiptest验证是否成功。如果执行optimize时报“No suitable solver”99%是这一步没做干净见第5.1节。有一点要提醒各位这套模型是MILP如果只依赖MATLAB自带的linprog或intlinprog虽然intlinprog也能解0-1整数规划但33节点加几十个时段加多场景的规模性能会差很多。我之前试过用intlinprog跑30分钟还没收敛换Gurobi后同样问题几十秒出结果。所以如果你准备长期做这类研究求解器这个环节不要省。3.2 目录结构与数据准备拿到一套复现代码第一步不是双击运行而是先看目录。我习惯的工程化结构如下root/ ├─ main.m % 总入口数据加载→预布局→动态调度→绘图 ├─ case33.m % IEEE33节点参数支路阻抗、负荷、联络开关 ├─ load_data.m % 读取负荷曲线、故障场景、MES参数 ├─ params_mes.m % MES数量、容量、功率、速度、候选站点 ├─ model_pre_position.m % 预布局MILP建模函数 ├─ model_dynamic_schedule.m % 动态调度MILP建模函数 ├─ solve_wrapper.m % 统一调用Yalmip求解器的封装 ├─ plot_resilience.m % 画韧性曲线和拓扑图 ├─ plot_soc.m % 画SOC和功率曲线 └─ data/ ├─ load_profile_24h.mat ├─ fault_scenarios.mat └─ candidate_sites.mat其中case33.m是核心数据入口包含33个节点的负荷和32条支路的阻抗写成矩阵形式load_data.m负责把负荷曲线、故障场景从data目录加载进来。建议所有数据都用.mat或xlsx格式硬编码虽然省事但改参数时容易漏。数据里有三个最值得注意的点。一是负荷曲线通常取24小时日曲线15分钟或1小时一个点二是故障场景每个场景是一组断开支路编号和预计修复时间可以用蒙特卡洛抽样产生也可以用典型灾害场景人工指定三是MES参数建议单独写成params_mes.m方便做台数和容量灵敏度分析。3.3 主程序流程与关键函数说明main.m的流程基本是四段式。第一段加载所有数据初始化结果存储结构体。第二段调用model_pre_position求解预布局得到mes_init_position。第三段进入时间循环对每个调度周期调用model_dynamic_schedule求解滚动优化并把结果写入records结构体。第四段调用绘图函数输出韧性曲线、SOC曲线、电压剖面。预布局函数model_pre_position.m内部流程遍历场景提取每个场景的故障线路和负荷修正系数建立决策变量u布点0-1、初始时刻的MES位置z、以及简化调度变量x写目标函数期望失负荷最小和约束数量限制、潮流、储能、耦合调用solve_wrapper求解输出u。动态调度函数model_dynamic_schedule.m内部流程输入当前时刻t0、当前故障状态、MES位置和SOC初值构建未来Ts个时段内的决策变量x、P_ch、P_dis、位置转移变量写目标与所有约束求解并返回前一步的动作序列滚动执行。如果你不熟悉Yalmip记住一个核心套路sdpvar定义连续变量binvar定义0-1变量assign给变量赋初值optimize(Constraints, Objective, options)求解value()取值。这套结构非常清晰所有约束都往Constraints里追加即可。3.4 核心代码段解读下面给三段代码都是在复现过程中绕不开的。第一段定义动态调度变量和主线约束。T 24; % 调度时域 nB 33; % 节点数 nM 3; % MES台数 x_load binvar(nB, T, full); % 负荷供电状态 P_ch sdpvar(nM, T, full); % MES充电功率 P_dis sdpvar(nM, T, full); % MES放电功率 E sdpvar(nM, T, full); % MES 能量 b_ch binvar(nM, T, full); % 充电状态标志 b_dis binvar(nM, T, full); % 放电状态标志 pos binvar(nM, nB, T, full); % MES所在节点 trans binvar(nM, nB, nB, T, full); % 转移弧变量第二段SOC递推和充放电互斥约束。for k 1:nM for t 2:T Constraints [Constraints, E(k,t) E(k,t-1) ... eta_ch * P_ch(k,t) * dt ... - P_dis(k,t) / eta_dis * dt]; end Constraints [Constraints, P_ch(k,:) P_rated * b_ch(k,:)]; Constraints [Constraints, P_dis(k,:) P_rated * b_dis(k,:)]; Constraints [Constraints, b_ch(k,:) b_dis(k,:) 1]; Constraints [Constraints, E_lo E(k,:) E_up]; Constraints [Constraints, E(k,1) E_init(k)]; end第三段位置唯一性和转移约束。for k 1:nM for t 1:T Constraints [Constraints, sum(pos(k,:,t), 2) 1]; end for t 2:T % 位置变化依赖转移变量并且行驶中的时段不能充放电 for i 1:nB for j 1:nB if t tau_ij(i,j) 1 Constraints [Constraints, ...]; end end end end end第三段代码我故意省略了细节原因是转移弧约束的完整写法要根据你定义的trans变量语义来定。如果你的trans(k,i,j,t)表示第k台MES在t时刻从i到j那么约束是t时刻位置pos(k,:,t)与t-1时刻位置之间的关系满足“如果发生转移则位置改变”并且转移时段功率强制为0。不同论文的记号不同复现时建议先画一张时空网格图把“停留弧”和“行驶弧”标出来再写约束基本不会错。这是我在第一次复现时反复改bug的地方后面第5.3节还会提到。4. 完整复现流程与结果验证4.1 从零运行的详细步骤假设你已经把代码和数据放到同一个目录按照下面步骤跑通整套流程。第一步在MATLAB中切换到代码根目录先执行一次数据检查load_data; % 或直接运行 case33 并查看输出看看负荷曲线、候选站点、故障场景三个变量的维数是否符合预期。我发现大部分“复现不了”的问题都出在初始数据没加载上而不是模型写错。第二步执行预布局求解。在main.m里把run_dynamic_flag设为0只运行预布局输出mes_init_position。记录一下求解时间如果超过10分钟就要检查求解器配置或模型规模见第5.3节。第三步打开动态调度把run_dynamic_flag设为1让主程序按时间循环滚动求解。每个时段求解完成后用disp输出当前解的状态确认没有infeasible。第四步运行绘图脚本plot_resilience和plot_soc检查三条曲线韧性F(t)、各台MES的SOC、关键节点的电压。如果这三张图和论文里的定性规律一致就可以认为复现成功。需要提醒的是运行前一定要确认工作目录里有result字段初始化防止循环里第一次写入时就报错。我推荐把所有输出统一写到结构体records里而不是散落一堆全局变量调试时会轻松很多。4.2 结果图表怎么查看和验证一套合格的韧性提升代码至少要输出四类图。第一类是系统拓扑与预布局结果图。把33节点系统按实际连接关系画成放射状拓扑正常节点用圆圈失电孤岛用方块MES初始位置用红色五角星标出。“好的”预布局结果是MES大多落在重要负荷节点附近且分布在不同馈线分支上而不是挤在同一个变电站出口。第二类是韧性曲线F(t)。横轴是小时纵轴是负荷供应比例。你应该看到三条曲线无MES、固定储能、MES预布局动态调度。无MES曲线在故障后跌得最深恢复最慢固定储能会有一个小的支撑峰MES策略的曲线下方凹陷最小恢复上升最快。曲线下面积就是韧性值可以用附表方式把数值列出来。第三类是MES的SOC-功率图。理想情况下MES在灾害初期放电低SOC时移动到有电区域充电然后再回到失电节点放电SOC曲线呈现“高-低-高-低”的锯齿形。如果SOC曲线一直是平的说明移动充电功能没被触发大概率是移动约束写松了求解器选择了原地放电不动。第四类是节点电压剖面。MES放电的节点电压应该被维持在0.95~1.05p.u.之间。如果电压越界说明潮流约束或MES功率上限给得不对或者是负荷权重压倒了电压越界的惩罚。这四类图都要和“论文复现目标”对照。我自己验证的方法是把论文里的曲线截图放一边把代码生成的曲线放另一边逐段比较变化趋势重点看拐点的时间位置。数值允许有小的偏差受场景随机性影响但趋势必须一致。4.3 对照实验与灵敏度分析复现不只是把代码跑通还要用对照实验证明策略的有效性。我在这套代码里预留了三组最容易做的灵敏度分析改动量很小产出很高。第一组改变MES台数。把params_mes.m里的nM从1改到5分别跑完整流程记录失负荷量和韧性值。通常会得到一条边际递减曲线从无MES到1台MES改善最明显从3台到5台改善趋缓。这个图可以直接支撑结论“MES数量不是越多越好要考虑投资成本”。第二组改变预布局的候选站点集合。候选站点只开放重要负荷节点和全部负荷节点两种情况对比预布局结果和韧性指标。你会发现候选站点太少时MES预布局会失去灵活性动态调度的发挥空间也变小。这解释了为什么预布局阶段就要做站址初筛而不是把布点问题完全交给动态调度。第三组改变故障场景数量。从10个场景增加到200个场景预布局解的稳定性会变好但计算时间线性上升。你可以画一张“场景数-求解时间”和“场景数-韧性值”的双轴图说明采用场景抽样时的权衡。下面是一个典型的表格输出格式我自己写报告时常用方案失负荷量(MWh)韧性值求解时间(s)无MES32.40.682-固定储能×326.80.73745MES预布局动态调度×319.50.80978这类表格在论文里放出去比堆一堆曲线更直观。4.4 性能与收敛性分析MILP求解性能是需要提前规划的不然很容易出现第一轮调度求解就要半小时后面的滚动循环根本跑不完。影响求解时间的因素主要有三个二进制变量数量、时间步数量、场景数量。以33节点、24时段、3台MES为例位置变量pos就是3×33×242376个0-1变量转移变量trans如果是全连接那规模是3×33×33×2478408个0-1变量这个量级求解器会非常吃力。一个非常实用的缩减法不是所有节点之间都存在可行转移只对满足道路距离约束或同馈线可达的节点对建立转移变量能砍掉90%以上的二进制变量。针对求解性能我在代码里通常会设置三个求解器选项options sdpsettings(solver,gurobi, ... gurobi.MIPGap,0.01, ... gurobi.TimeLimit,600, ... verbose,2);MIPGap设到0.01通常足够工程精度TimeLimit设600秒防止个别时段卡死。如果发现某个时段超时可以把该时段的模型单独拿出来用更小的T_s或者更粗的时间步长比如从0.25小时改成1小时重跑。这个思路比盲目增加TimeLimit有效得多。还有一个小技巧滚动调度时上一轮求出的下一时段解可以作为当前轮次的MIP start热启动。在Yalmip里用assign函数给变量赋初值再把warmstart选项打开对加速很有帮助尤其是在连续多个时段场景变化不大的情况下经常能省一半求解时间。5. 复现过程中的常见问题与排查5.1 求解器安装和许可证问题这个问题出现的频率绝对排第一。症状很典型运行optimize时报“No suitable solver for...”或者“solver not found”。排查路径按照下面顺序走确认Gurobi或CPLEX已经安装并且版本和MATLAB位数一致64位MATLAB配64位求解器在MATLAB里运行gurobi_setup或cplex_setup看到“Added ... to path”才算成功运行yalmiptest查看输出里对应solver的状态是否为“available”如果还是不行检查环境变量路径是否配好重启MATLAB。我第一次装的时候就是漏了第4步环境变量没写进系统gurobi_setup虽然提示成功但重启MATLAB后又失效。解决办法是手动把安装目录加入系统环境变量PATH然后在MATLAB里重新验证。还有一个常见的坑Gurobi学术许可证文件gurobi.lic默认放在用户目录下有时Windows系统下权限问题导致找不到许可证。建议把许可证路径明确设到环境变量GRB_LICENSE_FILE确保MATLAB能读取。5.2 矩阵维度不匹配与索引越界Yalmip建模时最烦的报错是Inner matrix dimensions must agree。这类问题几乎都出在维度定义和数组索引不一致上。我常用的三个检查手段在定义完所有变量后用size()逐一检查每个变量的维度重点检查sdpvar和binvar定义时行列是否写反在追加任何一条约束前先验证涉及的矩阵如支路导纳矩阵、负荷矩阵的行列数与节点数、时段数是否对得上使用调试模式断点暂停在报错行看Yalmip内部变量大小再回头查数据。出现维度错误时八成是某个矩阵是33×1而另一个是1×33而约束表达式直接相加。统一用列向量表示节点维度nB×1用行向量表示时段维度1×T再配合repmat或reshape能极大减少这类低级错误。还有一个和索引相关的坑MATLAB索引从1开始而很多数据表里的节点编号从0开始比如某些IEEE数据文件。如果复制外部数据后忘了加1就会频繁出现“预布局解出来的节点号比实际最大节点数还大”的荒谬结果。建议在case33.m里定义线性索引表并在读数后马上断言max(node_id)1≤nB。5.3 模型不可行与求解时间爆炸动态调度出现Infeasible problem是复现中另一个让人头大的问题。真正的原因是约束之间互相矛盾常见有三类。第一类是MES移动时间约束过于理想化。如果假设MES可以在1个时段内从节点1移动到节点30但现实距离根本不可能那么某些时序约束、位置约束、供电约束就会冲突。排查方法先把移动约束全部注释掉看看模型是否可行如果可行说明就是移动约束太紧需要把候选转移节点对缩减到道路可达范围。第二类是SOC初值设置不合理。如果预布局阶段给出的某台MES初始SOC本来就很低而灾害刚开始又需要它连续放电10小时很容易在某个中间时段跌破SOC下限。解决办法是给预布局目标函数加一个“初始SOC惩罚”或者在动态调度里把SOC下限稍微放松比如从0.2放到0.1观察韧性值变化。注意这只是排查手段正式实验还得把SOC下限调回工程合理值。第三类是潮流约束的线性化在极端场景下失真。33节点系统用LinDistFlow本来精度足够但如果某些节点有功功率很大、无功也大线性化后的电压误差可能达到几个百分点进而导致约束冲突。排查方法把LinDistFlow的电压上下限从0.95~1.05暂时放到0.90~1.10如果模型从不可行变成可行就能确认是潮流近似误差导致的再回到原约束下增加支路损耗修正量。如果模型本身可行但求解时间爆炸我通常按下面顺序处理减小时间步数T_s滚动时域从24降到12减少候选转移弧的二进制变量给MIPGap和TimeLimit设置明确阈值使用上一轮解的warm start。这些手段加起来通常能把单个时段求解时间从几分钟压到几十秒。5.4 结果不收敛怎么定位收敛性主要指两层含义一是求解器迭代是否收敛到可接受gap二是多次运行结果是否稳定。前者上面已经说了这里重点说后者。预布局和动态调度都依赖场景集合如果场景用随机抽样生成每次运行结果可能不同。为了保证可复现性在main.m最前面加rng(2024)固定随机数种子这样哪怕重跑100次结果也完全一样。这个细节很多人不在意但论文写“perfect reproduction”时这是基本要求。如果固定种子后结果仍然不稳定就要检查场景抽样数量是否太少。用10个场景和500个场景得到的预布局方案稳定性差异非常大。我的经验是作为快速验证用100个场景足够作为正式结论至少跑500个场景并做方差分析。不要等到审稿人质疑时才发现运行结果不稳定。还有一种“假不收敛”目标函数值差了几个数量级但曲线形状一模一样这时大概率是单位制的问题。比如目标函数里用了MWh而负荷单位是kW时间单位是h数值上差1000倍曲线当然看起来不收敛。我建议在模型文件头部统一做单位换算P_base 10; % MVA基准容量 % 所有功率变量统一先除以P_base转成标幺值标幺值化以后数值范围集中在0~1左右求解器的数值稳定性和收敛速度都会明显改善。下面是问题速查表贴在代码注释里也很有用现象可能原因排查动作求解器未找到环境未配置运行gurobi_setup、yalmiptest维度不匹配行列索引颠倒size()检查每个变量模型不可行移动约束过紧先注释移动约束测可行域结果不稳定随机种子未固定/场景过少rng固定增加场景数数值差异大单位不统一功率统一标幺值化在我自己复现这套策略的过程中最花时间的不是建模而是把单位制和索引从论文里的数学记号转换成MATLAB代码。上面这张表基本覆盖了我踩过的坑照着走一遍能省好几个晚上。最后再分享一个小技巧拿到任何一套复现代码先别急着跑全流程。把预布局单独跑一遍把动态调度单独跑一遍用测试数据把每一步的输出都打出来确认再组合起来。这个“分步验证”的习惯比任何调试工具都管用。后面的课题如果要扩展这套模型比如加维修队联合调度、加交通网约束、或者做多时段联合规划都可以基于这个框架逐步加模块整体代码不用推倒重来。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →