多微电网优化调度:MATLAB+Yalmip建模与求解全解析
发布时间:2026/10/1 23:03:50来源:尧图网络
做微电网优化的人十有八九都会卡在“多微电网”这三个字上。单微电网的调度问题很多资料都能讲清楚但一旦把多个微电网接进配电网让它们之间可以互相支援、共同参与功率调节问题的复杂度立刻上了一个台阶。我最近把一个《面向配电网的多微电网优化调度》的MATLAB项目完整复现了一遍这篇就把它从建模到求解的完整逻辑、代码结构和踩坑经验都摊开来说给同样在研究多微电网优化调度、配电网能量管理的同学做个参考。先说清楚这个项目到底是什么它解决的是“配电网下有多个微电网并联运行”这种场景下如何制定各微电网的日前发电计划。具体来说就是在一个已知负荷曲线、新能源出力曲线和分时电价的前提下让每个微电网内部的柴油机出力、储能充放电功率、与配电网的购售电功率以及微电网之间的交互功率全部算出来最终目标是使整个系统的综合运行成本最低。别小看这一步它涉及到的约束极多决策变量动辄上百个手算完全不可能所以用MATLAB建线性规划模型就是最主流的落地方式。这篇博文会对整个项目做一次非常细致的解剖从建模思路、目标函数和约束条件的设计到Yalmip工具箱建模、求解器调用、结果分析再到常见报错和验证方法适合正在做分布式能源调度、微电网优化或者毕业设计相关课题的同学直接抄作业。1. 多微电网优化调度到底在解什么问题1.1 从单微电网到多微电网难在哪里单微电网的优化调度大家比较熟悉本质上就是一个“源荷储”匹配问题已知某个微电网内部的负荷、光伏风电出力以及柴发、储能等可控资源求解一天24小时各台设备的出力计划让运行成本最低。但多微电网直接把这个题的难度抬了好几个量级。最核心的区别有三个方面第一是空间维度变多了。不再是“一个系统”而是多个独立的微电网各自都有自己的负荷、新能源出力、储能和可控电源。每个微网要满足自己的功率平衡但彼此不是孤立的。第二是功率可以互济。微网A的光伏出力在午间有富余它可以选择多卖给电网也可以选择通过联络线送给负荷更重的微网B。这就引出了“微网间交互功率”这个新变量而且每条联络线都有传输功率上限。第三是利益和约束耦合。最关键的虽然每个微网在物理上是独立的但整体调度时存在共同的约束——比如总购电量、总交互功率范围、甚至某些公共联络线容量。如果在程序中把这些耦合关系处理不好模型要么无解要么结果完全不合理。我用一个生活化的类比帮助理解单微电网就像一户家庭家里装了光伏和储能每天盘算怎么用电最省钱多微电网就是小区里的几户邻居每家都有自己的光伏和储能平时各自用电但谁家缺电时可以从邻居家拉一根线借一点电当然借多少还得看中间这根电线的粗细。整体目标不是某一户最省钱而是整个小区综合最优。1.2 面向配电网的典型应用场景这类项目被冠以“面向配电网”的前缀是有实际工程背景的。随着分布式光伏的大规模接入配电网末端的负载率波动很大单纯靠配电网层面的集中式调控越来越力不从心。微电网集群被看作是配电网的“主动资源”当配电网负荷高峰时微电网可以减少从电网的购电功率甚至向配电网倒送功率当配电网有故障检修或者电压异常时微电网可以孤岛运行或提供支撑。在实现层面配电网想的是“整个网架安全经济运行”各微电网考虑的是“我们这些局部区域怎么配合最省”。所以在调度模型里配电网对大电网的购电功率往往有一个总的上限约束微网之间的交互也要控制在一定范围内。这样一来多个微网的调度计划天然就是联动的。常见的应用案例包括叠加在10kV或35kV馈线上的多个工业型微电网每个微网内部有柴油发电机、储能、屋顶光伏和工业负荷。海岛微网群多个岛屿微网通过海缆互联在海缆容量约束下协调各岛的功率。新建园区型智能配电网微网之间通过直流母线和交流母线混合互联。我在项目里设置的是4个微电网接入同一个配电网节点的场景这也是这类课题里最经典的规模——规模太小体现不出多微网调度的意义规模太大求解时间又会影响调试体验。1.3 项目边界与简化假设在动手建模之前一定要先把项目的边界条件定清楚。很多同学一上来就直接写代码写着写着发现约束根本填不进去原因就是模型边界模糊。这个项目给出的边界是这样的时间尺度以1小时为一个调度时段优化周期24小时。虽然实际调度可能精细到15分钟但日前计划和教学场景用小时级最清晰。预测信息已知各微电网的24小时负荷、光伏出力、风电出力都是确定性的已知数据。不考虑预测误差和随机性。忽略网络潮流认为各微网都接在配电网的同一个电节点或者电压等级一致功率传输只用有功功率平衡约束来表示不做交流潮流计算。成本考虑生产成本主要是柴油机燃料成本、运维成本、储能老化成本和从电网购电费用售电收益在目标函数中为负。这些假设是否合理对于学习和验证调度逻辑来说完全合理。它把问题聚焦在“多主体协调优化”这个最核心的矛盾上。如果你后续想进阶可以在潮流、不确定性、分布式求解上下功夫这可以在第5章部分做扩展。2. 核心建模环节目标函数与约束设计2.1 目标函数经济成本怎么算才完整优化调度的目标函数是整套模型的心脏。常见的误区就是只写“购电费用燃料成本”储能和设备的运维成本一概忽略这样算出来的结果往往与实际工程决策偏差很大。这个项目的目标函数是整个多微电网系统的总运行成本最小化包括以下四部分购电成本各微电网从配电网购电的电费按分时电价计算。注意这里允许微网卖电给配电网卖电收益是负数项。柴油机燃料成本用二次函数近似表示即油耗成本与出力成二次关系。由于二次函数在优化中会增加求解难度实际代码中常采用分段线性化处理。设备运维成本柴油机和储能运行维护成本通常用输出功率乘以单位运维成本表示。储能老化成本充放电会带来电池循环寿命损耗折算成每kWh充放电量的折旧成本一般按放电深度估算。我记得有些版本的代码还会加入碳排放成本思路是把每台设备碳排放量乘以碳价折算出成本加入目标函数。这属于进阶玩法做双碳方向的同学可以加上。目标函数的表达形式如下总成本 购电费用 燃料费用 运维费用 储能老化费用 - 售电收益在Yalmip里写目标函数时只需要把上述所有项写成 sdpvar 变量的线性表达式即可调用 optimize(F, objective) 时求解器会自动识别它是线性规划问题还是二次规划问题。2.2 约束条件的完整清单与易错点多微电网优化调度之所以麻烦主要就麻烦在约束上。下面按类别梳理一遍这个清单可以直接抄进自己的模型里。第一类每个微电网的功率平衡约束这是最基础的约束要求任意时刻每个微网内部的发电功率加上从外部获取的功率等于负荷加上储能充电功率。公式上就是柴油机出力 储能放电功率 光伏出力 风电出力 从配电网购电功率 其他微网注入功率 本地负荷 储能充电功率 输出给其他微网的功率注意这里微网间的交互功率方向很关键我建议用“从微网i流向微网j”的单向变量来表示每条联络线上的功率。这样有清晰物理含义约束写起来不容易乱。第二类储能系统运行约束储能约束是这类模型里最容易写错的部分。基础约束包括储能充放电功率不得超过额定功率上限。同一时刻不能既充电又放电需要加互斥约束。如果求解器支持二进制变量用big-M法引入0-1变量如果用纯线性规划用互补或分时策略处理。储能SOC递推关系下一时刻的SOC等于当前SOC加上充电效率修正的充电功率减去放电效率修正的放电功率。SOC要保持在允许范围内比如20%到90%。调度周期结束时SOC尽量恢复到初始值这样才能保证第二天能继续调度。这个约束我也非常推荐加上否则模型会把储能电在最后一个时段全部放光结果看起来“很省”实际完全不合理。第三类柴油机组运行约束出力上下限约束。爬坡约束相邻时段出力变化量不能超过爬坡速率。对柴油机和燃气轮机这类响应速度有限的机组尤其关键。第四类与配电网交互功率约束每个微网从配电网购电、向配电网售电的功率上限。所有微网在同一个配电台区下的总购电功率上限。这个约束是体现“面向配电网”的关键它把各微网调度计划真正耦联在了一起。第五类微网间联络线功率约束每条联络线传输功率在允许范围内。如果输电有损耗可以用一个固定的效率系数来修正简单模型通常忽略这部分。在上面所有约束里我觉得充放电互斥和SOC初末状态一致是两个最经典的大坑。我第一次调试时模型求出来的结果出现大段同时充电和放电当时还以为是求解器问题后来才意识到是对互斥约束处理不当。2.3 参数设计一组可以直接用的示例参数为了方便复现我给出项目中实际使用的一组典型参数。4个微电网编号为MG1到MG4。参数MG1MG2MG3MG4柴油机组额定功率(kW)500400450300储能额定容量(kWh)600500700400储能额定充放电功率(kW)200150220120储能SOC下限/上限0.2 / 0.90.2 / 0.90.15 / 0.90.25 / 0.95光伏装机(kW)300250400200风电装机(kW)1500100200与配电网交互功率上限(kW)500400350450微网间联络线功率上限(kW)200250150180分时电价我采用常见的一般工商业峰谷电价结构峰时段10:00-15:00、18:00-21:00购电电价1.2元/kWh平时段7:00-10:00、15:00-18:00、21:00-23:000.8元/kWh谷时段23:00-次日7:000.4元/kWh。售电电价按上网电价0.45元/kWh统一处理。柴油机单位燃料成本系数按典型柴油机组运行成本折算为出力的一次项系数约0.35元/kWh二次项系数取0.0002元/kWh²。储能运维成本0.03元/kWh柴油机运维成本0.02元/kWh储能老化折旧成本0.1元/kWh。这些参数不一定与某个实际工程完全一致但作为教学示例非常合适。实际工程项目中参数主要来自设备厂家技术说明书、历史运行数据统计以及当地电价文件。3. 基于MATLABYalmip的实现过程3.1 为什么标配是Yalmip和求解器的组合建模求解的方案其实不少可以手写线性规划单纯形法可以直接用MATLAB优化工具箱的linprog可以用CVX也可以用Yalmip。但实际做项目的工程师和学生绝大多数都选Yalmip。原因很直接Yalmip是一个建模层工具箱它把复杂的优化问题用贴近数学公式的方式写出来然后自动转换成求解器能吃的标准形式再调用CPLEX、Gurobi、SCS等底层求解器算出结果。这就好比你用标准SQL写查询语句底层用的是MySQL还是PostgreSQL你不需要过度关心。它最大的价值是快速迭代。我前期探索模型结构时可能一天要改七八版约束如果没有Yalmip这种高级建模工具光是矩阵维度转换就足够让人崩溃。搭配的求解器方面如果装了CPLEX或Gurobi性能最好适合大规模场景。如果用的是MATLAB优化工具箱自带的linprog配合Yalmip也很方便适合中规模问题。如果没有商业求解器Yalmip还支持多种开源求解器如SCS、ECOS、GLPK等小规模教学演示完全够用。我在这个项目里就是用Yalmip建模搭配内点法类求解器求解4个微网24时段的问题规模在几秒内就能算完非常轻量。3.2 决策变量与约束的MATLAB写法下面给出核心代码框架注意这段代码是脱胎于完整项目后的精简示意版本重点展示建模骨架。数据导入方面假设已经有4个微网的负荷、光伏和风电数据存在矩阵里维度都是4×24每个元素表示相应微网在相应时段的功率单位kW。决策变量这样定义% 各微网柴油机出力 P_dg sdpvar(n_MG, T, full); % 储能充电/放电功率 P_ch sdpvar(n_MG, T, full); P_dis sdpvar(n_MG, T, full); % 各微网与配电网的交互功率正为购电负为售电 P_grid sdpvar(n_MG, T, full); % 储能SOC初始SOC为0.5 SOC sdpvar(n_MG, T, full); % 微网间联络线功率L矩阵的每一行表示一条联络线 P_line sdpvar(n_line, T, full);Yalmip中sdpvar就是变量声明函数full表示声明为全变量矩阵这在循环构建约束时会更方便也更接近用户习惯。功率平衡约束的写法如下Constraints []; for t 1:T for i 1:n_MG % 注入功率 本地出力 负荷 充电功率 流出功率 constr P_dg(i,t) P_dis(i,t) P_pv(i,t) P_wt(i,t) ... P_grid(i,t) sum(P_in(i,:,t)) ... P_load(i,t) P_ch(i,t) sum(P_out(i,:,t)); Constraints [Constraints, constr]; end end这里P_in和P_out其实是从P_line根据接线关系映射出来的矩阵表示各微网从其他微网接收到的功率和发送给其他微网的功率。为了清晰在完整代码里会用稀疏矩阵完成这个映射。SOC递推约束写法% SOC递推关系SOC(t1) SOC(t) eta_ch*P_ch(t) - P_dis(t)/eta_dis for i 1:n_MG for t 1:T-1 Constraints [Constraints, SOC(i,t1) SOC(i,t) eta_ch * P_ch(i,t) / Cap(i) ... - P_dis(i,t) / (eta_dis * Cap(i))]; end % 储能SOC上下限 Constraints [Constraints, SOC(i,:) SOC_min(i)]; Constraints [Constraints, SOC(i,:) SOC_max(i)]; % 末时刻SOC恢复初始值 Constraints [Constraints, SOC(i,T) SOC_init(i)]; end充放电互斥约束我用了big-M法处理% 引入二进制变量 u_ch binvar(n_MG, T, full); u_dis binvar(n_MG, T, full); % 充电时不能放电放电时不能充电 for i 1:n_MG for t 1:T Constraints [Constraints, P_ch(i,t) M * u_ch(i,t)]; Constraints [Constraints, P_dis(i,t) M * u_dis(i,t)]; Constraints [Constraints, u_ch(i,t) u_dis(i,t) 1]; end end这里M是足够大的常数通常设为储能额定充放电功率的两倍即可不用取无穷大取值过大会影响数值稳定性这点后面问题排查里会细说。柴油机爬坡约束for i 1:n_MG for t 2:T Constraints [Constraints, ... P_dg(i,t) - P_dg(i,t-1) ramp_up(i)]; Constraints [Constraints, ... P_dg(i,t-1) - P_dg(i,t) ramp_down(i)]; end end目标函数objective 0; % 购电费用 objective objective sum(sum(P_grid_price .* max(P_grid,0))); % 售电收益 objective objective - sum(sum(P_sell_price .* max(-P_grid,0))); % 柴油机燃料成本与运维成本 objective objective sum(sum(a * P_dg b * P_dg.^2)); % 储能老化成本 objective objective sum(sum(c_om * (P_ch P_dis)));注意max函数里面如果有sdpvar表达式Yalmip会把模型转成带辅助变量的形式可能在特定求解器下报错。更稳妥的做法是引入两个非负变量分别表示购电量和售电量用等式约束拆开P_grid这样目标函数里的绝对值、最大值就全部线性化了。然后统一求解options sdpsettings(verbose, 1, solver, quadprog); optimize(Constraints, objective, options); value(P_dg);3.3 从模型到结果求解与可视化求解完成后最重要的就是检查结果合理性而不是急着画图。我一般按照下面几步验证先看最优目标值是不是正常量级。4个微网24小时总运行成本应该在几千到两三万元这个范围。如果算出来是几十万元说明目标函数单位搞错了或者约束被罚得太狠。然后看柴油机出力曲线、储能SOC曲线和联络线功率曲线是否符合物理直觉。峰值电价时段储能应该倾向于放电谷价时段储能应该倾向于充电光伏大发的中午各微网之间应该出现明显的功率互济而不是傻乎乎地各自向配电网买电或卖电。可视化这部分很简单figure; subplot(2,2,1); stairs(1:24, value(P_dg(1,:)), LineWidth, 1.5); xlabel(时段); ylabel(出力功率/kWh); title(MG1柴油机出力);储能SOC曲线subplot(2,2,2); stairs(1:24, value(SOC(1,:)), LineWidth, 1.5); xlabel(时段); ylabel(SOC/pu); title(MG1储能SOC变化);微网之间交互功率可以直接用三维柱状图表示横轴时段、纵轴联络线编号、柱高表示传输功率。还有一个很有价值的对比实验独立调度 vs 联合调度。把微网间的联络线功率全部强制设为0重新求解一次得到每个微网完全独立运行时的总成本。再把允许互济时的总成本拿来对比两者的差额就是多微电网联合调度带来的经济收益。这个数字在项目报告里是最有说服力的一个结论。常见的场景下联合调度能比完全独立运行节省5%-15%的成本具体要看各微网负荷和新能源出力的互补程度。4. 常见问题与排查技巧实录4.1 求不出来、结果不对先查这几个地方做优化项目的人最崩溃的不是模型复杂而是模型报错或者结果诡异怎么都定位不到问题。下面这个表格来源于我实际调试过程中真正遇到过的问题整理成了速查风格。现象可能原因排查和解决办法求解器提示无解约束之间存在矛盾先移除部分约束如SOC末状态约束看是否有解逐步定位冲突约束结果同时充放电未加充放电互斥约束或big-M系数过小检查互斥逻辑增大M或改用两组非负变量拆解目标值为负数售电收益设置过大或约束失效校核售电电价检查约束是否全部生效柴油机出力一直停在最大值爬坡约束或出力上限写错检查求解后的边界条件是否与约束定义一致储能SOC曲线锯齿状充放电功率上限与电量单位不匹配检查功率单位是kW电量单位是kWh换算系数要正确求解时间特别长问题含二进制变量且规模大尽量精简变量数量使用gurobi或cplex这类高性能求解器数据里有NaN或Inf导入的Excel存在空格或空行用isnan或isfinite检查数据补全或剔除矩阵维度不匹配数据行列方向定义一致统一“微网数×时段数”的维度约定4.2 验证模型正确性的三板斧除了直接看图之外我还有三个验证思路可以在提交或汇报前快速确认模型没有逻辑硬伤。第一板斧是退化测试。把“多微电网调度”退化到“单微电网调度”的特殊情形比如把联络线功率的上限设为0那么就回到了各微网独立调度再退一步把储能容量设为0就变成了纯负荷平衡问题。每一步退化结果都应该跟简化模型的数值解或人工计算的简单场景高度吻合。第二板斧是约束松弛检验。如果把某个约束放开目标值应该只可能变好不可能变差。比如放开储能SOC上下限约束后总成本应该下降。如果发现约束放开后成本反而上升那就说明目标函数或约束中存在方向性错误。第三板斧是最优性条件复核。对于小型案例可以用枚举法或穷举法手算验证看最优解是否真的满足所有约束条件且成本最低。这虽然是“笨办法”但却是验证线性规划模型最可靠的手段。4.3 提升求解性能的三个习惯实际工程问题往往不止4个微网可能是10个甚至更多。我在把项目扩展到8个微网、96个时段时遇到了明显的求解性能瓶颈。总结下来有三个习惯能够显著改善体验第一个习惯是优先使用线性约束。能用线性表达的约束不要用非线性。很多同学在处理功率平衡时为了图省事写了“乘积”或者“max”函数这在Yalmip中会自动引入辅助变量甚至把你推向非线性求解器性能直接掉一个档次。我的经验是把P_grid拆成正购电P_buy和负售电P_sell两个非负变量所有地方都用这两个变量的线性组合模型清爽又高效。第二个习惯是把常数计算下沉到矩阵层面。不要在每个时段循环里写复杂的表达式提前在矩阵里算好。比如分时电价矩阵、每时刻的光伏容量系数、联络线拓扑数组都在数据预处理阶段生成约束循环里只做矩阵运算和索引速度提升非常明显。第三个习惯是合理控制二进制变量数量。充放电互斥确实需要0-1变量但对于连续型储能模型也可以先用SOC变化方向决定充放电通过合理的目标函数引导系统不会烯意同时充放。这属于模型降维思路详细细节可以在做大规模系统时再研究。5. 从基础调度到进阶可以怎么扩展5.1 加入碳交易与环保目标很多课题现在已经把碳中和纳入优化目标了。扩展的思路很简单在目标函数中加入碳排放成本的线性项柴油机的碳排放因子乘以出力就是碳排放量再引入碳配额约束系统总碳排放不能超过配额超出部分要在碳市场购买配额。代码上只需要增加一个约束和一个成本项非常轻量但是模型就从纯经济调度变成了“经济-碳”多目标问题。如果想进一步做多目标优化可以同时计算“最低成本”和“最低碳排放”两个极端方案得到帕累托前沿然后用加权法或者ε-约束法选取折中方案。这是论文中非常经典的分析框架。5.2 考虑不确定性从确定性问题到鲁棒优化我前面的模型假设光伏和负荷是已知的但真实系统里它们有很强的随机性。最直接的扩展是做随机场景法生成大量光伏和负荷场景每个场景有出现概率目标函数变成期望成本最小化。更稳妥的做法是鲁棒优化把光伏出力看作不确定参数取值范围在预测值的上下浮动区间内目标是保证在最恶劣场景下系统仍然安全且成本可控。这样做出来的调度计划抗风险能力很强但模型复杂度显著上升需要列和约束生成算法来求解篇幅上够再写一篇长文了。5.3 从集中式调度走向分布式算法多微电网优化调度天然适合分布式求解。因为每个微电网都有自己的自治需求如果把所有数据都集中到中央调度中心不仅通信成本高而且有隐私问题。比较热门的方案是ADMM交替方向乘子法把原来的全局目标分解为各微网自己的局部问题通过迭代交换边界变量如交互功率和电价信号达成一致。我在扩展版本中用ADMM实现了4个微网的分布式调度收敛结果与集中式求解基本一致这个过程的核心是企业微信、飞书之类的协同工具无法替代的需要你真正把每一次迭代的更新公式写清楚。不过要提醒一点如果你连集中式都没跑通千万不要先去碰分布式。先保证Yalmip模型和集中式调度结果是正确的、可解释的再考虑分解和迭代否则光分解步骤里的符号定义就够让人混乱好几天。结尾在整个复现和调试过程中我最深刻的一个体会就是多微电网优化调度这类项目真正的难点从来不在MATLAB语法本身而在模型逻辑。Yalmip确实省去了大量低级的矩阵构建工作但它并不会帮你判断“SOC初末状态一致性是否该加”、“微网间联络线功率方向会不会搞反”、“充放电互斥到底需不需要显式约束”这些判断必须建立在透彻理解物理过程的基础上。所以我特别推荐一个稳妥的实践路径先拿2个微电网、6个时段的小例子手写出所有约束和预期结果再用代码复现逐行验证全部跑通后再扩大到4个微网24小时甚至96时段。你会在一步步扩大的过程里真正明白哪些约束是决定性的哪些其实可以适当简化。我当初就是急着一步到位结果在8个微网96时段的大模型里调试了整整两天最后发现只是最早的小例子时期已经犯过的一个约束方向错误。如果早点做小规模验证半天就能完事。如果你想在现有代码基础上继续扩展我建议优先做两件事一是把分时电价改成实时电价观察储能策略变化二是做一次灵敏度分析把光伏渗透率从20%逐步提高到80%记录总成本和配电网购电功率的变化曲线。这两组图放在任何报告或论文里都是非常有说服力的结果。
网站建设高端定制企业官网