ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

考虑V2G的微电网多目标日前优化调度:改进MOGWO与Matlab实现

考虑V2G的微电网多目标日前优化调度:改进MOGWO与Matlab实现 做微电网调度的朋友应该都有过类似的经历模型、算法、代码全跑通优化结果一出成本曲线漂亮得很但仔细一查EV集群的剩余电量发现它把人家的车全“放干”了。这个场景我在复现V2G相关调度文献时遇到不止一次。真正要把“考虑V2G技术的风、光、荷、储微网多目标日前优化调度”做对难点其实不在算法有多花哨而在模型约束写没写全、多目标算法怎么改进、以及Matlab代码如何组织才能批量复现实验。这篇文章把我这次完整项目的思路拆开讲从数学建模、改进多目标灰狼优化算法MOGWO的具体策略到代码模块和结果解读一次性说清楚。如果你正在做微电网优化调度方向或者需要复现类似论文仿真手里主要工具是Matlab那这篇文章的思路应该能直接帮你少走弯路。我不会刻意绕开公式和代码骨架只要把细节讲透你完全可以照着搭一套自己的实验框架。1. 从“单目标成本最优”到“多目标权衡”这个课题到底在解决什么问题1.1 微网日前调度在做什么微电网由风电、光伏、储能、常规可控机组比如微型燃气轮机和负荷组成。日前调度的本质就是提前一天以1小时为时间分辨率安排24小时内各设备的出力计划。输入数据无非三样风光预测出力曲线、负荷预测曲线、分时电价。输出则是一张调度表燃气轮机每小时发多少电储能什么时候充、什么时候放EV集群怎么参与和主网交互功率有多大。听起来像线性规划问题但一旦加入多目标和非线性约束情况就变了。最常见的处理方式是把它写成多目标优化问题用进化算法求解因为这类问题往往非凸、有大量离散逻辑和时序耦合约束传统数学规划工具用起来并不顺手。这也是灰狼优化算法这类元启发式方法被大量应用的原因。1.2 为什么是“多目标”而不是单纯成本最低单纯做成本最低当然可以但论文和实际项目里运行成本、碳排放、新能源消纳或者说净负荷波动是三个天然冲突的量。燃气轮机补功率会拉高成本和碳排放减少向主网购电意味着本地机组和储能、EV要承担更多调节任务折旧和补偿成本又上去了想让净负荷曲线平滑就要频繁调用储能和EV同样增加运行损耗。多目标优化的结果不是唯一解而是一个Pareto前沿。前沿上的每个点代表一种权衡方案有的更省钱有的更低碳有的让净负荷更平稳。决策者根据实际偏好挑一个折中解。所以课题叫“多目标”不只是一个噱头而是工程现实需要。1.3 V2G是增加了一个电源还是增加了一堆约束V2G技术的核心是把电动汽车集群当作可调度的双向功率单元。EV在谷电时段充电在峰电时段向微网放电相当于给微网加了一块“会跑路”的储能。但必须清醒EV首先属于用户它接入微网的时段有限接入时的SOC随机离开时还必须保证有足够的电够用户出行。优化算法如果只看目标函数很容易做出“把EV电量放空来省钱”的荒唐方案。所以V2G建模时最关键的其实是那群约束条件而不是那点发电能力。把EV集群当成一个带电量上下限和终值约束的可调度单元是最基本但最容易被写漏的部分。1.4 我最终确定的三目标框架这次项目和常见的文献框架保持一致三个目标分别是运行成本最小包括向主网购电费用、燃气轮机燃料成本、储能充放电损耗成本、EV用户参与V2G的放电补偿。碳排放最少包括外购电力等效碳排放和燃气轮机燃烧排放。净负荷波动最小让扣除风光后的等效负荷曲线尽量平稳这在一定程度上等价于提升新能源就地消纳比率。三目标比双目标更能反映微网调度的真实权衡但对算法的多样性要求也更高。这也是后面要专门改进灰狼算法的直接原因。2. 建模的坑目标函数、约束条件和决策变量编码怎么设计才不出错2.1 决策变量编码把电网交互功率当作“松弛变量”这个问题一旦想明白代码实现能少踩很多坑。决策变量不需要把每个设备的每个时刻出力都直接编码。常见的做法是只编码燃气轮机出力、储能功率、EV功率三组决定变量每组都是24维。然后每个时刻的主网交互功率由功率平衡方程直接反推出来P_grid(t) P_load(t) - P_MT(t) - P_WT(t) - P_PV(t) - P_ESS(t) - P_EV(t)注意P_ESS和P_EV用“带符号功率”正值表示放电负值表示充电。这样一来功率平衡等式约束天然满足程序里只需检查反推出来的P_grid是否在上下限范围内越界就罚。这个手法在数学规划里叫“变量消元”在启发式算法里特别实用。如果不这样做而把P_grid也当作独立决策变量再加上等式约束罚函数经常会出现“总出力不等于总负荷”的假最优解而且梯度信息也没有调罚函数系数调到怀疑人生。我实际测试下来用松弛变量法之后等式约束的违反量直接降为零后面只需要专注处理不等式约束。2.2 三个目标函数的具体构造运行成本函数可以写成f1 购电成本 燃气轮机燃料成本 储能折旧成本 EV放电补偿成本购电成本就是P_grid和分时电价逐时刻相乘。储能折旧成本按充放电电量折算到单位电量损耗而不是简单按一个常数EV放电补偿成本是为了让EV用户愿意参与V2G按放电电量给补偿这个补偿价格要定得比单纯充电电价高才有激励效果但也别高过峰电价格否则算法会进入一种“用EV电价套利”的失真状态。碳排放目标写为f2 主网购电等效碳排放 燃气轮机碳排放主网购电的碳排放系数可以参考电网平均碳排放因子燃气轮机则按燃料消耗量和排放因子折算。这里不追求精确的环保计算重点是让优化器看到“越依赖外购电或越频繁开燃气轮机碳排放越高”这个趋势关系。净负荷波动目标f3 sum( |P_net(t) - P_net_mean| )P_net(t)是每个时刻原始负荷减去风电、光伏出力后的净负荷。这个目标越小说明经过储能和EV调节后系统需要从主网或燃气轮机获得的功率曲线越平缓新能源利用率也越高。三个目标直接作为多目标优化的三个维度不提前加权重。2.3 最容易写漏的约束条件约束条件按性质可以分成四类。第一类是设备出力上下限燃气轮机、储能、EV都有对应的物理限制。第二类是时序耦合约束储能和EV的电量都有递推关系SOC(t1) SOC(t) - P_ESS(t) * Δt / E_capacity第三类是穿越边界约束比如储能要求调度结束时的SOC不低于初始值的一定比例EV集群要求离开时刻的剩余总电量不低于用户需求电量和预期出行耗电之和。第四类是和主网的交换功率约束以及燃气轮机爬坡约束。这里特别提醒三类坑EV终值约束经常被忽略导致算法“榨干”EV电量。爬坡约束如果直接写成罚函数罚系数不对时燃气轮机出力会在相邻时段剧烈跳变曲线看起来像锯齿明显不符合实际。储能充放电互斥逻辑。很多代码直接用一个带符号功率变量这行得通如果拆成充、放两个变量就必须引入额外的二进制标志否则会出现同一时刻又充又放的“永动机”解。2.4 量纲和归一化以及“内部要不要归一化”的疑惑三个目标的量纲不同成本是元碳排放是千克净负荷波动是千瓦。如果你用的是权重和法做单目标化那就必须归一化否则成本目标会淹没其他目标。但用多目标算法本文用改进MOGWO时算法内部不用归一化它比较的是支配关系量纲不影响比较结果。归一化真正起作用的地方在最后的折中解选择模糊隶属度函数需要把不同目标的差异压到同一个尺度。我建议在写代码时把三个目标函数分开独立返回不要在目标函数内部做任何加权或归一化这样后续分析不同目标间的冲突关系会更直观。3. 改进多目标灰狼优化算法标准MOGWO在微网调度上的短板3.1 灰狼算法的基础机制灰狼优化算法GWO是Mirjalili在2014年提出的群体智能算法模仿灰狼种群的等级狩猎机制。种群里有四层角色α、β、δ是领导狼负责引导搜索其余狼是ω跟随三匹领导狼更新位置。位置更新公式可以简化为X(t1) X_leader(t) - A * |C * X_leader(t) - X(t)|其中A由收敛因子a决定C是随机分量。收敛因子a从2线性递减到0前期鼓励探索后期偏重开发。3.2 从GWO到MOGWO外部档案是核心单目标GWO扩展到多目标核心变化是引入外部档案Archive用来保存当前找到的非支配解。每一代里领导狼从外部档案中挑选而不再只是种群里的个体如果外部档案满了就按某种规则删掉拥挤区域的解腾出空间给新解。标准MOGWO采用的是网格法来管理外部档案把目标空间划分成网格统计每个网格里解的个数优先删除个数多的网格里的解以维持分布性。这个方法思路没问题但实现比较粗糙网格宽度对结果影响很大而且边缘解容易被误删导致Pareto前沿两端丢失。3.3 标准MOGWO在微网调度问题上暴露的两个短板我拿标准MOGWO跑微网算例之后直观感受是两个问题一是初始化太“随缘”。纯随机初始化在72维的决策空间里初始解在三个目标空间中的分布非常不均匀外部档案从一开始就存在大片空白区域。进化后期想把这些空白补上代价很高经常出现Pareto前沿局部集中、极值解缺失的情况。二是收敛因子线性递减导致探索期不足。GWO的收敛因子a是线性下降的前期探索和后期开发的时间比例在理论上并不差但多目标问题往往有多个等效Pareto区域前期需要更强的探索能力来发现不同区域的候选解。标准线性衰减曲线在迭代中期就开始快速压低a值导致群体很快收缩到局部占优面附近。3.4 改进方向的选择逻辑既然诊断出问题改进方向就很明确用混沌序列初始化种群增加初始多样性。把收敛因子从线性改成余弦型让探索期更长、更均质。用“快速非支配排序拥挤距离”替代网格法维护外部档案。引入多项式变异算子避免算法后期陷入局部Pareto面。这四个改进点的设计逻辑都很朴素没有任何一个会让代码复杂度暴涨但每一项都能在实验指标上看到对应提升。我不建议堆砌太多花哨策略改得越多变量之间的交互越难解释。4. 四项改进逐个拆解初始化、收敛因子、档案维护和变异算子4.1 Tent混沌映射初始化让初始种群先均匀“铺开”混沌映射在群体智能算法里不算新鲜但确实有效。相比Logistic映射Tent映射的遍历均匀性更好不易出现序列堆积在某个区间的问题。最简单的Tent映射形式x(n1) 2x(n)当 x(n) 0.5 x(n1) 2(1 - x(n))当 x(n) 0.5实际使用的时候初始值避开0、0.25、0.5、0.75这些容易陷入周期轨道的点就行。对每个决策变量维度我生成一条独立的混沌序列再线性映射到决策变量的上下界得到初始种群。我在Matlab里写了一个独立函数输入种群规模和维度输出混沌初始种群。实测下来混沌初始化让外部档案在第一代就有更宽覆盖Pareto前沿的极值点在整个搜索过程中都能被保留得更好。4.2 余弦型收敛因子和自适应领导权重标准GWO的收敛因子是线性下降a(t) 2 - 2*(t / MaxIt)改成余弦型之后a(t) 2 * cos(0.5 * pi * t / MaxIt)我计算过几组代数值这个曲线在迭代前期下降缓慢中后期加快下降相当于给算法更长的“大范围搜索”时间到后期再快速收敛到局部精细搜索。这在多目标问题里尤其重要因为前期需要尽量铺满整个Pareto前沿。另外原版MOGWO在更新位置时对α、β、δ三匹领导狼取平均。我改成按迭代进程动态调整权重前期β和δ的权重稍大让群体敢于偏离alpha后期α权重逐渐增大聚焦alpha附近收敛。这个权重调整写成代码就是两行但配合余弦收敛因子收敛性和分布性的平衡会明显改善。4.3 外部档案的两级筛选非支配排序拥挤距离我把外部档案的维护完全改成类似NSGA-II的思路。新候选解进入档案时按下述逻辑处理如果新解被档案里某个解支配丢弃。如果新解支配档案里某些解删除被支配解插入新解。否则让新解入档。档案容量超限时按拥挤距离排序删掉拥挤距离最小的解。拥挤距离计算需要把目标值归一化然后看每两个相邻解在每个目标上的距离之和。这个值反映了解在目标空间中周围有多“空”保留拥挤距离大的解是为了让Pareto前沿分布更均匀边缘点不会被删掉。领导者选择也直接和拥挤距离挂钩——每次选领导者时优先从档案里拥挤距离大的区域选。这比标准MOGWO随机选领导者更合理等于主动让群体去填补前沿的空白段。4.4 多项式变异算子防止“终点即死胡同”多目标进化后期整个种群都集中在Pareto前沿附近此时如果没有变异机制一旦前沿局部是凹形或间断的算法很难跳出去。我在每次位置更新之后引入多项式变异变异概率设为1/维度对每个维度按多项式分布产生扰动。多项式变异是Deb在NSGA-II里用的算子分布指数设为20左右。扰动幅度前期可以是全局的后期逐渐变小。这里有个细节变异算子的幅度要跟收敛因子联动。如果收敛因子已经很小变异幅度还很大那整个种群会在后期反复横跳影响收敛性。我的做法是把多项式变异步长上限乘以(1 - t/MaxIt)让变异幅度随迭代递减。改进策略汇总改进项针对的短板实现思路预期效果Tent混沌初始化初始种群分布不均每个维度独立混沌序列映射提高初始外部档案覆盖率余弦收敛因子探索期不足a(t)2cos(πt/2MaxIt)延长探索、控制收敛节奏自适应领导权重开发/探索失衡前中期增大β、δ权重减少对alpha路径的过度依赖档案二级筛选网格法分布性差非支配排序拥挤距离保留边缘解、改善前沿均匀度多项式变异后期陷入局部Pareto面Deb多项式变异幅度衰减跳出局部占优面我在实际对比中发现真正让Pareto前沿质量提升最大的是档案维护方式从网格法改成拥挤距离法其次是混沌初始化。收敛因子和变异的影响相对温和。如果你时间有限优先改档案维护。5. Matlab代码实现模块划分、核心循环与可视化脚本5.1 代码目录结构项目代码我用纯Matlab脚本实现不依赖任何额外工具箱R2020a以上版本都能跑。目录结构分成数据、算法、结果三块。microgrid_mogwo/ main.m data/ wind_forecast.mat pv_forecast.mat load_forecast.mat price.mat lib/ improved_mogwo.m initialize_chaos.m objective_fun.m constraint_check.m update_archive.m fuzzy_decision.m plot_results.m result/ pareto_front.mat这种分层的好处是算法代码和目标函数代码完全解耦。后续你想换一组预测数据或者把算例从三目标换成两目标只需要改main.m里的数据加载和目标函数不用动优化器。5.2 主程序流程main.m的逻辑很直白加载数据、设置参数、调优化器、画图。要设置的参数包括种群规模N100最大迭代次数MaxIt200外部档案容量ArchiveSize100决策变量维度nVar72燃气轮机24维、储能24维、EV集群24维以及各设备上下界。变量上下界要和目标函数里的约束保持一致否则优化器会频繁触碰边界。迭代过程中我让改进MOGWO在每一代都记录非支配解数量、HV指标和最差目标值方便事后分析收敛曲线。注意别把中间日志写太重Matlab的for循环里频繁用disp和表格赋值会拖慢速度。5.3 目标函数和约束处理罚函数数量级要单独调目标函数建议写成function [f1, f2, f3, violation] objective_fun(x, data)函数内部先解码出P_MT、P_ESS、P_EV三组变量然后用松弛公式计算P_grid。到这里功率平衡已经满足。接着计算储能SOC序列和EV电量序列检查所有约束越界量。越界量累加得到violation目标值本身仍然独立计算。对外输出时如果violation不为零就在每个目标上叠加Penalty violation * 1e5。这个罚系数不是拍脑袋定的我试过1e3到1e9之间的不同数量级。低于1e4约束违反很容易混进Pareto前沿高于1e7可行域边界太“陡”种群一旦越界就完全失去方向。综合下来1e5比较稳。EV终值约束最好单独用更大的罚系数因为它的违反很难从目标值上直观发现。我在EV电量越界判定上把罚系数提高到了1e6这样算法在进化过程中会优先保证EV剩余电量达标。5.4 核心循环骨架代码改进MOGWO的主循环骨架大致如下重点看灰狼位置更新的向量化写法function [Archive, Archive_F] improved_mogwo(obj_fun, nVar, lb, ub, params) N params.N; MaxIt params.MaxIt; Archive []; for t 1:MaxIt a 2 * cos(0.5 * pi * t / MaxIt); % 余弦收敛因子 for i 1:N % 从档案中选择领导者优先拥挤距离大的解 [alpha, beta, delta] select_leaders(Archive, Archive_F); for d 1:nVar A1 2*a*rand - a; C1 2*rand; D1 abs(C1*alpha(d) - pop(i,d)); X1 alpha(d) - A1*D1; % 类似计算X2、X3 w adaptive_weight(t, MaxIt); pop(i,d) w(1)*X1 w(2)*X2 w(3)*X3; end end % 多项式变异 pop polynomial_mutation(pop, lb, ub, t, MaxIt); % 边界吸定计算目标更新档案 ... end end这个骨架只是示意性的真正的代码还需要处理边界吸定、领导者不可用时的回退策略、档案满了之后的拥挤距离删除。写成向量化的好处是100个个体乘72维的更新在Matlab里只需要两次矩阵操作运行速度可以接受。我的算例规模下100×200次目标函数调用每次要跑24小时时序递推在普通i5电脑上大约3到5分钟出完整Pareto前沿。如果你的变量维度更高可以适当把种群降到80迭代降到150指标差异不大。5.5 可视化脚本结果至少要画三张图第一张是Pareto前沿的三维散点图展示三个目标的权衡关系。用marker大小或颜色表示拥挤距离方便直接看到分布密度。第二张是折中解对应的24小时各单元出力曲线。把燃气轮机、储能、EV、主网购电画在同一张图里。第三张是无V2G和含V2G两种模式的净负荷曲线对比这张图直观展示EV集群对削峰填谷的贡献。plot_results.m里建议用sgtitle一次性组织多个子图省得后期拼图。6. 调度结果长什么样Pareto前沿、折中解和单元出力曲线6.1 Pareto前沿的形状说明了很多问题跑出来的三维Pareto前沿我一般会先看它在成本-碳排放平面的投影。这个投影通常是一个单调下降曲线左侧的散点带说明两个目标确实冲突。碳排放低的方案购电少、燃气轮机出力也少但储能和EV的参与成本高因此总成本更高。如果投影图上出现大量“离散孤岛”说明算法多样性不足如果前沿明显偏向某一侧可能是罚函数权重失衡或初始化导致搜索区域受限。改进后的MOGWO跑出来前沿边缘点和中间段的密度比较均匀没有明显的断裂带。6.2 折中解选择模糊隶属度是怎么用的Pareto前沿上一堆解总得给决策者一个“推荐的均衡解”。我用模糊隶属度函数做归一化对每个解计算它在每个目标上的满意度mu_i (f_target_max - f_i) / (f_target_max - f_target_min)目标值越小越好所以f_i越接近最小值mu越接近1。三个目标都算出mu后取最小的那个作为这个解的“最差满意度”然后选最差满意度最大的解作为折中解。这个逻辑很直白我被迫在三个冲突目标之间做妥协妥协的结果要保证最被牺牲的那个目标也不过差。用这个方法选出来的折中解通常落在功率平稳和成本之间较为均衡的位置燃气轮机和储能的利用率都处于中等水平不会出现极端压榨某一个设备的情况。6.3 出力曲线判断原则看着“反直觉”的方案往往有约束bug折中解对应的出力曲线我第一眼看的是燃气轮机是否在峰荷时段出力、低谷时段低出力。如果燃气轮机半夜满发、白天反而停机那多半是电价或爬坡约束配置有问题。储能曲线应该呈现典型的充放交替凌晨低谷充电、上午放电、午间平段充电、晚间高峰放电。EV集群应该呈现类似储能的充放模式但注意它的放电时段不一定完全跟储能同步因为EV电量终值约束会限制它在晚间的放电幅度。主网购电曲线如果出现“高峰段大额购电”除非是净负荷波动目标压得很低迫使系统必须购电否则也是异常信号。每次看到这种结果我都优先检查分时电价数据是否加载错位这个看似简单的检查能拦截大量模型配置错误。6.4 V2G参与的对比效果为了验证V2G建模有效我单独跑了一组“EV固定充电、不参与调度”的对照算例。对照组的EV负荷按照无序充电曲线作为固定负荷加入不参与充放电调度。结果符合预期包含V2G的优化方案里微网总运行成本大约降低8%到12%净负荷峰谷差也更小。EV集群在电价谷段多充电、峰段放电等效于给微网增加了一块低成本储能。这里必须再强调一句如果你跑了V2G模型成本反而比无序充电高通常是V2G补偿价格定得不合理或者EV电量上下限约束太紧而不是算法出了错。7. 调试复盘代码跑通之后还要检查哪些一眼看不出问题的地方7.1 最经典的“假最优”EV电量被优化算法偷偷放空这个问题我在开头提到过。现象是有V2G之后目标成本漂亮地下降了10%以上但你去看EV集群电量曲线会发现从中午开始一路猛跌到晚上已经逼近零第二天用户根本开不了车。原因就是EV电量终值约束没写或写成了不等式但罚系数太低。判断方法很简单把EV集群的SOC序列单独画出来看调度结束时的剩余电量是否不低于用户需求。我用EV集群总电量的形式建模设定了一个“最低可接受剩余电量”阈值。如果终值违反了直接加一个硬罚。这个bug是V2G调度代码里最隐蔽也最致命的复现文献前务必先确认对方有没有写这条约束。7.2 罚函数数量级导致的“等约束越界”松弛变量法解决了功率平衡约束但如果把储能、EV的SOC上下限也写成罚函数数量级不对会出现另一种假象算法宁可让SOC轻微越界也要拼出一个低目标值因为越界量小、惩罚不足多目标优化器认为这个解是“占优”的。我的经验是SOC这类硬约束最好不使用连续罚函数而是在检查越界时直接把violation加到一个较大的量级比如每个越界点各加1再乘基础罚系数1e5。同时查看目标函数返回的violation向量如果在最终Pareto前沿里出现大量非零violation就得提高罚系数。7.3 做算法消融实验顺序是先测试函数后工程算例改进MOGWO到底比标准MOGWO好在哪里建议先在ZDT1、ZDT2这类标准多目标测试函数上对比再看微网算例。直接用工程算例对比有时候指标变好只是因为你改过的算法碰巧更适应这个特定罚函数换了问题完全失灵。我这次做消融实验时分别对比了完整改进、去掉混沌初始化、去掉档案筛选、去掉变异一共四种配置。每项改进的贡献用HV指标和均匀分布指标来衡量。至少在ZDT函数上档案筛选贡献最大变异和混沌初始化各占一部分贡献余弦收敛因子对收敛速度改善明显。7.4 效率和精度怎么平衡向量化与提前终止Matlab的元启发式算法最怕在循环里反复用cell数组、动态增长数组、逐时刻调用函数。我的代码里所有24小时序列都用行向量或矩阵运算一次算完比如SOC递推可以用cumsum实现避免for循环逐小时推。还有一个小技巧如果连续30代HV指标基本不变可以提前终止迭代。多目标进化后期Pareto前沿基本定型再多跑只是微调边界解浪费时间。加上这个提前终止条件后我的平均实验时长从5分钟降到4分钟出头指标几乎无损失。做这个项目最深的体会是算法改进不是越花哨越好模型约束写对才是第一步。一个严谨的EV电量约束比任何一个高级算子的贡献都大。后续如果想继续扩展可以把风电、光伏预测误差作为随机场景来处理或者给EV接入时间、初始SOC加入概率分布让V2G模型更接近真实用户行为。这些都是在现有这个代码框架上可以逐步叠加的内容希望这次的思路能帮你把复现路走得稳一点。
返回列表