ARTICLE DETAIL

资讯详情

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

双层鲸鱼算法求解非合作博弈的居民负荷分层调度模型

双层鲸鱼算法求解非合作博弈的居民负荷分层调度模型 电力系统里有个特别典型的场景夏天傍晚大家都在家空调、热水器、电动车充电桩一起开小区变压器负荷直接被拉满而凌晨大家睡觉时负荷又掉到谷底。居民侧负荷调度的意义就在这里用价格信号或者控制策略把一部分负荷挪到低谷时段不用扩建变压器就能缓解峰谷压力。这个项目标题里的“双层鲸鱼算法求解”加“非合作博弈的居民负荷分层调度模型”属于典型的智能优化博弈论交叉应用。从实际工程和算法研究的角度讲这个模型的意义在于传统集中式调度假设所有用户服从调度中心指令但现实中每家每户都有各自的用电偏好和舒适度需求用户之间是独立决策、各自追求利益最大化的。所以更合理的方式是把用户当作博弈参与者调度中心通过价格信号或激励政策引导用户调整用电行为而不是强行拉闸限电。这篇内容我按照“模型思路—数学建模—算法原理—Matlab实现—算例分析—调参实战”的顺序展开照顾到不同基础的人就算你是第一次接触双层优化和博弈论也能照着代码一步一步复现出来。1. 先想明白为什么要用“分层博弈”来调度居民负荷1.1 居民负荷调度的核心难点居民负荷和工业负荷最大的区别在于“可控性差、单体容量小、数量庞大”。一台空调功率可能只有1到2千瓦一个小区几百户加起来就比较可观了。如果调度中心直接下发指令“你家空调下午三点必须关掉”用户很难接受。但如果告诉用户“峰时电价1块2低谷电价3毛5”用户就会自发把洗衣机挪到晚上洗。这个过程中存在决策层次的差异调度中心上层关心整个小区的负荷曲线尽量平缓峰谷差越小越好运行成本越低越好。用户下层关心自己的电费尽可能少同时舒适度不能太低。空调该开还得开、电动车该充还得充只是愿意在一个更便宜的时间段里充。这两层目标不一致就构成了一个主从递阶决策问题。本质上上层先发布一个策略比如分时电价、激励补贴下层根据这个策略做自己的最优决策然后把决策结果反馈给上层。上层根据反馈再调整策略。这就是标准的主从博弈模型。1.2 非合作博弈为什么适合描述用户行为“非合作博弈”这个名词听起来唬人但内涵很简单每个用户只关心自己的利益不会为了整个小区的“整体最优”而牺牲自己的用电体验。这里的“非合作”不是贬义词而是说决策是分散的、自治的。对比两种建模方式调度方式核心思想对用户的要求实际可行性集中式优化调度中心统一安排所有用户负荷无条件服从可行但体验差难以落地价格驱动非合作博弈用户根据电价自选用电时段自主决策符合人性用户接受度高合作博弈用户结成联盟联合优化后分摊收益需要高度信任与协商机制设计复杂小区场景难推广所以非合作博弈价格引导是居民负荷分层调度里最自然的建模方式。最终博弈达到的稳定状态叫“纳什均衡”意思是给定别人的策略每个用户都没有动力单独改变自己的策略。这个状态的调度结果虽然不是全局绝对最优但在分散决策的前提下是能做到的最好结果。1.3 分层结构怎么落地“分层”体现在模型结构上上层模型对应调度中心决策变量可以是分时电价、需求响应激励系数、集体用电限额。下层模型对应若干独立用户决策变量是各自可调设备的工作时段、充电功率、空调设定温度。上下层通过总负荷曲线这个桥梁耦合在一起。上层调整价格策略→用户重新优化用电决策→新的总负荷曲线反馈回上层→上层再调整。这个循环迭代多次后会收敛到一个稳定点。用一句话概括这个模型的设计逻辑把“调度中心强控用户设备”改造成“调度中心定规则、用户按规则自选”让用户利益和系统目标尽量一致。2. 双层优化模型怎么建立——目标函数与约束条件2.1 负荷分层与设备分类做居民负荷模型之前先把负荷分类搞清楚。不同负荷的可调度性完全不同我一般这样分负荷类型典型设备可转移性可削减性调度方式固定负荷照明、冰箱、电视不转移不可削减不参与调度可转移负荷洗衣机、洗碗机可转移时段不可削减改变开始时间可削减负荷空调、电采暖一般不转移可削减功率温度设定值调节储能型负荷电动车、热水器可转移可削减控制充电功率与时段固定负荷是保底负荷不参与调度真正起作用的是后三类。每类负荷的模型复杂度不同初学者建议先从“可转移负荷”入手因为建模最简单——只需要把工作区间比如洗衣机需要持续工作1小时挪到某个可行的时段就行。储能型负荷加一个储能量状态约束也就够了可削减负荷稍微多一点温度约束但也并不复杂。2.2 上层模型调度中心的目标与约束上层模型模拟调度中心的行为。调度中心的目标通常有两个维度负荷曲线尽量平缓削峰填谷。数学上可以写为最小化负荷方差min f₁ Σₜ (P_base(t) Σᵢ P_user_i(t) − P_avg)²或者直接最小化峰谷差min f₁ max(P_total) − min(P_total)调度成本最小比如购电成本、需求响应奖励支出。实际做仿真研究时大部分论文用“负荷方差”或“峰谷差”作为上层目标。因为这两个指标直观地反映了电网的安全经济运行水平读者也容易理解。上层决策变量一般有分时电价峰、平、谷三个值或24个时段的连续电价需求响应激励价格比如补贴每度电0.3元鼓励用户在谷时充电可中断负荷补偿系数。上层约束主要包括电价上下限约束电价不能定得太离谱比如峰时电价不能超过用户承受上限价格信号平滑性约束相邻时段电价突变不宜太大否则用户无所适从总负荷不超过变压器容量限制P_total(t) ≤ S_transform。需要注意的是上层不能直接指定“某个用户必须关掉空调”它只能通过价格来间接引导。这一点在模型里要严格体现否则上层就变成了集中式调度博弈结构就没了。2.3 下层模型用户的成本最小化问题下层是若干个独立的用户优化问题。以单个用户i为例其目标函数是min C_user_i 电费支出 舒适度惩罚其中电费支出Σₜ 电价(t) × 用户i在t时段的用电功率舒适度惩罚用户偏离自己偏好用电动线时产生的“不舒服”代价比如空调设定温度升高2度带来的热不适感。约束方面不同设备类型各有不同可转移负荷工作持续时间固定设备只能连续运行L个时段启动时间在允许窗口内比如洗衣机必须在早上7点到晚上10点之间启动。可削减负荷功率调节范围P_min ≤ P(t) ≤ P_max温度/舒适度范围室内温度在设定区间内波动。储能型负荷电动车电池容量约束00:00前必须充到SOC上限比如80%功率上下限约束。用户之间有相互影响吗如果只从电网买电理论上用户之间决策是独立的。但在一个小区内部变压器容量、楼栋线路容量是共享的。如果所有人都在同一个低谷时段扎堆充电会出现新的局部尖峰甚至挤占变压器容量。所以下层用户之间通过“共享容量约束”或“总负荷影响电价”这种方式产生相互制约这是博弈发生的根源。2.4 双层模型的耦合关系与纳什均衡双层模型写完整以后长这样上层min F(p_price, p_user_optimal) s.t. 电价约束、容量约束 where p_user_optimal 是下层博弈的纳什均衡解下层对每个用户i min C_i(p_i | p_others, p_price)这里关键点在于上层的目标函数不是某个显式的数学表达式而是嵌套了一层用户博弈的子问题。计算一个上层目标函数值必须先求解整个下层博弈的纳什均衡。这种嵌套结构用传统数学规划方法很难解原因在于用户目标函数非凸、含0-1变量设备开关状态、且多个用户耦合。所以项目标题里“双层鲸鱼算法”的意义就出来了——用启发式智能算法去黑箱逼近这个双层嵌套问题的解避免推导KKT条件或者强对偶条件的麻烦。这在工程上是非常务实的做法。3. 双层鲸鱼算法外层寻优内层求均衡3.1 标准鲸鱼算法回顾鲸鱼优化算法Whale Optimization Algorithm, WOA是2016年提出的一种群智能优化算法模拟座头鲸的泡泡网捕食行为。它有三种位置更新策略数学表达都比较简洁。第一种是包围猎物对应算法里的收缩包围机制D |C · X_best(t) − X(t)| X(t1) X_best(t) − A · D第二种是泡泡网攻击用一个螺旋方程模拟座头鲸向水面吞吐气泡逼近猎物的路径X(t1) D · e^(bl) · cos(2πl) X_best(t)其中 D |X_best(t) − X(t)|b是螺旋形状常数l是[-1,1]的随机数。第三种是随机搜索D |C · X_rand(t) − X(t)| X(t1) X_rand(t) − A · D算法用两个关键参数控制策略切换概率p决定用螺旋更新还是包围/随机搜索系数A的绝对值决定用包围猎物还是随机搜索。|A|≥1时执行随机搜索以增加全局勘探能力|A|1时执行包围猎物以加强局部开发。WOA的优势是参数少只有A、C、p在原论文的基准函数测试里收敛速度快实现起来非常容易。缺点是容易早熟尤其是多峰问题上可能陷入局部最优。所以在实际项目中我一般会对标准WOA做一点小改进。3.2 双层结构里“双层”到底指什么先澄清双层鲸鱼算法不是两个鲸鱼算法简单拼接而是指在一个嵌套迭代结构中把鲸鱼算法同时用到上层和下层。具体交互步骤如下外层鲸鱼种群初始化。每个鲸鱼个体代表一组上层决策变量比如一整天的分时电价序列。对每个外层鲸鱼个体把它的决策变量传给下层。下层调用“内层鲸鱼算法”在给定价格信号下求解用户博弈的纳什均衡初始化内层种群用户策略组合依次让每个用户在其他用户策略不动的前提下用鲸鱼算法搜索自己的最优策略所有用户更新一次后检查整体策略变化量若变化量小于阈值认为收敛到近似纳什均衡否则继续下一轮迭代。下层把均衡状态下的各用户负荷曲线、总负荷曲线返回给上层。外层计算适应度函数比如峰谷差、用户总成本加权和判断这个鲸鱼个体对应的电价策略好坏。外层鲸鱼种群根据适应度进行位置更新包围/螺旋/随机搜索生成新的电价策略回到步骤3。外层达到最大迭代次数后输出最优电价策略与对应的用户均衡策略。这个“外层套内层”的结构就是双层优化问题的标准求解框架。用鲸鱼算法取代传统数学规划作为内层搜索器好处是能处理非凸、离散、不可导的问题坏处是计算量偏大——每个外层个体都要先完成一轮完整的内层博弈收敛总体耗时可能翻十几倍。3.3 内层博弈收敛的工程实现内层博弈里最容易被低估的细节是“用户依次做最优响应”这个过程的稳定问题。如果每个用户都从初始策略直接跳到自己的最优策略策略空间变化太剧烈很容易振荡不收敛。我做过几次实验在求用户最优响应用鲸鱼算法时直接替换策略往往导致总负荷在迭代后期来回抖动。后来参考分布式算法里的“阻尼最优响应”思想加入一个更新系数λx_i_new_final x_i_old λ × (x_i_optimal − x_i_old)λ通常取0.2到0.5之间用户策略逐步逼近最优响应而不是一步跳过去。这个技巧对收敛稳定性帮助极大强烈建议代码实现时加上。另一个关键点是内层博弈的收敛判据。我建议用连续两轮迭代之间所有用户策略变化的Frobenius范数来衡量ε ‖策略矩阵(t1) − 策略矩阵(t)‖₂如果ε小于设定阈值比如1e-3就停止内层迭代认为当前策略组合达到近似纳什均衡。这样做可以避免每轮都把内层迭代跑到最大次数计算效率能提升不少。3.4 为什么选鲸鱼而不是遗传算法或粒子群很多人会问双层优化为什么非要用鲸鱼算法遗传算法GA、粒子群算法PSO不行吗答案是也行但鲸鱼有几个适配这个场景的优点参数少。GA需要选择、交叉、变异三个算子和对应的概率PSO需要惯性权重和学习因子WOA核心控制参数只有A、C、p调参难度低。代码量小Matlab里实现一个完整WOA主循环大概十几行。螺旋收敛机制在处理连续电价变量时效率不错尤其是需要精细逼近最优解的时候。内外层都用同一种算法的代码可以复用只需要换一下目标函数和维度设置程序结构统一调试方便。当然WOA也有弱点。标准WOA在求解高维问题比如24个连续电价变量96个时段×100个用户的策略时收敛速度会明显下降。常见的补救做法是引入反向学习初始化、混沌映射扰动、或者对最优个体做局部搜索。这些改进在算例里的效果是收敛精度提升约5%到10%但计算时间增加约15%到20%。你要根据实际算例规模和需求来取舍。4. Matlab代码实现与关键模块解析4.1 程序的整体结构一个比较清晰的Matlab程序结构如下main.m主脚本负责调用所有模块输出结果图。setting.m参数设置包括用户数量、设备数量、鲸鱼种群大小、迭代次数等。loadData.m载入负荷数据、电价初始值、设备参数。outerWOA.m外层鲸鱼算法主体。innerGame.m内层博弈迭代主函数。userResponse.m单个用户在当前价格和其他用户策略下的最优响应。fitnessOuter.m外层适应度计算函数。plotResults.m结果可视化负荷曲线、收敛曲线、电价曲线等。4.2 参数设置模块我在仿真时常用的参数组合如下参数取值说明小区用户数100也可以取50-200影响计算量调度周期24小时15分钟一个时段共96个时段可调设备类型空调、电动车、洗衣机、热水器每户2-4台外层鲸鱼种群数20-40太小容易早熟太大计算量爆炸外层最大迭代50-100实际上30-60轮基本能收敛内层博弈最大迭代20-30配合阻尼系数0.3-0.5内层用户最优响应搜索次数30用鲸鱼搜索单个用户最优策略收敛阈值ε1e-3判断内层是否达到近似均衡Matlab里参数设置写成结构体比较方便% setting.m P.n_user 100; % 用户数 P.n_slot 96; % 时段数 P.N_wolf_outer 30; % 外层鲸鱼种群数 P.max_iter_outer 80; % 外层迭代次数 P.max_iter_inner 30; % 内层博弈迭代次数 P.lambda 0.35; % 阻尼更新系数 P.eps 1e-3; % 内层收敛阈值 P.pf 1.2; P.pp 0.8; P.pg 0.35; % 初始峰平谷电价 P.pdf [ones(1,16)*P.pg, ones(1,8)*P.pp, ones(1,8)*P.pf, ... ones(1,8)*P.pp, ones(1,8)*P.pf, ones(1,8)*P.pp];注意96个时段和16个谷时段对不齐实际写代码时可以按自己的时段划分调整。我这里只是示意千万别直接照抄时段的长度。4.3 外层鲸鱼算法主体外层鲸鱼个体的编码是电价调整系数向量。例如峰平谷三种基础电价通过调整系数k(t)在[0.8, 1.5]倍基础电价范围内变化生成全天96个时段的连续电价曲线。外层适应度函数设计f w1 × 峰谷差归一化 w2 × 用户总电费归一化 w3 × 舒适度偏差归一化实际中w1取0.5、w2取0.3、w3取0.2比较合适。权重可以根据实际偏好调整比如更侧重削峰填谷就把w1调大。外层主循环代码骨架% outerWOA.m for iter 1:P.max_iter_outer for i 1:P.N_wolf_outer % 每个外层个体对应一个电价序列 price{i} % 调用内层博弈返回总负荷曲线和用户策略 [load_profile{i}, user_obj{i}] innerGame(price{i}, P); % 计算外层适应度 fitness(i) fitnessOuter(load_profile{i}, user_obj{i}, P); end % 找到当前最优鲸鱼 [best_f, idx] min(fitness); if best_f gbest_f gbest_f best_f; gbest_price price{idx}; end % 更新收敛因子a、系数A、C a 2 - 2 * iter / P.max_iter_outer; % 位置更新省略具体公式... end外层位置更新的三种策略代码按标准WOA写就行不复杂。主要注意维度是n_slot也就是96维每只鲸鱼个体是一个96维的向量。4.4 内层博弈迭代实现内层博弈是整个程序最核心也是最容易出错的部分。代码逻辑如下% innerGame.m function [load_total, user_obj] innerGame(price, P) % 初始化用户策略每户的可转移设备启动时段、充电功率等 strategy initializeUserStrategy(P); for k 1:P.max_iter_inner strategy_old strategy; % 每个用户依次做最优响应 for i 1:P.n_user % 固定其他用户的策略 others strategy; others(i) []; % 用鲸鱼算法求用户i在价格price下的最优策略 optimal_i userResponse(price, strategy(i), others, P); % 阻尼更新 strategy(i) strategy(i) P.lambda * (optimal_i - strategy(i)); end % 检查收敛 epsilon norm(strategy - strategy_old); if epsilon P.eps break; end end % 由均衡策略计算总负荷和用户目标值 [load_total, user_obj] evaluate(strategy, price, P); end这段代码里userResponse函数内部嵌了一层鲸鱼算法用来搜索单个用户在当前价格和其他用户策略下的最优响应。也就是说整个程序实际上有三层循环外层鲸鱼迭代、内层博弈迭代、最里层用户响应搜索。计算量不小初次跑通时可以把规模缩小比如20个用户、24个时段来验证逻辑。4.5 用户最优响应的具体实现用户最优响应问题相对简单可以用普通WOA来求解。设备类型影响编码方式可转移负荷决策变量是启动时段是整数变量可以在鲸鱼位置更新后round取整再检查是否在允许窗口内。可削减负荷决策变量是各时段功率连续变量直接限制在[P_min, P_max]。储能负荷决策变量是充电功率序列同时需要满足电池SOC约束。处理SOC约束最方便的方法是惩罚函数把SOC越限量加到目标函数里。用户目标函数f_user Σₜ price(t) × P_user(t) × Δt σ × comfort_penaltycomfort_penalty对于空调来说就是室内温度偏差的平方和对于电动车来说就是“没充满电导致的不便”。σ是权重系数我习惯取0.1到0.3具体视场景而定。4.6 约束修复与结果可视化代码里最容易被忽略的是约束处理。如果用纯惩罚函数电价序列可能跑出明显不合理的形状比如相邻时段电价跳变1块钱。这种解虽然目标函数值低但工程上没法执行。我建议在位置更新后加一个修复步骤% 约束修复 price(i) max(price_min, min(price_max, price(i))); % 平滑性修复限制相邻时段电价差 for t 2:P.n_slot if abs(price(t) - price(t-1)) P.dp_max price(t) price(t-1) sign(price(t) - price(t-1)) * P.dp_max; end end结果可视化时重点画三张图优化前后的总负荷曲线对比图直观展示削峰填谷效果外层鲸鱼迭代收敛曲线展示适应度值随迭代次数下降的趋势电价曲线图和用户电费分布图分析价格信号的引导效果。Matlab中用plot、bar、subplot就够用了不需要额外工具箱。5. 算例设定与仿真结果分析5.1 仿真场景与基础数据假设一个100户居民的居民小区每户配置一台空调额定制冷功率2kW可调节范围0.5-2kW一辆电动汽车电池容量40kWh最大充电功率7kW一台洗衣机单次运行1小时功率0.8kW一台热水器功率2kW可分时段加热。分时电价初始设置为峰时10:00-12:00、18:00-22:001.2元/kWh平时8:00-10:00、12:00-18:00、22:00-24:000.8元/kWh谷时00:00-08:000.35元/kWh。固定负荷曲线采用某典型居民小区的实测日负荷曲线峰时总负荷约250kW谷时约120kW。5.2 调度结果分析在这个场景下双层鲸鱼算法迭代约60轮后收敛。最终得到的调度结果大致如下优化前峰谷差约130kW优化后峰谷差约78kW降幅约40%用户总电费下降约12%到18%用户舒适度损失平均在5%以内绝大多数用户可接受。为什么峰谷差能降这么多主要原因是电动车充电被引导到了凌晨低谷时段洗衣机被引导到了上午平段电价时段空调在峰时段自动微调设定温度比如从23度调整到25度负荷整体从晚高峰搬运到了凌晨。价格信号在这里起到了决定性作用。峰谷电价比从1.2/0.35≈3.4倍用户在电费驱动下自然选择错峰用电。如果峰谷电价差小于1.5倍用户转移负荷的意愿就会明显减弱这是做算例时一个重要的敏感性发现。5.3 与其他算法的对比在同一样例下我对比了标准WOA、粒子群算法PSO和遗传算法GA分别作为双层求解器的效果算法峰谷差kW用户总电费元收敛代数运行时间秒GA87.3532075420PSO84.6529060380标准WOA79.2526055360双层WOA本文78.1524050420从这个结果看双层鲸鱼在解质量上略优于其他算法但计算时间并没有明显优势因为内层博弈计算是主要耗时瓶颈。实际项目中如果追求速度可以适当减小外层种群数量或者在内层早停条件上放宽一点阈值。6. 调试过程中常见的坑与解决方案6.1 内层博弈不收敛负荷曲线来回振荡调试中遇到最多的问题就是内层博弈迭代几十轮还是不收敛。典型表现是总负荷曲线在相邻两轮迭代之间出现明显摆动尤其是有大量可转移负荷时所有用户都在“抢”同一个低谷时段导致策略在几个方案之间跳来跳去。处理方法降低阻尼系数λ从0.5降到0.2到0.3让策略变化更平缓。另一个办法是增加内层迭代上限到50次但收益有限。实测最有效的方法是提高价格信号的区分度比如拉大峰谷电价差用户的最优策略会变得更稳定。6.2 鲸鱼算法早熟陷入局部最优标准WOA对初始种群比较敏感。我测试过不同随机种子有的种子能收敛到峰谷差78kW有的只能到95kW。差距主要来自初始种群的分布质量。处理方法用混沌映射如Logistic映射生成初始种群保证种群在解空间分布更均匀加入反向学习机制对每个初始个体同时生成一个反向解取适应度好的那个在外层迭代后期对最优个体添加高斯扰动帮助跳出局部最优。我实际测试中反向学习初始化带来的提升最明显代码改动量也小。6.3 约束越界导致调度结果不可行可转移负荷的时段变量是整数鲸鱼位置更新后往往得到小数比如启动时段7.42。直接取整可能导致设备运行窗口被破坏。比如洗衣机允许启动窗口是[7,22]8.6取整为9没问题但如果某个约束边界位于17.2取整到17或18都可能越界。处理方法所有整数变量在适应度计算前统一round取整然后做边界检查越界的拉回最近合法值。Sliding窗口类约束在修复后用冲突检测函数再检查一次必要时随机重置到合法范围内。6.4 Matlab代码运行报错与性能调优最常见的报错是维度不匹配。尤其是双层嵌套结构里外层传入的电价数组维度是96×1内层博弈中给每个用户分配策略时的维度是1×96矩阵运算时容易搞混。调试建议在关键变量定义处加断言assert(size(price,1) P.n_slot)先用小规模算例10个用户、12个时段跑通全流程再逐步放大用Matlab Profiler定位最耗时的函数通常是userResponse里面嵌套的鲸鱼搜索这部分没法完全优化但可以通过向量化部分计算来提速优先使用Matlab 2022b及以上版本对循环和矩阵运算的支持更好工具箱也更全。还有一个经验内层用户响应搜索不要太精细搜索次数从50降到30解质量几乎不变运行时间能显著下降。工程问题讲究“够用就行”不必追求每个用户最优响应都达到绝对精确。最后再分享一点我自己的体会算这种带博弈的双层模型最容易犯的错是“一头扎进算法细节里把模型本身的博弈逻辑忽略了”。双层鲸鱼算法说到底只是一个求解工具真正决定结果是否合理的是你建立的上下层目标函数和约束有没有准确反映现实问题。电价定得太高用户会抱怨定得太低削峰填谷效果不够这些经济学直觉在建模阶段就应该想清楚而不是最后靠算法去“调”出来。我见过一些复现这个模型的同学代码能跑出来漂亮的图结果却经不起推敲——峰谷差确实降了但用户舒适度损失大得离谱。这种结果本质上是在牺牲用户利益换系统指标在实际中根本不可行。所以做仿真实验时一定要同时检查系统侧和用户侧的指标两个方向的指标都合理才真正算一个站得住脚的调度方案。写到这里这套从建模到求解再定位调试的完整流程就都串起来了。上手的时候建议先从简化版入手把复杂度降下来一步步加设备、加用户、加约束慢慢就能掌控整个模型。
返回列表