十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

基于粒子群算法的家庭微网优化模型Matlab实现

基于粒子群算法的家庭微网优化模型Matlab实现 最近在整理家庭微网优化方面的案例时发现一个很有意思的现象很多人一提到微网优化本能地就想用商业求解器或者复杂数学工具但真正落地时却往往被模型规模、非线性约束、参数耦合这些现实问题卡住。我自己在Matlab里搭了一版基于粒子群算法的家庭微网优化模型从负荷预测、光伏出力模拟到储能充放电策略进行了全流程验证整体效果很稳今天就把这套做法的思路和踩过的坑完整分享出来。这个模型解决的核心问题是在分时电价、光伏出力波动、家庭负荷随机性的三重约束下如何安排储能充放电和电网购售电策略让一天下来的电费最低、光伏自用率最高。适合正在做微网调度、储能控制、以及想入门智能优化算法的朋友参考尤其是已经有一定Matlab基础、但还没把粒子群算法真正用起来的那批人。下面直接进入正题。1. 家庭微网优化模型的基本思路1.1 家庭微网是什么为什么要做运行优化家庭微网本质上是一个小型的发-储-用系统典型构成是屋顶光伏、储能电池、家庭负荷以及和外部电网的连接点。它和大型微网的区别在于容量小通常几千瓦到几十千瓦、设备简单、控制目标非常明确——就是省钱和提升自给率。但问题没那么简单。光伏出力集中在白天家庭用电高峰却在傍晚和夜间储能的作用就是把这个时间错配给“挪”过来。然而储能电池的充放电效率不是100%循环寿命也不是无限的买电和卖电的价格更是有差异。所以所谓的“运行优化”就是要在这堆互相牵扯的条件里找一个整体最优的功率分配方案。如果只是靠经验规则比如“光伏多就多充电晚上统一放电”在电价波动平缓时问题不大但一旦进入分时电价或实时电价场景规则策略就很难接近最优解了。这也是我做这个项目的直接动机把优化的过程交给算法而不是拍脑袋。1.2 为什么选择粒子群算法来做优化家庭微网优化本质上是一个带约束的、非线性的、多时段的决策问题。常见的手段有动态规划、混合整数线性规划、遗传算法等但我最终选了粒子群算法PSO原因很实际第一问题规模不大。家庭微网以24小时为周期、15分钟到1小时为步长决策变量通常只有几十个维度远没到需要大规模求解器的程度PSO对付这种规模绰绰有余。第二模型里有非线性环节。电池充放电效率往往是分段或曲线的电网交互功率也可能存在阶梯约束这些东西会让MILP建模变得麻烦而PSO作为启发式算法对模型形式没有硬性要求目标函数只要能算出来就行。第三实现成本低。PSO的代码量很小不需要额外装求解器一个普通电脑跑几分钟就能出结果。对于学术验证和方案对比来说这个效率非常友好。当然PSO也有自己的短板容易陷入局部最优、参数敏感、多次运行结果可能不同。但这些在后面的调优和多次运行取最优策略里都能得到缓解属于可接受的工程代价。1.3 优化模型的核心构成一个完整的家庭微网优化模型至少需要四块东西决策变量储能充电功率序列、储能放电功率序列、向电网购电功率、向电网售电功率每一小时一个值组成整个时间序列。目标函数一天的总运行成本最小化包括购电费用、售电收益、电池退化成本作为惩罚项也可以把光伏自用率加权进去。约束条件功率平衡约束光伏 储能 电网 负荷、储能SOC递推关系、电池充放电功率限制、SOC上下限、电网交互功率限制。输入数据24小时负荷曲线、光伏出力曲线、分时电价、电池参数。这四块看起来不难但真正做起来细节非常多。尤其是储能SOC的递推和电池退化成本的引入方式直接决定了优化结果是否合理。我在第一次建模时忽略了退化成本结果算法给出的策略是“疯狂充放”系统成本虽然好看但电池寿命被严重透支这在实际项目中是绝对不能接受的。2. 家庭微网建模与数据准备2.1 基础数据怎么获取与处理优化模型的效果上限取决于输入数据的质量。我的项目里用了三类核心输入数据第一类负荷曲线。如果没有真实电表数据可以按典型家庭用电模式构造。一般情况是凌晨和上午负荷低午间有小幅上升傍晚到睡前是全天高峰期。我做了一个简单的示例24小时的负荷值大概是这样的规律峰值出现在19点到21点左右基础负荷在300W左右峰值能达到2400W左右。如果有真实数据直接从智能电表导出CSV即可。第二类光伏出力曲线。光伏出力主要受光照影响典型特征是午间达到峰值、早晚为零并伴随短时云层波动。做优化时一般不用考虑秒级波动按小时级平均出力就能满足调度需求。夏天晴天的光伏利用小时约4到5小时我这里用一个钟形曲线模拟峰值约3kW。第三类分时电价。国内很多地区已经执行峰谷分时电价常见做法是尖峰、高峰、平段、低谷四段。举例低谷时段0点到8点电价0.35元每度平段8点到10点和14点到18点0.68元左右高峰时段10点到14点和18点到21点1.1元上下尖峰时段21点到23点最贵能到1.3元。电价结构直接决定了储能的套利空间低谷充电、高峰放电就是储能赚钱的基本逻辑。这些数据准备好后建议统一整理成结构体struct存进MATLAB的工程目录下避免散落在脚本里。我习惯是把负荷、光伏、电价放进一个名为data的struct后续所有函数都能直接引用。2.2 储能系统建模要点储能建模是整个优化模型里最容易出问题的地方。很多初版模型只写了一个SOC递推公式就不管了但实际工程中至少要考虑以下几点SOC递推。SOC(k1) SOC(k) (充电功率 × 充电效率 / 电池容量) × 时间步长 - (放电功率 / 放电效率 / 电池容量) × 时间步长。注意充放电效率是分开的不能共用一个值。充放电不能同时进行。虽然理论上功率可以写成负值来表示放电但有些优化算法会在迭代时同时给“充”和“放”都赋了正值这就要求在适应度函数里加一个互斥检查——否则会出现又充又放SOC不变但系统损失大量效率的荒唐结果。功率限制。充电最大功率和放电最大功率由电池和逆变器共同决定一般取电池额定功率的0.5到1倍SOC上下限通常设0.1到0.9保护电池不过充过放。电池退化成本。磷酸铁锂等电池每多一个充放电循环寿命都会折损。这个成本必须进目标函数否则算法会倾向让电池一直满负荷充放。我用的退化模型比较简单设定循环寿命次数比如3000次购买成本均摊到每次循环再乘当天实际充放电的总能量。储能模型多做一点优化结果就会更“可信”一点。否则就是看着好看、落地全废。2.3 目标函数与约束的数学表达目标函数我按一天的总费用最小来写表达式可以拆解为总费用 购电成本 - 售电收益 电池退化惩罚其中购电成本 每小时购电量 × 对应电价从0点到23点累加售电收益 每小时售电量 × 上网电价。电池退化惩罚 单位退化成本 × 全天充放电总电量。约束方面核心是每个时刻的功率平衡约束光伏出力(k) 储能放电功率(k) 购电功率(k) 家庭负荷(k) 储能充电功率(k) 售电功率(k)此外还有SOC上下限约束、充放电功率上限约束、以及电网交互功率的上限约束。这些约束在PSO模型里通常不单独用求解器而是以“罚函数”的方式嵌入到适应度计算中。也就是如果某个解违反了约束就在适应度上增加一个很大的惩罚项让算法自动淘汰这些解。这种处理方式比强制修正更接近PSO的使用习惯容错率也高。3. 粒子群算法的原理与Matlab实现3.1 粒子群算法的核心思想粒子群算法的灵感来自鸟群觅食。把每一个候选解想象成一只鸟它在解空间里飞来飞去带着两组记忆自己飞过的最好位置pbest以及整个鸟群发现的最好位置gbest。每次移动时鸟会根据当前速度、朝自己历史最优的倾向、朝全局最优的倾向这三个方向来调整下一步的速度和位置。用生活化的说法就是每个人都在搜索自己的最优解但同时也关注着群里最牛的那个人在哪儿往那边靠一靠同时也保留自己的探索路线。反复迭代之后整个群就会聚集到一块比较好的区域。在Matlab里实现PSO核心变量就四个粒子位置即一组决策变量的取值。粒子速度每次迭代位置的改变量。个体最优pbest当前粒子历史最好适应度对应的位置。全局最优gbest所有粒子历史最好适应度对应的位置。位置和速度的更新公式很经典V(k1) w × V(k) c1 × rand × (pbest - X(k)) c2 × rand × (gbest - X(k))X(k1) X(k) V(k1)公式里的w是惯性权重越大越倾向于全局搜索越小越倾向于局部精细搜索c1和c2是学习因子c1管“向自己学”c2管“向群体学”。合理的参数组合能做到前期快速定位后期精细收敛。3.2 编码方案与种群初始化我用的编码方式是“实数编码”也就是一个粒子直接就是一个向量长度为决策变量的个数。这个项目里我取时间步长为1小时24个时段决策变量包括储能充电功率24个变量、储能放电功率24个变量、购电功率24个变量、售电功率24个变量总计96维。实际使用中因为功率平衡约束的存在购电功率可以直接用公式算出来不必放在粒子编码里这样可以把维度降到72维收敛速度会快一些。售电功率同理可以通过“光伏富余功率”推算。我在代码里保留了充放和购售电的显式编码是为了后续扩展需求响应等场景时更灵活。种群初始化时每个粒子的每个维度在允许范围内随机生成。储能的充放电功率在0到额定功率之间随机购售电功率在0到电网功率上限之间随机。随机种子要不要固定这个事建议运行对比场景时固定以排除随机性影响方便复现和比较。3.3 适应度函数与约束处理适应度函数是整个PSO的核心直接决定算法的进化方向。我的适应度函数接收一个96维的粒子向量解包成充放电和购售电序列再计算总费用。约束处理上我用了两种手段结合一种是硬性修正。电池SOC超出上下限时把SOC“钳”在边界值上充放电功率为负时直接置0。另一种是罚函数。如果某时刻功率平衡约束的误差超过容忍阈值就在适应度上增加一个很大的惩罚值这个阈值我设为1e-3。关键心得惩罚系数不能设得太离谱。设太大会让算法失去探索欲望所有解都因为罚项而一团糟设太小约束形同虚设解的可行性没法保证。我调试下来罚函数系数大约是目标函数正常数量级的一百到一千倍效果最好。3.4 完整Matlab代码实现下面是一份简化但能跑通的主循环代码。核心逻辑都在你可以直接拷贝到Matlab里看效果具体业务参数再自己补。%% PSO主循环 clear; clc; %% 基础数据示例24h load_data; % 内部生成 data 结构体负荷、光伏、分时电价、电池参数 %% PSO参数 nVar 72; % 决策变量个数24充24放24购售电按公式推 nPop 30; % 种群规模 maxIter 200; % 最大迭代次数 w 0.6; % 惯性权重 c1 1.5; % 个体学习因子 c2 1.5; % 群体学习因子 varMin [zeros(1,48), zeros(1,24)]; % 变量下界 varMax [data.PcMax*ones(1,24), data.PdMax*ones(1,24), data.PgridMax*ones(1,24)]; % 变量上界 %% 初始化种群 particle repmat(struct(position,[],velocity,[],cost,[],pbest,[],pbestCost,[]), nPop, 1); gBestCost inf; gBestPosition []; for i 1:nPop particle(i).velocity zeros(1, nVar); particle(i).position varMin (varMax - varMin) .* rand(1, nVar); particle(i).cost fitness(particle(i).position, data); particle(i).pbest particle(i).position; particle(i).pbestCost particle(i).cost; if particle(i).cost gBestCost gBestCost particle(i).cost; gBestPosition particle(i).position; end end %% 迭代优化 for iter 1:maxIter for i 1:nPop r1 rand(1, nVar); r2 rand(1, nVar); particle(i).velocity w * particle(i).velocity ... c1 * r1 .* (particle(i).pbest - particle(i).position) ... c2 * r2 .* (gBestPosition - particle(i).position); particle(i).position particle(i).position particle(i).velocity; % 边界处理 particle(i).position max(particle(i).position, varMin); particle(i).position min(particle(i).position, varMax); % 评估 particle(i).cost fitness(particle(i).position, data); % 更新个体最优 if particle(i).cost particle(i).pbestCost particle(i).pbest particle(i).position; particle(i).pbestCost particle(i).cost; end % 更新全局最优 if particle(i).cost gBestCost gBestCost particle(i).cost; gBestPosition particle(i).position; end end fprintf(Iter %d, Best Cost %.4f\n, iter, gBestCost); end %% 输出最优方案 Pch gBestPosition(1:24); Pdis gBestPosition(25:48); Pbuy gBestPosition(49:72); Psell max(0, data.Ppv Pdis - Pch - data.Pload Pbuy);单独提一句fitness函数的写法直接决定模型成不成。你需要在fitness里完成功率平衡计算、SOC递推、惩罚项累加最后返回一个标量。下面是一段fitness函数的关键结构function cost fitness(x, data) Pch x(1:24); Pdis x(25:48); Pbuy x(49:72); Ppv data.Ppv; Pload data.Pload; price data.price; SOC zeros(1,25); SOC(1) data.SOC_init; maxSOC data.SOC_max; minSOC data.SOC_min; totalCost 0; penalty 0; for k 1:24 % 功率平衡售电功率由富余功率计算 Psell max(0, Ppv(k) Pdis(k) - Pch(k) - Pload(k) Pbuy(k)); balance Ppv(k) Pdis(k) Pbuy(k) - Pch(k) - Pload(k) - Psell; if abs(balance) 1e-3 penalty penalty 1e6 * abs(balance); end % 储能SOC递推 SOC(k1) SOC(k) (Pch(k)*data.eta_ch - Pdis(k)/data.eta_dis) / data.capacity; totalCost totalCost price(k)*Pbuy(k) - data.price_sell * Psell; end % SOC约束惩罚 if any(SOC maxSOC) || any(SOC minSOC) penalty penalty 1e5 * (sum(max(0, SOC - maxSOC)) sum(max(0, minSOC - SOC))); end % 电池退化成本 degrade data.batteryCost / data.lifeCycles * (sum(Pch) sum(Pdis)); cost totalCost degrade penalty; end注意SOC的初值和终值问题。很多家庭储能要求每天结束时SOC回到初始水平第二天才能继续同样的策略。不加这个约束的模型算法会倾向于在最后时刻把电池放空虽然当日成本最低但和实际运行逻辑冲突。建议在fitness末尾加一项SOC(25)-SOC(1)的差值惩罚把终值锁到初值附近。4. 仿真结果分析与参数调优4.1 基准场景仿真结果我以一个典型夏季家庭为例光伏峰值约3kW、日发电量约11度家庭日用电量约15度晚高峰明显储能电池容量10kWh额定功率3kW初始SOC设为0.5执行峰谷分时电价。用上面的PSO跑200代、30个粒子典型结果是优化前无储能、光伏直接自用日购电费用约12.8元。优化后PSO调度储能光伏日购电费用约7.6元节省约40%。储能在低谷时段电价0.35元充满在高峰时段电价1.1元以上放电SOC曲线基本符合“晚上低、白天光伏充、傍晚放”的直觉但和纯规则策略不同的是算法会在上午电价平段时小幅充电以应对下午可能的阴天波动这种“未雨绸缪”的行为是规则策略很难体现的。光伏自用率从纯自发自用的62%提升到了89%左右富余电量大部分储存在电池里而不是低价上网。这个结果的核心含义是优化模型不是单纯让光伏“发得多”而是让每一度电都在价格最高的时段被自己用掉或者替代高价购电这才是收益的主要来源。4.2 PSO参数调优心得PSO参数的设置很多教程只给一个宽泛的范围但实际使用差别很大。我调参之后总结出几个规律惯性权重w一个固定值0.6在大多数场景下够用。如果想做得更精细可以用线性递减策略——从0.9降到0.4前100代偏全局搜索后100代偏局部精细搜索。实测收敛速度更快结果也更稳定。学习因子c1、c2经典取值0.8到2之间。c1偏大容易让粒子“自以为是”在自己的局部徘徊不出去c2偏大容易让所有粒子快速向一个位置聚集过早收敛。一般取c1 c2 1.5左右平衡感比较好。种群规模30到50足够。这个模型维度不到100种群再大只会拖慢速度收益不大。迭代次数200次左右能稳定到可接受误差。如果你发现结果在最后几十代还在明显下降就说明还没收敛需要加大迭代。我建议每次调参后至少跑5次比较最好值、平均值和方差。如果5次结果波动特别大说明参数或种群的探索性有问题一般是w偏小或种群太小。4.3 与规则策略的对比为了证明PSO的价值我用两种策略做了对比。第一种是“光伏优先固定时段充放”的规则策略白天光伏给电池充电电价高峰时段放电到负荷第二种是PSO优化策略。在相同数据上规则策略的日成本约9.2元PSO优化是7.6元差距约17%。如果全年累积下来这个差距就非常可观了。更重要的是当电价波动变复杂比如引入实时电价规则策略几乎没法维护而PSO只需要改电价数组就能重新优化鲁棒性很强。这个对比也说明一件事规则策略适合做初版方案或兜底但真正的精细化调度一定要上优化算法。5. 常见问题与排错实录5.1 常见问题速查表我在这个项目里踩过的坑和帮别人排查过的问题汇总成下面这张表很多问题网上搜不到答案但解决起来其实非常简单。症状根本原因解决办法优化结果全是边界值奇怪得很罚函数权重过小约束等于摆设把惩罚系数提高到目标函数的100到1000倍收敛非常慢跑了很久还在降惯性权重太大或迭代次数不足w从0.9线性降到0.4或增加迭代次数SOC曲线乱跳违反上下限硬性修正和罚函数没有同时用先用max/min钳制SOC再对越界量加罚充放电同时发生模型没做互斥约束粒子同时取正值在fitness里判断若Pch0且Pdis0加罚或强制清零每天最后一小时电池放空缺少SOC终值约束加SOC(25)-SOC(1)差值罚项锁定周期平衡多次运行结果差异过大粒子数太少或w固定导致随机性强粒子数至少30多次运行取最优或固定随机种子Matlab中文注释乱码编码格式不是UTF-8在“预设项-编辑器-语言”里设置UTF-8编码或重新保存成UTF-8格式适应度计算始终报NaN某个变量越界导致电池容量除0或根号负数检查fitness中除数和pow运算对极端值做保护5.2 参数灵敏度与全局最优的实践心得PSO是启发式算法全局最优的“保证”是不存在的只能通过多次运行和参数调整逐步逼近。我自己的操作习惯是每次跑10轮记录最优值和平均值最优值作为方案平均值用于评估算法稳定性。如果平均值和最优化差距在2%以内说明模型和参数都正常如果超过5%就得回头查参数或模型代码。还有一个很容易被忽略的点边界处理方式对结果影响很大。最粗暴的做法是边界截断超出上限就设为上限但这会让大量粒子堆积在边界上降低多样性。更好的做法是“反弹法”——速度反向让粒子重新弹回可行域。我用反弹法之后优化效果和收敛速度都有明显提升。最后再说说怎么判断模型结果是否可信。一个直接的验证方式把优化出的功率序列代入一个完全独立的潮流/平衡校验脚本看每个时刻的功率平衡误差是否接近0。很多模型跑出漂亮的目标函数但功率平衡误差达到几十瓦甚至上百瓦这在1kW量级的家庭微网里是不可接受的。6. 后续扩展方向这个模型做完之后我陆续给它加了几个实用的扩展每个都能直接沿用现在的PSO框架不需要改动太多加入电动汽车充电策略。把EV的充电功率和充电时间也作为决策变量以“最低总费用”为优化目标同时保证早上出门时EV电量满足行程需求。加入空调等温控负荷的弹性调度。在一定温度舒适度范围内允许空调提前制冷或延迟启动把部分负荷挪到光伏出力大或电价低的时段。与Simulink联合仿真。把PSO优化出的SOC曲线作为目标在Simulink里做储能双向变流器的底层控制仿真验证功率跟踪效果。这个方向上热词里提到的“基于Matlab和Simulink实现双向储能控制仿真模型”就是一个很自然的延伸优化层出目标控制层去跟踪。加入实时电价和预测误差。目前的光伏和负荷曲线是“已知未来”的离线优化实际应用中需要结合预测算法。我尝试过把短期预测误差以随机扰动的方式加入输入PSO依然能给出一个鲁棒的调度方案只不过需要把问题改写成滚动优化每15分钟重算一次未来4小时策略。这些扩展不需要推翻现有模型只要在问题规模和约束上做迭代粒子群算法的框架完全撑得住。这也是我推荐用成熟启发式算法做微网优化的核心原因先跑通闭环再逐步加深比一开始追求高大上的求解器实际得多。
返回列表