
两阶段鲁棒优化做微电网经济调度是这些年学术界和工程界都绕不开的方向。原因很简单光伏和负荷的预测误差躲不掉而传统确定性调度一遇到实际偏差就得重新算甚至会出现切负荷或者弃光这种被迫操作。我这次分享的是一个升级优化版本也就是在经典两阶段鲁棒框架上把微网与外部电网的电力调控策略、储能退化成本约束、以及滚动时域修正思路都整合进去了代码用Matlab实现求解侧走YALMIPCPLEX或Gurobi。如果你正在做微电网日前调度、或者准备参加类似的数学建模竞赛这篇内容应该能帮你省掉不少搭框架的时间。1. 项目背景与核心问题拆解先把问题说清楚微电网经济调度本质上是一个“在不确定性环境下如何制定发用电计划使得总成本最低”的优化问题。它和普通的电力系统经济调度最大的区别在于微电网的规模小、惯性小、调节手段有限光伏出力和负荷需求的预测误差对系统的影响会被放大。你今天早上预测中午光伏能发500千瓦结果到了中午一片云飘过来实际出力掉到250千瓦这时候如果调度方案没有预留足够的上调能力就容易出问题。行业内解决这个问题的思路有这么几条确定性优化、随机规划、鲁棒优化、以及模型预测控制。其中确定性优化最简单但缺点是抗扰动能力差随机规划需要提前知道预测误差的概率分布而且计算量很大鲁棒优化则是在“最坏情况”下做决策保证方案在预定义的误差范围内都可行。两阶段鲁棒优化是鲁棒优化的一种进阶形式它把决策拆成两个阶段第一阶段做“现在必须拍板”的决定比如机组启停、与外部电网的购售电计划第二阶段则等到不确定参数的实际值部分暴露后再做“调整性”决策比如储能充放电功率、柴油机出力、弃光弃风量等。标题里提到的[3]我理解指的是参考了某一类典型文献的处理方式通常是采用了盒式不确定集加预算约束的经典建模思路。升级优化版本则是在这基础上做了几个关键改动我会在后面的章节逐个展开。这套方法能解决什么问题简单说就是让你在不知道光伏实际出力、负荷实际大小的情况下依然能拿出一个“不管怎么变都不会翻车”的调度计划而且这个计划的成本不会比确定性方案高太多。2. 两阶段鲁棒优化的原理与模型构建2.1 为什么“两阶段”比“单阶段”更贴合实际调度很多刚接触鲁棒优化的同学会问一个问题既然鲁棒优化是考虑最坏情况为什么还要分两个阶段直接一个阶段把所有变量都优化了不就行了吗这里的关键在于有些决策是必须在不确定性发生之前就做出的而有些决策是可以等不确定性稍微明朗以后再调整的。单阶段鲁棒优化把所有决策都按“事前决策”来处理结果往往过于保守——为了应对最坏情况把储能充满、把柴油机开到最大出力成本高得离谱。两阶段结构的核心思想是“先承诺后调整”。以微电网调度为例日前阶段第一阶段需要确定的是明天每个时段是否启动柴油机、与外部电网的购售电功率基准值、储能的目标荷电状态等。这些决策的特点是响应慢、约束强、一旦定了就很难改。而日内阶段第二阶段需要确定的是在给定第一阶段的决策后面对实际的光伏出力和负荷需求储能的实际充放电功率、柴油机出力的修正量、弃光弃风量的切分等。这些决策可以在短时间内灵活调整用来吸收不确定性带来的偏差。这种“主问题子问题”的结构在数学表达上对应的是一个min-max-min三层优化问题。外层min是第一阶段成本中间max是找最坏情况下的不确定参数内层min是在最坏情况下的运行调整成本。这个结构和现实中的调度流程非常吻合也因此成为近年来的主流建模方式。2.2 不确定集的设计从“无限可能”到“有限对抗”两阶段鲁棒优化的核心之一是不确定集的构建。所谓不确定集就是把光伏出力和负荷需求的可能取值限制在一个合理的范围内。最常见的做法是盒式不确定集也就是给每个时段的预测值加上一个上下波动区间比如光伏预测为300千瓦波动幅度为正负20%那不确定集内的取值范围就是[240, 360]千瓦。但这种盒式集合假设所有时段的不确定参数同时达到最大值或最小值结果依然偏保守——实际中不可能一整天24个时段的光伏误差全都在边界上。所以升级版本里我采用了带预算约束的盒式不确定集。预算值用来限制“最坏情况出现的时段总数”比如说24个时段里最多有6个时段会同时达到波动边界其他时段的不确定程度相对温和。这种处理方式在文献中非常成熟它能够在不牺牲太多鲁棒性的前提下显著降低调度方案的保守性。预算值的取值通常可以取总时段数的15%到30%具体数值可以通过历史数据的误差统计来确定。在实际Matlab代码中不确定集的定义方式会直接影响后面子问题的对偶转化。我建议你在建模时就明确区分哪些变量属于不确定参数哪些属于决策变量这样后续对偶或者使用CG列与约束生成算法时会顺畅很多。2.3 目标函数与约束条件的升级点升级优化版本的模型目标函数在我的项目中分为三个主要部分第一阶段固定成本、第二阶段运行成本、以及与外部电网交互的惩罚项。第一部分包括柴油机的启动成本和最小运行时间带来的附加成本第二部分包括燃料成本、储能充放电损耗成本、以及弃光弃风成本第三部分则是和外部电网购售电的功率费用。储能退化成本是我在这版升级中特意加入的。传统调度模型往往只考虑储能充放电的效率损耗忽略了实际循环次数增加会缩短电池寿命这一事实。升级版本中我引入了一个以吞吐量为基础的退化惩罚项当储能在某一天的充放电吞吐量超过预设阈值时超出部分会按照一个更高的成本系数计入目标函数。这样在优化结果中储能不能被无节制地充放整体调度策略会更加贴近工程实际。3. 系统架构与升级优化点解析3.1 微电网物理架构与调度层级在展开代码之前先把系统架构梳理一遍。这个升级版本面向的是一个典型的交流微电网包含以下组成部分光伏发电单元、储能系统磷酸铁锂电池进行能量存储、柴油发电机作为可调电源、本地负荷以及与外部配电网的连接点。调度层级分为日前调度层和日内调整层日前调度层基于预测数据生成基准计划日内调整层则根据实际运行数据进行修正。标题相关热词里频繁提到“微网与外部电网电力调控策略”这部分在模型中的体现就是购售电功率变量。需要注意的是与外部电网交互的功率通常有上限约束而且分时电价下购售电价格不同。在升级版本中我添加了买卖功率不能同时大于零的约束避免模型在结算时通过“低价买高价卖”套利这在物理上是不允许的。3.2 从确定性模型到鲁棒模型的升级路径如果你手头已经有一个确定性的微电网调度代码怎么把它升级成两阶段鲁棒版本我总结下来有这么几个步骤第一步识别哪些约束中包含不确定参数。通常是光伏出力平衡等式和负荷平衡等式。第二步把包含不确定参数的约束和确定性约束分离确定哪些变量进第一阶段、哪些进第二阶段。第三步构建不确定集并确定预算约束。第四步把原问题改写为主问题-子问题结构。第五步编程实现CG迭代算法利用对偶或KKT条件处理内层的min问题。升级过程中最容易被忽略的是“非预期约束”。两阶段模型中第一阶段决策不能依赖于未来不确定参数的实现值这个隐含约束必须通过模型结构来保证。在CG算法中每次迭代生成的极端场景对应的子问题解会被作为新约束加入主问题这个过程天然保证了第一阶段决策的鲁棒性——但前提是你不能把第二阶段子问题的解直接“泄漏”到主问题的约束里否则求解结果就会失真。3.3 本版本相比常规两阶段鲁棒的3个改进点第一引入了滚动时域修正模块。这不是在线MPC那种秒级滚动而是以小时为周期的“慢滚动”——每运行完一个调度时段就把最新的实测数据代回未完成的计划中重新优化剩余时段。这样做的好处是能实时修正预测偏差的累积效应。第二增加了储能退化成本的非线性分段线性化处理。电池退化成本本质上是一个非线性函数但为了能用MILP求解我采用分段线性逼近的方式把它转化为线性约束这样整个模型还能保持混合整数线性规划形式可以直接用CPLEX或Gurobi求解。第三设置了面向求解器友好性的约束聚合。微电网模型最怕出现大量Big-M约束导致的松弛问题我把部分取值范围约束转化为等价的逻辑约束减少了Big-M变量的数量迭代求解速度能提升不少。4. Matlab代码实现完整流程4.1 代码结构总览整个项目的Matlab代码文件组织结构大概是这样主文件、数据文件、模型构建函数、求解函数、结果可视化脚本。主文件负责设置参数、调用函数、输出结果。数据文件以结构体形式存放所有输入参数包括各时段预测值、波动范围、电价值、储能参数等。模型构建函数基于YALMIP建模语言实现把主问题和子问题的约束写清楚求解函数负责调用CPLEX或Gurobi求解器。我用的是YALMIPR2023bCPLEX的搭配。YALMIP是一个Matlab下的免费建模工具安装起来很方便它能把优化问题翻译成求解器能理解的格式。如果你手头没有CPLEX也可以用Gurobi甚至在部分场景下直接用Matlab内置的intlinprog也能跑只是规模大的时候求解速度会明显变慢。4.2 主问题建模代码要点主问题是原问题的松弛版本包含第一阶段决策变量和所有确定性约束。在YALMIP中这个部分通常用类似的代码结构搭建。第一阶段决策变量中机组启停状态是二进制变量其余如购售电功率和储能基准功率是连续变量。约束包括功率平衡、机组出力上下限、储能容量约束、与外部电网交互功率限制、线路潮流约束等。主问题每次迭代后都会新增一组与极端场景相关的约束这些约束的系数来自子问题返回的极端场景中的不确定性参数。代码实现时我建议用一个循环来动态拼接这些新增约束并在每次迭代结束后清空旧约束重新构建主问题。这个操作在YALMIP中并不复杂时间复杂度也很低。4.3 子问题建模与对偶处理子问题的本质是给定第一阶段决策和不确定参数后求解最坏情况下的运行成本最小值。这个内层是一个min问题外层对不确定参数取max。常见的处理方式是先对min部分取其拉格朗日对偶把内层min转化为对偶问题的max这样整个子问题就变成一个纯最大化问题直接把目标函数中的max-min嵌套处理掉了。在实际代码中子问题的求解步骤可以拆成首先固定第一阶段决策变量其次把内层优化问题的约束写成标准形式然后利用对偶理论写出其对偶问题最后整体求解时的目标函数就是对外层max变量的优化结果。需要特别提醒的是如果模型中含有二进制变量那么对偶转化会比较麻烦因为对偶理论在线性规划中成立的前提是原问题本身是连续的线性规划。因此在设计子问题时尽量避免在其中放置二进制变量如果确有需要通常的做法是把二进制变量连同第一阶段决策一起放到主问题中。4.4 CG迭代算法核心逻辑CG列与约束生成算法是求解两阶段鲁棒优化问题的主流方法。它的核心思路是不断在主问题中加入与极端场景相关的变量和约束逐步逼近最优解。具体迭代流程是初始化阶段先给定一个任意可行解然后求解子问题得到最坏场景下的运行成本和对应场景变量如果新增的约束和变量改变了主问题的最优解则把该子问题的场景变量和约束加入主问题重新求解如此反复直到上下界差满足收敛阈值。我在迭代循环中设定了两个终止条件一是上下界的相对误差小于0.01%二是最大迭代次数不超过15次。从实测数据来看大多数算例在5到8次迭代内就能收敛效率还是令人满意的。整个循环过程的Matlab实现并不复杂关键在于把场景索引和变量维度的对应关系处理好。5. 核心参数配置与调试经验5.1 不确定集与预算值的设定预算值的选择对调度结果的保守性影响很大。我做过一个简单的敏感性分析当预算值从0增加到12时第一阶段的总成本上升了约8%但第二阶段的最坏情况成本下降了约15%。这说明适当增加预算值能显著提升鲁棒性但代价是预安排成本升高。如何选预算值我建议从历史预测误差数据中统计出“实际误差超过预测值20%的时段比例”以此来标定预算值的取值范围。5.2 求解器参数与性能调优在求解器的参数设置上我建议开启CPLEX或Gurobi的MIP gap控制。对于微电网调度这类规模适中的模型设定MIP gap为0.1%以及开启并行求解是一个稳健的选择。另外要防止出现数值问题尤其是约束间的数量级差异较大时功率量级可能到几百千瓦电价却只有零点几元。这种情况下可以给所有功率相关的变量乘一个统一的缩放因子比如全部转换为以兆瓦为单位否则求解器在计算对偶问题时容易出现数值病态。5.3 结果可视化与调度曲线展示调度结果的输出我一般会画四张图第一张是光伏预测值与实际值的对比曲线第二张是储能SOC随时间的演变曲线第三张是柴油机出力和购售电功率的堆叠柱状图第四张是总运行成本的累积曲线。这些图对验证模型行为很有帮助。比如如果你发现储能的SOC曲线在一天之内频繁触顶或触及下限这通常说明储能容量约束设置得不合理或者退化的惩罚系数太小导致储能被过度利用。6. 常见问题与排查技巧实录6.1 求解时间过长或无法收敛这个问题的出现频率最高。原因通常有三类第一类是不确定集的规模太大导致子问题的变量和约束数量过多。修复的方法是通过预算约束的松紧来控制不确定参数的组合数量或者把24个时段的不确定参数按4个时段为一组进行聚合减少子问题的计算规模。第二类是Big-M参数选取不合理导致求解器在线性松弛阶段浪费太多时间。第三类是MIP gap设置过严适当放宽至0.5%可以显著加速求解。6.2 子问题对偶转换出错子问题对偶转换是最容易写错的地方尤其是当模型中有等式约束时对偶变量没有符号限制容易在处理时搞混。一个实用的排查方法是将对偶问题的目标函数值与原问题的目标函数值进行对比如果两者不一致检查原问题是否有冗余约束或不可行约束。另外强烈建议在编写子问题代码前先在一个简化模型上手工验证一次KKT条件的正确性而不是直接在大模型上调试。6.3 鲁棒解过于保守如果你发现鲁棒优化得到的调度方案成本比确定性方案高出50%以上大概率是不确定集设计得太“宽”了。可以把盒式区间的波动幅度从正负30%缩小到正负15%同时适度降低预算值。还有一种情况是储能容量配置不足导致系统缺乏足够的调节能力来应对不确定性这时在目标函数中增加对储能退化成本的惩罚反而有助于让储能留有更多应对不确定性的空间。6.4 YALMIP报“无法识别运算符”错误这类错误在升级版本中经常出现原因是使用了一些求解器不支持的运算操作比如非线性函数的直接调用。YALMIP本身支持很多非线性表达式但CPLEX和Gurobi作为MILP求解器并不支持非线性约束。如果出现这种提示检查是否存在指数函数、绝对值函数或变量相乘的表达式。我的做法是用分段线性化工具或引入辅助变量来重构这些约束。7. 从鲁棒优化到滚动时域调度的扩展思考最后再聊聊扩展性。两阶段鲁棒优化虽然解决了不少问题但它本质上仍然是一种“开环”的调度方式也就是说日前制定完计划后日内不会根据实测数据对后续时段进行修正。解决这个问题的方法是引入模型预测控制的思路在日内的每个采样周期内用最新实测数据更新预测值并基于当前状态重新求解一个短时域的两阶段鲁棒模型只执行第一个时段的决策。这正是相关热词中“滚动时域”的含义。我目前的做法是在鲁棒优化的最外层套一个滚动时域循环每个循环求解一个时间窗口为6小时的鲁棒模型执行第一个小时的调度指令后进入下一个循环。实测效果非常明显原本开环模式下下午时段储能容量被耗尽的情况明显减少系统应对光伏波动性的灵活度更高。代价是计算时间增加了但配合高效的求解器配置完全可以在可接受的范围内运行。这个方向后续还可以继续扩展比如把电动汽车充放电、冷热电联供都纳入模型对应的问题规模会更大但也更有工程价值。如果你是自己做毕业设计或者科研实验我建议先跑通这个两阶段鲁棒版本掌握CG迭代的核心逻辑再往滚动时域或MPC方向延伸会顺很多。