调度系统这几年变得越来越复杂早些年做经济调度建模里基本就是火电机组加固定负荷曲线算出来结果也比较“稳”。但光伏渗透率上来之后负荷曲线开始被倒挂午后谷段不再一定是谷电动汽车保有量一大晚高峰的充电需求又叠加上去负荷曲线甚至可能出现“鸭子”。这种情况下再拿静态经济调度的思路去算一个断面算出来的方案往往在下一个时段就不可行了。我自己的做法是把问题拉成多时段的动态经济调度用飞蛾火焰算法去搜24小时的机组出力计划和电动汽车充放电策略光伏处理成可预测、可削减的分布式电源整套东西在Matlab里跑通实际效果比常规的静态调度要直观得多。这篇内容围绕动态经济调度展开会涉及目标函数怎么搭、约束怎么处理、飞蛾火焰算法的实现细节以及电动汽车和光伏接入后带来的时序耦合问题。适合正在做电力系统调度、微电网能量管理、或者想用智能优化算法解决实际工程问题的人参考尤其是用Matlab做论文验证或者工程预演的。1. 调度问题建模从单一火电走向“火电EV光伏”的横向扩展动态经济调度和静态经济调度的本质区别在于决策变量从某个固定时刻的功率分布变成了一个时间序列上的功率轨迹。拿一台火电机组来说静态调度只需要给出它在某一时刻的最优出力而动态调度需要给出它在24个调度时段里每15分钟或每1小时的最优出力变化路径同时还必须保证相邻时段之间的爬坡约束成立。这个变化听起来只是多了个时间维度但求解复杂度完全是另一回事。1.1 目标函数的构成与成本细节动态经济调度最核心的目标是在满足负荷需求的前提下最小化系统总运行成本。在我搭建的Matlab模型里目标函数包含四个部分火电机组的燃料成本、电动汽车参与充放电的电池损耗成本、光伏削减惩罚项以及火电机组的启停成本。火电燃料成本用二次函数拟合比较常规即其中 是机组在第 时段的出力。二次函数的系数可以通过机组热效率曲线拟合得到不同机组的成本曲线差异很大实际建模时不能拍脑袋统一设一个参数。电动汽车的成本处理有争议很多文献把EV当成纯负荷只算充电电费这在V2G场景下是不完整的。只要EV具备向电网放电的能力电池循环寿命损耗就必须进目标函数否则算法会在不需要放电的时候也疯狂放电结果没有参考价值。我用的退化成本模型是简化版按放电量乘以一个单位退化成本系数来估算比如放电1kWh对应0.15元的容量损耗成本具体数值可以根据电池型号和循环寿命测试数据动态调整。光伏削减惩罚项是为了避免算法“浪费”光伏。光伏出力给定时如果系统不需要那么多电算法可能会选择弃光但弃光会产生惩罚成本。这样设置的目标是让算法优先消纳光伏实在消纳不了时才允许削减。目标函数整体是这样表示的1.2 约束集合的数学表达约束条件是我觉得整份代码里最值得仔细梳理的部分因为每类约束的“脾气”都不一样。功率平衡约束是所有调度问题的底线物理上必须满足这个式子需要特别注意符号方向。我把EV充电功率定义为正放电功率定义为负光伏出力为正值火电出力为正值所以功率平衡表达式要保证所有电源出力和负荷之间的差值等于零。在实际编码中这条约束最常见的问题是忘记把EV充电功率从负荷侧拿出来单独考虑导致平衡约束写错。火电机组的出力上下限约束比较直接爬坡约束是动态调度区别于静态调度的关键约束它把相邻时段的出力耦合在一起其中 和 分别是机组的向上爬坡速率和向下爬坡速率。这里有个工程细节我之前在代码里卡了很久爬坡约束的单位是MW/min而调度时段间隔通常是min需要把爬坡速率乘上时间间隔换算成相邻时段允许的出力变化量而不是直接把MW/min当成MW去比较。电动汽车的约束包括充放电功率限制和电池电量约束。如果用荷电状态SOC来跟踪电量状态那么相邻时段的SOC递推关系为其中 是充电效率 是放电效率是电池容量。SOC的上下限约束为还有一个很容易被忽略的约束是EV在调度周期结束时的SOC不能太低。如果只约束SOC在范围内算法为了让成本最小会把EV的电在这个周期内全部放光导致调度结束时EV无电可用下个周期没法开工。我一般会加一个终端SOC约束比如要求 保证调度周期结束时EV还有足够电量支撑下一次出行。光伏出力约束相对简单实际出力不能超过预测出力1.3 为什么静态经济调度在这里不够用静态经济调度把每个时段当成独立的优化问题求解得到的“最优解”往往在多个时段间是跳变的。举个例子夜间风电或光伏出力下降某个时段火电出力需要大幅上调但静态调度不会自动保证这个上调过程满足爬坡速率限制于是算出来的发电计划在物理上根本无法执行。动态经济调度把所有时段放在一个模型里同时优化爬坡约束自然就被纳入了可行域。代价是决策变量数量成倍增加求解空间变大传统的线性规划方法处理起来会比较吃力这正是智能优化算法适合切入的地方。飞蛾火焰算法在解决这类高维非线性优化问题时不需要计算梯度对目标函数的非线性特征不敏感而且结构简单、参数少适合在Matlab环境下快速搭建和验证。2. 飞蛾火焰算法MFO的核心机制与调参逻辑飞蛾火焰算法Moth-Flame Optimization是Mirjalili在2015年提出的一种元启发式优化算法。它的灵感来源很直观飞蛾夜间飞行时依靠月光导航以固定角度朝光源飞行但当人造光源出现时飞蛾会被螺旋形轨迹吸引过去。算法把候选解看成飞蛾把当前找到的最优解看成火焰通过模拟飞蛾绕火焰飞行的螺旋轨迹实现搜索。2.1 对数螺旋机制的搜索原理MFO算法里每个飞蛾的位置就代表一组决策变量的取值。在Matlab实现中我用一个矩阵表示整个飞蛾种群行数是种群规模列数是决策变量数量。每次迭代每个飞蛾按照对数螺旋公式更新自己的位置其中 是飞蛾新位置 是飞蛾要逼近的火焰位置 表示飞蛾和火焰之间的距离 是浮点系数控制螺旋的形状 是一个随机数。螺旋更新的妙处在于它同时兼顾了局部开发和全局探索。当飞蛾离火焰很近时更新步长小主要在火焰附近精细搜索局部最优区域当飞蛾离火焰较远时更新步长自然变大相当于在更大范围内探索新区域。这个特性让MFO在处理经济调度这类多峰问题时具有一定优势。2.2 火焰数量的自适应缩减策略MFO的一个关键细节是火焰数量会随着迭代次数逐步减少。迭代初期火焰数量等于飞蛾数量每只飞蛾围绕不同的火焰搜寻保持种群多样性。随着迭代进行火焰数量按线性公式递减飞蛾逐渐收敛到少量优质火焰附近最终集中于最优解区域。这个策略的逻辑是迭代初期解空间充满不确定性多点搜索更有利于发现优质区域迭代后期需要集中火力精细打磨此时再让飞蛾四散寻找性价比太低。在Matlab代码里火焰数量的更新代码只有几行但对收敛效果的影响非常明显。调参方面MFO相比其他算法确实省心不少。种群规模一般取30到60最大迭代次数取100到500剩下的核心参数就是螺旋形状系数。系数越小飞蛾绕火焰飞行的螺旋越紧密局部搜索能力强但容易陷入局部最优系数越大螺旋越松散全局搜索能力强但收敛偏慢。实际调试时可以从1这个默认值开始观察收敛曲线如果下降不够快就适当减小如果陷入平台期跳不出来就增大一些。2.3 与粒子群、遗传算法对比的选型理由用飞蛾火焰算法前我也对比过粒子群算法和遗传算法。粒子群的优势是收敛快通过个体历史最优和群体历史最优相互牵引在连续变量优化问题上表现很稳定但在高维约束优化场景里容易出现早熟收敛。遗传算法的交叉变异操作对离散变量处理比较顺手但参数多交叉率、变异率、锦标赛规模都要调调不好收敛过程很折磨人。MFO的螺旋更新机制天然适合连续变量优化经济调度里火电出力、EV充放电功率都是连续变量匹配度很高。而且MFO的火焰缩减机制提供了比较自然的探索-开发平衡在不额外增加复杂参数的情况下能保持不错的种群多样性。当然没有免费的午餐MFO在简单问题上不一定比粒子群快但在这个动态经济调度的场景下整体表现更稳尤其是处理多峰目标函数时不容易被过早锁定在局部最优区域。3. Matlab代码架构与不可跳过的数据初始化代码结构直接决定后期调试效率。我写这套代码时用的结构是主程序文件、目标函数文件、约束处理函数文件、数据初始化脚本、结果绘图脚本。主程序只负责调用种群初始化和迭代循环目标函数和约束处理独立成模块这样后续换数据集或者改动约束条件时不需要在大一坨代码里翻找。3.1 电源数据与负荷时序的组织方式数据初始化脚本里需要准备四类数据火电机组参数、负荷时序、光伏出力时序、电动汽车参数。火电机组参数包括机组数量、各机组的成本系数、出力上下限、爬坡速率、最小启停时间。我习惯用结构体数组存储每个机组是一个结构体字段清晰易读。比如数据太大就不逐个贴了。负荷数据和光伏出力时序建议直接设成24维列向量对应24个调度时段。这里有个容易踩的坑如果你的调度时段是15分钟那么一天是96个时段所有时序数据的维度必须一致很多人就是维度没对齐导致矩阵运算报错一查才发现负荷序列和光伏序列长度不一样。电动汽车参数在代码里是一个小结构体数组包含EV数量、电池容量、充电功率上限、放电功率上限、初始SOC、终端SOC要求、充放电效率等字段。多个EV如果不考虑聚合逐台建模会导致决策变量爆炸式增长24时段、10台EV、每台EV有充放电两个变量就是480个决策变量对MFO来说搜索空间太庞大。实际工程中更合理的做法是采用聚合EV模型把所有EV聚合成一个虚拟储能单元用总SOC来描述整体电量状态大幅降低变量维度。我这个代码采用了聚合模型好处是计算量小、收敛快缺点是不同EV之间的SOC差异被忽略。如果是做调度策略研究聚合模型完全够用如果是做充电桩层面的具体控制再考虑逐一建EV模型。3.2 决策变量的编码方式与维度设计决策变量编码是整个代码中最影响算法性能的设计决策。在我的方案里每个飞蛾个体一行位置向量包含两类决策变量所有火电机组在每个时段的出力以及EV聚合体在每个时段的充放电功率。假设有 台火电机组、 个时段、1个EV聚合体那么决策变量总数就是 。以3台火电机组、24时段、1个聚合EV为例决策变量维度是 个。向量的前半部分存放火电出力后半部分存放EV充放电功率用一组索引变量来分隔。编码时还需要考虑变量取值范围的边界映射。MFO初始化时随机生成0到1之间的值然后映射到各个变量的上下限。火电出力的下限是机组最小技术出力上限是额定容量EV充放电功率的下限是最大充电功率负值或正值要看符号定义上限是最大放电功率。这段映射代码虽然短但很容易写出顺序错乱的问题建议在初始化之后立刻加一个维度检查把各段变量的真实最大值最小值打印一遍肉眼确认无误再往下走。3.3 算法主循环的搭建步骤主循环的思路按照MFO的标准流程来写大致分为下面几步读取数据初始化脚本生成的全部参数。初始化种群把每个飞蛾的位置映射到决策变量真实范围。计算每个飞蛾的目标函数值调用目标函数模块。排序将当前最优解记为火焰矩阵。进入主循环对每个飞蛾根据火焰位置做对数螺旋更新越界变量做边界修复重新计算目标函数值更新火焰矩阵缩减火焰数量。循环结束后输出最优解和对应目标函数值。核心迭代代码的骨架如下按照这个结构去填充就不会乱这一小段已经把MFO的核心迭代流程覆盖了。注意更新完位置后必须做边界修复否则下个时段的功率可能超出机组限值目标函数计算时会因为约束破坏太多而变得没有参考意义。4. 约束处理是这份代码中最容易出错的地方约束处理我放到单独一章来讲因为这一块在代码里占比不大但折腾人的程度远超其他部分。实际用智能算法求解约束优化问题时常见思路有三种惩罚函数法、可行性修复法、以及将约束作为额外目标的约束支配法。在我这套代码里主约束用的是惩罚函数法个别物理约束用修复法辅助。4.1 惩罚函数法的实现与系数调节惩罚函数法的思想是当某个解违反了约束时在目标函数值上增加一个惩罚项让这个解变得“不划算”算法在后续迭代中自然会避开这些不可行解。惩罚项设计的好坏直接决定最终解的质量。对每个时段我把约束破坏量定义为功率平衡偏差的绝对值加上火电爬坡越限量的绝对值。惩罚项的形式是约束破坏量的平方乘一个大系数。用平方而不是一次方的目的是让轻微越限和严重越限在惩罚力度上拉开差距促使算法优先修复严重越限的解。惩罚系数本身需要反复试。系数的量级会影响算法搜索行为系数太大算法会过分追求可行解而忽略目标函数的优化收敛过程会变得缓慢系数太小算法会大量接受不可行解最终结果虽然目标函数值很好看但解根本不可执行。我的经验是从 这个量级起步跑几次看结果如果所有时段的功率平衡误差都在允许范围内再逐步把系数调下来给目标函数优化更多空间。MATLAB里可以用隐式扩展来高效计算平衡偏差直接向量化不用写for循环代码执行速度快不少。4.2 爬坡约束与时序耦合的处理细节爬坡约束因为涉及相邻时段处理逻辑需要特别小心。我在目标函数循环里单独写了一个函数来检查所有机组在所有时段的爬坡越限情况。逻辑是初始化一个零矩阵记录越限量对每台机组从第2个时段开始计算 和上一时段出力的差值如果差值大于向上爬坡能力就记录越限量同理检查向下爬坡方向。这个函数的输出是一个标量惩罚值计算方法是对所有机组的越限量平方求和再乘以惩罚系数。然后将这个惩罚值加到总目标函数中。实际调试中我发现爬坡约束导致的不可行解往往是一串连续时段的连锁反应比如第5时段越限后第6时段为了补偿又越限。这种情况下单纯靠惩罚项修正非常慢算法反复试探多次才可能找到可行的爬坡路径。更有效的做法是结合修复策略在目标函数计算之前先对每个解做一次局部修复把超出爬坡能力的相邻时段出力强制压回可行范围然后再计算目标函数。这样可以保证参与迭代的解基本都落在可行域附近收敛速度快非常多。修复逻辑的伪代码如下这个方法属于启发式修复严格来说会改变解本身但对于智能优化算法来说这种修复在计算效率和最终解可行性之间的平衡是相当划算的。4.3 SOC递推与终端电量约束的工程化处理EV聚合体的SOC递推关系属于强时序耦合约束处理不好会导致SOC曲线飘出边界或者出现不合理的跳变。我用的是递推更新法在计算目标函数时根据EV充放电功率序列从头到尾逐步更新SOC每一步检查SOC是否越界一旦越界就记录惩罚。递推更新法的好处是SOC曲线天然满足动态一致性不会出现某个时段SOC上下界满足但前后时段互相矛盾的情况。缺点是需要在目标函数里多跑一个for循环对计算速度有一点影响但在常规的24时段、3机组问题规模下可忽略不计。终端SOC约束我用了一个带死区的惩罚函数即只要最终SOC低于设定值就按偏差平方乘以惩罚系数计入目标函数。死区的存在是为了避免算法过度纠结于微小偏差因为终端SOC差个0.5%在工程上完全不影响下一轮调度。5. 实验结果怎么看收敛曲线和调度曲线缺一不可代码跑完之后输出一堆数字并不能说明问题必须通过绘图来分析结果。我自己的习惯是至少画三张图收敛曲线、火电出力与负荷的时序匹配图、EV充放电功率和SOC时序图。三张图配合起来基本上能判断算法是否收敛到合理的调度方案。5.1 收敛曲线的读取方式收敛曲线记录每轮迭代的最优目标函数值。正常情况下曲线是单调下降然后逐渐水平最后趋于稳定。如果收敛曲线在前几次迭代就迅速变平且目标函数值远高于预期大概率是陷入了局部最优或者搜索空间映射出了问题。如果收敛曲线一直到迭代末尾仍在明显下降说明迭代次数不够需要增加最大迭代次数。我遇到的典型情况是部分种群在迭代后期陷入一个局部最优区域火焰数量已经缩减为1整个种群的螺旋更新都围着同一个火焰打转无法跳出。这时可以考虑在更新公式里引入一定的随机扰动比如在螺旋公式的系数中加一点高斯噪声让飞蛾偶尔跳离火焰远一点再飞回来往往能有效摆脱局部最优。5.2 火电出力与EV行为的协同规律从火电出力时序图里能看到机组是否合理地承担了基荷和峰荷角色。价格成本低的机组通常出力靠近上限成本高的机组只在高峰时段补充出力。爬坡路径是否平滑也是观察重点如果出力曲线出现锯齿状跳变说明爬坡约束的惩罚或修复逻辑没有完全生效。EV充放电功率曲线则反映了算法对激励信号的响应。典型规律是在光伏出力大或电价低谷时段EV倾向充电在系统负荷高峰时段EV倾向放电。如果曲线的行为完全违背了这个规律比如在光伏大发的午间时段EV不充电反而放电需要检查成本参数是否设置反了或者SOC约束是否限得过死。SOC曲线则要重点观察两件事一是整个调度周期内SOC是否始终在允许范围内二是终值是否达到设定要求。我经常对着SOC曲线检查有没有突然的跳变如果有多半是充放电功率序列和SOC递推逻辑之间出现了符号或效率换算的问题。5.3 结果导出与对外汇报的表格整理整理结果时不要直接拼接Matlab工作区的数组建议把关键指标汇总成表格总运行成本、各机组各时段出力表、EV各时段充放电功率和SOC表、光伏消纳量和削减量。用writetable函数导出成csv再在Excel里加工成报告格式非常方便。这里提醒一个小细节导出时要注意数值单位的一致性成本是用万元还是元、功率是用MW还是kW、SOC是百分比还是0到1之间的小数全部统一好之后再导出否则汇报的时候还要反复换算非常容易出错。6. 实测中遇到的典型问题与排查思路这部分我挑三个自己真实踩过的坑来讲每个都花了不少时间才定位到根因希望其他人能少走弯路。6.1 光伏渗透率增高后功率平衡频繁越限最初版本的光伏处理方式比较简单直接把光伏预测出力当成负的负荷叠加进净负荷曲线然后让火电加EV去平衡净负荷。但光伏出力曲线变化剧烈的时段特别是多云天气下光伏出力短时间内大幅波动火电机组受爬坡约束限制根本跟不上导致功率平衡惩罚长期居高不下。后来我把约束处理升级成双层结构外层用惩罚函数法评估解的约束破坏程度内层增加一个功率再平衡修复环节。当算法生成的调度方案中出现功率不平衡时优先调整EV的充放电功率进行平抑如果EV功率已经到边界再调整火电出力。通过这种修复解的可行性大幅提升收敛速度也明显加快。6.2 EV终端SOC约束导致的收敛停滞调参的时候遇到过一个很奇怪的现象收敛曲线在前50次迭代下降正常50次之后几乎原地踏步。排查后发现终端SOC约束的惩罚系数设得太高导致所有飞蛾都优先满足终端SOC把目标函数中火电成本和EV放电收益的部分压得几乎没有优化空间。群体陷入了“为满足末端电量而牺牲经济性”的局部最优区域。解决方案比较粗暴但有效把终端SOC约束软化成带死区的弱惩罚同时对不满足条件的解在修复阶段强制补充充电。也就是说让约束满足不直接通过惩罚逼迫而是通过修复操作直接修改解把满足约束的成本分摊到每一次迭代中而不是让算法自己去艰难寻找可行路径。6.3 不同数据场景下的参数自适应建议最后说一点关于参数自适应的问题。经济调度问题的复杂度随系统规模变化很大3台机组、1个EV聚合体的场景和小型微电网的场景参数不能通用。我建议做一套参数映射逻辑根据决策变量维度和约束数量动态调整种群规模和迭代次数。维度越大种群规模相应扩大迭代次数也增加代价是计算时间变长。如果计算资源充足可以多跑几次取最优解因为智能优化算法的单次结果带有随机性多次运行取最优或者平均结果稳定性会好很多。在Matlab里实现这套映射逻辑并不复杂初始化阶段根据决策变量维度计算种群规模和迭代次数比如种群规模取维度数量的5倍再向上取整到偶数迭代次数取维度数量的20倍左右。效果比我固定用一套参数要好得多也省去了针对每套数据单独调参的麻烦。
阅读完成 · 觉得有帮助?