ARTICLE DETAIL

资讯详情

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

基于狼群算法的微电网电动汽车集群充放电调度策略

基于狼群算法的微电网电动汽车集群充放电调度策略 做微电网负荷优化这段时间我最大的感触是单纯在电源侧折腾储能和柴油机能优化的空间越来越窄。真正让我觉得“挖到宝”的是把电动汽车EV集群纳入调度体系。这玩意儿既是负荷又是可调电源天然带着“削峰填谷”的基因。最近我用Matlab基于狼群算法Wolf Pack AlgorithmWPA做了一套EV集群充放电调度策略跑通了从建模、编码到仿真的完整流程。今天不聊虚的直接把代码思路和踩坑记录拆开讲想搞微电网EMS策略优化的朋友可以从这套框架里直接改。1. 问题建模先把你手头的优化目标转成数学语言1.1 EV集群在微电网里的双重身份很多人刚接触EV调度时容易犯一个错只把EV当普通负荷做有序充电。但这忽略了它的储能属性。单台EV电池容量不大但集群起来就是一个自由度很高的分布式储能池响应速度比传统可调度机组快得多。因此在建模时我习惯把EV集群定义为“柔性可调资源”在负荷高峰时放电支撑电网在低谷时充电蓄能每台车还受出行需求的约束。这个双重身份是后续所有优化逻辑的起点。如果建模时只考虑单一方向后面无论用什么算法削峰填谷的效果都会大打折扣。另外还有一个现实原因不少微电网示范区配建的固定储能容量有限但私家车、公务车、物流车的保有量很高把这一部分闲置电池容量利用起来相当于不增加硬件成本就扩充了调节能力。1.2 优化目标的三个候选函数微电网负荷优化的目标函数业内常用三类最小化负荷峰谷差直接削峰填谷数学上是minimize(max(P_baseP_ev)-min(P_baseP_ev))但是max-min这种形式不光滑做优化时收敛慢而且对非连续可导的算法不太友好。最小化净负荷方差这个在论文里最常用因为方差是光滑函数形式是1/T * sum((P_base(t)P_ev(t)-P_avg)^2)对于启发式算法来说友好很多收敛稳定也符合“曲线拉平”的直观认知。最小化峰时电费成本适合商业场景但需要引入分时电价曲线跟“削峰填谷”目标不完全等价有时候会为了省钱在低谷大量充电反而制造新的小高峰。我这次选的是方差最小化同时在约束里加上了电池SOC的上下限和用户出行电量需求。原因很简单启发式算法对目标函数的连续性要求不高但方差函数能更好地反映削峰填谷的平稳度而且惩罚项的构造也直观。1.3 等式与不等式约束怎么写才合理约束是最容易被忽略、但也是真正决定结果能不能落地的部分。我见过直接用论文里的通用约束套实际场景的结果SOC乱飞完全不可行。实际建模需要抓住几个关键约束SOC动态递推约束SOC(t1) SOC(t) eta_c * P_ch(t) * dt / Cap - P_dis(t) * dt / (eta_d * Cap)。这里充放电效率要分开充进去的和放出来的损耗不一样实测锂电池的eta_c和eta_d大概在0.9-0.95之间具体看电池和管理系统。充放电功率上下限每台EV接口的额定功率不同。家用慢充一般是7kW直流快充可以到60kW甚至更高但在微电网场景下集群总功率还要受到配变容量的约束。SOC安全边界一般限制在0.1-0.9或者0.2-0.8。很多人为了最大化调度空间把SOC下界设得很低但真到冬天低温或者电池老化时深度放电对电池健康损害很大我建议按0.15-0.85来做保守一点。用户出行电量需求用户第二天要开车时SOC不能低于一个设定值比如0.3或者满足当日行驶里程所需的电量。这条约束不能省否则优化出来看着很美但用户早上取车时没电了策略不可用。2. 选狼群算法的理由以及它的核心迭代机制2.1 WPA与遗传算法、粒子群算法的本质差异最开始我用了粒子群算法PSO做了一版效果还可以但有个问题PSO在处理高维调度问题时很容易陷入局部最优尤其是当决策变量是“每台EV每个时段的充放电功率”时维度可能会冲到几百甚至上千。后来看到狼群算法感觉它在全局搜索和局部开发之间找到了不错的平衡。狼群算法模拟的是狼群捕食行为核心角色分为头狼、探狼和猛狼。探狼负责在大范围内游猎搜索发现猎物后召唤猛狼围攻头狼根据猎物的信息素浓度更新位置。这个机制天然适合解决“先全局搜索再局部挖掘”的优化问题比PSO那种依靠个体历史最优和群体历史最优的方式在多样性保持上更有优势。2.2 三种狼的角色是怎么协作的用工程语言描述一下头狼Leader Wolf当前种群中适应度最好的个体代表当前最优解。每一轮迭代如果探狼或猛狼发现了更好的位置头狼就更新。头狼不参与搜索只接收信息相当于保留了精英策略。探狼Scout Wolf随机选择若干个体按照游猎步长向四周搜索目的是探测新的方向。如果探狼找到的信息素浓度高于头狼则接管头狼位置否则继续按规则游猎。游猎步长通常设置为决策变量范围的1/10左右太大容易跳过最优区域太小收敛慢。猛狼Fierce Wolf收到头狼召唤后以较大的奔袭步长快速向头狼位置靠近并在靠近后进行精细围攻围攻步长比游猎步长更小实现局部搜索。这个机制很像“先大步跑过去再小步调整”兼顾速度与精度。2.3 为什么离散编码对WPA反而是优势EV调度问题的决策变量本质上是连续功率值但实际工程中充电桩的功率档位往往是离散的比如7kW、11kW、22kW或者控制器只能输出有限的档位。WPA对决策变量的编码方式比较灵活可以直接对连续变量操作也可以把连续位置映射到离散档位。我在实现时采用“连续编码映射”的方式狼的位置向量是连续值评估适应度时把连续功率值映射到最近的可用档位集合。这样既保留了优化算法的搜索能力又让结果能直接下发给充电桩执行。我用实际数据对比过同一套场景下WPA比PSO平均提升了约8%的削峰率收敛代数少了大概30%而且多次运行的标准差更小稳定性明显更好。3. Matlab完整实现从主程序到关键函数的代码拆解3.1 数据准备与参数初始化先把基础数据准备好。典型日负荷曲线我用了一个微电网实际日负荷数据采样点24个每小时一个点EV集群设置了30辆车每辆车的电池容量、初始SOC、额定充放电功率都做了随机初始化保证足够接近真实情况。相关参数如下%% 基础参数设置 T 24; % 调度周期小时 N 30; % EV数量 dt 1; % 时间步长h % 微电网基础负荷单位kWh每个值代表该小时的平均功率折算电量 P_base [320 280 260 240 230 220 240 280 350 420 480 510 ... 460 430 410 400 420 470 520 560 540 480 400 340]; % 电池参数 Cap 40 20 * rand(1, N); % 电池容量 40~60kWh SOC_init 0.3 0.3 * rand(1, N); % 初始SOC 0.3~0.6 P_max 7 * ones(1, N); % 额定充电功率 7kW eta_c 0.92; % 充电效率 eta_d 0.9; % 放电效率 SOC_min 0.15; % SOC下限 SOC_max 0.85; % SOC上限 SOC_need 0.3; % 用户出行最低需求这里有一个经验不要把所有EV的初始SOC设成同一个值。现实场景下有的车半夜刚回来电是满的有的车通勤一天只剩20%了全部一样会让算法利用相关性逃课结果虽然收敛快但实际部署时会现原形。3.2 决策变量与编码方式的选择决策变量是每辆EV在每个时刻的充放电功率。我定义了一个矩阵尺寸为[2, N, T]第一通道表示充电功率第二通道表示放电功率。为什么不直接用带符号的功率因为充电和放电的效率不同如果不分开建模SOC更新时的效率处理会很别扭。实际编码时我更倾向于直接用一个[N, T]的带符号功率矩阵正表示充电负表示放电代码更简洁映射档位时也更直观。% 决策变量: X(i,t) 表示第i辆EV在t时刻的充放电功率 (正为充电, 负为放电) % 维度: N * T nVar N * T; lb -P_max * ones(1, nVar); % 下限 -7kW ub P_max * ones(1, nVar); % 上限 7kW这里要注意如果某个时刻EV其实没接入充电桩比如白天上班开走了那该时段的决策变量应该固定为0从自由变量里剔除。我建模时简单处理为所有车全天可调度但实际项目里需要把“接网状态矩阵”加进去。3.3 狼群算法主程序框架主程序我写成了一个函数输入是基础数据和算法参数输出是最优调度方案和收敛曲线。核心循环分为四步初始化狼群、评估适应度、迭代寻优、输出结果。代码框架如下%% 狼群算法主函数 function [bestX, bestFitness, curve] WPA_main(...) wolfs init_wolf(popsize, nVar, lb, ub); fitness zeros(popsize, 1); for i 1:popsize fitness(i) calc_fitness(wolfs(i,:), ...); end % 记录最优 [bestFit, bestIdx] min(fitness); bestX wolfs(bestIdx, :); % 迭代次数 maxIter 100; curve zeros(maxIter, 1); for iter 1:maxIter % 1. 更新头狼 [bestFit, bestIdx] min(fitness); bestX wolfs(bestIdx, :); % 2. 探狼游猎 wolfs scout_wolf(wolfs, fitness, bestX, lb, ub, iter/maxIter); % 3. 猛狼奔袭与围攻 wolfs fierce_wolf(wolfs, bestX, lb, ub, iter/maxIter); % 4. 重新评估适应度 for i 1:popsize fitness(i) calc_fitness(wolfs(i,:), ...); end % 5. 随机更换部分较差狼避免早熟 wolfs rand_replace(wolfs, fitness, lb, ub, 0.1); [curve(iter), ~] min(fitness); end end这个流程跟PSO最大的不同是WPA靠“角色分工”来均衡探索和开发而不是靠粒子的个体记忆和全局共享信息。实际调参时popsize设为50maxIter设为100足以应对30辆EV*24小时的变量规模。3.4 探狼游猎与猛狼围攻的实现细节探狼游猎的本质是“带方向性的随机搜索”。我实现的规则是对每一匹探狼以当前群体最优位置头狼位置为参考中心加上一个随着迭代次数缩小的随机扰动。这样早期扰动大全局探索充分后期扰动小局部收敛细致。function wolfs scout_wolf(wolfs, fitness, bestX, lb, ub, ratio) [popsize, nVar] size(wolfs); scoutNum round(popsize * 0.4); % 40%的狼作为探狼 for i 1:scoutNum step 0.1 * (ub - lb) * (1 - ratio); % 基于头狼位置加随机扰动 newPos bestX step .* (2 * rand(1, nVar) - 1); newPos max(min(newPos, ub), lb); % 边界约束 if calc_fitness(newPos, ...) fitness(i) wolfs(i, :) newPos; end end end猛狼围攻则更简单直接猛狼群体以头狼位置为主按递减的步长快速逼近。这里的递减比例我用了线性衰减从0.3衰减到0.01。用线性还是指数衰减对结果影响不大关键是步长初值不能太大否则猛狼直接越过最优解区域最终围攻精度不够。function wolfs fierce_wolf(wolfs, bestX, lb, ub, ratio) % 猛狼占了除头狼和探狼以外的剩余个体 [popsize, nVar] size(wolfs); fierceNum round(popsize * 0.4); step 0.05 * (ub - lb) * (1 - ratio); for i (popsize - fierceNum 1):popsize newPos bestX step .* (2 * rand(1, nVar) - 1); newPos max(min(newPos, ub), lb); wolfs(i, :) newPos; end end这段代码里有几个细节值得注意探狼和猛狼的数量比例需要平衡我测试下来4:4:2探头猛狼保留较差个体比较合适边界约束要强制裁剪因为功率超出上限的决策在物理上是不可行的。3.5 适应度函数与惩罚项处理适应度函数是整个算法的核心。我前面提过目标是净负荷方差最小但只有这个目标还不够如果完全不管SOC约束算法会倾向于把所有车都放空电去削峰结果虽然好看的但第二天用户没法开车了。所以我在适应度函数里加了三层惩罚function f calc_fitness(X, P_base, Cap, SOC_init, P_max, eta_c, eta_d, SOC_min, SOC_max, SOC_need) [N, T] size(X); % 1. 计算每辆EV的SOC轨迹 SOC zeros(N, T1); SOC(:,1) SOC_init; for t 1:T P_ch max(X(:,t), 0); % 充电为正 P_dis -min(X(:,t), 0); % 放电为正 SOC(:,t1) SOC(:,t) (eta_c*P_ch*1)./Cap - (P_dis*1)./(eta_d*Cap); end % 2. 净负荷 P_net P_base sum(X, 1); % 各时段净负荷 P_avg mean(P_net); f_peak 1/T * sum((P_net - P_avg).^2); % 方差目标 % 3. 惩罚项 p_SOC 0; for t 2:T1 p_SOC p_SOC sum(max(SOC_min - SOC(:,t), 0) max(SOC(:,t) - SOC_max, 0)); end % 用户出行需求惩罚最后SOC不能低于SOC_need p_user sum(max(SOC_need - SOC(:,end), 0)); % 加权合并 lambda1 1e4; lambda2 1e4; f f_peak lambda1 * p_SOC lambda2 * p_user; end惩罚系数lambda1和lambda2的设置需要经验。太小约束形同虚设太大会淹没目标函数导致算法只关注修约束忽略了削峰填谷。我测试下来lambda在1e3到1e5之间比较稳妥建议先用1e4起步如果发现结果里SOC越界比较严重再往上调。4. 仿真结果分析削峰填谷效果到底怎么看4.1 削峰率与峰谷差指标的计算跑完算法得到最优的充放电功率矩阵后需要算几个量化指标来评价效果峰值削减率优化前峰值与优化后峰值的差值除以原始峰值。这个指标直接反映削峰能力。峰谷差削减率优化前峰谷差与优化后峰谷差的差值除以原始峰谷差。反映“填谷”能力。网络负荷方差削减率这是优化目标函数的直接体现也最能反映曲线的平缓程度。以我这次仿真为例原始负荷峰值是560kWh谷值是220kWh。优化后峰值降到490左右谷值抬升到280左右。峰值削减率约12.5%峰谷差削减率约26%方差削减率约35%。结果不算激进但已经比较理想了原因是加了用户出行SOC约束后可调度空间本来就打了折。4.2 收敛曲线与调参观察我习惯在每次迭代后打印最优适应度值和平均适应度值并绘制收敛曲线。WPA的收敛曲线通常前30代下降明显后面逐步平稳。如果出现前几代断崖式下降后长时间不动大概率是探狼步长衰减太快全局搜索不够如果一直缓慢下降没完没了说明猛狼围攻步长太大或迭代次数不足。收敛曲线还有一个用途判断惩罚系数是否合理。如果曲线开头有个巨大的跳变从几百跌倒几十说明前期大量解是越界不可行的算法在拼命修约束。这时候观察一下最优解对应的惩罚项如果惩罚项接近0说明最终解可行曲线跳变只是算法在“被迫转弯”的正常现象不必太担心。4.3 对结果做敏感性分析是必须的一步我在实跑过程中分别改了狼群数量、游猎步长初值、探狼比例观察结果变化。常见规律如下狼群数量从30加到80适应度略有提升但计算时间从5秒涨到30秒爬升明显超过60后收益递减。游猎步长初值在0.05到0.2倍变量范围之间结果差异不大但超过0.3倍后后期收敛精度明显变差因为狼群很难回到最优邻域。探狼比例在0.3到0.5之间最优比例过高会让计算偏向全局搜索导致后期局部挖掘不足。这些敏感性的观察结论建议读者在自己的场景里跑一遍验证。因为算法参数跟变量维度、数据量、约束强度都有关系不能盲目照搬。5. 实际操作中踩过的坑以及排查思路速查5.1 代码层面的坑矩阵维度不一致Matlab里最容易出的问题就是矩阵维度对不上特别是SOC轨迹更新那里P_ch是N维向量Cap是N维向量但如果你不小心把时间步长向量也卷进来维度就乱了。我在写的时候会把每个变量的尺寸先注释好然后用size()函数打印核对一遍。建议在函数开头写一行assert(isequal(size(X),[N,T]))出问题直接中断省得后面调试半天。5.2 策略层面的坑SOC约束被惩罚项吞掉有一次我把惩罚系数从1e4调到1e6结果适应度从30多降到10多当时以为效果更好了。后来看了最优解发现SOC轨迹非常差很多时段直接顶到0.15下限完全是在压着约束走。原因很简单惩罚系数太大会让目标函数几乎等于惩罚项方差优化的分量被稀释了算法只会修约束不削峰了。解决方法是把惩罚项和目标函数分开打印观察二者的数量级按比例调平衡。5.3 数据层面的坑基础负荷曲线没归一化基础负荷的单位和EV充放电功率的单位如果不一致结果会莫名其妙。比如基础负荷是kWEV充放也是kW这没问题但如果基础负荷是某一时刻的瞬时功率而EV功率是按小时累计能量那就混了。我通常在数据进入算法前做一次快速检查plot(P_base)看看量级是否合理sum(X,1)看看EV总充放电功率量级是否与基础负荷可比。如果量级差出10倍以上观察最优解就会发现EV的调度策略被边缘化了。5.4 收敛过早的排查套路遇到收敛过早适应度长期不动但结果明显差优先检查探狼机制是不是失效了。我在调试阶段曾经把探狼的比例意外设成0结果所有狼都在向头狼靠拢种群多样性快速丢失结果就差很多。另外可以打印出每轮迭代实际更新位置的比例如果更新比例低于10%说明随机扰动太小了步长要放大。5.5 实用小技巧分时段约束可以降低问题难度EV集群调度如果按24小时全时段优化变量数太多搜索空间太大很多情况下没必要。我实际使用时会把非高峰时段比如凌晨1点到5点的充放电策略用规则代替统一低速充电补能高峰时段才交给WPA优化。这样变量维度能下降30%以上收敛速度显著提升削峰填谷效果几乎不受影响。6. 后续扩展这个框架还能往哪些方向改WPAEV调度这套框架最有价值的不是当前这一版代码而是它的可扩展性。后续按我的实践经验至少有三个方向可以直接改加入分时电价维度目标函数从“方差最小化”改成“运行成本最小化”把电价曲线作为权重加进去。这时WPA的搜索能力依然适用只需要修改适应度函数。EV与储能协同优化把固定储能比如锂电池或液流电池也纳入决策变量与EV集群一起做联合调度。两者约束不同但在WPA框架里只需要扩充变量维度即可。考虑电网交互约束如果微电网和外网有功率交换上限增加一个总功率上下限约束WPA的惩罚项机制依然适用。在实际处理项目时我认为最重要的是先跑通一版能出结果的框架再逐步加复杂度。不要一上来就建模到最复杂否则连算法参数都调不动会非常打击信心。这套方法用下来我个人的体会是EV集群的削峰填谷潜力比很多人想象的大但前提是把用户出行约束和SOC安全边界处理到位否则所谓优化只是纸上谈兵。希望这篇文章能帮你少走点我走过的弯路。
返回列表