☰
能源集线器双层出清模型MATLAB实现:从KKT到MILP全解析
2026/10/3 10:32:59 网站建设 项目流程

做综合能源优化研究的人,应该都绕不开“能源集线器”这个词。最近我把一个典型的电热综合能源市场双层出清模型完整落地了一遍,用MATLAB从建模、求解到结果分析全程跑通,整个过程踩了不少坑,也积累了一些很实用的经验。这个模型解决的是一类很现实的问题:当多个能源集线器同时接入电力和热力市场,它们各自追求自身利润最大化,而市场运营方还要兼顾整体社会福利,双方目标不一致,用传统的单层优化根本无法准确描述这种博弈关系,只能走双层出清的路子。这篇博客就是把我从模型拆解、KKT条件转化到MATLAB代码实现、调试排错的全过程梳理出来,适合正在做综合能源系统、电力市场出清、能源集线器模型方向的研究生和工程师参考。文章里不会只贴公式和代码,更多是讲清楚为什么这样建模、为什么这样求解,以及实际写代码时容易在哪里翻车。

1. 从标题拆解开始:这个模型到底在做什么

1.1 “能源集线器”不是一块铁板,而是能源转换的纽带

很多刚接触综合能源的同学,看到“能源集线器”第一反应是某个具体设备,其实它更像一个“能量路由器”的抽象壳子。一个典型的能源集线器内部可以同时包含热电联产机组CHP、燃气锅炉、电锅炉、变压器,甚至蓄热罐,输入端是电力、天然气,输出端是电、热(也可以扩展到冷)。它的核心价值在于刻画不同能源形式之间的转换和耦合,用一个耦合矩阵就能把“输入是什么、输出是什么、转换效率多少”描述清楚。

拿我做的小型测试系统举例,其中1号能源集线器EH1只装了CHP和燃气锅炉,输入是电和天然气,输出是电和热。CHP的电效率是0.35,热电比1.2,燃气锅炉效率0.9,那么这台EH对外的特性就很明确:烧气既能发电也能供热,买电只能通过变压器直接供电。这种结构化描述的好处是,不管EH内部设备多复杂,对市场层面来说就是一个可调节的“电-热联供节点”。

在双层出清框架下,能源集线器不是简单被调度的对象,而是有自己经济诉求的市场主体。它会根据市场给出的电、热价格,自主决定买多少电、买多少气、内部哪些设备开机。这种“自主决策”的行为,正是双层模型要刻画的。

1.2 双层出清:为什么单层模型做不到?

很多人会问,单层模型把全系统的设备统一优化,目标函数做成总成本最小,不是更简单吗?确实更简单,但那隐含了一个前提:所有设备都由同一个调度中心直接控制,设备所有者没有自己的利益诉求。

真实市场显然不是这样。能源集线器的持有者是一个独立运营商,他关心的是自己赚了多少钱,而不是整个系统的总成本。给他下指令“你这台CHP要开50%出力”,他可能因为边际成本高于市场电价而拒绝;但是如果你告诉他“市场出清价格现在是0.52元/kWh,在电价高的时候多发电卖给系统,在气价低的时候多烧气制热”,那他就会自己算清楚账,做出对自身最有利的决策。上层定价格、下层做响应,这种层级决策关系就是双层模型的来源。

单层模型最大的毛病是把所有主体的目标硬揉成一个,抹平了利益冲突;双层模型保留了这种冲突,用“价格”作为上下层之间的桥梁。上层市场运营商发布出清价格,下层能源集线器看到价格后调整购能策略,而这些策略又反过来影响上层的供需平衡和价格,最终收敛到一个均衡状态。这是完全不同的求解逻辑。

1.3 完整市场框架:谁在上一层,谁在下一层

我搭的框架是这样:上层是一个独立系统运营商ISO或者叫市场交易中心,负责统一出清电、热两个能量市场。它从上级电网买电、从天然气源买气,然后卖给各个能源集线器,同时还要满足系统中不经过EH的刚性电、热负荷。上层追求的目标是系统总供能成本最小化,输出的是各时段出清电价、出清热价以及各EH的中标购能量。

下层是若干个能源集线器运营商。每个EH在自己所在的区域有固定的电负荷和热负荷,必须满足;它从市场上买电、买气,通过内部设备转换后供给用户。EH的目标是自身利润最大化,利润等于向用户售能的收入减去购电购气的成本和设备运维成本。

上下层之间就是通过价格联动的:上层先给出价格,下层在价格指导下做最优决策;下层的最优决策又必须满足上层的供需平衡。这个循环在数学上不是简单迭代,而是用一个叫做MPEC(Mathematical Program with Equilibrium Constraints,均衡约束数学规划)的模型一次性刻画,后面我会详细讲怎么把它变成能交给求解器跑的MILP。

2. 数学模型:把博弈关系写成可求解的优化问题

2.1 上层出清模型的目标函数与约束

先定义上层需要决策的量。我设了24个时段,每个时段有:从上级电网购入的功率P_grid(t)、从天然气源购入的气量G_gas(t,折算成kWh)、以及市场上对每个EH的中标电量P_buy,i(t)和中标气量G_buy,i(t)。所有这些变量都由上层优化决定,但要受到下层回应行为的约束。

上层目标函数是系统总供能成本最小化:

min Σ_t [ C_grid(t)·P_grid(t) + C_gas·G_gas(t) ]

其中C_grid(t)是时段t向上级电网购电的单位成本,C_gas是天然气折算成单位能量的成本。注意这里不是“出清价格”,而是运营商的采购成本。真正给用户看到的市场出清价,是后面平衡约束对应的拉格朗日乘子,我放到3.4节讲怎么提取。

上层的约束分几类:

  • 电力平衡约束:P_grid(t) + Σ_i P_buy,i(t) = D_e(t),其中D_e(t)是全系统在时段t的总电负荷;
  • 热力平衡约束:Σ_i H_buy,i(t) + H_aux(t) = D_h(t),H_buy,i是EH i在热市场上的中标热量,H_aux是后备热源出力;
  • 上级电网购电上限:0 ≤ P_grid(t) ≤ P_grid_max;
  • 后备热源出力上限:0 ≤ H_aux(t) ≤ H_aux_max;
  • 天然气源同样有供气上限,但一般算充裕的,设为较大值即可。

这里有个容易混淆的点:EH在热市场上买的热量H_buy,i,实际上是它内部燃气锅炉和CHP产热的总量减去自身消耗后的净外送量?还是EH直接从热网买的热?在电热综合市场里,我更倾向于把热力市场设计成“热力交易中心平衡热量供需”的形式:EH产热多的时候可以把热卖给热力市场,产热少的时候从市场买热补足自身不平衡。为了不让模型一开始就复杂到失控,我的做法是:假设每个EH的产热优先满足自身区域热负荷,如果产热有富余就卖给热网,不足就从热网买入。上层的热力平衡约束里,所有EH的热力交易量代数和加上后备热源,等于总热负荷。这样既保留了热力市场的耦合,又不需要引入完整的热网潮流方程,对于博客演示和大多数论文前期验证是足够的。

提示:如果论文要求更严谨,可以引入热网节点热力潮流模型,比如节点热功率平衡和管道传输损耗。但对于双层出清问题的核心博弈刻画来说,热力平衡约束用集中式简化并不会改变结论的大方向,计算量却能降一个量级。

2.2 下层能源集线器运行模型

下层是每个EH独立的利润最大化问题。以EH1为例,它内部有CHP和燃气锅炉。设p_chp(t)为CHP在t时段的电出力,h_gb(t)为燃气锅炉热出力,P_buy(t)为EH从市场买电的量,G_buy(t)为从市场买气的量。用户侧电负荷L_e(t)和热负荷L_h(t)是固定的。

EH1的电平衡约束:

P_buy(t) + p_chp(t) = L_e(t)

热平衡约束:

k_hr·p_chp(t) + h_gb(t) = L_h(t)

其中k_hr是CHP的热电比,k_hr·p_chp就是CHP产热量。天然气购买量和设备出力的关系是:

G_buy(t) = p_chp(t)/η_chp_e + h_gb(t)/η_gb

η_chp_e是CHP电效率,η_gb是燃气锅炉效率。这里G_buy和P_buy的单位都统一成kWh,天然气的价格C_gas也按kWh折算,避免单位换算的麻烦。

EH的目标函数是利润最大化:

max Σ_t [ π_e(t)·L_e(t) + π_h(t)·L_h(t) - π_e(t)·P_buy(t) - π_g(t)·G_buy(t) - c_chp·p_chp(t) - c_gb·h_gb(t) ]

这里π_e(t)和π_h(t)是上层给出的出清电价和出清热价,在EH视角看是已知参数;π_g(t)是天然气价格,也可以理解成市场发布的天然气价格。售能收入π_e·L_e和π_h·L_h因为负荷是固定值,等价于常数,所以实际上EH最大化的是“卖能收入减去买能成本和设备运维成本”。变量之间有耦合,CHP出力多了可以降低购电量,但会增加购气量;燃气锅炉烧气多可以少买热,但也要多买气。正是这种替代关系让下层问题有真实的优化自由度。

设备约束包括:

  • 0 ≤ p_chp(t) ≤ p_chp_max;
  • 0 ≤ h_gb(t) ≤ h_gb_max;
  • 0 ≤ P_buy(t) ≤ P_buy_max;
  • 0 ≤ G_buy(t) ≤ G_buy_max。

这个下层问题是典型的线性规划LP,决策变量连续,目标函数线性,约束全部线性。这非常重要,因为只有当底层问题是凸的,KKT条件才是全局最优的充要条件,后面转成MPEC才有理论保障。

2.3 双层问题的等价转化:KKT与强对偶

双层模型直接扔给求解器是没法解的,因为上层不知道下层会怎么反应。标准解法是用下层问题的一阶最优性条件KKT条件来替换下层问题本身,把双层问题变成一个单层的MPEC问题。

具体做三步。

第一步,写下层问题的拉格朗日函数。对EH1来说,引入电平衡约束的对偶乘子λ_e(t),热平衡约束的对偶乘子λ_h(t),设备上下限约束对应的乘子μ_1到μ_8。令拉格朗日函数对所有决策变量(p_chp、h_gb、P_buy、G_buy)求偏导等于零,得到一组线性等式,也就是驻点条件。

第二步,处理不等式约束的互补松弛条件。比如p_chp(t)的上限约束对应的互补条件就是:μ_up(t)·(p_chp_max - p_chp(t)) = 0,μ_up(t) ≥ 0。这个条件是非线性的,而且包含“要么这个为0、要么那个为0”的组合逻辑,直接塞给MILP求解器不行。通用做法是引入0-1二进制变量z,用大M法线性化:p_chp_max - p_chp(t) ≤ M·z,μ_up(t) ≤ M·(1-z)。当z=1时上限约束可以松弛,乘子必须为0;当z=0时乘子可以自由,上限约束必须满足。这本质上是用整数变量把一个“二选一”的互补关系转成一组线性约束。

第三步,处理下层目标函数里的双线性项π_e(t)·P_buy(t)。π_e是上层给的价格,P_buy是下层变量,两者相乘在目标函数里是非线性的。很多教程会卡在这一步,其实只要下层问题是凸的,强对偶定理就成立:下层问题的最优目标值等于其对偶问题的最优目标值。利用这个关系,可以把双线性项替换成对偶变量和约束右端项的组合,整体变成线性。这一步做完之后,整个MPEC就是一个标准MILP(混合整数线性规划),交给Gurobi或CPLEX就能求全局最优解。

注意:强对偶成立的前提是原问题可行且有界,LP天然满足。这也是为什么我刻意把下层建模成纯线性规划,哪怕少刻画一些非线性设备特性,也要保住可求解性。如果下层是非线性问题,KKT不再等价,强对偶也失效,那整个求解难度就完全不是一个量级了。

3. MATLAB实现:从数学公式到可运行代码

3.1 运行环境与工具选型

我用的环境是MATLAB R2023b加YALMIP再加Gurobi 10.0。为什么选这套组合,不是因为它最热门,而是因为它最适合做双层优化的快速验证。YALMIP是一个建模层,让你用接近数学公式的方式写优化问题,不用手动把所有约束展开成矩阵形式;Gurobi是目前求解MILP速度最快的商业求解器之一。如果你手头有CPLEX或者MATLAB自带intlinprog,也可以替换,但实测下来Gurobi在带大量二进制变量的问题上明显更稳。

网上经常有人纠结YALMIP到底怎么安装,其实很简单:从GitHub下载YALMIP源码,把整个文件夹加入MATLAB路径,然后在YALMIP目录下运行yalmiptest检查环境是否识别到求解器即可。我建议用比较新的版本,老版本的YALMIP在处理某些大M约束和乘子提取时会有莫名其妙的bug。

需要注意的一点是,我前面说的“用正版授权环境”,你安装的MATLAB和Gurobi都应该是合法授权的。Gurobi有学术授权,学生用邮箱申请一个licence,个人电脑上就能跑,不用去碰网上那些乱七八糟的破解包,费时间也不安全。

3.2 测试系统参数设计

我在初版验证时用了3个能源集线器,24个时段,集成了一组小型测试数据。设备参数和价格参数如下表:

参数EH1EH2EH3
设备组合CHP+燃气锅炉燃气锅炉+电锅炉CHP+电锅炉
CHP电效率0.35-0.32
CHP热电比1.2-1.0
燃气锅炉效率0.900.92-
电锅炉效率-0.950.95
CHP最大电出力/kW300-250
燃气锅炉最大热出力/kW500600-
电锅炉最大热出力/kW-200300
电负荷峰值/kW500400450
热负荷峰值/kW400500350

系统的其他公共参数:上级电网购电上限2000kW,分时购电成本低谷0.30元/kWh、平段0.45元/kWh、高峰0.65元/kWh;天然气折算成本固定为0.32元/kWh;天然气源供气上限足够大,设为5000kW。后备热源容量200kW,成本0.18元/kWh。

关于天然气价格折算,有学生问过我怎么把元/m³换成元/kWh。天然气低热值一般取9.7 kWh/m³,如果气价3.1元/m³,那么每kWh天然气的成本就是3.1/9.7≈0.32元。这个换算是做综合能源仿真绕不开的基础操作,建议写进程序的参数注释里,不然隔一个月自己都忘了0.32是怎么来的。

3.3 主程序框架与关键代码逻辑

整个实现的核心思路是:先定义上层变量和约束,再定义下层EH问题并手写KKT条件,用大M法线性化互补松弛条件,最后合并成一个大优化问题求解。下面给出主程序的核心结构,我用的是YALMIP语法,尽量保留关键细节但去掉冗长的循环展开。

%% 双层出清模型主程序框架 T = 24; % 公共参数 C_grid = [ones(8,1)*0.30; ones(8,1)*0.45; ones(8,1)*0.65]; % 分时购电成本 C_gas = 0.32 * ones(T,1); P_grid_max = 2000; % 出清变量(上层) P_grid = sdpvar(T,1); G_gas = sdpvar(T,1); H_aux = sdpvar(T,1); % 每台EH的决策变量(下层,但最终并入上层模型) % 以EH1为例 P_buy1 = sdpvar(T,1); % EH1从市场购电 G_buy1 = sdpvar(T,1); % EH1从市场购气 p_chp1 = sdpvar(T,1); % EH1 CHP电出力 h_gb1 = sdpvar(T,1); % EH1 燃气锅炉热出力 % EH1设备参数 eta_chp_e1 = 0.35; k_hr1 = 1.2; eta_gb1 = 0.9; p_chp1_max = 300; h_gb1_max = 500; % 上层目标:系统供能总成本最小 Objective = sum(C_grid.*P_grid + C_gas.*G_gas + 0.18*H_aux); Constraints = []; % 上层平衡约束 Constraints = [Constraints, P_grid + P_buy1 == D_e_total]; % 实际要展开成所有EH Constraints = [Constraints, k_hr1*p_chp1 + h_gb1 + H_aux == D_h_total]; % 下层KKT条件:以EH1为例手动写出 % 1) 拉格朗日函数对p_chp1的偏导为0,引入对偶乘子 lambda_e1 = sdpvar(T,1); % 电平衡乘子 lambda_h1 = sdpvar(T,1); % 热平衡乘子 mu_chp_up = sdpvar(T,1); % CHP上限乘子 ... % 驻点条件示例 Constraints = [Constraints, ... % dL/dp_chp1 = 0 lambda_e1 + k_hr1*lambda_h1 - 1/eta_chp_e1*C_gas - c_chp - mu_chp_up + mu_chp_lo == 0]; % 2) 互补松弛条件线性化示例 M = 1000; z_chp_up = binvar(T, 1); Constraints = [Constraints, p_chp1_max - p_chp1 <= M*z_chp_up]; Constraints = [Constraints, mu_chp_up <= M*(1 - z_chp_up)]; % 最终求解 ops = sdpsettings('solver', 'gurobi', 'verbose', 2); optimize(Constraints, Objective, ops); % 提取出清价格 price_e = dual(Constraints_balance_e); price_h = dual(Constraints_balance_h);

上面这段代码只是框架,不能直接复制运行,但它展示了整个项目的核心逻辑:上层目标、平衡约束、下层驻点条件、互补松弛的二进制变量线性化。实际开发时要把这些结构包进循环函数里,对每个EH重复生成,代码量大概会到300到400行。有耐心的同学可以自己封装一个buildEHModel函数,输入EH参数,输出变量、约束和KKT条件,这样后续扩展EH数量很方便。

3.4 出清价格的提取方法

出清价格是整个模型最有经济含义的输出。它不是一个决策变量,而是平衡约束的拉格朗日乘子。在YALMIP里提取乘子很简单,先给平衡约束命名,比如Constraints_balance_e = [P_grid + P_buy1 == D_e_total],求解之后用dual(Constraints_balance_e)就能取到每个时段的出清电价。热价同理。

为什么要这么提取?从经济学角度理解,平衡约束乘子代表“多供应1kWh能量时系统总成本能降低多少”,也就是这个时段能量的边际成本。市场出清价格等于边际成本,这是所有能量市场的基本原理。如果你的模型里电力平衡约束松弛了,那这个时段的乘子就会是0,含义是该时段供大于求,能量已经没有稀缺性,价格自然拉低。

实操中我踩过一个坑:YALMIP里如果平衡约束中存在多个变量乘积或者约束被简化整理过,dual返回的乘子顺序可能和你预期不一致。解决办法是约束生成后立刻用display命令检查YALMIP的约束编号,确保提取时下标与时段一一对应。

4. 仿真结果分析:三种典型工况下发生了什么

4.1 场景设置与基准方案

为了验证模型的合理性,我设计了三组算例。方案A是基准场景:三个EH全部参与,天然气价格为0.32元/kWh,用户负荷按典型冬季日曲线给定。方案B是耦合增强场景:把EH1的CHP热电比从1.2提高到1.5,近似模拟CHP技术改造或工况调整。方案C是天然气涨价场景:气价涨到0.45元/kWh,其他条件与方案A一致。

这样设置的好处是能分别看出“设备特性变化”和“燃料价格变化”对市场出清结果的影响,也方便做敏感性分析。如果直接拿一个复杂场景跑完看结果,很难判断哪些现象是哪个参数造成的。

4.2 出清价格与购能策略结果解读

方案A跑出来的电价曲线呈现明显的两峰特征,高峰出现在上午10点到12点以及晚上18点到21点,最高出清电价0.71元/kWh,低谷段最低0.28元/kWh。热价整体跟随电价变化,但峰谷差要小一些,因为燃气锅炉的调节能力比电网购电路径更灵活。

仔细看EH的购能策略,最典型的发现是:在电价低谷时段,EH1会加大购电量,但CHP出力反而压到很低,因为直接买电比烧气发电划算;在电价高峰时段,EH1会把CHP出力拉满,同时燃气锅炉启动补充供热,尽量用气来“替代”高价电。这种“价格信号引导设备出力”的行为,正是双层模型想要捕捉的博弈结果。如果换用单层集中调度模型,这个替代逻辑也能出来,但EH1不会表现出“利润最大化”驱动的主动性,而是被动执行统一指令,两者在市场环境差异下会产生明显的结果偏差。

方案B把EH1热电比从1.2提高到1.5后,系统整体购气量上升了12.6%,电价高峰时段的出清价下降了约0.04元/kWh。原因是热电比提高后,CHP在同等发电量下能产生更多热,挤掉了一部分高成本燃气锅炉出力和热网购热需求,系统热力侧的供给压力变小,边际成本随之下降。这个结果对工程选题很有价值,说明CHP的热电比参数本身就是影响电-热耦合市场出清的关键变量。

4.3 参数敏感性测试与结果汇总

天然气价格对出清结果的影响很直接。方案C中气价从0.32元/kWh涨到0.45元/kWh,涨幅约40%,结果系统总成本上升了大约18%,高峰电价上升0.09元/kWh,EH总利润平均下降约22%。这里需要注意的是,气价上涨并不均匀影响所有EH,EH1这种以CHP为主体的单元受影响最大,而EH2因为装备了电锅炉,电转热路径可以替代一部分燃气供热,利润下降幅度就小得多。这说明设备组合的多样性本身就是应对燃料价格风险的对冲手段。

我把三组方案的核心指标整理成下面这张表:

指标方案A基准方案B热电比提高方案C气价上涨
系统总供能成本/元204361978224176
高峰出清电价/元/kWh0.710.670.80
低谷出清电价/元/kWh0.280.300.25
天然气总购入量/kWh142301602012150
EH平均利润/元312032802436

这张表最值得琢磨的是环境信号:气价上涨反而让天然气总购入量下降,这是价格机制起作用的正常结果。燃气驱动路径变得更贵,系统自然会寻求更多电转热和电网购电来满足负荷需求。

5. 少有人写的踩坑记录:双层模型调试实录

5.1 大M取值的两个极端

调试双层模型时,报错最多的地方就是大M参数。我一开始图省事设M=10000,结果求解器频繁报数值问题,松弛变量各种异常波动;后来试过M=100,解倒是快了,但部分工况下互补条件被错误截断,出清价格偏离理论值。

我的最终经验是:M的取值应该和模型中的物理量纲挂钩,一般取最大可能量级的10到20倍即可。比如设备出力上限是500kW,价格乘子量级在1元/kWh以内,那么互补松弛约束里的M取1000就够。理论上M=1000可能仍然偏大,但Gurobi对这类规模的MILP数值稳定性是有保证的,关键是不要取到万、十万那种量级,否则求解器内部容差会出现灾难性误差。

还有一个经验是M参数不要全局统一,可以按约束类型分别设置。产出上限约束的M就按产出上限算,价格乘子约束的M按价格上限算,各个约束独立取合适的M,整体数值条件会好很多。这也算是我调试了三个项目总结出来的通用套路。

5.2 互补松弛条件线性化的常见低级错误

很多第一次写KKT线性化的人容易把方向写反。互补松弛条件的本质是两个不等式不能同时“激活”:要么乘子为0、要么约束余量严格为正。我见过的最典型错误是把条件写成p_chp_max - p_chp ≥ M·z,这样当z=0时约束余量必须是正数,也就是CHP不允许达到上限,直接改变可行域。

正确写法是两种状态各用一个大M约束控制。以CHP上限约束为例:

  • 当z=0时,要求p_chp_max - p_chp ≤ M·0 = 0,即CHP出力必须等于上限;
  • 同时要求mu_chp_up ≤ M·(1-0)=M,乘子可以自由;
  • 当z=1时,要求p_chp_max - p_chp ≤ M,即出力可以不到上限;同时要求mu_chp_up ≤ 0,加上非负约束后乘子只能等于0。

理解这个逻辑之后,所有互补条件都不会写错。强烈建议在代码里给每个二进制变量写注释,说明它取1和取0分别代表哪种状态,不然第二天再看代码基本像看天书。

5.3 求解器报infeasible的排查顺序

双层模型一上来就跑出infeasible是家常便饭,我自己的排查顺序是:

第一步,先只跑上层模型,把EH的所有变量固定成一组合理值,看上层是否可行。如果不可行,说明上层平衡约束或上下限设置有矛盾。第二步,只跑单个EH的下层模型,给定固定的出清价格,看LP是否有解。如果无解,多半是设备容量设置得太小,负荷在某些时段无法被满足。第三步,把上下层通过KKT拼起来后如果还是不可行,重点检查互补松弛条件和乘子方向是否一致。第四步,再不行就考虑是不是大M取值过了头,把原可行解切掉了。

按这个顺序排查,通常能定位到具体是哪类约束出的问题,而不是像无头苍蝇一样乱试。我最高纪录是一次夜里调了两小时,最后发现是热平衡约束里有个热电比写成了0.12而不是1.2,一个低级错误导致所有工况全不可行。所以建议在调试阶段把热电比、效率这些关键参数用assert检查一遍取值是否在合理区间,能省大量时间。

5.4 计算效率优化经验

带二进制变量的MILP计算量会随EH数量和时段数快速增长。我见过的学生项目动辄上万个二进制变量,Gurobi跑起来非常慢。这里有几个实用优化技巧:

  • 能不加整数变量就不加。互补松弛条件的二进制变量数量等于“不等式约束数量×时段数”,尽量压缩设备约束的数量,比如把一些设备容量上限合并成购电上限,可以减少大量整数变量。
  • 上下层之间的固定耦合结构可以预消除。每个EH内部设备功率和购电购气量之间存在等式关系,可以在进入YALMIP之前用符号推导直接消掉一部分变量,减少求解规模。
  • 如果目标只是验证模型逻辑,先用3个时段跑通再扩展到24个时段。我调试时始终保留一个T=3的小模型,几秒钟就能出结果,改完参数先在小模型上验证,最后再全时段运行。

这套东西的后续扩展空间也很大。比如可以加上碳交易成本,把碳排放约束写成上层约束或下层成本项;也可以把热网改成有管道损耗和时延的详细模型,让整合度更高。但不管怎么扩展,双层的核心博弈结构和MATLAB实现框架都不会变。我个人做项目的体会是:前期多花点时间把下层EH模型的“经济学含义”想清楚,比后期调代码重要得多。当你拿到一条出清价格曲线时,如果脑中能立刻浮现出“电价高是因为从上级电网买电的边际成本拉动了边际价格、热价低是因为燃气锅炉富余容量在压价”这种画面,那基本就说明你不是在跑模型,而是在真正理解市场。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询