多微电网租赁共享储能的配电网博弈优化调度Matlab实现
发布时间:2026/9/10 8:08:53来源:尧图网络
先说个直观的场景一片工业园里并排建了三五个微电网每个都有屋顶光伏和本地负荷白天光伏大发用不完傍晚负荷上来光伏功率骤降必须向配电网买电。单独看每个微电网都觉得自己是“弱势买方”电价多少只能被动接受想自建储能吧一年有近半时间闲着收益率算下来还不如去理财。但如果它们把储能的账合起来算再联合起来跟配电网“讨价还价”情况完全不一样。这就是我最近在跑的一个项目——多微电网租赁共享储能的配电网博弈优化调度平台用的是Matlab求解器走的是YALMIPCplex路线。这个课题现在特别火核心就一句话多个微电网不自己买储能而是租一个共享储能电站组成联盟参与配电网的博弈调度。它把“共享经济”的思路搬到了电力系统里同时又用博弈论刻画了配电网和微电网联盟之间的利益博弈关系。这篇文章我会从模型逻辑讲到Matlab代码落地再到我实际调试中踩过的坑全部摊开来说。1. 多微电网为什么要“抱团租储能”成本与利用率的账1.1 单个微电网配储能算下来的确不划算很多刚开始接触这个方向的同学会问微电网自己装个储能不就完了为什么非要租算一笔简单的账。假设一个微电网峰值负荷5MW光伏装机3MW。白天光伏大发的时候可能用不完储能能把多余的电存下来但问题是储能容量配小了傍晚负荷高峰不够顶配大了夜间轻负荷时段只能躺在那里晒太阳全年实际利用率可能连30%都不到。再算投资账一套1MWh的磷酸铁锂储能系统落到项目上从电池、PCS、BMS到施工调试单位投资通常在1500~2000元/kWh左右1MWh就是150万到200万。一个微电网如果配2MWh四百万砸进去回收周期七八年都算乐观的。这还没算电池循环寿命衰减、运维人工、保险费用。对工业园区里那些本身经营压力就大的微电网来说自建储能的投资决策很难通过内部收益率审核。如果用租赁模式微电网不需要一次性掏一大笔钱而是按容量或者按实际使用的功率电量付费相当于把重资产变成了运营成本。储能利用率也上来了因为共享储能的容量池子可以覆盖多个微电网的互补需求。1.2 多微电网之间天然存在时空互补性多微电网为什么能共享储能本质上是它们的负荷曲线和新能源出力曲线存在互补性。举个我实际用过的算例。微电网A是白天生产的工业负荷光伏自用比例高晚上休息微电网B是商业综合体负荷高峰集中在傍晚和周末微电网C是小型居民社区早晚两个高峰明显。三条曲线叠在一起充电需求和放电需求实际上在时间上错开了。用同一个储能电站调配上午A的余电充进储能傍晚B、C需要顶峰时放出来储能一天可能完成两到三次完整循环而单个微电网自建储能可能一天只循环一次甚至还不到。除了时间互补还有功率互补。三个微电网的负荷峰值不会同时到达共享储能的总配置功率可以低于三个微电网独立配置功率之和这就是统计学上的“同时率”效应。体现在数学模型里就是共享储能容量的约束条件比三个独立储能约束条件的求和要宽松目标函数值自然更好看。1.3 题目里的核心逻辑链联盟参与配电网博弈这个项目的标题是“多微电网租赁共享储能组成微电网联盟参与配电网博弈优化调度”我拿到这个题目后拆解出来的逻辑链是多个微电网各自拥有新能源和负荷不单独建设储能而是共同向储能运营商租赁共享储能组成联盟联盟作为一个整体与上层配电网进行博弈配电网先给出电价策略联盟根据电价优化内部的调度也就是储能充放电、从配网购售电、新能源出力等配电网看到联盟的购电需求后再调整电价双方迭代直到达到博弈均衡点。这个模型放到现实里有很强的工程意义。对配电网来说微电网联盟的购电行为比单个微电网更可预测、更容易管理对微电网来说联盟的谈判筹码也比单打独斗大。博弈论在这里不是套个名词而是真实描述了两个决策主体之间的主从互动关系。2. 博弈模型的建模路线谁先出牌谁跟牌2.1 选主从博弈还是非合作博弈多微电网和配电网之间的博弈关系学术和工程上最常用的是主从博弈也就是Stackelberg博弈。原因很简单配电网作为电网运营方掌握着电价定价权和网络运行边界天然处于主导地位是博弈中的“领导者”微电网联盟只能根据给定的电价调整自己的购电策略是“跟随者”。这跟现实情况是一致的——微电网不能自己给配电网定电价。在多微电网联盟内部我选用的是合作博弈的思路因为联盟建立的前提就是共享储能、共同降低成本如果内部先互相博弈联盟本身就散了。在实际建模中内部采用集中优化以总成本最小为目标至于内部成本怎么分摊可以用Shapley值法或者核仁法在调度结束后算这是代码的扩展方向稍后我会详细说。2.2 配电网的优化目标售电收益最大化先把上层配电网模型写清楚。配电网在这里扮演的角色是电能的卖方和管理者它的决策变量是向微电网联盟出售电能的分时电价以及从微电网买电的上网电价。目标函数要最大化自己的收益配电网收益 向联盟售电的收入 - 从联盟购电的支出这里有几个需要注意的建模细节。分时电价不能随便给得设置上下限避免配电网把电价抬到天上去。工程上通常以配电网的基础运行成本作为下限以用户可承受的峰值电价为上限。另外配电网自身也可能有从上级电网购电的成本模型里可以简化成固定常数也可以外接一个上级电网电价曲线。项目里我采用的是后者更符合实际。2.3 微电网联盟的优化目标总运行成本最小下层微电网联盟的目标函数相对复杂一些因为它包含多个子项min C C_buy - C_sell C_storage_lease C_curtail C_buy从配电网购电费用 C_sell向上级电网售电收入目标函数里为负 C_storage_lease共享储能租赁费用 C_curtail弃光弃风惩罚购电费用和售电收入都是电价乘以功率再对时间积分只不过电价是配电网给定的参数功率是决策变量。这两个项合在一起构成了配电网和微电网联盟的核心博弈耦合点。配电网改电价联盟的购售电策略就变联盟的购售电策略变了配电网收益也变。共享储能租赁费用的建模是个关键点。我采用的是“容量租赁功率租赁”两段式计费C_storage_lease alpha * S_lease beta * P_leaseS_lease是联盟租赁的储能容量P_lease是租赁的储能最大功率alpha是容量单价beta是功率单价。这个计费方式的好处是贴近真实储能租赁商业模式——储能运营商按容量收取固定的基础费用再按功率收取使用费用或者两者打包。2.4 约束条件功率平衡、储能SOC和联络线限值约束条件主要分为三类。第一类是微电网内部的功率平衡约束。每个时刻微电网的光伏出力、风电出力、储能放电功率、从配电网购电功率要等于本地电负荷、储能充电功率、向配电网售电功率之和。这里要注意购电和售电不能同时发生需要引入0-1变量或者互补约束来限制。第二类是共享储能运行约束。储能SOC有上下限充放电功率有最大最小值SOC递推公式为SOC(t1) SOC(t) (P_ch(t) * eta_ch - P_dis(t) / eta_dis) * dt / S_leaseeta_ch和eta_dis是充放电效率一般取0.95左右这个递推公式看起来简单但在代码实现中特别容易出问题我后面会在调试章节专门讲。联盟租来的储能总容量在各微电网之间怎么分配这里有两种建模方式一种是各微电网独占一部分储能容量互不干扰另一种是整个联盟共用一个储能池微电网之间通过功率平衡互相配合。前者简单但储能利用率低后者更符合共享储能的理念但约束条件需要写成共享功率平衡的形式。第三类是线路传输容量约束。微电网联盟与配电网之间的公共连接点PCC点传输功率有限制这个约束在物理上保证了不会因为博弈调度导致线路过载。2.5 双层博弈模型的等价转化从双层变单层主从博弈模型天然是一个双层优化问题上层配电网优化电价下层微电网联盟优化调度。这种双层问题没法直接用优化求解器求解标准做法有三种迭代求解法上层先给定电价下层求解出购电需求上层再根据购电需求调整电价循环迭代直到收敛。这种方法实现简单但收敛性需要验证KKT条件转化法把下层的KKT最优性条件作为约束写进上层问题把双层问题转化为带互补约束的单层问题然后用大M法线性化。理论上精确但引入互补约束后求解难度上升规模稍大就会很慢强对偶转化法利用下层问题的强对偶性把下层目标函数的对偶间隙置零将双层问题转化为单层问题。条件苛刻要求下层问题严格凸。项目代码里我采用的是第一种迭代求解法原因很实际——后台精度要求24小时调度模型规模不算特别大迭代求解完全够用而且每次迭代都是凸优化问题Cplex求解非常快整套代码跑完不超过两分钟。如果你要发论文我建议在迭代求解基础上再补一个KKT转化方案做对比审稿人会更认可。3. Matlab代码实现从储能方程到博弈迭代主循环3.1 环境配置YALMIP和Cplex的安装顺序有讲究先说环境。代码基于Matlab R2023a优化建模用的是YALMIP求解器用的是IBM Cplex。这两者的安装顺序有讲究很多新手在这里卡住。先装Cplex再装YALMIP。因为YALMIP本质上是一个建模层它需要调用具体求解器来解决问题。装完Cplex之后把Cplex的Matlab接口所在的路径添加到Matlab搜索路径中addpath(C:/Program Files/IBM/ILOG/CPLEX_Studio2210/cplex/matlab/x64_win64); savepath;然后在Matlab里输入yalmiptest验证安装是否成功。如果YALMIP找不到Cplex通常就是路径没加对或者Cplex版本和Matlab版本不兼容。Cplex 12.10支持R2019a及以上版本太老的Matlab会识别不了新版的Java接口我在这上面吃过亏。3.2 数据准备负荷和光伏出力曲线怎么来代码的第一步是生成或者读入数据。标准做法是准备三个CSV文件分别存微电网负荷、光伏出力和分时电价初值%% 数据读取三个微电网24小时15分钟分辨率 T 96; % 一天24小时每15分钟一个点 n_MG 3; % 微电网数量 % 负荷数据n_MG行T列单位kW load_data xlsread(load_data.xlsx); % 光伏出力数据n_MG行T列单位kW pv_data xlsread(pv_data.xlsx); % 初始电价1行T列单位元/kWh price_init xlsread(price_init.xlsx);如果没有实测数据可以用正弦函数加随机扰动模拟。比如光伏出力模拟成半正弦形状峰值出现在12点到14点之间再用随机数叠加波动负荷曲线则根据不同微电网类型设置不同的峰谷时间段。模拟数据虽然简单但用来调代码逻辑足够了。3.3 变量定义连续变量和0-1变量怎么分工YALMIP建模的第一步是定义决策变量。我习惯把变量分成两组连续变量和0-1变量。连续变量包括储能充放电功率、储能SOC、各微电网购售电功率等0-1变量包括购电/售电互斥状态、储能充/放互斥状态。%% 决策变量定义 sdpvar p_buy(n_MG, T); % 微电网从配电网购电功率 sdpvar p_sell(n_MG, T); % 微电网向配电网售电功率 sdpvar p_ch(n_MG, T); % 储能充电功率 sdpvar p_dis(n_MG, T); % 储能放电功率 sdpvar soc(n_MG, T); % 储能SOC sdpvar S_lease; % 租赁储能容量 sdpvar P_lease; % 租赁储能最大功率 binvar u_buy(n_MG, T); % 购电状态1为购电 binvar u_ch(n_MG, T); % 充电状态1为充电这里有个细节用sdpvar声明连续变量binvar声明0-1变量不要用错。YALMIP在处理0-1变量时会自动把模型识别成混合整数线性规划或混合整数二次规划然后用Cplex的分支定界法求解。3.4 目标函数构建注意正负号目标函数里最容易被搞混的就是售电收益的正负号。微电网联盟的目标是总成本最小购电费用是正的售电收益是负的这一点写反了调度结果会完全乱套。%% 目标函数联盟总运行成本最小 obj 0; % 购电费用 for t 1:T for i 1:n_MG obj obj price_buy(t) * p_buy(i, t) * dt; obj obj - price_sell(t) * p_sell(i, t) * dt; end end % 共享储能租赁费用 obj obj alpha * S_lease beta * P_lease; % 弃光惩罚 obj obj gamma * sum(sum(pv_data - pv_use)) * dt;price_buy和price_sell是配电网下发的电价策略在迭代主循环每次都会更新alpha、beta是租赁单价gamma是弃光惩罚系数。这些系数怎么调我后面会讲经验。3.5 约束条件逐条写入这些坑早晚会踩关键约束条件逐个写。先是功率平衡约束%% 功率平衡约束光伏购电储能放电 负荷售电储能充电 cons []; for t 1:T for i 1:n_MG cons [cons, pv_data(i, t) p_buy(i, t) p_dis(i, t) ... load_data(i, t) p_sell(i, t) p_ch(i, t)]; end end这一条约束的含义是电能不能凭空产生也不能凭空消失。注意等式右边的负荷是刚性需求等式左边的光伏和储能是可用电源。这个等式用连接不要写成因为如果允许功率不平衡求解器总会找到更省钱的方案结果就是系统功率失衡。然后是储能SOC递推约束%% 储能SOC约束 soc(:, 1) 0.2 * S_lease; % 初始SOC为20% for t 1:T-1 for i 1:n_MG cons [cons, soc(i, t1) soc(i, t) ... (p_ch(i, t) * eta_ch - p_dis(i, t) / eta_dis) * dt]; cons [cons, soc(i, t) 0.9 * S_lease]; cons [cons, soc(i, t) 0.1 * S_lease]; end end这里SOC的上下限是0.9和0.1而不是0和1这是从电池保护角度考虑。实际储能系统的可用容量通常只有铭牌容量的80%深充深放会显著缩短电池寿命。充放电互斥约束一定要加。理论上P_ch和P_dis不会同时大于零但求解器为了最小化目标函数可能找出同时充放电的荒唐解必须用0-1变量限制%% 充放电互斥约束M为足够大的正数 M 10000; for t 1:T for i 1:n_MG cons [cons, p_ch(i, t) M * u_ch(i, t)]; cons [cons, p_dis(i, t) M * (1 - u_ch(i, t))]; end end大M法里的M参数需要足够大但又不能太大。M太大可能导致数值问题Cplex求解时会出现数值不稳定M太小可能把可行域卡掉。这个参数我通常取储能最大功率的10倍左右够用且数值稳定。购售电互斥同理%% 购售电互斥约束 for t 1:T for i 1:n_MG cons [cons, p_buy(i, t) M * u_buy(i, t)]; cons [cons, p_sell(i, t) M * (1 - u_buy(i, t))]; end end这是一个纯线性约束但对物理模型的准确性来说非常重要。没有这个约束求解器可能会在同一时刻低价买电再高价卖电利用电价差套利这在现实中是不可能的。联络线容量约束%% 联络线容量约束PCC点传输功率限值 P_pcc_max 5000; % kW for t 1:T cons [cons, sum(p_buy(:, t)) P_pcc_max]; cons [cons, sum(p_sell(:, t)) P_pcc_max]; end3.6 博弈迭代主循环电价更新怎么写模型建好之后进入核心的博弈迭代主循环。逻辑是先给定初始电价微电网联盟求解优化模型得到购电需求配电网根据购电需求调整电价然后重新求解直到两次电价差小于阈值。%% 博弈迭代主循环 maxIter 30; tol 1e-4; price_buy price_init; % 初始电价 price_sell 0.8 * price_init; % 上网电价通常是购电电价的80%左右 alpha_iter 0.3; % 电价更新步长 for iter 1:maxIter % 步骤1给定电价求解下层微电网联盟优化模型 ops sdpsettings(solver, cplex, verbose, 0, ... showprogress, 0, cplex.mip.tolerances.mipgap, 0.001); optimize(cons, obj, ops); P_buy_opt value(p_buy); % 微电网联盟的购电需求 P_sell_opt value(p_sell); % 微电网联盟的售电功率 % 步骤2配电网根据联盟购电需求调整电价 % 如果联盟购电需求增加说明当前电价低配电网会提价 price_buy_new price_buy alpha_iter * (sum(P_buy_opt, 1) - sum(P_buy_opt_old, 1)); % 步骤3检查收敛 if norm(price_buy_new - price_buy, 2) / norm(price_buy, 2) tol fprintf(收敛于第%d次迭代\n, iter); break; end % 步骤4更新电价 price_buy price_buy_new; end这个迭代框架的核心思想是让电价跟随购电需求做梯度调整。在实际调试中这个简单的梯度法则非常容易发散。原因很好理解电价调整步长如果太大可能会在最优解附近来回震荡如果步长太小收敛又太慢。我最终用的是自适应步长上一轮电价变化大就减小步长变化小就增大步长效果比较理想。3.7 储能租赁规模的确定写进优化模型还是单独算还有一个建模选择要说明租赁储能的容量S_lease和功率P_lease是作为决策变量放进模型一起优化还是事先给定。作为决策变量模型会在成本和收益之间自动权衡储能配置规模结果更优但求解难度增加因为SOC约束里出现了S_lease与充放电功率的乘积项模型变成了非线性问题YALMIP会报错或者求解很慢。项目代码里我做了简化先用粗粒度的手算确定储能容量然后在模型里以固定参数形式输入。具体做法是看多微电网联盟的净负荷曲线即总负荷减去总光伏出力低谷时段和高峰时段的电量差乘以一个修正系数就是需要的储能容量。如果要用联合优化方式需要把SOC约束改成线性化的形式对电池容量和充放电功率进行解耦处理这个细节我后面会讲。4. 调试记录双层博弈在YALMIP里的四个深坑4.1 坑一Cplex报出“Model is infeasible”这是最让人崩溃的报错我一共遇到过三次每次原因都不一样。第一次是功率平衡约束写错了方向。负荷数据里包含了储能充电功率但我又在约束里加了一部分导致总需求比总供给大模型永远找不到可行解。排查方法是把约束逐条注释掉注释到哪一条模型可解问题就出在哪一条。第二次是大M参数太大。M100000时Cplex在预处理阶段出现数值问题报错信息指向边界条件实际问题是M值过大导致约束矩阵的病态条件数太高数值求解精度崩了。把M改成10000后模型正常。第三次是SOC初始值设置和储能容量参数冲突。SOC初始值设为20%的储能容量但容量本身是决策变量初始值计算时容量还没确定导致取值范围冲突。后来把SOC初始值改成固定数值问题解决。4.2 坑二充放电互斥约束没加储能“边充边放”这是新手最容易犯的错误也是优化模型合理性的基本检验点。如果不加互斥约束求解器给出的调度方案可能包含储能同时以最大功率充电和放电。表面上两个决策变量的值相同真实物理过程不会出现这种现象但数学模型不管这些它只要求等式成立。因为充放电效率存在损耗同时充放消耗电量对求解器来说这是可能被接受的方案但会造成储能设备无意义的损耗。加互斥约束的正确做法是引入0-1变量每个时间间隔储能要么充、要么放、要么停三种状态只能取一。这增加了求解变量数但对于工程模型来说完全值得物理不合理的解没有任何参考价值。4.3 坑三博弈迭代不收敛电价来回震荡双层博弈迭代求解最容易遇到的就是振荡问题电价升高→购电需求下降→电价降低→购电需求上升→电价再升高陷入无限循环。我试过纯梯度法、平方法、阻尼法效果都不太理想。最终稳定可靠的是历史平均加权法每次电价更新时不直接跳到新电价而是用历史电价序列的平均值作为当前电价相当于给电价变化施加了惯性阻尼%% 历史平均法抑制震荡 % price_hist存储历史电价 if iter 3 price_buy mean(price_hist(end-2:end, :), 1); else price_buy price_buy_new; end另外收敛判据不能只看电价一次迭代的差值要连续三到五次迭代都满足容忍度才判断收敛避免滑动巧合。配电网收益和微电网成本也都要记录并检查是否达到平台期。我项目里的判据是连续迭代5次电价变化率都小于千分之一且联盟总成本不再下降此时认为达到纳什均衡。4.4 坑四NLP问题和MILP问题的选择这个项目的模型有一个容易让人感到困惑的地方SOC递推公式中SOC乘以储能容量S_lease会形成决策变量乘积出现双线性项此时模型不再是线性规划而是带非线性的规划问题。YALMIP支持这种模型但Cplex只能处理线性问题遇到非线性项会报错。我采用的解法是把储能容量S_lease从决策变量中提出来在模型外预估确定。具体做法是先用简化模型确定容量再用固定容量进入主模型。如果一定要搭建联合优化的完整模型那就需要用分段线性化的方式逼近非线性项让模型可解。这一步涉及数值计算方面的细节代码量比较多等跑通基础版本后我再单独抽时间分享。5. 代码扩展与个人实操体会5.1 扩展方向一内部成本分摊——Shapley值法联盟的总成本优化出来后内部怎么分摊是下一个重要问题。如果只是平均分摊出力小的微电网会不满可能导致联盟解体。常用的做法是用Shapley值法按各微电网的边际贡献分配联盟总收益。具体实现思路是把微电网联盟所有可能的子集都列出来计算每个子集单独运行的成本然后用Shapley值公式计算每个微电网应分摊的成本。这个计算量随微电网数量呈指数增长微电网数量超过5个以后计算量很大。工程上常用近似方法比如按储能使用电量比例分摊或者按弃光减少量比例分摊效果也不错。5.2 扩展方向二可再生能源出力的不确定性——鲁棒优化光伏和风电的预测误差会显著影响调度结果。基础版本用的是确定性的预测曲线如果要增强模型鲁棒性可以把光伏出力建模为区间用鲁棒优化处理最坏情况下的调度成本增加。Matlab代码里可以用YALMIP支持的不确定变量来实现或者用场景法生成多个出力场景做随机规划。算力充裕时随机规划效果更好但计算时间和内存消耗会大幅增加。5.3 扩展方向三引入碳排放流模型如果课题和双碳目标结合可以在功率平衡约束基础上增加碳排放约束比如联盟总碳排放不超过配额。碳排放强度根据购电来源区分配电网火电比例高购电碳排放就高光伏发电碳排放为0。这样相当于在模型里加入了碳排放成本推动微电网联盟优先用共享储能消纳光伏而不是向配电网购电。这个方向在目前的研究中非常热门发表论文的接受度也比较高。5.4 我实际调试中的几个心得最后说几个这次跑代码的真实体会。第一数据质量决定模型上限。代码调试过程中绝大多数的报错和看似“不合理”的结果根因都在数据上。负荷曲线和光伏曲线尽量用真实数据哪怕只有几天的历史数据也远比随机数生成的模拟数据更能暴露模型问题。如果只能用合成数据要把生成过程和参数写在注释里方便别人复现。第二先跑通小规模模型再上完整算例。我第一次直接把3个微电网、96个时间点全部跑起来Cplex求解花了很长时间还没有输出。后来改成2个微电网、24个时间点几秒就出结果逻辑排查效率提升很多。模型规模从小到大递进是优化调度代码调试的重要习惯。第三所有参数写在一个集中的配置文件里。电价上下限、储能效率、租赁单价、罚系数这些参数全部放在文件开头的配置区变量命名清晰注释齐全。否则改一个系数要在代码里找半天而且容易漏改。第四注意结果可视化的细节。调度结果用plot画图之后不能只看总成本降没降要逐条检查每个微电网的功率平衡是否满足储能SOC曲线是否连续变化出现跳变的地方往往就是约束条件遗漏的地方。我习惯把SOC曲线、购售电功率曲线、光伏出力曲线画在同一张图上发现问题一目了然。代码本身目前维持在一个相对基础但体例完整的版本能满足课程作业、科研开题和论文初步对比的需求。往上走的方向很多但骨架是稳的——多微电网的共享储能建模、博弈迭代框架、YALMIPCplex求解链路这套东西的扩展性非常强。后续如果时间允许我打算补一个多场景对比的实验章节不同的租赁计费方式下的联盟成本差异应该能挖出一些更有意思的结论。
网站建设高端定制企业官网