资讯动态

微电网多时间尺度调度:PSO+MPC三级协同优化实战

发布时间:2026/9/9 23:53:08 来源:尧图企业网站定制
1. 先搞明白为什么单一时间尺度调度在含新能源场景下扛不住接手这个课题之前我其实先后踩过两个方向的弯路。最初我也和大家一样拿到多时间尺度联合调度的题目第一反应是找几篇综述把日前、日内、超短期的三层框架画出来然后Matlab里直接把PSO套上去。但真正把代码跑起来、把曲线一条条调出来看的时候才发现问题根本不在会不会调PSO而在为什么必须分三个时间尺度这件事没想透就写代码后面全是补丁。先说一个最直观的现象。同一套负荷数据提前24小时做的预测偏差普遍在5%到10%之间提前4小时做偏差能压到2%到5%等到提前15分钟再做预测误差通常可以控制在1%到3%以内。这不是哪个预测模型不够好而是预测问题本身的规律——时间越近信息越充分不确定性越小。风电光伏这类可变电源更是如此云层飘过来光伏出力十分钟内能掉一半这种短时波动在日前时间尺度上根本不可能被精确预知。这就是多时间尺度联合调度最底层的逻辑起点与其指望一次优化把所有时间段的决策都定死不如把一个大问题拆成事前安排事中修正的递进结构。日前先做一个全局性的经济安排日内和超短期再根据最新的预测信息进行滚动修正。换句话说单一时间尺度调度的核心矛盾不是算法不够强而是信息时间错配——你拿着24小时前的预测去决定15分钟后的出力再好的优化算法也救不了输入数据的时效性。另一个推动多时间尺度架构落地的现实因素是约束的多样性。日前调度只需要考虑小时级的功率平衡、机组爬坡、备用容量这些慢约束到了日内和超短期还要加上线路潮流越限、电压越限、储能SOC上下限、爬坡率限制这些快约束。如果全部塞进一个模型里问题规模会爆炸式增长而且约束之间的时间特性差异会导致求解器在数值上非常不稳定。分尺度之后每个层级的约束复杂度都大大下降问题性质也清晰得多。所以这篇东西我想从一个完整的工程实现视角来拆解这套东西涵盖三层时间尺度的目标函数差异设计、PSO和MPC的组合分工逻辑、Matlab代码实现时的数据流设计以及我实际调试中踩过的一堆坑。比较适合正在做微电网、综合能源系统或者虚拟电厂调度的研究生和工程师参考。1.1 负荷预测精度的时间尺度递减律先把这个规律量化一下它直接决定每级调度的模型复杂度和算法选择。调度层级时间窗口分辨率典型预测误差主要不确定性来源日前24小时1小时5%~10%气象预报误差、用电行为波动日内4小时15分钟2%~5%云层移动、温度突变、设备启停超短期15分钟5分钟/1分钟1%~3%局部风速湍流、光伏云遮蔽瞬时效应这组数据不是我编的你拿任意一个公开数据集做几组对照实验就能复现。关键在于不同时间尺度上的误差特征完全不同所以各级调度的目标函数侧重点也必须不一样。日前调度面对的是大范围、慢变化的不确定性这时候最优策略是追求全局经济性把机组组合、购电计划、储能充放电的大框架定下来。日内调度面对的是中等幅度、中等频率的波动它的任务是让实际运行轨迹尽量贴近日前计划同时允许局部调整来消化预测偏差。超短期调度面对的是高频小幅波动它追求的是功率平滑度和快速响应能力很多时候牺牲一点经济性也要把波动压住。这个递减律直接决定了我在后面设计目标函数时的权重分配逻辑——不同层的目标函数侧重点必须不一样不能用一个统一的目标函数包打天下。1.2 可变电源让传统一次调度定终身模式处处被动传统电力调度里日前计划做出来之后AGC自动发电控制系统在实时运行层面做小幅调整就够用了因为火电、水电这些可控电源的出力相对稳定负荷的波动也有规律可循。但风电光伏大规模接入之后情况完全变了。假设某天中午光伏出力预测是满发100MW按这个做了日前调度安排火电机组压低出力。结果下午两点云层聚集光伏实际出力只有40MW这时候如果只能靠AGC慢吞吞地往上调火电爬坡速率按3MW/分钟算补上60MW缺口需要20分钟中间这段功率不平衡只能靠系统惯性和备用硬扛。要是备用不足频率就开始往下掉严重时直接触发低频减载。这就是为什么日内和超短期滚动优化不可或缺。滚动优化的本质是不断用新信息替换旧假设——每到一个新的调度时刻就把最新的预测数据、最新的状态估计灌进优化模型重新计算未来一小段时间内的最优控制序列但只执行第一个控制动作然后等下一个调度周期再滚动一次。通过这种高频的局部调整把预测误差在变成实际事故之前就消化掉。多时间尺度调度架构的本质可以类比成开车导航日前计划像出发前规划的整体路线日内滚动像开在高速上根据实时路况调整车道超短期修正像临近出口时的最后微调。三层配合起来既保证了大方向的经济性和可行路径也兼顾了行驶过程的平稳性和灵活性。2. 三级时间尺度的职责划分与目标函数设计差异这个章节是整个课题的核心。很多文章会把日前采用经济性目标、日内采用跟踪目标、超短期采用平抑目标一句话带过但真正落到代码里你会发现每个字都需要翻译成具体的数学表达式和Matlab数组操作。这里我按自己的实现方案逐层拆开讲。2.1 日前计划层求解什么、用哪个目标日前调度层的时间窗口是24小时分辨率1小时决策变量包括各机组开停机状态0/1变量、各机组逐小时出力、储能逐小时充放电功率、与上级电网的交换功率。在这一层我使用的目标函数是系统综合运行成本最小化表达为[ \min \sum_{t1}^{24} \left[ \sum_{i} (a_i P_{i,t}^2 b_i P_{i,t} c_i) \cdot u_{i,t} C_{grid,t} \cdot P_{grid,t} \lambda_{ess} \cdot (P_{ch,t} P_{dis,t}) \right] ]其中 (u_{i,t}) 是机组启停状态(P_{grid,t}) 是购电功率负值为售电(\lambda_{ess}) 是储能充放电的折算损耗成本系数。这里需要特别提醒的是日前目标函数不要加入平抑波动或跟踪效果这类目标。原因很简单时间分辨率是1小时本身就滤掉了高频波动你在这一层考虑平滑性等于徒增计算负担还会牺牲经济性。数据上用Matlab的timeseries和resample函数把原始15分钟数据聚合成1小时数据时我建议用均值而不是求和否则负荷数据和光伏数据之间会出现量纲不一致的问题。这个细节很小但很多人在这里栽过跟头。日前层求解我用的就是PSO。为什么选PSO而不是二次规划或者混合整数线性规划因为日前问题里带了机组启停0/1变量、非线性发电成本曲线整个问题是非凸的PSO这类群体智能算法天然适合这种不需要凸性假设的黑箱优化场景。后面章节我会详细说PSO在这里的编码方式和参数配置。2.2 日内滚动层MPC如何接过接力棒日内调度层的窗口是未来4小时分辨率15分钟预测时域Np16步控制时域Nc4步。这一层的基本任务是让系统实际出力轨迹尽量贴近日前计划同时根据最新预测修正偏差并考虑设备调节代价。这里我选择MPC的核心理由是MPC天生就是为带约束的轨迹跟踪设计的。它把优化问题嵌入到一个反复执行的框架里每个周期求解一个有限时域优化问题然后只实施第一步控制动作下一个周期再重新求解。这种边走边看的特性与日内调度的需求完全吻合。日内MPC的目标函数我设计为三项加权和[ \min \sum_{k0}^{N_p-1} \left[ w_1 | P_{act}(tk) - P_{plan}(tk) |^2 w_2 | \Delta u(tk) |^2 w_3 | P_{tie}(tk) - P_{tie,ref}(tk) |^2 \right] ]第一项是实际出力与日前计划的偏差惩罚第二项是控制动作变化率的惩罚防止出力调整过猛第三项是联络线功率与参考值的偏差惩罚。这三个权重 (w_1, w_2, w_3) 怎么标定后面权重标定章节我会专门讲这里先提一句不要拍脑袋填1、1、1量纲完全不一样直接一组梯度实验定出来。MPC的约束处理相比日前层要精细得多。日前层只需要满足功率平衡、机组上下限、爬坡率约束日内层还必须加线路潮流约束、电压约束、储能SOC上下限约束。在Matlab里我用fmincon的内点法求解这个带约束二次规划问题预测模型用状态空间方程表达状态量是储能SOC控制量是储能功率和各机组出力修正量。2.3 超短期修正层最后一道关口超短期调度层的窗口是未来15分钟分辨率5分钟如果数据支持甚至可以到1分钟预测时域Np3步控制时域Nc1步。这一层的目标函数和前面两层有本质区别。它不是以经济性最优为目标也不是以跟踪日前计划为目标而是以功率平滑性和爬坡抑制为目标。原因是到了这个时间尺度光伏和风电的分钟级波动如果不加抑制会直接反映在并网点的功率质量上后续的继电保护、电能质量考核都会出问题。超短期MPC的目标函数我设计为[ \min \sum_{k0}^{N_p-1} \left[ \alpha | P_{out}(tk) - P_{out}(tk-1) |^2 \beta | \Delta P_{ess}(tk) |^2 \right] ]第一项惩罚输出功率的相邻时步变化也就是平滑性第二项惩罚储能功率的调整幅度防止储能过充过放或者频繁切换。注意这里根本不需要跟踪日前计划的项因为超短期层的主要矛盾已经变成了波动抑制。这也正是本项目标题中三级时间尺度采用不同目标函数的含义所在——每一层都是在解决自己那个时间尺度上最突出的矛盾而不是机械地做同样的目标传递。如果你把日前目标原样搬到超短期你会发现它完全不知道该怎么办它想省钱但15分钟尺度上哪里有什么经济可省它想跟踪计划但计划本身在这个尺度上已经失去了意义。2.4 多目标加权的数学形式与权重量纲匹配多目标加权是本项目里被问得最多的一块。由于不同目标量纲不一样直接加权会出现大数吃小数的问题。举一个真实例子经济性目标的数值量级是 (10^3) 元级别而功率平滑性目标的数值量级可能只有 (10^{-2}) 到 (10^{-1})如果直接相加平滑性目标对优化方向的贡献几乎为零整个加权完全白设。解决办法有两个方向我都试过。第一个方向是归一化每个子目标除以自己的基准值比如日前计划的成本值、不平衡功率的允许上限把目标值映射到0到1的量纲第二个方向是通过拉格朗日乘子或者对偶方法自适应调整权重但实现复杂度高很多。我建议在工程实现上优先选第一个方向。在Matlab里实现归一化加权的代码逻辑大致这样% 归一化目标函数 cost_norm cost / cost_base; % cost_base由日前计划得到 smooth_norm smooth_penalty / smooth_base; % smooth_base允许的波动上限 track_norm track_penalty / track_base; % track_base允许的跟踪偏差上限 % 加权组合 J lambda(1)*cost_norm lambda(2)*smooth_norm lambda(3)*track_norm;权重向量的初始化我建议用等差或等比扫描的方式而不是一次性猜一个值。比如(\lambda_2)从0.1扫到10步长设为0.1观察目标值变化曲线找到拐点区域再在拐点附近细化扫描。这个扫参过程可能要看几百条曲线但这是做多目标优化绕不开的笨功夫。3. PSO与MPC的组合逻辑为什么一个全局找一个滚动修这个章节我要解决一个很多人问过的问题既然有了MPC为什么日前调度不用MPC既然有了PSO这种强大的全局优化算法为什么日内和超短期不用PSO3.1 PSO适合什么样的调度问题PSO粒子群算法的基本思想是模拟鸟群觅食一组粒子在解空间里飞行每个粒子的位置代表一个候选解速度代表搜索方向通过个体最优和群体最优不断更新飞行方向。它的核心优势有三个不需要目标函数可导、不需要问题凸性、实现简单且并行性好。但PSO也有非常明显的短板。第一是无法保证全局最优只能说是大概率找到好的解第二是约束处理麻烦尤其是等式约束功率平衡和不等式约束爬坡率混杂的时候罚函数法的罚因子如果设置不当很容易导致解不可行第三是计算实时性差一个24维、种群规模50的粒子群优化每次迭代要计算50次适应度每次适应度要跑一次潮流整体算下来单次优化可能要几秒到几十秒。所以PSO适合的场景是离线或准离线优化的计划问题——问题规模中等、有充足时间计算、目标是找到一个足够好的全局方案。日前调度恰好满足这几点。24小时×1小时分辨率决策变量在60个左右计算时间控制在几秒到半分钟都是可以接受的。3.2 MPC的滚动优化到底滚动的是什么MPC的逻辑和PSO完全不同。MPC的核心不是找全局最优而是走一步看一步。每个控制周期内基于当前状态和预测模型求解未来Np步的最优控制序列但只执行第一步下一个周期重新求解。这里有个非常关键的理解点MPC的预测模型不需要特别精确但状态反馈必须准确及时。预测模型是用来算未来大致是什么样的参考真正让MPC发挥作用的是每步的状态测量/估计值——通过不断地用真实状态修正预测偏差系统才能紧紧咬住参考轨迹。MPC的另一个优势是处理约束非常干净。约束可以直接写进优化问题里通过求解器保证每个控制动作都在可行域内。这一点PSO很难做到——它处理约束的罚函数法本质上是允许你越界但让你付出代价而MPC是直接不允许你越界。所以MPC适合的场景是带周期性更新信息的控制问题——问题规模较小、有明确的状态反馈回路、必须在毫秒到秒级内给出控制指令。日内和超短期调度具备这些特征系统每隔15分钟或5分钟就能拿到最新的量测数据控制动作的响应时间要求在秒级且约束条件非常严苛。3.3 组合架构下信息流与控制流怎么对接那这两套算法在代码里是怎么衔接的呢信息流方向是自上而下传递参考自下而上反馈状态。具体来说日前层PSO: 输入24h预测数据 输出24h机组启停状态、逐时出力计划、储能充放电计划、购电计划 传递到日内层作为MPC的参考轨迹 P_plan(t) 日内层MPC每15min触发一次: 输入日前计划 P_plan、最新4h预测数据、当前系统状态储能SOC、机组当前出力 输出未来4h控制指令序列执行当前15min的控制动作 传递到超短期层作为MPC的功率设定点 P_set(t) 超短期层MPC每5min触发一次: 输入日内层功率设定点 P_set、最新15min预测数据、当前系统状态 输出未来15min控制指令序列执行当前5min的控制动作 执行储能功率指令、机组出力调整量反馈方向是反向的超短期层执行后发现实际出力与预期有偏差这个偏差会体现在下一次日内层滚动优化时的状态更新里日内层执行后发现实际功率轨迹偏离了日前计划这个偏差会在下一次日内层滚动优化时被明确纳入目标函数进行修正。这样一个上层定方向、下层做修正的架构恰好对应了不同算法在不同时间尺度上的计算能力和模型假设。把PSO和MPC说成竞争关系是错的它们在多时间尺度架构里是上下游合作关系。4. Matlab实现的核心模块与数据流设计这一章直接上干货讲代码层面的实现结构。我用的Matlab版本是2023a依赖工具箱为Global Optimization Toolbox用于PSO和Optimization Toolbox用于MPC的fmincon。如果你用的是旧版本PSO需要自己写代码也很短不必为此升级。4.1 代码整体框架整个项目的代码结构我整理成如下模块MultiTimeScaleScheduling/ ├── main.m % 主程序驱动三级调度执行 ├── data/ │ ├── load_data.m % 载入负荷、光伏、风电、电价数据 │ ├── generate_data.m % 无实测数据时可用的数据生成脚本 │ └── forecast_data.m % 模拟多时间尺度预测数据带误差 ├── day_ahead/ │ ├── da_pso.m % 日前调度的粒子群算法主体 │ ├── da_objective.m % 日前目标函数评估 │ ├── da_constraints.m % 日前约束处理 │ └── da_plan_output.m % 日前计划结果输出与可视化 ├── intraday/ │ ├── id_mpc.m % 日内MPC控制器 │ ├── id_predict_model.m % 日内预测模型状态空间 │ ├── id_objective.m % 日内目标函数 │ └── id_constraints.m % 日内约束潮流、电压、SOC ├── ultra_short/ │ ├── us_mpc.m % 超短期MPC控制器 │ ├── us_predict_model.m % 超短期预测模型更高频 │ ├── us_objective.m % 超短期目标函数平滑性 │ └── us_constraints.m % 超短期约束爬坡率为主 ├── utils/ │ ├── pso_core.m % PSO通用算法函数 │ ├── normalize_objective.m % 目标归一化工具 │ ├── weight_scan.m % 权重扫描工具 │ └── plot_results.m % 统一结果绘图脚本 └── results/ └── ... % 输出结果保存目录这个结构的好处是每个时间尺度的逻辑独立封装后期改一个层级的目标函数不会影响其他层级。我实际开发中体会最深的点是一定要把数据加载和优化求解完全分开否则等你要换数据集做对比实验的时候改起来会让你怀疑人生。4.2 PSO模块的粒子编码与适应度设计PSO设计里最核心的部分是粒子编码。如果直接用一个48维的向量来表示24小时所有机组的出力PSO搜索空间非常大且约束很难处理。我采用的编码方式是连续变量编码分段修复% 粒子的维度设计 % 维度1-24: 光伏/风电出力分配系数 k_pv(t), t1,...,24 % 维度25-48: 储能充放电功率 P_ess(t), t1,...,24 % 维度49-72: 燃机或火电出力 P_g(t), t1,...,24 % 注意机组启停状态不直接编码而是通过出力下限阈值判断 particle_dim 72;为什么启停状态不直接编码为0/1因为0/1变量会让PSO的搜索空间离散化群体智能算法的性能会大打折扣。我的做法是给每台机组设一个出力下限阈值当PSO优化出的出力低于阈值时判定该机组在该时段为停机实际出力置零否则为开机。这样把离散变量通过连续变量隐式表达PSO的搜索效率会高很多。适应度函数的公式我在第二章已经给出这里展示代码里关键的一段约束处理逻辑function [fitness, constraint_violation] da_objective(x, data) % x: 粒子位置向量72维 % 拆分粒子为发电计划、储能计划 P_pv_ratio x(1:24); P_ess x(25:48); P_g x(49:72); % 根据出力下限阈值修正机组启停状态 u_g P_g data.P_g_min; % 出力低于下限则判定停机 P_g_actual u_g .* P_g; % 功率平衡约束总出力 总负荷 储能充电 - 储能放电 联络线 P_balance P_pv_ratio .* data.P_pv_forecast P_g_actual ... P_ess data.P_grid - data.P_load; % 惩罚不可行解罚函数法 penalty sum(max(abs(P_balance) - data.balance_tolerance, 0)) * 1e6; % 成本目标 fuel_cost sum(data.a .* P_g_actual.^2 data.b .* P_g_actual data.c); grid_cost sum(data.grid_price .* data.P_grid); ess_cost sum(abs(P_ess)) * data.ess_cost_coef; fitness fuel_cost grid_cost ess_cost penalty; end罚函数系数取1e6这事不能一概而论要根据你的成本量级来设置。我见过的问题是目标函数量级 (10^4)惩罚系数取100结果所有粒子都在违反约束因为违反约束的代价比正常成本还低。我的建议是先算一下正常目标值的量级惩罚系数至少比它大两个数量级。4.3 MPC滚动优化的矩阵化实现MPC部分如果不用YALMIP或CVX这类建模工具直接用fmincon搭二次规划代码会比建模语言冗长一些但更可控。核心是把预测模型写成矩阵形式用矩阵运算代替循环。日内MPC的预测模型我用状态空间方程描述% 状态量x [储能SOC; 机组1出力修正量; 机组2出力修正量] % 控制量u [储能功率修正量; 机组1出力调整速率; 机组2出力调整速率] % 输出量y [联络线功率; 储能SOC] A [1, 0, 0; ... 0, 1, -dt/Tg1; ... 0, 0, 1 - dt/Tg2]; B [-eta_ch*dt/Capacity, 0, 0; ... 0, dt/Tg1, 0; ... 0, 0, dt/Tg2]; C [0, 1, 1; ... 1, 0, 0]; D zeros(2, 3); sys ss(A, B, C, D, Ts, dt);这里(dt)是15分钟换算成小时是0.25(Tg1, Tg2)是机组时间常数(C)矩阵的第一行是-1 1 1的组合关系表示联络线功率等于机组出力之和减去负荷。这些参数看起来简单但状态空间的维度和物理量纲一旦搞混MPC跑出来就是纯乱码。我建议先做一个开环仿真把系统状态变化曲线和物理直觉对照一遍确认无误后再接入MPC闭环。fmincon求解MPC优化问题的核心配置如下options optimoptions(fmincon, ... Algorithm, interior-point, ... MaxIterations, 500, ... MaxFunctionEvaluations, 10000, ... OptimalityTolerance, 1e-6, ... Display, off); % 决策变量是未来Nc步的控制增量序列 u0 zeros(Nc * n_u, 1); % 初始控制序列设为0 [u_opt, J_opt] fmincon((u) id_objective(u, x_current, data), ... u0, [], [], [], [], ... lb, ub, (u) id_constraint(u, x_current, data), options);超短期MPC的框架和日内完全一致只是预测模型的时间常数和约束范围不同。为了简化代码复用可以把MPC的求解部分写成一个通用函数输入预测模型、目标函数句柄、约束函数句柄输出控制序列。4.4 三级调度之间的数据衔接调度层级之间的数据传递是整个项目最容易出bug的地方原因很简单每一级的时间分辨率和时间起点都不同。日前层时间轴是 (t_{da} 0, 1, 2, ..., 23)代表小时序号。日内层时间轴是 (t_{id} 0, 15, 30, ..., 225) 分钟每15分钟触发一次每次优化未来4小时。超短期层时间轴是 (t_{us} 0, 5, 10, ..., 15) 分钟每5分钟触发一次每次优化未来15分钟。当天日层输出一个24维的日前计划向量后要作为日内MPC的参考轨迹。日内第一次触发时需要把日前计划向量插值到15分钟分辨率用Matlab的interp1函数% 日前计划从1h分辨率插值到15分钟分辨率 t_da 0:23; t_id 0:0.25:23.75; P_plan_ref interp1(t_da, P_da_plan, t_id, previous);这里用previous而不是默认的linear的原因日前计划是时段平均出力用前向插值保持每个15分钟时段内计划值不变更符合物理意义。如果用线性插值会把计划值在两个小时内平滑过渡反而偏离了日前计划的含义。另外一个隐藏坑是数据长度对齐。日内层每次滚动优化推进15分钟但是预测数据必须带4小时的前瞻量。如果你的预测数据是从当天的0点开始到24点结束那么最后一个日内触发时刻是23:45它需要预测到次日凌晨3:45这已经超出了当天数据范围。我的处理方式是在数据生成阶段就预留必要的尾部扩展否则运行到一天结束时会报索引越界。5. 实测中的坑与调试经验这一章是我最想分享的部分因为理论上说得通的东西到实际跑起来全是细节问题。我按照踩坑时间顺序写。5.1 PSO收敛慢、局部最优的问题第一次跑日前PSO的时候我设置了种群数量50、迭代次数200的常规配置结果收敛曲线在迭代到第60代左右就进入了平台期适应度值稳定在一个并不理想的水平。后来我检查了粒子初始分布发现问题在于初始种群在解空间分布太集中。解决办法有两个我最后是组合使用的。首先是拉丁超立方采样初始化替代纯随机初始化让粒子在决策变量范围内分布得更均匀% 使用lhsdesign生成拉丁超立方初始种群 X_initial lhsdesign(pop_size, particle_dim); X_lb repmat(lb, pop_size, 1); X_ub repmat(ub, pop_size, 1); X_pop X_lb X_initial .* (X_ub - X_lb);其次是惯性权重线性衰减。前期惯性权重大(w0.9)鼓励全局探索后期惯性权重小(w0.4)加强局部精细搜索。这个改进在多个测试问题上都有明显效果收敛速度提升约30%最终目标值改善2%到5%。还有一个容易被忽略的细节是速度钳位。粒子速度的初始上限如果设置过大粒子会反复穿越解空间边界导致适应度函数里罚函数频繁触发浪费大量计算。我建议速度上限设置为决策变量范围的10%到20%这样粒子飞行更有方向感。5.2 MPC无可行解的兜底策略MPC最让人头大的问题不是解的质量而是有时候会直接报无可行解。我在调试日内MPC时就遇到过一次储能SOC在下限附近同时负荷突然上升目标函数想让储能放电来补偿功率缺口但SOC约束不允许放电最终求解器返回无可行解。最开始我的处理方式是放宽约束边界把SOC的上下限从[0.2, 0.9]改成[0.15, 0.95]结果运行一段时间后发现SOC频繁触顶/触底系统稳定性反而更差了。正确的解法是引入松弛变量。在约束中允许一定的越限但把越限量加入目标函数作为惩罚。这样MPC在无严格可行解的情况下会选择一个破坏约束代价最小的次优解而不是直接崩溃。% 在目标函数中加入松弛变量的惩罚项 slack_soc_low max(0, soc_min - x(1)); % 低于SOC下限的松弛量 slack_soc_high max(0, x(1) - soc_max); % 高于SOC上限的松弛量 J J_tracking 1e4 * (slack_soc_low slack_soc_high);这个权重1e4不是随便定的它的量级应该比正常目标函数的量级大几个数量级确保松弛变量只在极端情况下被激活。测试下来加入松弛变量后整个系统在全天运行中没有再出现过无可行解的情况而且正常工况下松弛量为0对优化结果没有影响。5.3 权重系数的标定多目标加权里权重怎么标定是我被问得最多的问题之一。直接给结论不要想一次性给出一组完美权重而是做灵敏度扫描拐点选择。我的具体做法是固定(\lambda_1 1)把(\lambda_2)从0.01扫描到10对数坐标记录每个(\lambda_2)下的目标函数J1和J2的值画Pareto前沿图。前沿上的拐点曲率最大处就是最值得关注的区域。这个区域附近的权重往往对不同目标的平衡最好。举个例子假设扫描后发现(\lambda_2 0.3)时经济性只损失了1.5%但功率平滑性提升了25%而(\lambda_2 1.0)时经济性损失了10%平滑性只提升了28%。那0.3就是不折不扣的性价比最优权重。这个扫描过程在Matlab里用一行循环就能跑完我强烈建议每个项目都做一次不要直接抄别人论文里的权重。5.4 计算耗时优化整个系统跑起来之后你会发现计算耗时集中在两个地方日前PSO和日内MPC。日前PSO的耗时主要是每次适应度评估里的潮流计算。如果潮流计算用loadcaserunpf每组数据大概50毫秒种群50、迭代200次总耗时约500秒也就是8分钟。这个时间在离线调度场景下勉强可以接受但如果需要做蒙特卡洛或者多场景对比就太慢了。我的优化方式是用parfor并行计算种群适应度8分钟压到2分钟左右在适应度函数里加一个提前终止条件如果功率不平衡量的惩罚已经大于当前最优适应度直接返回一个极大值不再花时间算潮流日内MPC的耗时瓶颈在fmincon的求解。如果预测时域Np16、控制时域Nc4、决策变量维度12单次求解大概需要0.5秒到1秒。滚动一整天24小时×4次/小时96次就是100秒左右这个速度在离线仿真里可以接受。但如果要做实时仿真需要在15分钟内跑完一天的调度就需要进一步压缩。我的经验是% 使用并行求解多个滚动时段的MPC parfor k 1:96 u_opt_k solve_mpc(k, state_history(:,k), data); u_history(:,k) u_opt_k(1:n_u); end另外fmincon里MaxFunctionEvaluations默认值10000比较大实际很多情况下2000次就收敛了我把这个参数从默认值调小显著减少了每个求解周期的耗时。6. 调通之后我还做了哪些验证工作这套多时间尺度调度框架在代码层面跑通之后我心里其实还有几个坎没过去这套系统到底是看起来合理还是真的合理所以我做了一批对比实验来验证。这里挑几个比较有说服力的结果说一下。6.1 多时间尺度 vs 单一日前调度基准方案是只用日前PSO调度日内和超短期不启用用传统AGC方式近似处理实时波动。对比结果非常直观指标单一日前调度多时间尺度调度改善幅度总运行成本元1528014390-5.8%联络线功率波动标准差kW21587-59.5%储能SOC越限事件次数40100%机组爬坡越限次数11190.9%成本降低5.8%在电力系统优化里算非常可观的收益因为调度成本基数大几个百分点就是几十万级别的运营费用。更关键的是联络线功率波动降低了近60%这说明多时间尺度调度在削峰填谷和减少对上级电网冲击方面的作用非常明显。回过头来想为什么多时间尺度能同时改善经济性和稳定性因为日前PSO在看得远的尺度上做了更合理的全局安排MPC在看得近的尺度上及时修正了预测误差的冲击两者各司其职缺一不可。6.2 不同权重组合下的表现差异我设定了一组对比实验A组默认权重、B组强经济性权重、C组强平滑性权重每组跑完整24小时记录成本和平滑性指标。权重配置总成本元联络线波动标准差kW储能充放电次数A默认143908718B强经济1412013224C强平滑146804231这个结果证明了权重选择确实是在省钱和平缓之间做取舍没有绝对最优只有场景适配。B组适合电网侧对功率波动容忍度高的场景C组适合并网要求严格的弱电网场景A组则是综合平衡。这进一步印证了多目标加权的价值——同一套框架只需要调整权重就能适配不同的应用场景而不需要重新建模。6.3 预测误差灵敏度分析最后我想看看预测误差对调度结果的影响到底有多大。我在原始数据上叠加了不同幅度的正态分布随机噪声标准差为5%、10%、20%分别跑了一天调度预测误差水平总成本元相对偏差5%14210-1.25%10%基准143900%20%149804.10%这说明预测误差越大成本恶化越明显。但值得注意的是即使预测误差到了20%成本也只增加了4%左右这说明MPC的滚动修正机制在消化不确定性方面确实发挥了作用。如果换成纯开环调度20%的预测误差很可能导致成本增加10%以上甚至直接出现无法调度的情况。7. 最后一些实用建议与扩展思路代码调到稳定、实验做完之后我总结了几条比较过来人的经验供后面做类似课题的朋友参考。第一先做小规模模拟确认框架合理性再上大规模数据。一开始用6小时的窗口、3台机组、单日内层的简化版本把整套逻辑跑通了再逐步扩展。如果用完整数据去调bug出错了根本定位不到是哪一层的模块出了问题。第二数据可视化是调试的最好工具。把日前计划曲线、日内MPC跟踪曲线、超短期平抑曲线、储能SOC曲线、联络线功率曲线叠在一张图上一眼就能看出哪个环节出了问题。哪个时间段的曲线偏离了预期直接打log查那个时段的数据定位效率提高很多。第三所有随机算法包括PSO请固定随机种子。否则每次运行的结果都不一样你根本分不清某个改动是有效还是随机波动。在main.m开头加一行rng(42)能省掉大量重复验证的时间。第四把预测数据和真实数据并列保存在数据结构里。多时间尺度调度里每层用的预测数据其实是一种伪预测——用真实数据加上噪声模拟出来的。保留原始真实数据可以在每次滚动优化结束后结算控制效果算清楚预测误差究竟造成了多少损失。这个数据在论文和汇报里非常好用。关于扩展方向我觉得这个架构可以很自然地接入更多场景比如把储能换成电动汽车集群把火电换成氢燃料电池或者把微电网换成虚拟电厂参与电力市场的竞价策略。核心的三层架构和PSOMPC组合逻辑不需要动只需要调整目标函数中的子项和约束条件即可。另外一个很有价值的方向是在超短期层引入强化学习来替代MPC用数据驱动的方式学习最优平抑策略这样在模型不精确的场景下可能比MPC表现更好——但这是另一个课题了。这个项目的完整代码和数据文件信息如果你有需要可以关注同名CSDN账号后私信获取我会把主程序和配套数据打包发给你。折腾这套系统前后花了大几个昼夜但调通那一刻看着三级时间尺度曲线首尾衔接、优化结果合理稳定那种成就感还是很值当的。

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

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

免费获取报价