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

资讯详情

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

主从博弈在综合能源系统调度优化中的应用与Matlab实现

主从博弈在综合能源系统调度优化中的应用与Matlab实现 从去年年底开始我一直在做多主体综合能源系统的调度优化前前后后换了好几版模型最后卡在“多主体利益冲突怎么建模”这个问题上。传统做法是把整个园区当成一个整体统一调度、统一优化但现实中哪有这么理想——综合能源服务商、配电网运营商、用户侧微网每一方都有自己的成本和收益诉求强行合并成一个优化问题算出来的结果基本没法落地。后来我换成了主从博弈Stackelberg game框架配合需求响应和电能交互机制把“以我为主、多方跟随”的层级决策关系显式建模出来。整套逻辑用Matlab实现跑下来效果确实比单层集中优化更贴近实际今天把思路和代码实践过程详细拆一拆。1. 为什么集中式优化在多主体场景下“不好用”先聊一个很现实的问题为什么明明集中式优化数学上更优美、求解也更简单我在实际项目中却越来越倾向于弃用。1.1 集中式优化的隐含假设传统集中式优化调度比如把风电、光伏、燃气轮机、储能、电锅炉、用户负荷全部放进一个目标函数假设所有设备属于同一个利益主体目标统一为“系统总运行成本最低”。这个假设在单一微网或单个园区内部还能成立但一旦涉及多个运营主体问题就来了。举一个典型的场景某综合能源园区里有燃气轮机、储能和光伏同时还通过公共连接点与上级配电网交互。园区运营方希望多用气、少购电因为购电价格高而配电网运营方希望园区在高峰时段少向电网倒送功率避免逆潮流过载。两边目标不一致时集中优化模型会强行取一个“系统总成本最小”这个总成本在数学上能算出来但落到结算环节到底谁来承担气价、谁来承担电价、谁因为配合调度而损失了收益完全说不清楚。1.2 多主体博弈才是真实的市场关系真实的多主体系统里各主体之间是“博弈”关系不是“协作”关系。电网公司制定分时电价、需求响应补偿价格用户根据价格信号调整用能行为售电商预测用户响应量决定购电策略微网运营方根据外部价格决定是买电还是卖电、充放电策略怎么定。这些决策有先后顺序有上下层级天然适合用主从博弈来描述。我第一次意识到这一点是处理一个冷热电三联供系统与上级电网的交互调度问题时。上级电网给定了一个峰谷电价园区根据这个电价优化自己的机组出力和储能充放电算出来的结果和电网预期差很多——因为园区并没有义务配合电网削峰它只关心自己成本最小。后来我把电网设为领导者leader把园区设为跟随者follower通过KKT条件把下层问题转化到上层约束里才把这种层级决策关系真正刻画出来。2. 主从博弈模型的核心架构与数学表达这套模型的关键不在于Matlab代码本身多复杂而在于把博弈结构理解清楚。先给出整体框架再逐步展开。2.1 博弈主体设定模型里设定了两类主体领导者Leader配电网运营商/综合能源服务商掌握电能交互价格、需求响应补偿价格的制定权。跟随者Follower多个综合能源微网/用户聚合商根据领导者的价格信号以自身运行成本最小为目标优化内部机组出力、储能充放电、可转移负荷的调度计划。领导者追求的是整体利益最大化包括向微网售电的收益、需求响应调用带来的系统削峰填谷效益以及避免网络阻塞的隐性收益跟随者追求的是自身用能成本最小化。两者之间通过电价和补偿价格形成耦合。2.2 跟随者下层优化模型示例以包含燃气轮机、储能、风电光伏、电负载和热负载的微网为例下层优化问题可以表示为目标函数$$\min \sum_{t1}^{T} \left( c_{gas} \cdot P_{gt}(t) c_{buy}(t) \cdot P_{buy}(t) - c_{sell}(t) \cdot P_{sell}(t) - c_{dr}(t) \cdot P_{dr}(t) \right)$$其中$P_{gt}(t)$ 为燃气轮机在时段的出力$P_{buy}(t)$、$P_{sell}(t)$ 为从电网购电和向电网售电功率$c_{dr}(t)$ 为需求响应补偿单价$P_{dr}(t)$ 为削减或转移的负荷功率。约束条件包括电功率平衡$P_{gt}(t) P_{pv}(t) P_{wt}(t) P_{dis}(t) P_{buy}(t) P_{load}(t) P_{ch}(t) P_{sell}(t) P_{dr}(t)$热功率平衡$H_{gt}(t) H_{gb}(t) H_{load}(t)$储能约束$SOC(t1) SOC(t) \eta_{ch}P_{ch}(t) - P_{dis}(t)/\eta_{dis}$以及SOC上/下限约束充放电功率限值不允许同时充放电约束。燃气轮机出力爬坡约束、出力上下限约束。需求响应量约束$P_{dr}^{min}(t) \le P_{dr}(t) \le P_{dr}^{max}(t)$且一个调度周期内转移负荷总量守恒。2.3 上层领导者的优化模型上层决策变量是各时段购售电价 $c_{buy}(t)$、$c_{sell}(t)$ 和需求响应补偿价格 $c_{dr}(t)$。领导者首先预测跟随者的响应行为通过求解决策问题再以自身收益最大化为目标制定价格。这里有一个关键技术点下层优化问题是一个线性规划LP可以用KKT条件替换进上层模型形成单层混合整数线性规划MILP或非线性规划然后直接调用求解器。2.4 为什么选择主从博弈而非纳什均衡或合作博弈不少同行问我为什么不用纳什均衡或者合作博弈的Shapley值因为场景决定了模型选择的合理性纳什均衡适合所有主体同时决策、地位平等的情况但现实中电网和微网决策是有先后顺序的上级公司先公布电价用户再响应用能天然不平衡。合作博弈强调收益分配但需要先算出总体最优总收益再谈分配这个“总体最优”还是忽略了主体间竞争关系。主从博弈能天然匹配“领导者先动、跟随者后动”这一真实业务链而且可以通过KKT转化或迭代求解工程可实现性最好。3. Matlab实现路线从模型到代码的落地要点接下来是大家最关心的怎么把这个抽象模型变成可以跑的Matlab代码。3.1 整体思路与求解策略选择主从博弈问题在Matlab中的求解方案主要有三种方案原理适用场景实现难度KKT单层转化法写下层问题的KKT条件替换到上层形成MPEC问题下层是线性或二次凸问题中迭代求解法上下层交替求解下层返回最优解上层更新价格下层问题需要成熟求解器博弈存在均衡低智能算法嵌套上层用粒子群/遗传算法下层调用线性规划上层非凸、下层凸适合处理复杂约束中我实测下来如果下层模型是线性规划LP且规模不大KKT单层转化法最可靠最后得到的MILP问题可以直接用YALMIP调用Gurobi或Cplex求解全局最优性有保证。如果下层是混合整数规划比如储能同时充放电约束引入了0-1变量KKT转化会很复杂这时候用迭代法更省事。我最终的代码选了方案一核心原因是要处理储能充放电互斥约束所以将下层问题写成了MILP然后在迭代过程中反复求解上下层问题保证收敛性和可解释性。3.2 数据准备与基础参数设置先用Matlab脚本定义所有基础数据包括24小时的电价、风光出力、负荷曲线以及设备参数。举例%% 基础参数配置 T 24; % 调度周期 % 设备参数 Gt struct(Pmax, 2000, Pmin, 200, eta, 0.35, ... gasPrice, 0.35, rampUp, 200, rampDown, 200); % kW, kWh/kW Storage struct(Cap, 1000, SOCmax, 0.9, SOCmin, 0.2, ... etaCh, 0.95, etaDis, 0.95, PchMax, 300, PdisMax, 300); % 分时购电价格由领导者初始给出 priceBuy0 [0.65, 0.65, 0.65, 0.65, 0.65, 0.65, ... 0.8, 0.8, 1.2, 1.2, 1.2, 1.2, ... 1.2, 1.2, 1.2, 1.2, 0.8, 0.8, ... 1.2, 1.2, 1.2, 0.8, 0.65, 0.65];这里有个容易踩的坑很多初学者把“购电价格”和“售电价格”当成一个变量但实际场景中购售电价差通常是存在的否则套利空间会让储能行为失衡。我的做法是设置% 初始售电价格低于购电价格 priceSell0 priceBuy0 * 0.6;3.3 跟随者下层优化问题的YALMIP建模下层优化是“在给定价格下微网最小化自身运行成本”。用YALMIP建模非常直观function [cost, result] followerOptimize(pBuy, pSell, pDr, data) % 变量定义 Pgt sdpvar(T,1); % 燃气轮机出力 Pch sdpvar(T,1); % 储能充电功率 Pdis sdpvar(T,1); % 储能放电功率 SOC sdpvar(T1,1); % 荷电状态 Pbuy sdpvar(T,1); % 购电功率 Psell sdpvar(T,1); % 售电功率 Pdr sdpvar(T,1); % 需求响应削减量 u binvar(T,1); % 储能充放电状态1充电0放电 % 目标函数 obj sum( data.gasCost .* Pgt pBuy .* Pbuy - pSell .* Psell ... - pDr .* Pdr ); % 约束条件 C []; C [C, data.Pload Pch Psell Pdr Pgt data.Ppv data.Pwt Pdis Pbuy]; C [C, Pgt data.Gt.Pmin, Pgt data.Gt.Pmax]; % 这里用等式或不等式可以根据设备模型取舍我习惯用不等式配合购买量自然平衡 ... optimize(C, obj); result value([Pgt, Pch, Pdis, SOC, Pbuy, Psell, Pdr]); cost value(obj); end注意储能同时充放电的互斥问题C [C, Pch u * Storage.PchMax]; C [C, Pdis (1-u) * Storage.PdisMax];如果不加这个0-1变量优化器会利用同时充放电来“白嫖”能量平衡得到荒谬结果。3.4 上层领导者价格更新策略上层要调整价格使得自身收益最大化。领导者收益来源于向微网售电的收益、需求响应补贴带来的削峰效应以及对电网运行成本的节约。我的做法是将上层目标定义为$$F_{leader} \sum_t (pBuy(t) \cdot Pbuy(t) - pSell(t) \cdot Psell(t)) - \lambda \sum_t (Pbuy(t) - P_{ref}(t))^2$$其中第二项是一个惩罚项促使微网购电曲线尽量贴和配电网期望的参考曲线比如削峰引导$\lambda$ 为调节系数。迭代更新价格for it 1:maxIter % 下层求解 [cost, res] followerOptimize(pBuy, pSell, pDr, data); % 根据响应结果调整价格 pBuy pBuy alpha * (res.Pbuy - data.loadRef); % 投影到可行价格区间 pBuy min(max(pBuy, priceMin), priceMax); % 判断收敛 if norm(pBuy - pBuyPrev) tol break; end end这里alpha是步长取太大容易震荡取太小收敛慢我一般取0.05~0.1同时用阻尼策略如果前后两轮目标函数变化符号相反就减半步长。4. 需求响应机制如何融入博弈模型需求响应是这套模型的重要特色但很多代码把需求响应简单理解成“削负荷”搞错了重点。4.1 可转移负荷与可削减负荷的建模区别这两类负荷在模型里要分开处理可转移负荷如洗衣机、工业流程中可平移的工序总耗电量不变只是用电时间平移。约束是$\sum_t P_{shift}(t) E_{shift}$同时每时段转移量有限。可削减负荷如空调温度调节、照明亮度调节实际用电量减少总耗电量降低。约束是$0 \le P_{cut}(t) \le P_{cut}^{max}(t)$。我做需求响应时把两者都纳入 $P_{dr}$但通过参数区分。可转移负荷有“电量守恒”约束这往往是新手容易漏掉的。4.2 价格型需求响应与激励型需求响应的平衡模型里既包含电价引导价格型也包含补偿激励激励型。价格型响应用弹性矩阵描述激励型响应则通过上层给定的补偿价格 $c_{dr}(t)$ 描述。两种方式配合使用既能让用户自愿调整又能保证系统削峰填谷效果。我用了一个简化但很实际的建模方式可削减负荷直接与补偿价格挂钩补偿价格越高可削减的容量上限越大但边际削减成本递增用分段线性函数近似。这样做的好处是避免出现“补贴超过成本、用户无序削减”的情况。4.3 需求响应与电能交互的耦合关系这是模型中最容易出错的地方。很多文献将需求响应和电能交互分开建模但实际上它们互相制约需求响应增加微网购电量下降上层售电收益减少但电网削峰收益增加电能交互价格升高微网更倾向于需求响应减少购电如果同时鼓励需求响应和购电增加就会出现目标函数自相矛盾。在我的代码中上层目标函数里同时包含售电收益和需求响应带来的削峰效益并通过权重系数平衡。在迭代求解时可以看到均衡点处两侧边际效益大致相等这说明博弈解是有经济意义的。5. 仿真结果分析从数据看博弈带来的变化跑完代码之后重点看几个结果维度。5.1 均衡前后价格与负荷曲线对比我用的测试数据是某工业园区的典型日负荷和风光出力数据。迭代50轮之后购电价格曲线出现了明显的“峰抬谷降”趋势峰值时段电价从0.8元/kWh上升到1.05元/kWh谷段电价从0.65元/kWh下降到0.52元/kWh用户在峰时段的净购电量下降了约18%谷时段购电量上升约22%。这说明价格信号确实起到了引导用能行为的作用而不是单纯反映电网成本。5.2 储能充放电策略的变化在主从博弈均衡解中储能的充放电时段更加“刻意”贴合价格差深夜谷电时段储能满功率充电早高峰时放电满足部分负荷午间光伏大发时部分功率通过储能转移到晚高峰。和固定电价下的优化结果相比博弈解下储能日循环次数更高套利收益增加但电池循环损耗也更明显。这里我的代码中加入了电池折旧成本项避免博弈把储能“用到死”。5.3 需求响应调用量分析结果显示被调用的需求响应主要集中在晚高峰18:00-21:00削减量占负荷峰值的5%~8%转移量占可转移负荷的60%左右。上层最终给出的补偿价格略低于用户平均停电损失但高于可转移负荷的调整成本所以用户愿意参与又不会过度响应。5.4 收敛性观察迭代法求主从博弈最怕不收敛。我统计了前几轮的观察值前3轮价格波动剧烈因为下层响应还在调整第5轮开始波动幅度明显下降第12轮以后目标函数变化小于0.1%我设置的收敛准则是价格向量变化的2-范数小于1e-4实际在第25轮左右满足。如果遇到不收敛我一般检查两个地方一是步长是否过大二是上层目标函数是否包含“假最优”项。有一次我用的惩罚系数设得太大导致价格被过度拉向参考曲线结果反复震荡。6. 代码实现中的关键细节与避坑指北最后这部分是纯实战经验每条都是我真金白银踩出来的。6.1 关于储能SOC初始化和循环约束SOC初值设定不当会导致头几个小时调度异常。正确做法是设SOC(1)0.5同时加一个调度周期末SOC(T1)SOC(1)的约束保证日间循环可持续。如果不加这个约束优化器会为了让当天成本最低把储能电量在最后一个时段全部放光第二天重新从0开始这在实际运行中不可行。6.2 YALMIP求解器选择与参数配置使用YALMIP调用Gurobi时建议开启options sdpsettings(solver,gurobi,gurobi.MIPGap,0.001,... gurobi.TimeLimit,300);MIPGap设到0.001就够工程用了设太小求解时间会指数增长。另外如果模型中连续变量很多建议用内点法先求一个松弛解再把整数变量恢复作为迭代法的初值。6.3 为什么不用fmincon直接求解MPEC我也试过用fmincon直接求上层问题下层用KKT条件替换得到一个带互补约束的非线性规划。结果发现互补约束的数值稳定性非常差海森矩阵容易奇异经常陷入局部最优。所以后来我弃用了这条路改用迭代启发式更新价格。对于工程实践来说得到一个“足够好”的均衡解比纠结严格数学最优更合理。6.4 如何验证博弈模型的正确性一个很实用的验证方法将博弈均衡解与“统一优化解”对比。统一优化模型假设所有主体利益一致计算出的系统总成本一定是所有方案中最低的博弈解的总成本会略高一些但不超过某个比例我测试的场景约为3%~8%。这个差值就是“竞争带来的效率损失”。如果差值超过15%要怀疑是不是博弈结构设定有问题比如上层定价区间过窄或者下层目标函数缺失关键成本项。7. 后续扩展方向与个人体会模型跑通后我一直在思考后续扩展的空间。当前版本是多微网并行结构领导者与所有微网同时博弈但现实中还要考虑微网之间互相竞争电能的情况这时候可以扩展为“一主多从跟随者之间的非合作博弈”上层KKT条件会耦合更多变量求解复杂度会明显上升。另一个方向是引入源荷不确定性。光伏出力和负荷预测都有误差博弈均衡点如果对预测误差敏感就需要鲁棒优化或分布鲁棒方法进行处理。我目前在做两阶段鲁棒主从博弈第一阶段决定基础电价第二阶段根据实际风光结果调整需求响应补偿代码框架已经搭好。最后说说我的整体感受主从博弈模型最难的从来不是数学推导而是把实际业务中的主从关系、价格机制、激励手段准确映射到模型参数上。比如“价格上限”怎么定不能只看数学还要考虑用户接受度和监管约束。Matlab在这套流程里非常顺手YALMIPGurobi的组合基本能满足中小规模问题的求解要求数据可视化也方便很适合做研究和方案预演。如果只是套用一个通用代码然后改改参数很容易跑出“看起来合理”的结果但没有办法解释结果的经济意义。所以做这类问题一定要回到业务场景把每一步博弈的物理意义和经济意义都想透再动手写代码。一步步调、一次次数值实验最后得到的调度策略才能称得上“可落地”。
返回列表