ARTICLE DETAIL

资讯详情

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

主从博弈与共享储能:综合能源微网优化从模型到代码全解析

主从博弈与共享储能:综合能源微网优化从模型到代码全解析 主从博弈论、共享储能、综合能源微网优化运行——这三个关键词放在一起基本就锁定了这是一篇电力系统经济运行方向的典型文章。我花了两周时间把这类模型从公式到代码完整复现了一遍过程中踩了不少坑也顺手把整套代码框架整理成了自己的标准模板。这篇文章围绕复现过程把模型思路、数学细节、代码实现方案和排错经验都梳理清楚给后面要做共享储能、微网优化、主从博弈方向的朋友一个能直接上手的参考。先说个结论复现这类文章的难点从来不在“读懂公式”而在于“把双层优化转成可求解的单层问题”以及“让求解器在合理时间内收敛到一个稳定解”。如果你正卡在这两个环节这篇文章可以帮你省下大量试错时间。1. 为什么偏偏是主从博弈论1.1 集中式优化的“一刀切”问题出在哪在接触主从博弈之前大部分微网优化类文章用的是集中式优化一个调度中心掌握所有信息把储能、微燃机、电锅炉、负荷全部纳入一个大规模优化问题求全局最优解。集中式优化的优势很明显——数学上优雅物理上可控求解器直接就能处理。但放到“共享储能”这个商业模式里它有一个根本性的漏洞储能设备是谁的如果是微网自己的储能集中式调度没问题资产归属统一状态可控。但共享储能的典型场景是储能设施由独立的投资商或第三方运营商建设微网用户只是“租用”或“购买服务”。这时候储能运营商希望制定一个对自己最有利的价格策略微网则根据这个价格调整用能计划——两个决策主体目标不同、信息不对称、决策有先后集中式优化把两者强行捏成一个整体既不符合商业逻辑算出来的结果也没有落地的意义。这就是主从博弈论进入这个场景的根本原因它不是概念的堆砌而是共享储能商业模式天然对应的决策结构。1.2 共享储能商业模式天然需要一个“领导者”主从博弈也叫Stackelberg博弈核心特征是决策存在层级领导者先做决策跟随者基于领导者的决策做出最优响应领导者再根据跟随者的响应调整自己的决策最终达到一个两方都无法单独变好的平衡状态。映射到共享储能场景结构是这样的上层领导者共享储能运营商/投资商。决策变量是储能建设容量、充放电功率上限、向微网收取的储能服务价格或者充放电价差。下层跟随者综合能源微网。决策变量是各时段从电网购电功率、购气量、储能充放电量、电锅炉出力、CHP机组出力、弃光/弃风量等。为什么这个结构合理因为储能运营商先定价格微网无法影响这个价格、只能在这个价格下优化自己的用电策略这恰恰是现实中“运营商定价、用户响应”的写照。反过来如果微网用户数量足够多、或者用户联合起来有议价能力那模型就应该换成交互式博弈甚至合作博弈——但绝大多数文章讨论的共享储能场景用户还是价格接受者所以主从博弈成了默认选择。1.3 与其他博弈形式的取舍为什么不是古诺或合作博弈复现时容易遇到的第一个困惑是为什么这类型文章不用古诺博弈Cournot或者合作博弈古诺博弈适合多个运营商同时决策产量、相互竞争的场景而共享储能场景通常是“一个储能运营商多个微网用户”运营商具有先动优势不是平行竞争关系。合作博弈则强调联盟收益分配适合多个微网联合共享储能之后讨论如何分钱这个目标函数和约束结构跟主导式定价问题完全不是一回事。所以看文章时先判断决策关系有先后、有主从就是Stackelberg框架平行决策、互相影响才是Nash博弈。搞混了模型结构就全错了。2. 模型核心在数学上怎么写2.1 上层问题储能运营商的年化收益最大化上层模型的目标函数基本可以拆成三块总收入、总投资成本、总运维成本。以我复现的典型模型为例上层目标大致是收入部分储能放电给微网的服务费收入 充电服务费收入如果有容量租赁费还要加上租赁收入。成本部分储能单位容量建设成本 × 容量用等年值法折算成逐时或逐日成本运维成本通常按充放电量线性计。决策变量是储能容量、充放电功率上下限和各时段服务价格。容易忽略的细节是价格不是随便定的通常要加上下限约束防止模型为了收益无限抬价。如果文章里说“根据政策文件取价格上限”那么复现时就必须显式写出来否则模型很可能跑飞。2.2 下层问题微网用能成本最小化下层模型是综合能源微网的运行优化。典型的设备集合包括光伏或风电出力不可控按预测曲线给定。燃气轮机/CHP机组输入天然气同时输出电和热电热比固定或可调。电锅炉输入电输出热。储能在共享储能运营商给定的价格下决定充放电。负荷电负荷和热负荷分别有平衡约束。与电网交互允许购电甚至允许售电。下层目标就是逐时运行成本最小化购电费用 购气费用 储能服务费用 设备启停/运维费用。约束上电平衡、热平衡、气平衡、设备出力上下限、爬坡约束、储能SOC递推约束一个都不能少。这里有一个容易掉坑的地方下层模型的能源流向。很多综合能源微网文章把燃气轮机的余热回收、电锅炉的制热同时建模热负荷平衡就要写对热负荷 燃气轮机余热回收热量 电锅炉制热量。扣漏一个设备整个下层可行域就变了上层算出来的均衡价格自然也不对。2.3 KKT条件、强对偶与单层重构的完整推导思路复现这类文章最核心的数学工作就是把双层模型转成单层可求解模型。转换方法主流有几种用下层问题的KKT条件替换下层优化问题将双层模型变成一个带互补松弛约束的单层MPEC问题。对互补松弛约束做线性化Big-M法把MPEC近似或等价为MILP/MIQP。用强对偶定理把下层目标函数中的乘积项转化到对偶变量上解决“目标函数里有上层变量和下层变量相乘”的问题。具体来说下层是一个线性规划LP当Slater条件满足时KKT条件既必要又充分。把下层问题的拉格朗日函数写出来对各自的变量求偏导0再加上原始约束、对偶变量非负约束、互补松弛约束就能把下层替换掉。这样整个模型变成单层但出现了大量的双线性乘积项对偶变量×原始约束残差必须线性化。线性化的通用做法是引入Big-M。对互补松弛约束μ⊥g(x)≤0引入二进制变量z写成μ ≤ M·z-g(x) ≤ M·(1-z)M的取值非常关键。取大了数值稳定性差、求解器跑得慢取小了可能剪掉真正的最优解。我在复现时踩过这个坑M直接取了10^6结果模型解出来储能充放电行为怪异检查发现是M太大导致互补条件被过度松弛。后来根据约束的量级分档设M效果明显改善。另一个需要处理的是“下层目标中乘积项”的处理。当下层目标含有上层价格变量×下层功率变量比如储能充电量乘以充电价格时转成单层后目标函数里会出现两个变量的乘积。如果只做KKT替换这类项还在。解决办法是用强对偶定理下层问题达到最优时原始目标值等于对偶目标值把乘积项换成只含对偶变量的表达式从而消掉双线性项。这一步是很多初学者搞不懂却绕不过去的核心操作。3. 从公式到代码的完整实操3.1 工具链选型MATLABYALMIP还是PythonPyomo复现之前的第一个实际问题用什么工具实现我复现用的环境是MATLAB YALMIP Gurobi之所以这么选是因为这类文章的原始代码大部分基于这套工具链网上能找到的参考资料也最多。YALMIP的优势在于建模语言接近人的思维方式约束就是一左一右写不等式变量类型用sdpsettings指定非常方便。缺点是调试起来信息不够直观报错信息偶尔不那么友好。如果你更熟悉Python可以用Pyomo配合Gurobi或者用pao库专门处理双层优化问题。Pyomo的优势是生态好、可读性强、方便做数据前后处理但写互补约束、双线性项转换时的自动化程度不如YALMIP顺手。我的建议是第一遍复现、重点是理解模型时用MATLABYALMIP快速搭框架后续如果要做大量的参数扫描、实验对比再用Python做批处理。我个人实际使用中发现YALMIP里最容易出问题的就是“变量类型声明不一致”。你声明了一个二元变量但后面在约束里让它跟连续变量相乘YALMIP会默认这是一个非凸双线性项直接调用求解器的非凸MIQP能力求解速度骤降。所以声明变量之前想清楚哪些是连续、哪些是二元这是代码性能的关键。3.2 核心模块的数据结构与参数表构建代码实现的第一步不是写约束而是把数据整理清楚。我复现时习惯建一张参数总表分两层上层参数储能候选容量集合如果做容量优化、单位容量成本、运维成本、价格上限/下限、储能充放电效率、SOC上下限、年化系数。下层参数微网的负荷曲线电/热、光伏出力曲线、天然气价格、分时电价、CHP电效率/热效率、电锅炉效率、各设备功率上下限、爬坡约束速率、微网是否允许向电网售电。数据量不小建议直接用Excel或MATLAB的.mat文件统一管理别硬编码在程序里。比如分时电价用time-of-use结构存储在每个时段约束里按索引引用后续改参数只需要改数据文件不需要动代码。3.3 关键约束的代码化表达与求解框架写代码时一些细节值得注意。以YALMIP为例储能SOC递推约束写成soc(t1) soc(t) (eta_c * P_ch(t) - P_dis(t) / eta_d) * delta_t这里P_ch和P_dis是充电/放电功率eta_c、eta_d是充放电效率delta_t是时段长度。注意YALMIP里这类等式约束没问题但如果你想做“充放电不能同时进行”的约束就需要引入二元变量互斥并且用Big-M处理这会让问题变为MILP而不是LP求解难度提高。好在很多文章的模型里充放电效率价格机制已经能让储能避免同时充放电但有的场景比如价格波动不大仍然需要显式互斥约束否则会出现“又充电又放电”的荒谬解。下层模型的电平衡约束写成矩阵形式用电负荷 光伏出力 电网购电 CHP发电 储能放电 - 储能充电 - 电锅炉用电热平衡约束热负荷 CHP余热回收 电锅炉制热这些约束在YALMIP里直接用sdpvar变量建立、用方括号把左右向量化关系写清楚最后交给optimize。求解之前在sdpsettings里指定求解器Gurobi或CPLEX、打开输出日志、设置收敛容差这些都是关键步骤。3.4 收敛判据与迭代求解流程除了直接做KKT转单层很多文章还采用迭代求解法先给定上层价格初值求解下层优化得到微网响应再把响应带回上层优化上层价格反复迭代直到价格和功率变量不再变化。迭代法实现简单但收敛性是最让人头疼的地方。实际复现中我遇到的问题很典型上下层交替迭代价格震荡无法收敛最后在约束边界来回跳。解决方法通常有这么几类对上层价格更新加阻尼/步长因子新价格 旧价格 α ×本次求解价格 - 旧价格α取0.3~0.5能大幅缓解震荡。增强收敛判据不仅看价格差还要看功率响应的最大差值两个指标同时满足才算收敛。设置最大迭代次数上限避免死循环卡死在某个状态。我在自己的实验里是这么做的先跑一次“直接KKT转单层”得到基准最优解再用迭代法跑同一算例对比。如果迭代法的终值跟KKT单层法的解在3%以内说明迭代法调参到位了。这个方法在复现调试阶段非常好用强烈推荐。另外很多文章的模型看似复杂其实惩罚项设计也是有门道的上层目标里如果完全不做惩罚价格优化自由度大可能直接冲到价格上限这样博弈就退化了。所以复现的时候检查一下文章是否有价格上限或价格弹性机制如果没有模型结果很可能出现“极端定价”的不合理现象。4. 复现中遇到的典型问题与排查技巧4.1 常见报错与原因速查调试过程中我整理了最常遇到的几类问题和排查方向这里直接分享一个速查表问题现象可能原因排查方法YALMIP提示“No solver available”未正确安装/配置求解器检查solver路径测试一个简单LP是否可用求解器返回“Infeasible”约束存在冲突通常是变量维度不匹配或某个上下限取值矛盾先把所有等式约束的左右两端维度打印出来逐一核对解出来储能同时充放电缺少互斥约束或充放电效率过小导致“边充边放”有利可图确保价格差超过效率损失必要时加二元互斥求解时间爆炸存在非凸双线性项或Big-M取值过大排查目标函数中是否残留双线性项用强对偶替换调整M值上层价格直接冲到上限缺少价格约束或价格弹性不足加上价格上下限参考文章给定的政策价格区间SOC曲线不连续或越界SOC递推公式中效率写反或边界条件缺失手推前两个时段的SOC递推并与代码结果对照经验就是遇到“Infeasible”别慌先从最简单的情况排查。删掉一半约束只留平衡约束跑一遍看是否可行然后逐渐加回这样能快速定位冲突源。我复现时发现大多数不可行问题都出在CHP出力的电热耦合约束上——电出力和热出力不是独立变量写约束的时候少写了耦合关系就会导致无解。4.2 不收敛、震荡与次优解的深水区排查迭代法不收敛是复现这类文章时最难啃的骨头。除了前面提到加阻尼因子外还有一个值得注意的经验下层模型如果有多个等优解目标函数值相同但变量取值不同迭代法就会在几个等优解之间反复跳变无法稳定。解决办法是给下层目标函数加一个极小正则项比如“加上0.001乘以各功率变量的平方和”让下层在所有最优解里选择最“平稳”的那一个。这个技巧在文献中也叫随机扰动或正则化实际操作效果立竿见影。我在复现中加了正则项后价格震荡的规模直接从5%降到0.5%以内。另一个深水区问题是“次优解”。KKT单层化后的模型本身是非凸的Gurobi求出来的可能只是局部最优。验证方法也很朴素换不同的求解器CPLEX、Gurobi、MOSEK和不同的初始点比较最终目标值如果结果一致说明解的稳定性尚可如果差异显著就要考虑是不是模型线性化过程出了问题尤其是Big-M或强对偶相关步骤。还有一个检查点看看离散曲面和原始双层的真实目标值是否一致——先固定上层解得的下层目标值和单层模型里下层目标值不一定完全一致因为做了强对偶替换。这个偏差不要忽略可以用它来判断线性化是否无损。4.3 版本兼容与老代码移植的坑复现文章时能找到源代码是最好的情况但大多数论文附带的代码都是很久以前的运行在旧版MATLAB和YALMIP上拿到新环境里几乎必出问题。我遇到的典型情况有这么几类旧版YALMIP的等价写法在新版本里不再支持比如某些投影约束、非连续函数的建模方式。求解器调用接口变化Gurobi的许可证版本和MATLAB接口版本不匹配。数据文件格式不兼容早期代码常用xlsread读取Excel现在还要考虑数据文件缺失和路径问题。遇到这种问题我的建议是不要试图在原代码上打补丁而是读懂代码的意图之后用自己的框架重写。重写的好处是你能真正掌握每个约束和变量后面修改模型做拓展比如加入碳交易、需求响应、热泵替代电锅炉都会容易得多。原代码可以当参考——尤其是里面的参数取值、边界范围很多文章正文没有写清楚却藏在了代码里。我复现时最关键的一个参数——储能容量租赁价格上限就是翻原始代码才找到的文章正文里根本没有直接给出。配套的排查技巧是结果合理性的交叉验证。最基本的验证包括负荷平衡是否满足、储能SOC首尾一致、购电量在价格低谷时段更大、CHP在热负荷大时出力高——这些物理规律如果全满足模型大概率没问题有任何一条不符合回头检查对应约束。最后说点个人体会复现这类文章真正花时间的不是写代码而是理解两层决策结构背后的问题建模思路。主从博弈、共享储能、综合能源微网这类方向公式推导和代码实现都很繁琐但是一旦跑通一条完整的路径——读懂模型、写出单层化代码、调通求解器、验证结果——再拿到新文章基本可以一两天内复现出主要模型。如果你也是刚起步最实际的建议是先找一篇结构简单、包含一个储能运营商和两三个微网用户的算例文章顺着模型复现一遍跑通后再看更多复杂的场景。手里的模板沉淀下来后续可能就是你的“代表作基础”。
返回列表