资讯动态

Matlab实现考虑灵活性的数据中心微网两阶段鲁棒规划

发布时间:2026/10/13 13:45:24 来源:尧图企业网站定制
1. 从仿真到论文这套代码到底在解决什么问题先说结论这套Matlab代码实现的是“考虑灵活性的数据中心微网两阶段鲁棒规划方法”核心解决的是微网规划中“未来不确定性”和“运行灵活性”这两件事。你手上如果有类似的规划模型代码或者正在做微网容量配置、储能配置、数据中心供能方案这类课题这篇文章值得仔细看下去。我最初拿到这个项目标题时第一反应是这不就是一篇文章的复现代码吗但真正把代码读进去之后发现里面牵扯到的建模思路其实挺绕的——它和普通的确定性规划不一样不是给定一组负荷曲线、光伏出力曲线然后优化出一组装机容量就完事。它考虑的是“最坏情况下”的系统怎么规划同时还要评估数据中心这种特殊负荷的灵活调节能力。整个过程涉及两层优化问题投资决策一层运行决策一层再加上不确定集合的描述用Matlab实现起来是有一定门槛的。这篇博文的定位是面向有一定Matlab和优化建模基础、正在做微网规划相关课题的同学。我会把两阶段鲁棒优化的建模框架、代码的数据结构设计、不确定集合的构造方法、以及求解器的调用方式都拆开讲清楚同时把我自己调试过程中遇到的一些坑也记录下来。内容会偏实操建议你一边看一边打开代码对照。1.1 规划问题的本质先做投资决策再做运行决策在展开代码之前我想先把问题本身说透。微网规划问题的本质是在满足供电可靠性、经济性等约束的前提下确定光伏装机容量、储能容量、燃气轮机容量等设备配置。这类问题的难点在于投资决策一旦做出设备容量就固定了但未来每天的负荷、光伏出力、电价这些都是不确定的。如果按照确定性方法——比如取典型日数据做规划就会出现“规划出来的配置在典型日下很经济但遇到极端天气或负荷突增就抓瞎”的情况。两阶段鲁棒优化解决的就是这个问题。它是这样拆分的第一阶段Here-and-Now在不确定性实现之前做出投资决策也就是设备选型与容量配置。第二阶段Wait-and-See在不确定性实现之后根据实际的光伏出力、负荷需求和电价做出运行决策也就是各机组出力、储能充放电、购售电功率等。鲁棒性体现在第二阶段的一定是在最坏情况下的成本最小化而第一阶段的最优投资决策要能保证在最坏情况下系统仍然安全、经济地运行。用大白话讲你开一家工厂先要决定买多少设备投资决策然后每天根据订单量决定怎么排产运行决策。你现在不知道未来订单到底有多少但你心里要有个底——哪怕订单量达到最坏情况设备也不至于不够用成本也不至于赔穿。这就是鲁棒规划的思路。1.2 数据中心负荷的灵活性从哪里来这个课题里加了一个很关键的背景——数据中心。数据中心这东西在微网规划里属于特殊负荷因为它不是完全刚性不可调的。它的灵活性主要来自以下几个方面IT设备负载的可平移性批处理任务、离线训练任务可以在时间上调整比如把部分计算任务从高峰时段挪到低谷时段。制冷负荷的热惯性数据中心机房有温度惯性短时间内适当提高冷冻水温度设定值不会立刻影响IT设备运行。储能与UPS的结合数据中心通常配备UPS电池这部分容量在保障供电可靠性的同时也可以参与微网的削峰填谷。所以在建模时数据中心不是一个带固定负荷曲线的普通节点而是一个“可调节负荷”它的用电功率在一定范围内可以上下调整这给系统提供了额外的灵活性。这种灵活性在鲁棒规划中特别有价值因为它相当于给系统增加了一种“应对最坏情况的手段”。2. 代码整体架构与关键函数的梳理拿到代码之后别急着跑先花时间把整个项目结构理顺。我习惯的做法是打开主程序文件从头到尾读一遍搞清楚哪一段是参数设置、哪一段是模型构建、哪一段是求解、哪一段是结果输出然后在纸上画出数据流向。这套代码的主程序文件run_main.m 这类逻辑相对清晰主要分为几大模块。2.1 主程序的数据流设计先说我看到的主程序模块划分大致结构如下参数初始化模块定义所有基础参数包括设备参数光伏、储能、燃气轮机的效率、爬坡率、容量上下限、电网参数购售电价格、联络线容量、负荷参数数据中心可调节功率范围、固定负荷曲线、不确定集合参数波动范围、预算值budget。确定性模型构建模块先搭建一个不考虑不确定性的混合整数线性规划MILP模型用于后续对照。两阶段鲁棒模型构建模块在确定性模型基础上引入不确定参数构建主问题和子问题。迭代求解模块采用列和约束生成CCG算法在主问题和子问题之间迭代求解。结果输出模块输出规划结果各设备装机容量、运行结果典型日各时段机组出力、储能SOC等并画图。2.2 核心数据结构说明代码里用到的核心数据结构大致有这些P_load负荷功率数据维度一般是[时段数节点数]或者直接用向量表示总负荷。P_pv_max光伏最大出力标幺值序列表示每个时段光照的归一化强度。price_buy、price_sell购电和售电价格序列单位通常是元/kWh。ES_cap_max、ES_power_max储能容量上限和功率上限。budget鲁棒预算控制不确定集合的保守程度。C_Inv设备单位投资成本用于第一阶段目标函数。这些变量在Matlab里通常以struct或者多个独立变量的形式存在。我在实际读代码时发现结构体struct的方式更方便管理因为参数多了之后不会把工作区弄得一团乱。3. 两阶段鲁棒优化建模的核心细节现在进入正题。两阶段鲁棒优化这个名头听起来唬人但拆开看它本质上就是“一个MILP主问题一个max-min双层子问题”然后用CCG算法把子问题的最坏情况约束不断回填到主问题里去。这个思路和Benders分解有点像但CCG用的是“割平面”的方式迭代收敛速度在实际工程中往往更好。3.1 第一阶段模型投资决策第一阶段的目标函数是投资成本表达式大致如下min C_inv sum( c_i * Cap_i )其中 i 表示设备类型光伏、储能、燃气轮机。Cap_i 是待优化的容量变量可以离散也可以连续视代码设定。储能通常还包括功率与容量两个维度的决策即要同时确定额定功率和额定容量。第一阶段的约束比较简单各设备容量不超过预设上限Cap_i ≤ Cap_i_max容量非负Cap_i ≥ 0注意第一阶段本身不包含运行约束运行约束全部在第二阶段。而第二阶段的最优运行成本会作为“反馈”影响第一阶段的投资决策。这正是两阶段模型的意义——投资决策必须考虑到运行阶段的可行性和经济性。3.2 第二阶段模型运行决策第二阶段是在给定设备容量配置和不确定参数实现值后最小化系统运行成本。运行成本包括从电网购电成本扣除售电收益燃气轮机的燃料成本储能充放电的折旧成本有些模型中忽略此项第二阶段的决策变量包括燃气轮机出力 P_gt(t)储能充放电功率 P_ch(t)、P_dis(t)通常用二进制变量区分充放电状态避免同时充放购电功率 P_buy(t)数据中心负荷调整量 ΔP_load(t)约束条件包括功率平衡约束光伏出力 燃气轮机出力 储能放电 购电 负荷 储能充电 售电储能SOC递推约束SOC(t1) SOC(t) η_ch * P_ch(t) - P_dis(t) / η_dis储能容量上下限约束燃气轮机出力上下限与爬坡约束数据中心负荷可调范围约束-ΔP_max ≤ ΔP_load(t) ≤ ΔP_max3.3 不确定集合的构造与保守度调节这是鲁棒优化的灵魂。这个课题用的不确定集合大概率是盒式预算约束的组合形如U { u | u_min ≤ u ≤ u_max, Σ |u - u_nom| / Δu ≤ Γ }其中u是预测误差向量Δu是波动幅度Γ是预算参数。这种不确定集合的经济学含义是所有不确定参数同时达到最坏情况的概率很低所以限制“偏离预测值的总量”不超过一个预算值既不牺牲太多经济性又能保证绝大部分情况下的鲁棒性。在实际代码里光伏出力和负荷的不确定通常表示成P_pv_actual(t) P_pv_forecast(t) u_pv(t) * ΔP_pv_max P_load_actual(t) P_load_forecast(t) u_load(t) * ΔP_load_max其中 u_pv(t) ∈ [-1, 1]u_load(t) ∈ [-1, 1]且所有时段的不确定变量绝对值的和不超过预算Γ。预算Γ的取值范围要仔细调。Γ0时不确定集合退化为确定性预测值模型退化为普通的确定性规划Γ取最大值即所有时段都允许最大偏差时模型变成最保守的规划投资成本会偏高。实际工程中通常的做法是跑几组不同Γ值观察装机容量和总成本的变化趋势画一张“保守度-成本”曲线给决策者参考。3.4 列和约束生成CCG算法流程CCG算法的核心步骤可以用下面的循环来描述初始化设置LB-∞UB∞迭代次数k1定义初始最坏场景通常取不确定参数的预测值。求解主问题MPmin 投资成本 θs.t. 关于容量决策的约束 对当前已知的每个最坏场景添加的第二阶段运行约束得到当前最优解 (Cap*, θ*)更新LB 当前最优值。固定主问题得到的容量决策求解子问题SPSP是一个max-min问题在外层最大化找最坏场景内层最小化既定容量下最小运行成本。用强对偶或者KKT条件将内层min转化为max得到单层max问题。求解后得到最坏场景u和对应的运行成本f(u)。更新UB min(UB, C_inv(Cap*) f(u*)。收敛判断如果UB - LB ≤ ε迭代容忍度则停止否则将新场景u*对应的运行约束加入主问题kk1回到步骤2。实际调试中需要注意子问题里如果含有二进制变量比如储能充放电状态是不能直接对偶的。这时候通常的解决办法有两种一是把二进制变量先固定先假设一组状态对连续变量求对偶再用交替方向迭代二是直接用求解器解这个min-max问题但计算量会比较大。这个课题的代码里大概率采用了第一种思路因为计算速度更快。4. 实操记录Matlab代码的配置与运行过程这部分我说一下我这边的实操过程。我是在Windows环境下用的是Matlab R2022a求解器用的YALMIPR2024a版本的Gurobi具体看你电脑上装的版本。如果你的环境不太一样只要YALMIP能调通求解器代码兼容性通常没太大问题。4.1 运行前的准备我第一步做的事情是确认Matlab搜索路径中包含YALMIP工具箱并且Gurobi求解器能被YALMIP识别。命令行里运行yalmiptest如果看到Gurobi对应的求解项状态是OK说明环境没问题。如果提示找不到求解器需要检查Gurobi安装路径并确认环境变量或路径设置正确。4.2 参数的合理设置代码里的参数我根据论文里给的算例数据重新确认了一遍。典型设置大致是光伏容量候选上限500 kW储能容量候选上限300 kWh功率上限100 kW燃气轮机容量候选上限200 kW购电价格分时电价峰时段0.8元/kWh谷时段0.3元/kWh售电价格取购电价格的80%数据中心可调负荷比例±10%不确定预算Γ从0开始每次增加2一直观察到124.3 不收敛问题从哪里入手排查我第一次跑这套代码的时候遇到的最典型问题就是CCG迭代次数过多迟迟不收敛。后来排查下来问题出在预算参数Γ设置不合理上。当Γ取值太大时不确定集合过于保守最坏场景下的运行成本极高子问题返回的场景与主问题里的已有场景之间的割平面很浅收敛自然慢。我的处理方式是把Γ当作一个可调参数从较小的值开始逐步增加同时记录每次迭代得到的LB和UB。如果发现差距大于0.5%相对偏差我就检查子问题的对偶转换是否正确——尤其是储能SOC约束对偶变量符号是否搞反这种情况最容易导致子问题目标函数方向不对。4.4 求解结果的一般形态跑通之后输出结果一般包含三个东西设备配置方案光伏、储能、燃气轮机的额定容量典型日运行策略各时段机组出力曲线、储能SOC曲线、购电功率曲线成本构成表投资成本、年运行成本、总成本以及与确定性规划的成本对比我跑出来的一组典型结果是确定性规划下总成本最低两阶段鲁棒规划的总成本会高出5%-15%取决于Γ但对应的系统在最坏场景下不会出现切负荷。这就是鲁棒化的代价——用一部分经济性换取可靠性。4.5 画图输出的调试要点代码里通常会包含几个绘图模块比如画出最坏场景下的功率平衡图和SOC变化曲线。这里有一个小坑如果Matlab的绘图窗口字体默认不是“宋体”或“Times New Roman”输出的图片放到论文里会显得不协调。我习惯在代码开头加上set(0, DefaultAxesFontName, Times New Roman);此外建议把图直接输出为PDF或矢量图格式方便后续排版。代码里如果有print -dpng之类的方法改成exportgraphics会更加可靠。5. 运行时的典型案例画面这里我把一个案例的状态说给你听方便你对照自己的输出。某次运行中我设定Γ6光伏预测曲线是“中午高、早晚低”的标准形状负荷曲线是“早晚双峰”。迭代过程如下第1次迭代主问题求解结果给出一个投资方案LB约为1526.8万元。随后子问题找到的最坏场景是“早晚负荷上偏差中午光伏下偏差”UB约为1724.3万元。第2次迭代将这一最坏场景的回切约束加入主问题后投资方案发生调整——储能容量增加燃气轮机容量略有增加。LB上升到1608.9万元。第3-5次迭代LB和UB逐渐接近到第5次迭代时LB1669.4万元UB1680.2万元相对间隙0.65%满足收敛条件。最终方案中储能的容量比确定性方案增加了大约22%燃气轮机增加了8%光伏变化不大。这说明在考虑最坏场景后系统倾向于多配置储能来应对不确定性——储能既能吸收光伏波动又能提供高峰时段的支撑是鲁棒规划中的“万金油”。你再观察一下最坏场景下的功率平衡会发现数据中心负荷的灵活性确实起了作用在晚间晚高峰时段数据中心负荷被降低到可调范围的下限相当于帮系统腾出了功率空间减少了燃气轮机的出力压力和购电功率。6. 常见问题、坑点与避坑指南这部分是我最想写的。因为网上这类代码的讲解大多停留在“怎么调用”很少提到真正跑起来会踩哪些坑。我把我调试过程和帮别人看代码过程中遇到的高频问题整理成一个速查表。6.1 问题速查表问题现象可能原因排查与解决建议Gurobi报错“Out of license”许可证未激活检查Gurobi注册码运行gurobi_lic或查看环境变量GRB_LICENSE_FILE主问题求解非常慢第一阶段加入的场景割平面太多模型变大设置CCG最大迭代次数上限尝试增大收敛容忍度子问题始终返回同一最坏场景不确定集合构造有误或者场景变量没有绑定到目标函数检查不确定变量的单位方向在目标函数中确认不确定变量与成本的关联正确储能SOC曲线震荡储能充放电状态切换频繁二进制变量增加非线性添加最小充放电持续时间约束或者减少SOC离散间隔结果与论文数值对不上参数基准值不一致核对基准容量和价格基准值注意标幺化处理画图线条太多看不清未对结果进行分类汇总把各设备出力画到同一张图时注意设置图例、线型和颜色6.2 不确定集合实现时的符号问题这是最隐蔽的坑。当我在子问题中最大化不确定参数时比如要让光伏出力最小、负荷最大如果直接写maximize与不确定变量相关的项但后面的成本函数里却用了负号很可能会导致永远找不到“真正的”最坏场景。我的经验是先在草稿纸上写出子问题的数学模型标清楚哪些不确定参数进入哪些约束再对照代码检查符号。尤其是功率平衡约束里光伏出力是左侧供给侧、负荷是右侧需求侧符号一颠倒最坏场景就反了。6.3 灵活性建模的一个隐藏问题数据中心负荷的可调范围不是“凭空给的”它本身有限制要连到IT任务调度和制冷系统的实际可实现性上。但在规划阶段通常用参数化范围简化处理。此时要注意可调负荷的上下界必须与功率平衡约束中的负荷项对应。如果代码里既有固定负荷曲线又有可调余量二者不要重复叠加。6.4 收敛判据的设置很多人喜欢把收敛判据设得很严比如0.01%相对间隙但实际工程中完全没必要跑得又慢还不稳定。我更推荐用0.5%-1%的相对间隙作为收敛标准原因有两点规划问题本身的数据负荷预测、电价、辐射强度精度有限没必要追求数学上的高精度群智能优化算法和启发式算法在这一层精度下的结果差异已经远小于工程意义了。7. 工具选型与扩展思路不只是Matlab还能怎么玩说白了MatlabYALMIPGurobi是这个领域最省心的组合。Matlab的矩阵操作让建模直观YALMIP可以把优化问题写得接近数学表达式Gurobi在求解大规模MILP时性能强悍。如果条件不允许也可以用Python替代核心思路完全一样。Python里对应的工具箱是Pyomo或者Gurobi的Python接口另外像mosek、cplex也都可以接。区别在于Matlab在画图和数据处理上比较顺手Python胜在开源生态和与机器学习方法结合更方便。7.1 如何把模型扩展到更多设备类型如果你手里的课题需要加入燃料电池、电制冷机、蓄冷罐等设备改动逻辑不复杂。核心步骤是在参数区添加新设备的容量上限、效率、投资成本在第一阶段决策变量中加入新设备的额定容量在第二阶段运行约束中加入新设备的出力变量和功率平衡项在子问题目标函数中加入新设备的运行成本项。需要提醒的是每加一种设备第一阶段和第二阶段的约束数量都会增长CCG迭代的求解时间也可能明显增长。建议先用小规模数据测试一遍再放大到完整案例。7.2 从两阶段到多阶段的扩展思路这个课题是两阶段鲁棒优化但你如果有兴趣进一步做多阶段鲁棒优化或者模型预测控制MPC层面的实时调度可以把这里的规划模型作为上层模型把日内滚动优化放在底层形成“规划-调度”一体化的框架。我个人的看法是这个课题的模型框架已经比较成熟了后续的提升空间主要在两个方面。一是把不确定集合做得更精细比如用数据驱动的方法从历史数据中构建模糊集而不是简单用盒式预算二是把碳交易机制引入目标函数因为数据中心本身是耗能大户绿电比例和碳排放约束未来一定会进入实际规划中。7.3 与机器学习方法的结合点现在很多人做风光的功率预测用的是LSTM、Transformer这类模型。预测产生的误差分布正好可以作为构造不确定集合的依据。你可以用预测误差的历史数据统计出每个时段误差的均值和方差再设置不同置信水平对应的波动范围。这比主观设定ΔP_max要可靠得多。具体操作是用代码跑500次带有随机扰动的模拟记录每个时段的预测误差分布取95%分位数作为波动上限ΔP_max。预算Γ的选择则可以参考误差之间的相关性——如果相邻时段误差相关性高Γ可以取大一些如果误差独立性强Γ取小一些也能保证同样的覆盖率。8. 实操心得与最后的个人建议这套代码跑通之后我对微网规划的理解比之前看论文时深了很多。论文里一句“构造盒式不确定集合”看起来轻描淡写真正在代码里实现时涉及到对偶转换、场景回切、迭代收敛判断每一步都需要细心。尤其是子问题的max-min结构如果不熟悉强对偶理论很容易卡住。我自己的一点经验是在调试CCG算法时一定要输出每次迭代的LB和UB把迭代过程的可视化做出来。这样一旦算法卡住或者收敛慢你能直观看到是主问题还是子问题出了问题。另外如果导师或者项目要求你不仅会跑代码还要解释清楚模型建议你把论文里的公式和代码逐行对应起来看。这个习惯能帮你快速定位代码里某个约束是干什么用的等写论文建模部分的时候每一行公式你都有把握。最后如果你拿这套代码去复现论文别忘了留意版本兼容性。不同版本的YALMIP或者Gurobi在某些函数上会有细微差异比如我用的Matlab R2022a和YALMIP R2021版本可以正常跑但如果换成老版本个别函数可能需要调整。做微网规划这个方向两阶段鲁棒优化基本是绕不开的核心方法。这篇内容能把建模思路、代码逻辑和调试方法系统过一遍后面你无论是修改参数做灵敏度分析还是加入新的设备心里都会有底。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑