ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

综合能源系统优化调度Matlab实现:MILP建模与Yalmip求解详解

综合能源系统优化调度Matlab实现:MILP建模与Yalmip求解详解 做综合能源系统优化调度的人都知道真正难的往往不是把数学模型写出来而是怎么把一套包含电力、热力、天然气多种能源耦合的约束体系落到一套可运行、可复现、可调试的Matlab代码里。IESIntegrated Energy System综合能源系统的优化调度方案核心就一件事在满足各时段冷、热、电负荷需求的前提下协调燃气轮机、锅炉、电制冷机、储能等设备的出力让整个系统一天的总运行成本最低。这篇博文我打算完整拆解一套我常用的Matlab实现方案从设备建模、约束构建、成本函数到Yalmip工具箱下的MILP求解流程再到典型案例的结果分析最后附上我调试过程中踩过的坑。如果你是刚接触IES调度的研究生或者在做园区综合能源项目的工程师这篇内容应该能帮你少走不少弯路。1. 项目核心拆解IES优化调度到底在算什么1.1 先拆清楚多能互补到底在补什么综合能源系统这个词听起来很宏大但落到工程上最常见的形态就是冷热电联供系统CCHP。一个典型的园区级IES里燃汽轮机或内燃机烧天然气发电发电产生的余热通过余热回收装置收集一部分去驱动吸收式制冷机供冷一部分通过换热站供热。电不够了就从电网买热不够了燃气锅炉补冷不够了电制冷机顶上再配一套电储能和蓄热罐做削峰填谷。这个结构里最核心的经济逻辑是能源的梯级利用。天然气先发电发完电的余热再拿去制冷或供热一份天然气当两份甚至三份能源用。但问题是发电、供热、供冷三种负荷的峰谷时段往往不一致比如夏天中午电负荷高但冷负荷也高冬天早晚热负荷高但电负荷相对低。如果每个设备都独立运行不考虑时段耦合整个系统的运行成本肯定不是最优的。优化调度要做的就是在一个统一的时间框架内通常是24小时、1小时一个时段把每个设备每个时段的出力、启停状态、储能充放策略全部算出来让总成本最低。1.2 输入输出逻辑给代码什么代码给你什么从代码实现的角度看IES优化调度问题本质上是数学优化里的混合整数线性规划MILP。把它拆解成输入和输出逻辑非常清晰输入一负荷预测数据包括逐时的电负荷、热负荷、冷负荷这是约束的右侧项。输入二能源价格参数分时电价、天然气价这是目标函数的系数。输入三设备参数包括容量上下限、效率、COP、爬坡速率、启停时间等。输出一各设备逐时出力计划包括燃气轮机发电功率、余热回收量、锅炉产热量、电制冷机耗电量等。输出二电网购电功率、天然气购买量。输出三电储能和蓄热罐的逐时充放功率与荷电状态。输出四总运行成本以及购能成本、启停成本、运维成本的分项明细。明白了输入输出代码结构就呼之欲出了读数据、定义变量、写约束、设目标、求解、画图。后面的内容全部围绕这六步展开。2. 设备建模与约束体系从物理设备到数学表达2.1 能量转换设备效率、爬坡和出力区间把所有设备抽象出来综合能源系统的核心设备分两类一类是能量转换设备一类是储能设备。先说转换设备。燃气轮机的建模最需要注意的是发电和余热回收之间的耦合关系。燃气轮机烧天然气发电发电功率 (P_{gt}) 对应的耗气量 (F_{gt}) 可以用发电效率表示[ F_{gt} \frac{P_{gt}}{\eta_{ge}} ]这里的 (\eta_{ge}) 是发电效率。但燃气轮机还有一个重要特性发电的同时产生余热。余热回收功率 (H_{gt}) 的经验公式一般是[ H_{gt} \frac{P_{gt}}{\eta_{ge}} \times (1 - \eta_{ge} - \eta_{loss}) \times \eta_{hr} ]其中 (\eta_{loss}) 是散热损失系数(\eta_{hr}) 是余热回收效率。这个公式的物理含义就是天然气总能量中一部分变成电一部分变成余热还有一部分散失掉了余热中能回收多少取决于回收装置效率。这里有一个在代码里必须处理的坑燃气轮机的发电效率不是常数它随部分负荷率变化。如果按常数算模型会严重偏离实际。但精确的非线性效率曲线会让问题变成非凸的求解困难。常规做法是——先用额定效率做基准线性模型再用分段线性化逼近真实效率曲线这样既保留精度又能保持MILP的可解性。新手建议先跑通常数效率版本再升级成分段线性化。出力区间约束也很关键。每个设备都有最小技术出力燃气轮机通常有个最小运行负荷率比如30%低于这个值干脆停机。用数学语言描述就是[ P_{gt}^{min} \cdot u_{gt}(t) \leq P_{gt}(t) \leq P_{gt}^{max} \cdot u_{gt}(t) ](u_{gt}(t)) 是0-1启停变量这个约束保证了“停机时出力只能为0开机时出力必须高于最小值”。燃气锅炉、电锅炉、电制冷机、吸收式制冷机这些设备的建模相对简单本质就是一个能量转换关系[ Q_{out} \eta \cdot P_{in} \quad \text{或} \quad Q_{cool} COP \cdot P_{ele} ]比如电制冷机的耗电量和制冷量关系就是 (Q_{ec} COP_{ec} \cdot P_{ec})COP取3.5到5之间。锅炉就是效率乘以输入燃料/电功率。注意COP和效率属性的区别锅炉的效率小于1因为损失热制冷机的COP大于1因为它搬运热量而不是生产热量这个物理含义要在写代码时想清楚别把COP和效率混用。2.2 储能设备一个二进制变量挡住所有穿越风险电储能和蓄热罐的建模套路几乎一样只是参数不同。以电储能为例子核心是荷电状态SOC的递推关系[ SOC(t) SOC(t-1) \cdot (1 - \sigma) \eta_{ch} \cdot P_{ch}(t) - \frac{P_{dis}(t)}{\eta_{dis}} ]其中 (\sigma) 是自放电率(\eta_{ch})、(\eta_{dis}) 是充放电效率(P_{ch})、(P_{dis}) 是充放电功率。这个公式要按每个小时滚动计算所以它天然是一个带时序的约束。储能建模最容易犯的错误是忘记加“同一时刻不能同时充放电”的约束。如果不加求解器为了满足某些平衡约束可能出现“一边充电一边放电”的荒唐结果白白浪费能源成本反而更高。必须在代码里加[ P_{ch}(t) \leq M \cdot u_{ch}(t) ] [ P_{dis}(t) \leq M \cdot u_{dis}(t) ] [ u_{ch}(t) u_{dis}(t) \leq 1 ]M是一个足够大的常数(u_{ch})、(u_{dis}) 是0-1变量。这组约束的含义是充电和放电的二进制状态互斥不可能同时成立。这个细节直接决定储能模型的正确性非常重要。蓄热罐的建模思路一模一样区别只是单位从电功率变成热功率而且蓄热罐的自损耗通常用热损失系数表示一般比电储能的自放电率高一些。还有一点蓄热罐的SOC如果写的是蓄热量MWh那么热功率和蓄热量之间的时间步长要乘以1小时不能直接相加不然量纲对不上这一步会在后面的代码部分具体展示。2.3 供需平衡约束一个小时内电、热、冷必须两边相等综合能源系统里最难写、也最不能出错的就是能源平衡约束。这类约束描述的是“能源不能凭空产生也不能凭空消失”每个时段各能源品种的供给与需求必须严格相等。电平衡相对直接涉及的所有用电设备和供电设备都要列出来[ P_{buy}(t) P_{gt}(t) P_{dis}(t) P_{load}(t) P_{ec}(t) P_{eb}(t) P_{ch}(t) ]左边是供电源电网购电、燃气轮机发电、储能放电右边是负荷侧电负荷、电制冷机耗电、电锅炉耗电、储能充电。注意等式两边必须带上所有用电设备漏掉一个电锅炉的耗电平衡约束偏松成本计算就会出错。热平衡稍微复杂一点因为热源很多[ H_{gt}(t) H_{gb}(t) H_{eb}(t) H_{dis,th}(t) \geq H_{load}(t) H_{ch,th}(t) ]左边是热源燃气轮机余热回收、燃气锅炉产热、电锅炉产热、蓄热罐放热右边是热负荷加蓄热罐蓄热。这里我用的是大于等于号实际工程中热负荷可以适当少供热舒适度允许一定偏差但如果你希望严格精确直接写等号也行。我更推荐按“最小供热量约束”处理给热负荷加一个可调度区间这样求解器有更灵活的调节空间成本会更低也更接近实际运行中热用户的弹性需求。冷平衡同样是把冷源都列出来[ Q_{ac}(t) Q_{ec}(t) Q_{dis,c}(t) \geq Q_{cool,load}(t) ](Q_{ac}) 是吸收式制冷机的供冷量(Q_{ec}) 是电制冷机的供冷量蓄冷罐的放冷量如果有加进来。注意吸收式制冷机的输入是热功率输出是冷功率中间有个COP所以它的热耗变量同时出现在热平衡约束的左侧供冷量又出现在冷平衡约束的左侧这个“跨能源品种耦合”正是IES和独立系统最大的区别。3. 目标函数与成本模型最低运行成本怎么算3.1 成本构成购能成本是绝对大头优化调度问题的目标函数通常是最小化总运行成本。总成本由三块组成购能成本、设备启停成本、运维成本。购能成本是绝对大头包括购电成本和购气成本。分时电价下电网购电成本是逐时段电价乘以购电功率的累加[ C_{grid} \sum_{t1}^{24} \pi_{ele}(t) \cdot P_{buy}(t) ]购气成本更复杂一些因为天然气同时供给燃气轮机和燃气锅炉[ C_{gas} \sum_{t1}^{24} \pi_{gas} \cdot \left( F_{gt}(t) F_{gb}(t) \right) ]其中 (F_{gt}) 是燃气轮机的耗气量(F_{gb}) 是燃气锅炉的耗气量。如果用的是阶梯气价需要把购气成本分段线性化但大多数园区级项目还是按固定气价计算先跑通再说。启停成本是很多新手容易忽略的。燃气轮机启动一次有一定的燃料消耗成本和设备损耗成本频繁启停会显著影响运行经济性。在模型里用如下方式表达[ C_{start} \sum_{t1}^{24} \gamma_{start} \cdot \max(0, u_{gt}(t) - u_{gt}(t-1)) ]这个 (\max(0, u(t)-u(t-1))) 是非线性的但可以线性化引入一个启动变量 (v_{gt}(t))满足 (v_{gt}(t) \geq u_{gt}(t) - u_{gt}(t-1))然后把 (C_{start} \sum \gamma_{start} \cdot v_{gt}(t)) 放进目标函数。运维成本按设备运行状态计算通常是单位出力的系数比如电储能运维成本是每MWh充放电量的一个很小比例[ C_{om} \sum_{t} \left( k_{gt} \cdot P_{gt}(t) k_{gb} \cdot Q_{gb}(t) k_{ec} \cdot P_{ec}(t) \right) ]把三块加起来目标函数长这样[ \min \quad C_{grid} C_{gas} C_{start} C_{om} ]3.2 为什么用混合整数线性规划而不是粒子群很多做这个方向的同学第一反应是用粒子群算法、遗传算法或者改进灰狼算法去求解。我的建议非常明确如果追求工程可靠性和全局最优用Yalmip工具箱建模、调用Cplex或Gurobi求解器求解MILP远胜于任何启发式算法。原因有几个。第一IES调度问题的规模并不大决策变量通常是几千到几万个这个规模对商用求解器来说是小菜一碟几秒到几十秒就能得到全局最优解。第二MILP的求解结果有最优性gap的数学保证可以明确知道当前解离理论最优有多远而启发式算法只能给你“一个不错的结果”无法保证最优性。第三MILP模型后期扩展方便——加设备、加约束、改价格曲线都是加几行代码的事粒子群改一次适应度函数要折腾大半天。当然粒子群也不是一无是处。如果你要处理的是带非线性设备模型、包含大量非凸约束的复杂问题MILP可能无能为力这时候启发式算法反而是唯一选择。但那是进阶研究方向不是常规IES调度的最优解。我个人的经验是先写MILP模型用求解器计算如果确实有非线性模块需要保留再把MILP的结果作为初始解喂给启发式算法做二次优化。这种“精确解启发式精修”的组合在实际项目中非常实用。4. 求解方法与Matlab实现流程4.1 用Yalmip定义变量sdpvar、binvar和约束拼接Matlab下做优化建模我强烈推荐Yalmip工具箱。它的语法极其简洁把变量定义、约束组装、目标函数表达这几个环节简化到了近乎自然语言的程度。当然Yalmip本身不直接求解它只是个建模语言真正干活的是背后的Cplex或Gurobi。如果没装求解器Yalmip会调用Matlab自带的linprog处理纯线性问题但整数变量存在时linprog是搞不定的所以还是乖乖装一个Gurobi。变量定义分三类连续优化变量用sdpvar比如燃气轮机逐时出力、储能充放电功率。二进制变量用binvar表示设备启停状态、储能充放状态。整数变量用intvarIES里偶尔用于表示设备台数比如多台同型号机组并列运行时的台数调度。一个典型的变量定义代码是% 时间范围 T 24; % 定义连续变量 P_gt sdpvar(1, T); % 燃气轮机发电功率 H_gt sdpvar(1, T); % 余热回收功率 P_buy sdpvar(1, T); % 电网购电功率 P_ch sdpvar(1, T); % 储能充电功率 P_dis sdpvar(1, T); % 储能放电功率 SOC sdpvar(1, T); % 储能荷电状态 F_gt sdpvar(1, T); % 燃气轮机耗气量 F_gb sdpvar(1, T); % 燃气锅炉耗气量 % 定义二进制变量 u_gt binvar(1, T); % 燃气轮机启停 u_ch binvar(1, T); % 储能充电状态 u_dis binvar(1, T); % 储能放电状态我习惯把每个变量的物理含义写清楚注释。这个习惯在后期检查约束时能救命——几百行代码如果没有清晰的命名和注释两天后你自己都看不懂自己写的什么。4.2 约束组装用循环和向量化写平衡约束Yalmip写约束最基础的方式是循环。比如电平衡约束可以这样写Constraints []; for t 1:T Constraints [Constraints, P_buy(t) P_gt(t) P_dis(t) P_load(t) P_ec(t) P_eb(t) P_ch(t)]; end注意是等式约束和是不等式约束。Yalmip会自动识别这些符号生成约束。如果你不想用循环Matlab的向量化写法更快Constraints [Constraints, P_buy P_gt P_dis P_load P_ec P_eb P_ch];这个写法等于一次性生成一整条约束Yalmip内部会逐元素展开。我建议在约束少时用循环方便调试约束多时用向量化提升性能两种写法最终生成的模型是等价的。储能SOC约束也按这个思路写Constraints [Constraints, SOC(1) SOC_initial * (1 - sigma) eta_ch * P_ch(1) - P_dis(1) / eta_dis]; for t 2:T Constraints [Constraints, SOC(t) SOC(t-1) * (1 - sigma) eta_ch * P_ch(t) - P_dis(t) / eta_dis]; end这里特别强调一个新手容易犯的错SOC(1)那一条必须单独写因为SOC(0)不存在不能从零开始套递推公式。还有储能SOC要限制上下限for t 1:T Constraints [Constraints, SOC_min SOC(t) SOC_max]; end如果不限SOC范围求解器为了降低成本可能会把SOC充到超出物理极限的值。4.3 目标函数与求解调用optimize一句搞定目标函数的组装同样简单把各成本项的累加表达式列出来即可% 购电成本 C_grid sum(price_ele .* P_buy); % 购气成本 C_gas sum(price_gas .* (F_gt F_gb)); % 启停成本线性化后的启动变量 v_gt binvar(1, T); for t 1:T if t 1 Constraints [Constraints, v_gt(1) u_gt(1) - 0]; else Constraints [Constraints, v_gt(t) u_gt(t) - u_gt(t-1)]; end end C_start sum(start_cost_gt .* v_gt); % 总目标 Objective C_grid C_gas C_start; % 求解 options sdpsettings(solver, gurobi, verbose, 1, mipgap, 0.0001); optimize(Constraints, Objective, options);求解完之后用value()取结果P_gt_opt value(P_gt); P_buy_opt value(P_buy); SOC_opt value(SOC); objective_opt value(Objective);这里sdpsettings里的mipgap参数很关键它控制求解器允许的最优性gap。设成0.0001表示求解器要在0.01%的gap范围内停止设置太严格会拖慢求解太宽松则结果精度不够。一般工程场景设0.001到0.0001就够用了。4.4 结果输出与可视化画图之前先算对单位求解只完成了一半工作另一半是结果分析和出图。我见过太多人求解完只打印一个成本数值完全不知道调度方案长什么样。这不对优化调度的价值就在于每个时段的设备出力决策不画图根本看不出规律。常用可视化命令是figure; plot(1:T, P_gt_opt, r-, LineWidth, 1.5); hold on; plot(1:T, P_buy_opt, b-, LineWidth, 1.5); plot(1:T, P_load, k--, LineWidth, 1.5); legend(燃气轮机出力, 电网购电, 电负荷); xlabel(时刻/h); ylabel(功率/MW); grid on;画图之前先检查单位。如果你输入的电负荷单位是kW但设备容量单位是MW画出来的图会乱得一塌糊涂。我通常统一用MW作为所有功率变量的单位时间步长为1小时那么能量单位就是MWh购电成本就是电价元/MWh乘以购电量MWh得到元量纲全程对齐。5. 案例演示一个典型园区的IES日调度5.1 案例参数与负荷数据设定用一个虚构的园区数据来完整演示这套流程。假设某园区有稳定的冷热电负荷设备配置为一台1.5MW燃气轮机、一台2MW燃气锅炉、一台0.8MW电锅炉、一台1MW电制冷机、一台1MW吸收式制冷机、一套0.5MW/1MWh电储能、一座2MW/4MWh蓄热罐。设备参数如下表设备参数数值燃气轮机发电效率0.35燃气轮机最小技术出力0.3 MW燃气轮机余热回收效率0.45燃气锅炉热效率0.90电锅炉热效率0.95电制冷机COP3.5吸收式制冷机COP1.2电储能充电效率0.95电储能放电效率0.95电储能SOC上限/下限0.9 / 0.1分时电价采用典型的峰平谷三段结构峰时10:00-15:00、18:00-21:001.2元/kWh平时7:00-10:00、15:00-18:00、21:00-23:000.75元/kWh谷时23:00-7:000.4元/kWh。天然气单价2.5元/m³折算成热值后大约是0.25元/kWh。电负荷在白天有两个高峰分别是上午10点和晚上19点峰值约1.6MW热负荷早晚高、中午低峰值约1.2MW冷负荷在下午高峰值约1.0MW。这些负荷曲线我直接写成数组放进代码里。5.2 求解结果与成本分析跑完之后结果很有规律。燃气轮机在全天的多数时段保持开机但出力跟随电负荷波动上午和晚上电负荷高时接近满发凌晨电负荷低时降低到最小技术出力附近。电网购电则集中在谷时和平时的前半段峰时段的购电量非常少。电储能的策略是典型的谷充峰放凌晨1点到6点充电上午10点到12点和晚上19点到21点放电把谷时电价差的收益全部吃满。蓄热罐的调度逻辑和电储能类似但更受热负荷影响。它在凌晨蓄热白天热负荷高峰时放热配合燃气轮机的余热显著减少了燃气锅炉在高峰期的出力燃气锅炉在一天中只启动了少量时段。电锅炉由于电价在峰时太贵几乎没有运行。总运行成本的构成大概是购电成本占30%购气成本占60%启停成本和运维成本占10%。购气成本是大头这件事并不意外因为燃气轮机燃气锅炉承担了大部分热负荷和一部分电负荷。但这个比例会随着电价和气价的变化而显著漂移也是后面敏感性分析要关注的重点。5.3 方案对比协同调度比独立运行省多少为了体现IES多能协同的经济价值我做了一个对比实验把同样的负荷数据按分产系统的方式计算成本即电负荷全部从电网购买热负荷由燃气锅炉独立供应冷负荷由电制冷机独立供应没有余热回收、没有储能、没有设备间的能源耦合。结果很直观分产系统的日运行成本比IES协同调度高出约18%到25%具体数字取决于当天的负荷曲线和电价水平。成本差异主要来自两个原因一是余热回收把原本浪费的燃气轮机余热变成了有用的热源减少了燃气锅炉的天然气消耗二是储能设备让一部分电价较高的峰时用电转移到了电价较低的谷时平滑了购电成本。这个对比结果几乎每个案例都会出现但幅度不同。如果你的IES项目里热负荷占比高、且燃气轮机长时间运行余热回收的价值就特别大。如果冷负荷占比高吸收式制冷机相比电制冷机的边际成本优势就会体现出来。做方案汇报时我很喜欢用这个对比图来展示“多能互补到底补出了多少钱”。6. 常见问题与调试经验写代码时最容易踩的坑6.1 模型无解约束冲突怎么定位这是新手问我最多的问题optimize返回的是Inf模型无解怎么办。无解的本质是约束之间互相矛盾但几百行约束里找到矛盾点并不容易。我的排查方法是“约束松弛法”。从最简单的约束集合开始求解逐步加约束每一步都验证可解性。具体操作如下先只加设备容量变量和边界约束求解能解再加平衡约束求解能解再加储能递推约束求解能解再加充放互斥约束求解。哪一步开始无解矛盾就出在哪一类约束里。还有一种很隐蔽的问题是SOC的初始值设置和最终值约束矛盾。比如SOC初值是0.5设置SOC终值必须等于0.5但储能在低谷时段充电后没有足够的放电时段把SOC降回来优化器怎么调整都达不到终值要求模型就无解。处理办法是要么放宽终值范围比如0.4到0.6之间要么延长调度周期要么让储能每天满充满放一次。工程上我更倾向于把SOC终值设为与初值相等但允许一定偏差这会大幅提升模型可解性。6.2 数值病态问题单位、量纲与求解器容差另一个高频问题是结果数值异常比如购电功率出现极小量1e-9而不是0或者SOC曲线出现不合理的微小波动。这通常不是建模逻辑错误而是求解器的数值容差在作怪。第一个要检查的是单位统一。我见过把设备容量设为MW、但负荷数据导入的是kW的案例结果平衡约束两侧量级差了1000倍CPLEX内部的数值缩放彻底乱了输出结果惨不忍睹。务必在数据导入后统一单位推荐全程用MW和MWh。第二个要检查的是“大M”的取值。储能充放互斥约束里的M如果取太大比如1e6会造成数值病态取太小比如小于最大充放电功率约束又会失效把可行解给砍掉。经验值是M取该设备最大充放电功率的1.1到1.5倍既能保证约束有效性又不至于破坏数值稳定性。求解器容差也值得微调。Gurobi默认的整数可行性容差IntFeasTol是1e-5一般场景够用。但如果结果里出现SOC曲线在某个时段出现0.09999这种值这就是容差导致的边界松弛不影响决策。如果你对结果精度要求苛刻可以设FeasibilityTol 1e-7但求解时间会变长个人觉得没太大必要。6.3 结果不符合物理直觉如何验证模型的正确性模型能解出数值不代表结果是对的。我见过有人跑完模型储能曲线看起来合理但购气量计算出来竟然是负数——后来发现是燃气轮机耗气量约束没加非负约束求解器为了满足平衡约束给了一个物理上不可能的负值。所以每个设备出力的变量都要加非负约束Constraints [Constraints, P_gt 0, H_gt 0, P_buy 0];最有效的验证方法是做“退化测试”。把系统简化成纯购电模式即关掉燃气轮机强制 (u_{gt}0)和储能强制 (P_{ch}P_{dis}0)看购电量是否等于电负荷。再做纯气模式即禁止购电看燃气轮机锅炉能否单独满足电负荷和热负荷。如果退化模型的结果和手算一致说明核心约束正确问题基本不在建模而在边界条件。还有一招很实用是做单设备启停测试。固定其他设备不运行只让燃气轮机运行观测它在不同负荷下的出力、耗气量、余热关系是否符合预期。这个测试能暴露效率公式写错、量纲转换错误、余热回收关系不符等隐蔽缺陷。6.4 收敛慢与性能优化技巧模型规模大时求解时间可能飙升到几分钟甚至更久。排在第一位的优化手段是减少整数变量个数。整数变量是MILP求解时间的主要瓶颈能用连续变量表达的约束就不用整数变量。比如电储能充放互斥如果你确定系统运行策略不会出现同时充放因为同时充放肯定增加成本最优解自然回避可以不加二进制变量只写SOC递推和非负约束。但这依赖于经济性驱动的隐性约束严格来说不加互斥变量不一定保证物理可行所以我个人还是建议保留除非你非常确信问题结构足够简单。第二个手段是设置MIP gap。工程上没必要追求proof of optimality的极限精度把mipgap设到0.0050.5%求解时间可能从20分钟降到30秒而结果成本只差0.3%以内。这个性价比非常高。第三个手段是合理设置时间限制。sdpsettings(solver, gurobi, timelimit, 300)让求解器最多跑5分钟超过时限就返回当前最优整数解。对于97%的工程场景5分钟内得到的解已经足够好。第四个手段是冷启动。先把模型简化比如把二进制变量全部固定到某个初始猜测值求解一遍把解作为MILP的MIP start传给求解器。Gurobi支持MIP start它能大幅缩减分支定界的搜索范围实测能在某些大规模模型上提速40%以上。这个技巧稍微进阶但值得掌握。最后分享一个小习惯我每次搭建新的IES调度模型从来不在完整模型上硬调。先花半个小时把系统缩成一个“微型版”——只有一台燃气轮机和一台电锅炉时间步长从24小时缩到6小时手动构造几组可以手算的负荷数据跑通之后校验结果验证通过后再逐步加入储能、冷负荷、多设备。这个习惯帮我过滤掉了大量低级建模错误让最终全规模模型一次求解成功。如果你刚开始接触这个方向强烈建议也试试这个流程——先在小模型上找到所有坑再放大到完整系统效率会高很多。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进