ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

数据中心微网两阶段鲁棒优化:灵活性资源与CCG算法实现

数据中心微网两阶段鲁棒优化:灵活性资源与CCG算法实现 1. 问题拆解数据中心微网规划到底在优化什么做这个课题之前我一直有个直觉——数据中心微网和普通园区微网最大的区别不在拓扑上而在“负荷”本身。普通微网规划负荷基本是刚性的你只能被动去匹配。但数据中心不一样它的IT负载、UPS储能、制冷系统甚至算力调度都能参与调节这就把传统的“源-荷”规划问题变成了“源-网-荷-储-算”的耦合优化问题。所以论文标题里“考虑灵活性”这五个字其实是整篇的题眼。我们这套两阶段鲁棒规划本质上回答两个层面的问题第一阶段投资决策在光伏、储能、柴油发电机、燃气轮机这些候选设备里选哪些、装多大容量让总投资成本最小。这个决策是“现在就要拍板”的建完就不能改了。第二阶段运行决策在设备装完之后面对每天波动的负荷、光伏出力和电价怎么调度这些设备让日运行成本最小。这个决策是“每天滚动做的”随不确定性的实现而调整。两阶段之间通过投资容量耦合你第一阶段买的储能容量越大第二阶段调度的灵活空间就越大运行成本就越低但投资成本也越高。这个权衡关系单阶段确定性优化是算不清的必须用两阶段框架。为什么偏偏要加“鲁棒”因为数据中心的供电可靠性要求太高了四个九、五个九是常态。你如果按确定性场景优化万一光伏出力没预测得那么高、或者IT负载突发高峰就可能出现切负荷。鲁棒优化的思路不赌某一个场景而是构建一个不确定集保证集合内最恶劣的情形下系统也能安全运行。代价是结果偏保守但数据中心这类负荷保守一点完全合理。另外论文标题里的“EI复现”指的是复现已发表期刊论文的方法。这里我特别想提醒一句EI论文的复现核心难点从来不是读懂公式而是把数学建模转成可求解的数学规划再在Matlab里落地。这个从公式到代码的鸿沟远比想象中大。文章里我会把整套建模和代码实现思路拆开讲透。2. 两阶段优化框架的建模思路2.1 第一阶段投资决策模型第一阶段决策变量是设备选型与容量配置常见候选设备包括光伏PV单位容量投资成本约5000-8000元/kW使用寿命20年上下储能BESS单位容量投资成本约1500-2500元/kWh功率成本约2000-3000元/kW柴油发电机DG单位容量投资成本约1500-3000元/kW运维成本高碳排放高燃气轮机MT单位容量投资成本约4000-7000元/kW效率高但需要天然气供应。复现时我习惯用x_pv, x_bess_e, x_bess_p, x_dg, x_mt这些0-1变量表示“是否建设”用C_pv, C_bess, C_dg, C_mt等连续变量表示“建设容量”。投资成本目标函数写成inv_cost sum(C_inv_pv .* C_pv) sum(C_inv_bess_e .* C_bess_e C_inv_bess_p .* C_bess_p) ...注意储能要分能量kWh和功率kW两个维度分别建容量因为成本构成不同运行约束也是分开的。这个细节不处理好后面的充放电约束很容易写错。第一阶段还含二进制变量所以整问题是MILP混合整数线性规划。我用YALMIP定义变量时最常踩的坑是指数维度不匹配电池的充放电非负变量维度写成(T,1)但容量变量写成(1,1)导致约束传不进去。建议统一用repmat扩展成场景数×时段数的矩阵再说。确定性等价形式下第一阶段目标函数是投资成本 所有场景下第二阶段运行成本的期望第二阶段换成鲁棒就不是期望了而是“所有场景里最恶劣的那个场景下的运行成本”。这时候目标函数变成投资成本 max_{u∈U} min_{y∈Ω(x,u)} 运行成本这个max-min结构就是两阶段鲁棒的核心。2.2 第二阶段运行决策模型第二阶段运行决策变量包括变量含义常见边界P_pv(t)光伏实际出力0 ≤ P_pv ≤ P_pv_predP_ch(t), P_dis(t)储能充、放电功率0 ≤ P ≤ P_max且不能同时充放SOC(t)储能荷电状态0.1 ≤ SOC ≤ 0.9P_dg(t), P_mt(t)柴油机/燃气轮机出力0 ≤ P ≤ P_ratedP_buy(t), P_sell(t)与上级电网购/售电P_buy ≥ 0P_sell ≥ 0P_it(t)IT负载实际消耗可调节P_it_min ≤ P_it ≤ P_it_max功率平衡约束节点kP_pv(k,t) P_dis(k,t) P_dg(k,t) P_mt(k,t) P_buy(k,t) P_it(k,t) P_ch(k,t) P_sell(k,t) P_cool(k,t)制冷负载P_cool和IT负载有耦合关系——服务器功率越高发热越大制冷耗电越多。简化建模里我常写P_cool α·P_itα取0.3~0.5。这个耦合关系就是“灵活性”的一部分也是数据中心区别于普通园区的地方。储能充放电约束是第二阶段最容易出错的地方SOC(t1) SOC(t) (eta_ch * P_ch(t) - P_dis(t) / eta_dis) * dt / E_rated; P_ch(t) P_dis(t) P_rate_max; % 不能同时充放电或用0-1约束这里dt的单位要和容量单位一致。如果用小时dt1如果用15分钟间隔dt0.25。我见过很多论文复现跑出SOC漂移十有八九是dt和容量单位没对齐。2.3 为什么不能直接求解max-min问题max-min结构不能直接丢给求解器原因很简单max和min分别对应不同玩家的决策目标函数在两者之间是鞍点关系不满足单一优化问题的KKT条件。你得先想办法把它转成单层问题。常见的三种转化路线对偶转化把min问题取对偶变成max-max结构再把外层max合并。适用于第二阶段是LP线性规划的情形。KKT条件把内层min问题的KKT条件写出来加互补松弛约束变成单层MPEC数学规划带均衡约束。但互补松弛含非线性项处理麻烦。CCG列与约束生成算法把min问题按场景拆开通过迭代不断添加场景约束和对应变量逐步逼近最恶劣场景。这是目前最主流的方法也是我复现时首选的路线。CCG的思路用大白话说先假设一个最恶劣场景求解两阶段问题得到一个投资方案和运行方案然后固定这个投资方案去搜一个让系统运行成本更高的新场景如果新场景确实更恶劣就把这个场景对应的约束加进去重新求解否则停止。这样反复迭代相当于把“无穷多场景”的安全约束用有限次迭代一点一点压进模型里。3. 灵活性的建模细节数据中心微网的独家变量3.1 IT负载的时移特性与算力调度数据中心最值钱的灵活性来自IT负载本身。一个大型数据中心内可能有成千上万个虚拟机、容器或批处理任务它们不是必须在某个具体时刻运行——比如离线训练任务、数据备份、日志处理晚一两个小时跑完完全没问题。建模上我通常把IT负载分成两类刚性负载必须实时供电的在线业务比如Web请求、数据库查询P_it_fixed柔性负载可以时移或调度的批处理任务P_it_flex。柔性负载的灵活性约束长这样% 某个时间窗内的总能耗必须满足任务需求 sum(P_it_flex(t_start:t_end)) E_task; % 每个时刻的功率有上限 P_it_flex(t) P_it_flex_max(t);这个模型的价值在于当电价高或光伏出力低时系统可以压低柔性负载把用电平移到光伏大发或电价低谷时段。这比单纯配储能的成本要低得多因为算力调度本身不产生额外投资。复现时如果你想简化可以不用建任务队列这么细直接给一个可调比例系数P_it(t) P_it_fixed(t) delta_flex(t)·P_it_flex_max其中delta_flex是一个0-1可调变量表示柔性负载的参与率。这样既能体现灵活性又不会让模型复杂到难以收敛。另外提醒一下服务器功耗不要按额定功率算。实测中服务器负载率在10%到100%之间波动功耗非线性增长。建模里如果追求精度用P_server P_idle (P_max - P_idle)·u其中u是CPU利用率。但考虑到MILP求解规模我在复现时直接用线性近似就足够了——目标函数的误差通常小于3%。3.2 储能与UPS的双重身份数据中心本来就有UPS不间断电源正常运行时就是给服务器“保驾护航”但在微网框架下UPS完全可以兼职当储能用。UPS通常有两类在线式双变换UPS正常时AC-DC-AC双重变换效率85%~95%后备式UPS正常时旁路直供断电时才切到电池。从规划角度看UPS电池如果能参与日常调度那就相当于免费获得了一部分储能容量。但有两个坑UPS电池循环寿命有限铅酸电池在1000~1500次循环左右锂电好一些但频繁充放会加速衰减。如果规划模型不考虑寿命折损会高估UPS参与调度的收益。UPS的充电策略通常是浮充设计寿命7~10年按浮充算改成循环充放后可能3年就报废。所以更严谨的做法是加一个全生命周期成本修正系数复现时可以把UPS循环成本设成0.5~1.0元/kWh用于惩罚深度充放。如果论文里没有明确区分UPS和储能代码实现时可以合并建模但需要把效率参数分开设置。UPS放电效率通常比储能略低几个百分点对5%~8%的效率差异敏感的结果要小心。3.3 制冷系统与电冷耦合数据中心的制冷系统能耗通常占IT设备能耗的30%~50%是仅次于IT设备的第二耗电大户。考虑到灵活性制冷系统有几个可玩的空间蓄冷罐像储能电池一样低谷电价时段蓄冷高峰时段释冷减少电制冷机组启停温度调宽机房温度设定点从22°C放宽到27°C制冷负荷可以压降10%~20%但对IT设备的可靠性有边际影响自然冷源在寒冷地区直接引入室外空气冷却替代电制冷减少用电。复现时如果论文模型包含电冷耦合我推荐用COP能效比建一个简化模型P_cool(t) Q_cool(t) / COP(t); Q_cool_min Q_cool(t) Q_cool_max;COP和环境温度相关夏天低冬天高但简化时取一个典型值3.5~5.0也行。蓄冷罐则可以参照储能建模只是“电”换成“冷”SoC换成蓄冷量充放变量换成蓄冷/释冷功率。我自己的经验是除非论文里明确研究制冷灵活性否则不要一上来就把制冷细节全建模进去否则第二阶段问题维度爆炸CCG迭代一次要算很久。先用固定比例P_coolα·P_it做基准再逐步加复杂度。4. 两阶段鲁棒规划的核心算法CCG的Matlab实现4.1 不确定集怎么定义两阶段鲁棒里最关键的抽象是“不确定性从哪里来”。数据中心微网的不确定性源主要有三个光伏出力波动受天气影响预测误差可达20%~30%IT负载波动受业务流量影响尤其在电商大促、流量突增时段波动明显电价波动现货市场电价有时段性也可能出现极端尖峰。最简单的处理方式是盒式不确定集u ∈ [u_min, u_max]也就是每个不确定参数都落在预测值加减一个偏差范围内。这个模型简单但有个问题是它会包含所有参数同时达到最恶劣值的场景实际几乎不可能发生导致结果过度保守。更合理的是预算不确定集Budget Uncertainty Set也叫Budgeted Uncertainty Set它在盒式基础上附加一个总量限制sum |u_i - u_i_mean| / delta_i GammaGamma是预算参数控制所有参数同时偏离预测值的总程度。如果Gamma0就是确定性模型Gamma越大鲁棒性越强成本越高。复现时要跑Gamma的敏感性分析画一条“成本-鲁棒性”权衡曲线这种图在论文里非常有说服力。那谁来充当“决策者”选择最恶劣场景呢就是外层max问题。我们不需要人为指定哪个场景最恶劣而是在不确定集范围内搜索让系统运行成本最大化。CCG每轮迭代就是在做这个搜索。4.2 CCG算法流程与Matlab伪代码CCG迭代求解两阶段鲁棒问题的算法流程如下初始化LB -infUB infk 1初始不确定场景取预测均值或某一个名义场景主问题MP在第一阶段投资决策基础上纳入前k轮识别出的所有恶劣场景的运行约束求解得到最优投资方案x和总成本。更新下界LB MP目标值子问题SP固定主问题求出的投资方案x求解第二阶段运行问题在不确定集下的max-min形式找出最恶劣场景u_k1。子问题的最优值加上已求得的投资成本按对应x重新算投资成本再叠加更新上界UB收敛判断如果(UB-LB)/UB epsilon通常取1e-3停止否则kk1把新场景u_k1对应的运行变量和约束添加到主问题中回到第2步。MatlabYALMIP的框架下CCG实现不会太复杂在第k轮迭代时我们固定了不确定变量u的取值比如光伏出力、IT负载、电价都取当前最恶劣场景的具体值此时子问题变成min_{y} f(y) 线性目标固定u s.t. A(x*) B(y) ≤ C(u_k) D y ≥ 0这个子问题直接调用线性规划求解器解出最优值给出该场景下的最小运行成本。然后我们在不确定集U上搜索新场景u_k1让这个最优值最大。实际CCG实现中最恶劣场景不一定需要显式搜有些实现直接把子问题的对偶乘子用来构造最优割平面能更快收敛。CCG的优势在于它不断把新场景对应的运行变量和约束直接加进主问题而不是通过对偶加割平面因此主问题是完整MILP求解器能利用它的结构。Matlab实现中主问题和子问题要用不同的优化变量对象。我们通常是复制一套子问题变量每次迭代把新场景的约束加到主问题里再把部分变量“绑定”到上一轮的解上。这就特别考验变量索引管理如果从第1轮开始就规划好统一的命名规则比如y{k}{t,1}代表第k个场景t时段的变量后面加场景就是加一行索引不会乱。4.3 求解器选型与参数调优Matlab下求解MILP首选Gurobi或Mosek次选CPLEX。YALMIP作为建模层的好处是语法统一换求解器只是改一行ops sdpsettings(solver,gurobi)的事。我自己用的组合是Matlab 2023b YALMIP Gurobi 10.xGurobi破解版或学术版申请具体因人而异。几个实用的求解器设置ops sdpsettings(solver,gurobi,verbose,2); ops.gurobi.MIPGap 0.01; % 1%的MIP Gap ops.gurobi.TimeLimit 600; % 600秒上限 ops.gurobi.NumericFocus 3; % 数值稳定性优先NumericFocus这个参数很少人调但很有用。两阶段鲁棒模型里投资成本动辄百万级运行成本几千块数值尺度差距巨大Gurobi的默认尺度处理可能会损失精度。把NumericFocus调到2或3能有效减少“整数变量但解出来的值是0.9999999”这类问题。另外在YALMIP里定义约束时能用implies就用implies尤其储能不能同时充放电的约束。但要注意implies会引入额外二进制变量规模大的时候反而拖慢求解速度。我实测下来如果模型只有几百个二进制变量直接用大M法把非负变量对P_ch和P_dis改成互斥约束更高效P_ch(t) M * z_ch(t); P_dis(t) M * z_dis(t); z_ch(t) z_dis(t) 1;M不需要取得很大取所有设备额定功率之和的1.2倍就够。M太大会增加数值困难太小又会误伤解空间这个度需要自己试。5. Matlab代码实现从参数初始化到结果可视化5.1 数据初始化与参数设计复现的第一步不是写代码而是把参数表整理清楚。我建议在代码开头用一个结构体把所有参数集中管理别散落在各处——调试的时候散落的参数最让人头大。% 参数结构体定义 par.t 24; % 调度时段数小时 par.dt 1; % 单位时段h par.node_num 5; % 微网节点数视拓扑而定 % 负荷数据数据中心的典型日负荷曲线 par.load_IT [0.6 0.6 0.55 0.55 0.5 0.5 0.55 0.7 0.8 0.9 0.95 1.0 ... 0.95 0.9 0.85 0.8 0.85 0.9 0.95 0.9 0.8 0.7 0.65 0.6] * 1e3; % kW % 光伏预测出力标幺值乘以额定容量得实际出力 par.pv_pu [0 0 0 0 0 0.05 0.15 0.35 0.55 0.75 0.85 0.9 ... 0.85 0.75 0.6 0.45 0.3 0.15 0.05 0 0 0 0 0]; % 峰谷平时段划分购电价元/kWh par.price_buy [0.5 0.5 0.5 0.5 0.5 0.6 0.8 1.1 1.2 1.1 1.0 0.9 ... 0.9 0.9 1.0 1.1 1.2 1.2 1.0 0.8 0.7 0.6 0.5 0.5]; % 不确定集合参数 par.delta_pv 0.2; % 光伏偏差系数 par.delta_load 0.1; % 负荷偏差系数 par.Gamma 6; % 预算不确定参数调度时段内最多允许6个时段同时达到最恶劣这里几个设计意图IT负载曲线在白天和晚间有两个高峰是因为在线业务流量集中在白天而夜间有批处理任务也能压一部分。光伏出力曲线要能反映中午缺失的单调性与实际出力规律匹配。电价峰谷时段要与数据中心可调节负荷时段错开鲁棒优化才有收益空间。5.2 主问题建模与迭代过程中的变量管理CCG主问题的YALMIP建模有个技巧每轮迭代的动态变量怎么声明。主问题要包含所有已经发现的场景。我的做法是自定义一个场景结构数组每轮迭代把新场景追加进去。for k 1:K % 迭代轮次 % 声明当前场景相关的运行变量 P_ch{k} sdpvar(par.t, 1, full); P_dis{k} sdpvar(par.t, 1, full); SOC{k} sdpvar(par.t1, 1, full); P_buy{k} sdpvar(par.t, 1, full); % 所有场景共享第一阶段容量变量 C_bess sdpvar(1, 1, full); x_bess binvar(1, 1); end主问题的约束分两类一类是静态约束所有场景通用另一类是动态约束每个场景各自的功率平衡、储能约束。动态约束需要在循环体里加进去。SOC(1)是初始荷电状态我一般设0.5。如果你要让系统每天循环运行而不是只跑一天可以在末尾加约束SOC(241) SOC(1)保证一天结束储能回到初始水平。这个约束会显著影响结果别漏了。每轮迭代结束时把本轮子问题找出的最恶劣场景存下来scenarios{k}.pv pv_worst; % 最恶劣光伏出力场景 scenarios{k}.load load_worst; % 最恶劣负荷场景 scenarios{k}.price price_worst;% 最恶劣电价场景主问题求解时这些历史场景的约束要一直保留这是CCG正确性的保证——切掉任何一个历史最恶劣场景UB和LB都可能不收敛。5.3 子问题的max-min结构怎么线性化子问题固定了第一阶段投资容量后形式是max_u min_y。直接求解这个两层结构依旧困难常见解法是内层min是LP当第二阶段无整数变量时取对偶变成max于是子问题变成max_u max_λ对偶变量的结构合并成一个max问题但不确定度和对偶变量相乘产生双线性项这个双线性项可以通过强对偶条件和大M法线性化更实用的是在Matlab里直接调用uncertain()和robust求解。我用YALMIP的鲁棒优化模块试过发现对规模小的算例可以但一旦节点多、时段长求解器处理不确定声明的预处理会很慢。所以复现论文时我都是手写线性化。基本思路是写出内层min问题的对偶问题强对偶条件a^T y b^T λ由此把max-min的目标值转换成可计算的表达式把不确定变量与对偶变量的乘积项用McCormick包络或大M法线性化。这个过程容易出错建议每步验证一下先固定数据把外层的max去掉手工检查对偶问题的目标和约束与原LP的目标和约束是否一致。这个验证比什么都重要。5.4 收敛性判断与可视化输出CCG循环中每一轮迭代主问题的目标函数是下界子问题目标函数加上当前投资成本后是上界。收敛判据写成if abs(UB - LB) / abs(LB) 1e-3 break; end注意当LB很小时除以一个很小的数会放大误差所以绝对误差和相对误差可以结合使用或者直接用abs(UB - LB) 1e-3。迭代收敛后输出三张图各设备容量配置柱状图光伏、储能、柴油机、燃气轮机用于对比不同Gamma取值下的配置差异最恶劣场景下的24小时调度曲线展示储能SOC曲线、购电功率、光伏出力、IT负载调节情况这张图最好画成堆叠面积图能很直观看到各电源的出力占比上下界收敛曲线横轴是迭代次数纵轴是成本一条阶梯下降UB一条阶梯上升LB两条线夹逼到同一个值。这张图直接放论文的仿真章节审稿人一看就懂。6. 工具链与复现环境准备6.1 Matlab环境配置与工具箱依赖做这个项目Matlab版本选择很关键。我用过2020a到2023b整体体验是2023b对YALMIP和Gurobi的兼容性最省心。Matlab 2023a到2023b之间有个优化工具箱接口的变化老版本YALMIP可能报“Unable to detect solver”之类的问题新版本基本没这个毛病。如果你用的是Matlab 2022b或更老版本遇到奇奇怪怪的求解器兼容问题别急着改代码先去检查YALMIP版本和求解器接口版本是否匹配。很多“代码跑不通”的报错源头其实是环境兼容不是算法写错。工具箱方面必须有优化工具箱YALMIP本身依赖它做默认求解器兜底。如果装的是精简版Matlab很可能缺了建模工具箱、并行计算工具箱这时候YALMIP的某些函数会调用失败。Linux服务器上装Matlab更是要严格按顺序装先装核心Matlab再装工具箱包然后手动激活。如果激活失败常见报错是license manager error -8多数是mac地址绑定错误或者license路径没写对。需要在activate工具里重新指定license文件。有时候还会遇到中文乱码问题——Linux上Matlab默认编码是UTF-8Windows上默认是GBK代码文件在Windows下用ANSI编码保存的中文注释拿到Linux上会乱成一团。解决方法是统一用UTF-8编码保存所有.m文件Matlab 2020b之后在“预设项-常规-文件编码”里可以指定。6.2 求解器选型与性能对比在这个项目里求解器的性能直接影响你的复现效率。我的实测数据一个5节点、24时段、3类不确定参数的算例CCG迭代10轮左右主问题MILP规模大概几百个二进制变量、数千个连续变量。Gurobi 10.x跑一轮主问题约10~30秒整个CCG流程3~6分钟。对比一下几个常见求解器求解器MILP求解速度鲁棒优化支持许可成本备注Gurobi最快无内建支持需手写线性化学术免费/商业付费首选数值稳定性好Mosek快尤其连续问题无内建支持学术免费对LP的二次维也处理能力强CPLEX快无内建支持学术免费老牌接口稳定MATLAB intlinprog慢一个数量级无随Matlab自带小算例验证够用大规模不建议我的建议写代码和调试用小算例用intlinprog就行方便最终跑论文结果用Gurobi。用Gurobi时记得在YALMIP里显式传参ops.gurobi.OptimalityTol等YALMIP默认的参数不一定是最优配置。6.3 快速验证的小算例设计正式跑全规模算例前强烈建议先设计一个3节点、6时段的最小算例用来验证算法正确性。6时段的好处是人工心算也能验算主要约束而且CCG迭代1~2轮就能收敛方便打断点观察中间结果。小算例的设计原则只保留1台光伏、1台储能、1台柴油机IT负载只有一个高峰时段其他时段平稳电价只分峰/谷两段不确定集只考虑光伏一个参数Gamma取1或2。先跑通这个小算例确认CCG收敛、UB/LB单调变化、各约束都满足再去扩规模。这样做省下的调试时间至少半天起。复现中还有一个我多次遇到的坑把24时段和15分钟间隔搞混。很多论文里用15分钟作为调度步长但案例数据表又写成24小时平均值导致功率和能量的单位错位储能SOC算出来要么超过1要么低于0。我自己的习惯是第一步就把时间颗粒度写进参数表里所有公式统一用par.dt不在任何地方硬编码。7. 复现论文中的常见问题与对策7.1 场景膨胀导致主问题内存爆炸CCG迭代过程中每轮把最恶劣场景加进主问题但主问题的规模和迭代轮次线性增长。如果迭代20轮就是20个场景的约束和变量同时参与求MILP。算例中等规模还好大型微网10节点以上、时段96段可能会在10轮之后明显变慢甚至内存不足。对策有几个方向场景压缩如果多个历史场景对应的运行约束高度相似可以考虑只保留“代表性”场景但这会损失理论保证审稿人可能不接受增加收敛判据的容忍度MIPGap从1e-3放宽到5e-3能显著减少迭代轮数代价是结果偏差0.5%左右给每轮主问题加时间限制比如600秒超时返回当前最优整数解而不是继续搜这样即使不能收敛到全局最优也能得到可行方案用Benders分解替代CCG的一部分约束添加但实现复杂度会上升。我实测下来最有用的是MIPGap放松到1e-3再结合TimeLimit。精度损失在可接受范围求解时间能缩短一半以上。7.2 不确定集参数Gamma的取值范围怎么定Gamma取值太小鲁棒性体现不出来结果和确定性差不多取值太大系统设计过于保守储能光伏容量严重冗余运行成本高得离谱。推荐做法先跑Gamma0的确定性基线和Gamma10的极端鲁棒对比两个方案下的成本差和容量差再在之间等距取5~7个点画灵敏度曲线。如果曲线在Gamma4到6之间出现明显拐点那论文讨论就可以聚焦在这个区间。值得注意的是Gamma的物理意义和不确定参数的个数直接相关。比如有24个时段的光伏不确定参数Gamma6意味着允许最多6个时段的光伏出力同时遭最恶劣偏差也就是最不利时间段的四分之一。Gamma这个口径一定要在论文表述里写清楚别让审稿人猜。7.3 数据单位与量纲的常见陷阱还有几个我和学生复现时反复中招的单位问题功率用kW但电价按元/kWh计算购电成本时是功率乘以电价再乘以时间步长小时储能容量用kWh但不能直接和功率约束比较要先乘额定功率或时长再比较碳排放成本如果按tCO2算注意燃料的排放因子乘以出力kW和时间h再除以1000换算成吨如果给的是标幺值p.u.要清楚基准容量是多少MW否则所有结果都是错的。安全起见你可以在代码里写一个断言检查assert(max(SOC_opt) 1.01 min(SOC_opt) -0.01, SOC越界);每一轮迭代都检查一遍结果越界就停下来回头查模型。做仿真的数据校验的功夫省不了。7.4 和论文结果对不上怎么处理EI复现最让人头疼的就是跑了老半天出来的成本和论文里的数值差一大截有时根本不在一个量级。这时候可以从几个角度排查参数口径论文里是否包含了折旧系数、通货膨胀率、残值有些论文的投资成本是等年值有些是总现值转成同一个口径再比时间范围规划年限是10年还是20年折现率是8%还是5%对最终成本的量级影响很大不确定集合几何论文用的是盒式还是预算Gamma取值多少差一个Gamma就可能差10%以上的成本基础假设光伏投资成本是不是考虑了补贴储能是不是按倍率比如2C配置的这些细节论文里常一笔带过复现时全是坑。我的建议是不要追求和论文数值完全一致重点是复现“趋势”。只要容量配置随Gamma增加的趋势一致、成本曲线形状一致、不同方案优劣排序一致你的复现就算成功了。数值有个5%~15%的偏差在论文复现里太正常了。8. 最后再分享一点个人体会做这个方向的复现我前前后后写了不下五个版本从最开始的确定性优化到盒式鲁棒到预算鲁棒再到CCG每一步都踩了不少坑。印象最深的一次是子问题对偶变换漏了一个非负变量约束结果CCG迭代了20轮都不收敛UB和LB越拉越开最后发现是松了对偶变量的符号约束导致对偶问题不可行。从那以后我每次写完对偶都要先跑随机数据验证一遍再进主流程。另外Matlab代码的工程化也值得下点功夫。我见过很多复现代码变量全是a、b、tmp根本没法维护。建议从一开始就用有意义的变量名P_ch_ess储能充电功率、P_dch_ess储能放电功率、SOC_ess储能荷电状态、P_pv_curtail光伏弃光量。多写几个字母不累但调试的时候能省你几个小时。如果你也想复现这个论文可以按这样的学习路径走第一步把确定性两阶段模型建起来跑通一个24时段算例这是基本功第二步加盒式不确定集用枚举法手算最恶劣场景理解鲁棒的意义第三步换预算不确定集实现CCG画出收敛曲线第四步逐步添加灵活性建模时移负载、UPS、蓄冷对比不同灵活资源对规划结果的影响。每一步都能产出有意义的结果也都能单独成文。这样按阶段推进比一口气想复现整个论文要稳得多。以后有机会我再写一篇专门讲怎么把CCG扩展成多阶段鲁棒或者分布鲁棒的文章。这是一个越研究越有嚼头的方向建模和算法都有很多可以挖的细节。
返回列表