
做多微电网调度的项目做了也有几年我印象最深的一点是绝大多数人最先卡住的不是算法本身而是没想明白“到底谁在跟谁博弈”。多微电网接入配电网之后配电网运营商希望网络运行安全经济微电网希望自己运行成本越低越好储能则牵扯到“谁建、谁用、谁出钱”的问题。如果每个微电网都自己配一套储能投资大、利用率低想在项目评审上站住脚很难。后来我接触到“共享储能租赁”的思路配电网作为运营方把储能容量租给多个微电网使用再配合博弈优化调度把三方决策串起来。这套路在国内园区级微网、分布式能源聚合场景里已经是相当主流的研究方向也是很多毕业设计和横向课题的选题源头。这篇文章把从模型设计到Matlab代码实现的核心链路完整捋一遍包括共享储能怎么建模、主从博弈怎么转成可求解的数学规划、YALMIP怎么搭、实际调参时踩过哪些坑。适合正在做多微电网优化调度、共享储能、电力市场方向的研究生和工程师参考。如果你刚接触博弈调度只要懂线性规划和Matlab基础顺着思路也能把框架跑起来。1. 先把博弈框架想清楚谁是领导者谁是跟随者1.1 三个参与主体各自的“小算盘”多微电网系统的物理结构其实不复杂配电网通过公共连接点PCC连接若干微电网每个微电网内部有光伏、常规负荷、可调度机组部分方案还会留出用户侧储能接口。在这个拓扑里至少有三个角色在打各自的算盘。第一个是配电网运营商DSO。它管着网络层面的功率平衡和线路安全手里握着共享储能资产同时又能和主网交易。它既想降低自己的购电成本、减少网损又想通过出租储能、向微电网卖电来赚钱。第二个是微电网MG。每个微电网都是一个独立利益主体它只需要在给定的电价信号下安排自己的购售电量、机组出力和储能充放电计划让自己的总运行成本最小。第三个是共享储能本身。它不再是一台只服务某个微电网的专属设备而是一个可以被多个微电网按需租用的公共资源租赁价格和容量分配就是博弈的焦点。在工程视角下这三方天然存在“上下级”关系DSO先定价格机制微电网再根据价格决策反过来价格又会影响微电网的用电行为这就是典型的主从博弈结构。在我做过的项目里这种模型最贴近实际因为现实中微电网不会把内部数据全部上报给配电网大家各自有私有信息只能通过“价格信号”来交互。1.2 为什么主从博弈比集中式优化更合理有人会问既然所有目标函数和约束都已知为什么不做一个大一统的集中式优化把所有微电网和储能全部揉在一起求个全局最优解这确实是一条路而且求解简单。问题在于集中式优化抹掉了各方的独立利益诉求。实际场景里微电网运营商不会为了全局最优而牺牲自己的收益电力市场环境下每个主体都希望自己利益最大化。主从博弈的建模方式更贴近现实上层配电网运营商先公布共享储能租赁价格和内部购售电价格下层微电网看到价格后各自独立优化。最后达到的状态是“均衡”——任何一方单方面改变策略都不能再让自己变得更好。这就是Stackelberg均衡。我用一个生活类比解释配电网像出租平台微电网像租户。平台先定租金和规则租户再决定租多大空间、怎么使用。平台定的价格低了自己亏定高了租户不租储能闲置也亏。两边博弈的平衡点就是模型要求的东西。这种结构写进论文和项目报告里逻辑也比集中式优化更有说服力。1.3 三个角色的决策模型速查角色核心决策变量目标函数关键约束配电网运营商上层储能租赁单价、购售电价运行成本最小或整体收益最大电价上下限、储能总容量约束、网络功率平衡微电网下层购电功率、售电功率、储能充放电、机组出力自身运行成本最小功率平衡、机组出力上下限、储能SOC约束、联络线功率上限共享储能出租给各微电网的容量利用率最高、收益最大总容量约束、充放电功率限制做具体算例时决策变量之间的关系要严格对齐。比如微电网租用容量后在运行时刻能使用的储能功率上限、能量上限都取决于这个租用容量DSO定的电价要保证不低于主网购电价、不高于用户侧可接受电价否则博弈结果会出现极端化。2. 共享储能建模租赁机制与运行约束2.1 储能系统最基本的电气模型储能建模是整个调度的基础模型写得不严谨后面所有博弈结果都会跑偏。对于日前调度最常见的储能模型是能量状态递推方程$$SOC_{t1} SOC_t \left(\eta_c P_{c,t} - \frac{P_{d,t}}{\eta_d}\right)\frac{\Delta t}{E_{cap}}$$其中 \eta_c 是充电效率\eta_d 是放电效率E_{cap} 是储能额定容量Δt 是调度步长。实际工程中一般取 0.95 的充放电效率纯理论计算时也可以简单设为 1但那样会忽略损耗对决策的影响结果偏乐观。除了SOC递推还必须加上充放电功率约束、SOC上下限约束、周期始末约束。很多初学的人会漏掉“调度周期末SOC等于周期初SOC”这一个约束导致储能变成“免费电池”把深夜低价电全排到午间高峰期结果非常离谱。还有一点容易忽视的是充电和放电不能同时进行否则会同时出现“充电成本”和“放电收益”模型会在中间套利违背物理规律。处理办法是引入一个二进制变量 u_t充电时 u_t1放电时 u_t0用大M不等式把两段功率隔开。2.2 容量租赁机制怎么设计才合理共享储能的租赁机制有好几种设计方式最常见的是“容量租赁电量结算”模式配电网运营商定一个租赁单价 λ单位是元/kWh·天或者元/kW·月每个微电网根据自己的需要申报租用容量 R_i租用成本就是 λ × R_i这个成本进入微电网的目标函数。总租用容量还要满足不超过储能总容量也就是$$\sum_{i1}^{N_{MG}} R_i \leq E_{cap}$$为什么容量租赁在调度模型里最受欢迎因为它决策变量是线性的目标函数里最多出现“租赁单价 × 租用容量”这种双线性项处理起来相对友好。如果改成“按实际充电量计费”碳排放成本、电量电价耦合在一起模型复杂度会明显上升而且微电网可能通过调整充放电行为来规避费用博弈均衡的性质反而不太稳定。我在项目里一般还会加一条每个微电网租用容量后对应储能充放电功率的上限按租用容量比例折算。例如微电网租了 500 kWh储能总容量 2 MWh则它可用的最大充放电功率为额定功率的25%。这样微电网就不能“租小容量、用大功率”避免出现占便宜的行为也更符合实际运营逻辑。2.3 为什么微电网愿意租而不是自己建我在算例里给过一组对比单个微电网自建一套500kW/1MWh的用户侧储能初始投资约150万到200万元还要考虑运维、消防、场地、电池衰减年化成本算下来并不低而共享储能租赁模式下配电网统一建设一套大容量储能多个微电网错峰使用单微电网只需要支付租赁费前期不需要大额资本开支。两者的账算下来共享租赁对中小微电网更友好。这里有个典型的错峰场景微电网A的光伏中午大量富余微电网B的负荷高峰出现在晚上。自建储能的话A在中午充满电后晚上可能自己用不上B晚上缺电但自己没有储能两头都很尴尬。共享储能可以把A中午多发的电存下来晚上放给B用储能的循环次数和利用率明显提升整个配电网的弃光率也降下来。这套经济逻辑是共享储能模式站得住的根本原因写论文的时候记得把这类场景分析放进去能显著提升模型的解释力。3. 博弈模型数学化KKT让双层规划变成单层3.1 上层配电网运营商的数学模型配电网运营商作为博弈领导者决策变量是共享储能租赁单价和内部购售电价格。目标函数一般写成自己运行成本最小包括从主网购电的成本、储能运行维护成本、向微电网售电的成本折算减去向微电网售电的收入和储能租赁收入。用符号表示大致是$$\min ; F_{DSO} \sum_t \left( c_{grid,t} P_{grid,t} c_{om} P_{ess,t} \right) - \sum_t \sum_{i \in MG} \left( \rho_{buy,i,t} P_{buy,i,t} - \rho_{sell,i,t} P_{sell,i,t} \right) - \sum_i \lambda R_i$$约束包括储能租赁价格上下限、购售电价上下限、储能总容量约束、配电网功率平衡。需要特别说明的是DSO的目标并不是越大越好它不能随便把电价定得过高因为微电网作为理性主体电价太贵就会减少购电甚至自己想办法发电最后DSO的售电收入和租赁收入都会下降。这个“自我约束”正是博弈模型能写出均衡的核心机制也是它比纯优化模型更有趣的地方。3.2 下层微电网的数学模型每个微电网 i 的下层优化问题是在给定电价和租赁单价后最小化自身运行成本。目标函数一般包括从配网购电成本、燃气机组燃料成本、储能租赁费再减去向配电网售电的收益。约束条件包括功率平衡、机组出力上下限、爬坡约束、储能SOC约束和联络线传输功率上限。需要提醒的是下层问题里微电网之间没有直接耦合关系它们的联系是通过共享储能容量约束和配电网价格间接实现的。因此每个下层问题都是独立的线性规划或混合整数线性规划。这个结构非常关键它决定了解耦的可行性。3.3 KKT条件转换的原理和操作步骤把双层问题直接丢给求解器是不行的因为上层目标函数里含有下层问题的“解”本质上是一个隐函数没法直接处理。不过如果下层问题是凸的——线性规划本身就满足凸性——并且约束满足Slater条件那么下层问题的最优解可以用KKT条件等价描述。具体操作分三步写出下层问题的拉格朗日函数对下层决策变量求偏导得到稳定条件stationarity。列出原始可行条件primal feasibility、对偶可行条件dual feasibility。加入互补松弛条件complementary slackness即对偶变量与对应约束剩余量的乘积为0。把这三类条件全部加进上层问题双层规划就变成了单层数学规划。这类问题在文献里叫MPEC含平衡约束的数学规划如果所有互补约束都线性化成功最终可以转成MILP用商业求解器直接算。3.4 互补松弛条件线性化与大M取值的经验互补松弛条件是非线性的形如 μ·(g(x)) 0其中 μ≥0g(x)≤0。最简单粗暴的做法是直接把这个等式写进约束但这样模型就变成非线性规划Gurobi、CPLEX这类商业求解器处理不了。工程上常用的做法是大M法引入二进制变量 z把 μ·g(x)0 替换为g(x) ≤ M·(1 - z)μ ≤ M·z当 z1 时μ0当 z0 时约束取得临界值。这两个不等式就等价描述了“对偶变量和约束松弛量至少有一个为0”的逻辑。大M的取值是个经验活。M取太大数值稳定性差求解器容易陷入病态M取太小可能把真正的均衡点剪掉。我自己跑模型的习惯是先看决策变量和约束松弛量的数量级一般取最大量级值的10到100倍。比如约束量级在100 kW左右M可以取1000到10000如果约束量级在1e4M就取1e5到1e6。调M值时要反复试算对比SOC曲线和价格曲线是否合理。3.5 两种求解路径怎么选实际做工程时MPEC单层化和迭代交替求解各有应用场景我整理了一张对比表方法建模难度求解精度计算规模适用场景MPEC转MILP较难要手动推导KKT并线性化精确解二进制变量多规模受限系统规模小、需要严格均衡解迭代交替求解较容易上下层各写各的收敛后精度可控可扩展性强系统规模大、灵敏度分析多迭代法的基本思路是DSO先给定价格微电网求解得到最优功率DSO再根据微电网的响应更新价格循环直到价格和功率不再明显变化。迭代法最大的坑是价格振荡解决办法是加入阻尼系数或者用带步长衰减的梯度更新。后面第5章会专门讲这个。4. Matlab代码实现从数据准备到求解设置4.1 环境准备与求解器配置Matlab版本建议R2021a以上我用R2023a和R2024a都实测过运行稳定。建模工具箱强烈推荐YALMIP它是Matlab下最常用的优化建模语言可以把线性规划、整数规划、二次规划统一描述成模型然后交给底层求解器。求解器推荐顺序是Gurobi CPLEX 开源求解器。Gurobi和CPLEX对MILP问题求解效率显著优于开源方案做KKT转化之后的复杂组合优化问题基本是刚需。学术用户可以去官方渠道申请免费授权企业用户购买商业授权不要在外部渠道下载所谓“绿色版”“破解版”这类文件本身就有安全风险而且会在后续论文投稿和项目验收时埋雷。装完环境后第一件事是运行yalmiptest它会自动检测当前可用求解器列表。这一步能提前暴露求解器配置问题省得写了一大段模型才发现求解路径不通。4.2 输入数据怎么组织才不乱仿真数据建议用结构体或者mat文件统一管理。以我常用的IEEE 33节点配电台区为例改造方案是把网络分成3个区域每个区域接入一个微电网公共节点布置共享储能。输入数据包括24小时负荷曲线、24小时光伏出力曲线、分时购电价、储能容量和功率、充放电效率、初始SOC、机组发电成本系数。我习惯写成这样%% 系统公共参数 nMG 3; % 微电网数量 T 24; % 调度时段 dt 1; % 步长小时 %% 微电网参数结构体 MG struct(load, {}, pv, {}, Pmax, {}, cost_g, {}); for k 1:nMG MG(k).load load_coeff(k, :) .* base_load(k); % 负荷曲线 MG(k).pv pv_coeff(k, :) .* pv_capacity(k); % 光伏出力 MG(k).Pmax 0.8; % 机组最大出力 MG(k).cost_g 0.6; % 机组发电成本元/kWh end %% 共享储能参数 ESS.Ecap 2000; % 容量 kWh ESS.Pmax 500; % 最大功率 kW ESS.eta_ch 0.95; ESS.eta_dis 0.95; ESS.SOC0 0.2; ESS.SOC_max 0.9; ESS.SOC_min 0.1;把所有参数集中管理有一个额外好处后面做敏感性分析时只需要循环修改结构体字段批量跑多种场景不需要改模型主体代码。这个习惯帮我节省了大量重复劳动。4.3 YALMIP建模核心以单微电网下层问题为例下层微电网的YALMIP建模是整个代码里最需要仔细的部分。先把变量定义清楚再一层一层叠约束最后写目标函数和求解调用。一个简化的微电网经济调度核心代码如下%% 定义下层微电网优化变量 Pbuy sdpvar(1, T, full); % 从配网购电功率 Psell sdpvar(1, T, full); % 向配网售电功率 Pg sdpvar(1, T, full); % 燃气机组出力 Pch sdpvar(1, T, full); % 储能充电功率 Pdis sdpvar(1, T, full); % 储能放电功率 SOC sdpvar(1, T1, full); % SOC轨迹 uB binvar(1, T); % 充放状态二进制变量 %% 约束 Cons []; Cons [Cons, SOC(1) ESS.SOC0 * ESS.Ecap]; for t 1:T % 功率平衡 Cons [Cons, Pbuy(t) Ppv(t) Pg(t) Pdis(t) ... P_load(t) Pch(t) Psell(t)]; % 机组出力约束 Cons [Cons, 0 Pg(t) MG(k).Pmax]; % 储能充放电约束和SOC递推 Cons [Cons, 0 Pch(t) ESS.Pmax * uB(t)]; Cons [Cons, 0 Pdis(t) ESS.Pmax * (1 - uB(t))]; Cons [Cons, SOC(t1) SOC(t) ... (ESS.eta_ch*Pch(t) - Pdis(t)/ESS.eta_dis) * dt]; % SOC上下限 Cons [Cons, ESS.SOC_min*ESS.Ecap SOC(t) ESS.SOC_max*ESS.Ecap]; end % 周期始末SOC一致 Cons [Cons, SOC(T1) SOC(1)]; Cons [Cons, 0 Pbuy(t) 500, 0 Psell(t) 500]; %% 目标函数购电成本 - 售电收益 机组燃料成本 Obj sum(rho_buy .* Pbuy) - sum(rho_sell .* Psell) ... sum(MG(k).cost_g .* Pg); %% 求解 ops sdpsettings(solver, gurobi, verbose, 0); sol optimize(Cons, Obj, ops);多微电网情况就是把这段代码放到一个循环里每个微电网基于同一组价格变量分别建模。需要注意Pbuy、Psell的共享价格变量是上层传来的在迭代法中可以写成外部参数在MPEC化方法中它们本来就是上层决策变量。4.4 双层模型单层化的实现思路如果你走MPEC单层化路线需要在下层YALMIP模型的基础上额外构建KKT条件。用YALMIP做这件事最方便的方式是借助diff或jacobian函数直接把拉格朗日函数对决策变量求导但我个人建议宁可手写KKT也不要完全依赖符号自动求导因为网络规模大了之后符号求导会把很多约束重复展开模型膨胀得厉害求解时间翻好几倍。单层化后的模型在YALMIP里的写法大致是定义上层所有变量 下层所有变量和对应的对偶变量把下层的原始约束、对偶稳定条件、互补松弛线性化条件全部写成全局约束目标函数用上层的目标。这个模型变量多、约束多求解时建议先关闭求解器日志刷屏把求解器时间上限、MIP gap设置好否则一个算例可能跑几个小时没有结论。5. 调试实录今天遇到的最常见问题5.1 求解器返回“Infeasible”或一直卡在预求解双层转单层之后最常出现的坑是模型不可行。我之前调试一个三微电网算例怎么调都无解最后发现是KKT转化时互补松弛线性化的M值取得太小把实际可行的交易点给剪掉了。排查方法很直接先用一个微电网、简化上下层约束跑通再逐步增加微电网和约束条件每一步都验证解的合理性。此外可以打开Gurobi的IIS报告YALMIP里用sol.info和check(Cons)辅助定位是哪条约束出了问题。5.2 SOC曲线出现不正常的跳变SOC曲线跳变往往不是算法问题而是单位或步长写错了。比如储能容量单位是kWh功率单位是kWΔt取1小时时问题不大但如果把Δt当成分钟忘记除以60SOC的递推就会偏大几十倍。还有一种情况是没有约束调度周期末SOC回到初始值储能会把全天电量清空SOC曲线看起来就很“聪明”地把低价电抽干了现实中这是不允许的。5.3 充电和放电同时发生如果优化结果里同一时段充电功率和放电功率都大于0说明要么二进制变量没加要么互补松弛条件没有严格生效。补充二进制变量后要检查求解器是否把它当成MILP求解而不是把它当成连续问题求解。在YALMIP里如果变量包含binvar要确认sdpsettings(solver, gurobi)正确传递否则默认调用连续求解器二进制变量会被自动松弛UB和LB重合的间隙就会被钻空子。5.4 迭代法价格振荡不收敛迭代法最常见的现象是价格在两个值之间来回跳动不收敛。原因通常是微电网对价格的响应太灵敏价格更新步长又设得太大。我的经验是给价格更新加阻尼$$\rho_{new} \rho_{old} \alpha \cdot \Delta\rho$$其中 \alpha 从0.2开始尝试每次迭代缩小一点比如乘0.99收敛曲线会平滑很多。另外还可以设置价格归一化判据当相邻两次迭代的价格变化小于0.1%时就判定达到均衡而不是强求完全一致。5.5 模型规模大导致求解时间爆炸三微电网 24时段 KKT转化后问题规模很容易达到数万变量和约束二进制变量甚至上百个。如果求解时间无法接受可以先把时间粒度降成4小时一个时段或者先把微电网传感器数据聚合跑通模型后再逐步细化。还有一个实操技巧在目标函数里加一个极小量比如1e-6的功率二次项帮助求解器稳定收敛对均衡解的影响可以忽略不计。现象可能原因处理办法模型无解大M取值过小、约束冲突简化模型逐步排查调整M值SOC跳变单位写错、缺周期初末耦合检查递推方程加上SOC周期约束充放电同时为正二进制变量丢失或松弛确认binvar生效使用MILP求解迭代价格振荡步长过大、响应过灵敏加阻尼系数动态缩小步长求解时间过长二进制变量过多、约束冗余降粒度、化简模型、加MIP gap上限6. 这套模型能走多远应用边界与扩展方向6.1 现有模型做了哪些简化目前这套模型在工程上很实用但也需要清醒认识它的简化前提。第一很多实现采用单节点功率平衡没有考虑线路阻抗、电压约束和网损的空间分布。如果研究的是低压台区这种短线路场景误差还比较小一旦推广到中压配电网就需要引入DistFlow潮流模型。第二风光出力通常按典型日曲线处理没有把预测误差和随机波动纳入优化影响日内调度时的可靠性。第三储能的寿命衰减、温度影响、循环次数成本在大多数模型里都被忽略了长期维度下共享储能的投资回报评估还需要更细的模型。6.2 值得继续扩展的四个方向如果要把这个框架做成更完整的研究成果我建议从四个方向入手。不确定性处理是当前最热门的方向。风光出力可以改用场景法或者用分布鲁棒优化把最坏情景下的成本纳入目标函数。共享储能在这类场景下的应对价值会更明显因为储能本身就是对冲不确定性的天然工具。网架约束的精细化建模也很值得做。在配电网层引入DistFlow方程后博弈模型的解将不再只是功率和价格还包括节点电压这样就能做电压越限分析和无功优化调度。多微电网之间的非合作博弈可以叠加上去。当前框架里微电网只是跟DSO博弈微电网之间只通过共享储能间接耦合。如果多个微电网能互相交易就变成“上层DSO 下层微电网之间纳什博弈”的组合模型复杂度更高但贴近电力市场改革的方向。分布式求解方面可以考虑ADMM。当微电网数量上升到几十个的时候把所有模型集中到一个Matlab进程里基本跑不动分布式求解能保护各微电网隐私同时把计算压力分散这也是工程落地时更可行的路线。6.3 什么时候应该用这套模型我用这套模型的经验是它最适合“机制设计”类问题比如研究共享储能应该采用哪种租赁定价策略、微电网数量对储能收益的影响、分时电价对微电网响应行为的激励效果。如果目标只是想算某个具体配网的最优储能配置容量不涉及多个独立利益主体直接用集中式优化反而更高效。博弈模型不是万能的关键是看研究对象有没有“多个利益主体各自做决策”的本质特征。最后分享几个我实际跑这套模型的心得。第一次跑通时建议只用两个微电网不要一上来就是三个甚至更多先把KKT转化、大M取值和求解器配置这些坑摸清。每次修改参数前先跑一次纯集中式优化作为基准得到的全局最优目标值作为参照如果博弈结果比集中式结果差太多要警惕是不是模型参数或M取值出了问题。还有一个小技巧把全部算例参数放在一个结构体里起好文件名后批量跑不同场景后面做灵敏度分析可以省下大量重复劳动。这些经验都是踩了不少坑换来的希望能帮你少走弯路。