资讯动态

数据中心微网两阶段鲁棒规划方法解析及Matlab复现

发布时间:2026/10/16 21:21:17 来源:尧图企业网站定制
做电力系统优化方向的朋友最近应该没少刷到“数据中心微网”、“两阶段鲁棒”、“灵活性规划”这几个词组合在一起的标题。说实话这类工作真正落地起来并不难但很多人在第一步“看懂模型、搭好代码框架”就被卡住了。我这次复现的是一篇EI期刊上的《考虑灵活性的数据中心微网两阶段鲁棒规划方法》用Matlab完整跑通了算例并且把代码结构按CCG列与约束生成算法重新整理了一遍。这篇文章就把整个方法拆开揉碎讲清楚数据中心微网为什么要考虑灵活性、两阶段鲁棒规划到底在优化什么、Matlab代码怎么组织、以及我在复现过程中踩过的坑和排查思路。适合正在研究微网规划、综合能源系统、或者复现鲁棒优化论文的研究生和工程师参考。1. 先把问题想清楚数据中心微网规划到底在优化什么1.1 数据中心负荷的真正特点传统微网规划面对的是居民负荷、商业负荷负荷曲线相对规律峰谷差有一定节奏。数据中心不一样它有两个非常显著的特征一是全年8760小时基本都在高负荷运行IT设备的功率密度远高于普通建筑二是负荷虽然总量大但绝不是“刚性不可调”的。数据中心里往往同时存在多条业务线有些在线业务需要实时响应时延敏感有些离线业务、算力训练任务、批量存储任务是可以延迟执行的。这部分“可延迟负荷”就是天然的需求侧灵活性。另外数据中心还有配套的冷却系统冷冻水、精密空调、蓄冷罐这些设备本身就带蓄热能力相当于一个隐蔽的热储能。再加上数据中心普遍配置的UPS储能电池整个系统叠加起来灵活性资源相当可观。所以数据中心微网规划如果只看“配多大光伏、配多大储能、配多大柴发”就会忽略一个关键点数据中心自己的负荷侧和管理侧其实可以主动配合电网降低对储能和备用电源的依赖。规划模型如果不把这些灵活性考虑进去容量配置往往会偏保守投资成本虚高。1.2 为什么常规确定性规划不够用微网规划的传统做法是给定一个典型日负荷曲线、一个典型日光伏出力曲线然后建一个混合整数线性规划MILP决策储能容量、光伏容量优化目标是最小化年化投资成本和运行成本之和。这种做法最大的问题在于“以偏概全”真实的光伏出力和负荷不可能完全照着典型日走。到了阴雨天、连续雾霾天光伏出力可能只有晴天的20%数据中心负荷也会因为业务突变比预期高出一截。如果规划方案只让系统在“典型日”能自洽运行遇到极端但实际可能发生的场景就会出现失负荷、切负载甚至系统崩溃的情况。确定性规划看起来算得很快、结果也直观但它相当于“用一张过去的门票赌未来每天的天气”。两阶段鲁棒优化解决的就是这个“不确定性下的最坏情况”问题第一阶段先把投资容量定下来第二阶段在不确定参数集合里寻找最恶劣的场景来检验投资方案是否可行、运行成本是否可控。规划结果会有一个明确的鲁棒边界而不是靠拍脑袋加备用系数。1.3 “灵活性”在这里到底是什么很多人一提“考虑灵活性”第一反应是储能。储能当然算但数据中心微网的灵活性资源可以列得更细可延迟负荷就是前面提到的可转移的算力任务可以在电价低或光伏出力大的时段执行。建模上可以用“总用电量不变但各时段功率可变”来刻画。电池储能数据中心UPS本身就是储能规划时可以把它的容量统一纳入优化既能做备电也能做能量时移。蓄冷/空调热惯性冷却系统的热惯性让电制冷功率不必严格跟随冷负荷曲线等于给系统增加了一个小时级的可平移负荷。柴油发电机和并网交互电网购电和柴发出力是规划中应对最恶劣场景的兜底手段但柴发容量、购电上限都需要纳入投资和运行约束。把这些灵活性资源用数学语言写出来就是“决定投资容量的同时确定一套调度策略使系统在不确定场景下仍然能通过灵活性调节来保证供电可靠性和运行经济性”。这也是两阶段鲁棒模型里第二阶段运行优化的核心工作。2. 模型搭建两阶段鲁棒规划的标准范式2.1 第一阶段投资决策第一阶段是典型的“现在做决定、未来才看到效果”的问题。决策变量包括光伏装机容量储能额定容量和额定功率柴发装机容量是否配置蓄冷/储热设备及其容量是否需要扩容并网变压器。这些变量有一个共同特点建设周期长、资金投入大、一旦确定就很难短期调整。所以第一阶段目标函数里放的是投资费用包括设备购置费、安装费、以及按寿命期折算到每年的等年值成本。用等年值而不是总费用是为了和第二阶段运行费用单位是元/天或元/小时统一量纲。很多论文里还会在投资成本里加一个“是否上储能”的0-1变量用来避免求解结果出现一个特别小的储能容量比如0.5kWh这种工程上无意义的配置。实际操作中这个约束也很重要否则MILP求解器为了微调运行成本经常能给出奇怪的小容量结果。第一阶段模型写出来长这样伪代码形式min 投资成本涉及0-1变量和二阶段运行成本变量 s.t. 投资变量上限约束 0-1变量与容量连续变量耦合约束2.2 第二阶段运行调度与最坏场景第二阶段是“看到不确定性实现后做最经济的调度”。决策变量包括每个时段的光伏实际出力储能充放电功率和荷电状态SOC柴发出力从电网购电功率可延迟负荷的调度量蓄冷/蓄热设备充放能功率。不确定性参数主要考虑光伏出力和数据中心总负荷或者净负荷的波动。第二阶段的目标是给定第一阶段投资结果后在每个可能的不确定场景下最小化运行成本。两阶段鲁棒优化的核心是下面的min-max-min结构外层min第一阶段投资成本 内层max/min问题的最坏情况成本 内层max在不确定集合中找最恶劣的光伏/负荷场景 最内层min给定场景下的运行调度成本最小化写出来就是min C_inv(x) max_{u∈U} min_{y∈Ω(x,u)} C_ope(x, u, y)这里x代表投资决策u代表不确定参数光伏、负荷y代表运行决策。这个结构看起来很绕但逻辑上很好理解你现在投资假设未来总会出现一个最差的情况你希望在最差情况下系统依然能运行得经济可靠。这就是鲁棒优化与机会约束、随机规划的本质区别——随机规划考虑“平均情况”鲁棒规划考虑“最坏情况”。2.3 不确定性集合怎么设计两阶段鲁棒模型能不能求解、求解质量高不高很大程度上取决于不确定性集合U的设计。常用的有三种盒式不确定集合每个不确定参数都有上下界形式最简单但过于保守预算不确定集合Budget Set在盒式基础上规定“最多只有若干时段参数偏离预测值”避免所有极端情况同时发生保守性可控椭圆/多面体不确定集合用历史数据拟合协方差几何形状上更精细但建模和求解复杂度更高。在EI期刊这类规划方法论文里最常用的是预算不确定集合。光伏和负荷的不确定参数写成P_pv,t P_pv,t_forecast ξ_pv,t * ΔP_pv,t P_load,t P_load,t_forecast ξ_load,t * ΔP_load,t其中Δ是预测偏差上限ξ是偏离系数。预算约束写成sum_t |ξ_pv,t| sum_t |ξ_load,t| ≤ ΓΓ就是“预算参数”它限制了总偏离程度。Γ0时模型退化为确定性规划Γ越大鲁棒性越强但经济性越差。复现的时候画一条“总成本随Γ变化”的曲线几乎是这类论文的标配图一定要会做。2.4 完整数学模型与约束要点把两阶段模型具体展开核心约束有以下几组一是功率平衡约束。数据中心母线上光伏出力、柴发出力、储能放电、电网购电要等于负荷、储能充电、可延迟负载增加的功率之和。注意如果模型里考虑了蓄冷设备还要单独列一个冷功率平衡方程。二是储能约束。包括充电功率上限、放电功率上限通常取同值、SOC递推公式、SOC上下限、以及一个调度周期始末SOC相等的约束。SOC递推里的充放电效率是两套系数不能简单写成同一个否则能量守恒会出现偏差。三是柴发和电网约束。柴发有爬坡率限制有最小出力限制电网购电有联络线容量限制和功率因数限制如果考虑无功的话。这些约束对最坏场景下的可行性影响很大尤其爬坡约束很多第一次复现的人会漏。四是可延迟负荷约束。数据中心IT负载中可延迟部分的总能量必须满足生产需求比如一天内必须完成的总算力固定但各时段分配多少可以灵活变化。常用的写法是累计调度量等于总需求、各时段调度量上下限约束、以及调度连续性约束避免频繁启停。五是第二阶段的耦合约束。第一阶段投资变量x会出现在第二阶段约束的右侧或者作为容量上限出现比如储能充放电功率上限是储能额定功率乘以某个系数、光伏实际出力不能超过装机容量。这一步是CCG算法中主问题和子问题传递信息的关键接口。3. Matlab实现与求解器配置3.1 求解平台怎么选复现这类优化论文Matlab里通常有三种组合YALMIP CPLEX/Gurobi最省事建模逻辑清晰适合快速迭代纯MATLAB Gurobi/CPLEX接口手写约束矩阵效率高但改模型很痛苦逐步拆分子问题的KKT或对偶形式使用嵌套求解器。我建议复现阶段用YALMIP。它支持sdpvar定义变量约束写起来跟数学公式几乎一致调试时也容易定位是哪个约束出了问题。求解器方面如果gurobi可用优先用gurobi如果只有cplex也完全够用。两阶段鲁棒问题最终会退化成一系列MILP这两个求解器都能撑住。另外YALMIP里有一个细节值得注意sdpvar变量默认类型是连续变量整数变量要用binvar或intvar显式声明。两阶段模型里第一阶段如果包含0-1决策变量比如是否建设储能主问题里要记得用binvar定义子问题上如果出现了整数变量数据中心某些调度逻辑可能需要也不能直接用强对偶得换成KKT条件或大M法线性化处理。这个后面排查部分还会再提。3.2 直接套用的CCG迭代Matlab模板CCGColumn-and-Constraint Generation是求解两阶段鲁棒问题最常用的精确算法。它的核心思想是主问题里先不枚举所有不确定场景只在迭代中动态地向主问题添加“最坏场景对应的运行变量和约束”也就是“列生成”。CCG的主流程可以写成下面这段伪代码对应Matlab里的主循环% 初始化 LB -inf; UB inf; iter 0; max_iter 20; tol 1e-3; % 初始化不确定场景通常取预测场景 u0 forecast_scenario; while (UB - LB) / UB tol iter max_iter iter iter 1; % 求解主问题 [x, eta, obj_mp] solve_master_problem(u_all); LB obj_mp; % 求解子问题 [u_worst, obj_sp] solve_subproblem(x); UB min(UB, cost_inv(x) obj_sp); % 如果间隙不收敛向主问题添加最坏场景对应的约束和变量 if (UB - LB) / UB tol u_all{end1} u_worst; end end上面代码里u_all是一个细胞数组存的是已经生成的“最坏场景集合”。每轮迭代就把新找到的最坏场景连同对应的第二阶段变量一起加到主问题里这样主问题规模会慢慢变大但每轮都能给出一个更紧的下界。solver_master_problem内部本质就是一个MILP。决策变量包含第一阶段投资变量x、辅助标量η用来替代子问题目标函数值、以及当前所有已生成场景对应的第二阶段变量y1, y2,..., yk。约束就是每个场景各来一份运行约束。solve_subproblem内部则是一个两层问题内层是给定不确定参数u的调度优化min问题外层是找最坏umax问题。CCG实现时通常有两种处理方式方式一把内层min问题通过对偶变换转成max问题和外层max合并成一个单层max问题或max-min问题然后用对偶间隙迭代或直接求解MILP方式二保持min-max-min结构子问题里再嵌套一个“寻优不确定参数”的循环不过这种方式效率很低我一般不推荐。论文里用的子问题多数是选择对偶变换。如果第二阶段模型是纯LP问题就简单了内层min是LP写成对偶变成max两个max合并成一个max目标函数和约束里包含对偶变量最后是单层max问题。如果第二阶段里有整数变量对偶这条路走不通就得用KKT条件或者把整数变量放进外层再用大M法处理互补条件——复杂度立刻上一个台阶。这就是为什么我在搭建模型时尽量让第二阶段保持“纯LP”把0-1变量都排挤到第一阶段去。3.3 典型参数与数据准备复现的时候数据准备是绕不开的一步。我按论文常见口径给出参考值实际跑算例可以直接替换系统基准容量1 MVA数据中心典型日负荷峰值约1.8 MW可延迟负荷比例约15%~25%光伏预测曲线采用夏季典型日峰值出力按装机容量的0.85折算储能效率充电效率0.95放电效率0.95SOC范围[0.1, 0.9]柴发最小出力系数0.3爬坡速率0.2 MW/h分时电价峰时1.2元/kWh平时0.75元/kWh谷时0.38元/kWh预算参数Γ取4~8之间做敏感性分析。这些参数建议先用小规模算例验证。比如时间尺度用24小时不确定参数只考虑光伏和负荷预算参数Γ4。IEEE 33节点这类配电网算例太复杂数据中心微网通常就是一个单母线系统别一上来就搞多节点否则子问题求解时间会爆炸。3.4 一段可参考的子问题求解核心代码下面给出一个“已知投资x下找最坏场景”的子问题Matlab代码框架用的是YALMIP语法。这个代码对应“光伏出力偏差”和“负荷偏差”两个不确定参数的盒式集合加预算约束。function [u_worst, obj_sp] solve_subproblem(x) % 定义变量 P_pv sdpvar(T, 1); % 光伏实际出力 P_load sdpvar(T, 1); % 实际负荷 P_grid sdpvar(T, 1); % 购电功率 P_dis sdpvar(T, 1); % 储能放电 P_ch sdpvar(T, 1); % 储能充电 SOC sdpvar(T1, 1); % SOC状态 % 不确定参数偏差系数 xi_pv sdpvar(T, 1); xi_load sdpvar(T, 1); % 目标函数运行成本 减去 切负荷惩罚等 obj_sp sum(price .* P_grid) fuel_cost * sum(P_dg); % 约束不确定集合 Constraints []; Constraints [Constraints, P_pv P_pv_forecast xi_pv .* dP_pv]; Constraints [Constraints, P_load P_load_forecast xi_load .* dP_load]; Constraints [Constraints, -1 xi_pv 1, -1 xi_load 1]; Constraints [Constraints, sum(abs(xi_pv)) sum(abs(xi_load)) Gamma]; % 约束功率平衡 Constraints [Constraints, P_pv P_dg P_dis P_grid P_load P_ch]; % 约束储能SOC递推等... % 外层max最大化运行成本即找最坏场景 optimize(Constraints, -obj_sp, sdpsettings(solver, gurobi)); u_worst struct(xi_pv, value(xi_pv), xi_load, value(xi_load)); obj_sp value(obj_sp); end上面这段只是示意框架。实际运行的时候为了让子问题能用对偶转化目标函数和约束里涉及的不确定参数必须是线性的并且保证内层min问题有可行解。这段代码里如果直接调用optimize实际上是一个max-min嵌套问题YALMIP并不能直接处理这种情况需要手动把内层min的对偶形式写出来然后合并成单层max问题。所以完整的CCG实现分两头主问题直接用YALMIP的MILP求解器子问题则需要手工推导对偶。很多论文的附录里就是用来补这块推导过程的复现时建议先把对偶问题在纸上推一遍心里有底再写代码。4. 复现常见的坑与排查经验4.1 子问题对偶变换后双层问题变单层容易出错子问题的原始形式是“给定第一阶段x外层寻找max的u内层是给定u求min的运行成本”。直观理解就是在大自然想害你的场景里你以最小成本运行。这个嵌套结构如果直接在Matlab里写sdpvar然后调用optimize会得到“无法处理嵌套优化”的报错。我的经验是先把内层的调度问题完整写成一个“以y为变量的LP”然后拿到它的对偶问题。对偶问题的变量是内层LP的约束对应的对偶乘子内层min就变成了max。这样外层max和内层max就可以合并成一个目标统一的最大化问题。这一步最容易出错的地方有两个对偶方向搞反。YALMIP本身不提供自动对偶生成最好自己手推一遍然后代码里的约束顺序要和推导过程一一对应。对偶问题里的约束包含第一阶段投资变量x如果x在主问题里是sdpvar那么子问题求对偶时会把这个x当成参数。CCG迭代中每次传x的具体数值所以没问题。但如果你在编写子问题函数时把x仍然定义成sdpvar而没赋具体数值就会出现“变量y与变量x相乘”双线性项导致问题变成非凸。所以子问题函数入口一定要做x的“参数化赋值”推荐直接用value(x)或者把x作为数值数组传进来不要用sdpvar。我最初复现时在这个细节上卡了整整一天。4.2 CCG迭代不收敛或者收敛很慢CCG理论上在有限次迭代内可以收敛但实际代码跑起来经常出现两种情况一是上下界间隙在第四五次迭代后不再缩小二是UB直接变成负数明显不符合物理含义。先说说“间隙不缩小”的情况。最可能的原因是子问题找到的“最坏场景”没有真正挑战主问题方案的可行性。举个例子如果最坏场景只是让光伏出力为零但主问题已经配了足够的柴发和储能那运行成本就不会显著升高CCG添加的割约束也起不了作用。排查思路是检查不确定性预算Γ是不是设得太小导致不确定集合过于“温和”或者检查最坏场景搜索时是否还有其他自由度没有对齐比如装置启停状态没有参与寻优。还有一种可能是主问题的辅助变量η被错误定义了本该是“子问题目标函数值”的下界但你把η跟子问题目标函数值直接画了等号导致下界更新逻辑出错。再说说UB为负数的情况。这通常是目标函数里包含负项比如售电收益、光伏补贴收入而子问题又求解成了“最小化目标”但符号方向写反。建议先用一个不含不确定性的确定性场景去调试主问题和子问题两边算出来的最优目标值应该一致如果不一致就是符号约束问题跟鲁棒迭代无关。最后提一个经验“上下界间隙取相对值”(UB-LB)/UB而不是做绝对差值。因为在迭代早期UB往往是很大的数值因为子问题找到的成本乘上投资修正后很大绝对差值会给你“差得离谱”的错判相对值更稳定。4.3 数据单位、量纲和基准值不统一这个问题特别常见。论文里有时候用MW和MWh有时候用kW和kWh有时候干脆给标幺值。复现的时候要么全部换算成MW/MWh要么全部用标幺值千万不要混用。举个具体的例子分时电价如果是元/kWh储能SOC是MWh柴油发电机燃料消耗是L/h三者混合起来目标函数单位会乱掉。正确做法是全部折算成“元”柴发燃料成本也是元/h然后目标函数第一阶段的投资成本按等年值折算成“元/天”或者“元/年”跟第二阶段运行成本保持一致。如果用了标幺值就需要注意储能SOC递推公式里的基准功率不是1MW——很多同学在这一步推导不出来跑出来的SOC曲线毫无规律充满之后还继续充电就是因为量纲和基准值出了问题。4.4 鲁棒解的工程意义怎么体现最后说一个论文复现里容易忽略的收尾步骤做不确定性预算参数Γ的敏感性分析。跑出来之后画两条曲线一条是总投资成本随Γ的变化曲线一条是选定Γ时最坏场景下的系统运行成本曲线。你会发现Γ从0增大到4的时候总投资成本快速上升继续增大到8成本上升变缓说明“鲁棒性收益递减”。这种趋势能直观告诉读者数据中心微网规划需要多大程度的鲁棒保护才经济合理。另外我还习惯在代码里输出每个Γ对应的各类设备容量配置比如光伏、储能、柴发各自怎么变。通常随着Γ增大柴发容量会上升光伏容量可能先升后降储能容量趋势取决于电价结构。这些规律论文一般不会写全但极适合放进文章的图表分析部分也是非常好的答辩素材。5. 一些折腾之后的体会代码跑通之后再回头看这个课题最大的门槛其实不在CCG算法本身而在建模取舍。数据中心微网的灵活性资源非常多如果全建模进去第二阶段约束数量会急剧膨胀子问题成为MILP对偶和CCG的求解效率就成问题如果砍得太狠又失去“考虑灵活性”的论文卖点。我实际采用的折中方案是把数据中心“可延迟负荷”和“储能”作为主要灵活性资源建模蓄冷系统做了简化只保留了冷功率平衡和蓄冷罐的SOC约束关联。这样第二阶段仍然是LP子问题可以用对偶合变成单层MILP求解CCG每次迭代只有两个线性规划加一个MILP算例规模控制在24个时段整体运行时间在能接受的范围内。还有一些实现小技巧先在单时段、无预算约束的小例子上验证主问题子问题目标一致再上完整模型每次迭代把主问题新增的场景编号打出来方便检查是不是出现了重复场景子问题计算结果里顺便输出最坏场景对应的光伏、负荷曲线画出来看看是否符合直觉——如果最坏场景在深夜光伏为零同时还配了高负荷那大概率没问题如果最坏场景偏偏出现在光伏强盛的午后就要检查不确定方向是不是写反了。最后想多提一句这类两阶段鲁棒规划的Matlab复现代码网上版本很多但不少是拿确定性模型套了个CCG外壳逻辑上并没有真正实现max-min寻优。复现的时候不用迷信源代码先自己把模型推导明白再对照代码看核心循环和子问题定义基本一眼就能看出真假。

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

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

免费获取报价 →
↑