先说一下背景。我最近在研究园区级综合能源系统的日前调度问题,一开始天真地以为,只要把光伏和风电的预测曲线当成确定值塞进优化模型,算出来的就是能直接用的调度方案。结果一到实际运行就露馅了——某天光伏出力午间比我预测的高了30%,电储能直接被充满还被迫弃光,CHP机组照常满发,多了的电又卖不掉,整体运行成本比仿真结果高出快两成。后来我意识到,综合能源系统协同优化真正难的地方,不是把电、气、热多能流模型搭起来,而是怎么处理新能源出力不确定性。这篇博客就围绕我用Matlab做的一套"计及新能源出力不确定性的综合能源系统协同优化"代码,把建模思路、代码架构、求解过程和踩坑记录完整梳理一遍,希望对正在做相关方向毕业设计或科研课题的朋友有参考价值。
1. 为什么"不确定性"是综合能源系统协同优化的第一道坎
1.1 一个实际才能体会到的痛点:预测误差如何击穿调度方案
光伏和风电的出力预测,不管用数值天气预报还是统计学习方法,误差都客观存在。我做过一段时间的实测数据统计,在典型日尺度上,光伏功率预测的平均绝对百分比误差能做到10%~15%就算不错,遇到多云或突变天气,单点误差飙升到30%以上很常见。风电更夸张,风速的随机性导致出力波动范围很大,尤其在阵风时段,15分钟级出力可以从额定功率的20%跳到80%。
如果优化模型把预测值当真值处理,那么约束条件里的功率平衡方程在真实运行时大概率被打破。解决办法是实时调整,一调整就牵一发动全身:CHP机组爬坡跟不上、储能SOC被提前耗尽、电锅炉供热与热负荷错配。我印象最深的一次仿真,确定性调度方案给出的购电计划是平滑的阶梯曲线,但实际执行时几乎每隔一个时段就要重新修正,最终经济性还不如一个保守的固定方案。这就是不确定性带来的"隐形成本",它不会直接出现在确定性模型的公式里,却真实发生在每一次运行决策中。
所以,处理不确定性的本质,不是追求一个精确的"最优解",而是追求一个在各种可能出力场景下都不太差、且经济性可接受的"稳健解"。
1.2 不确定性建模的四种主流思路对比
在综合能源系统优化领域,处理新能源出力不确定性的主流方法大致有四类,我用了很长一段时间逐一调研和测试,这里直接给出对比结论。
| 建模方法 | 基本思想 | 优点 | 缺点 | 典型应用场景 |
|---|---|---|---|---|
| 随机规划(场景法) | 用离散场景集合近似连续概率分布 | 模型直观,能给出兼顾经济性的期望最优解 | 场景数量大时求解规模膨胀,缩减不当会丢失信息 | 日前调度、机组组合 |
| 鲁棒优化 | 用不确定集合描述出力波动范围,保证最坏情况下可行 | 决策保守但可靠性极高,求解效率高 | 结果偏保守,经济性偏差 | 极端天气安全校核 |
| 区间优化 | 用区间数直接描述出力上下界 | 只需上下界数据,建模简单 | 不能体现区间内概率分布信息 | 数据匮乏场景 |
| 模糊机会约束 | 用模糊隶属度函数描述不确定性 | 可以在一定置信水平下放松约束 | 隶属度函数选取主观性强 | 中长期规划 |
我的实际选择是随机场景法为主,结合同步回代缩减技术。原因是:综合能源系统协同优化本身已经包含电、气、热多种异质能流的耦合约束,鲁棒优化虽然求解快,但所有不确定约束都按最坏情况去卡,CHP机组出力和储能充放电会被严重限制,经济性损失太大;而场景法能比较精细地反映风电光伏出力的概率分布特性,配合场景缩减技术,可以用较少的典型场景逼近原始分布,兼顾精度和计算效率。
1.3 场景法落地时要回答的三个问题
用场景法做不确定性优化,代码实现前必须想清楚三件事:
- 场景从哪里来?通常做法是用历史数据拟合风速的Weibull分布和光照强度的Beta分布,再通过蒙特卡洛抽样生成大量初始场景。如果没有历史数据,也可以用典型日出力曲线叠加正态分布噪声来构造。我在项目里采用的是后一种思路,参数设置时参考了当地气象站多年平均数据,保证抽样结果的统计特征符合常识。
- 场景缩减到什么程度?初始场景我取了1000个,缩减到20个。缩减后的典型场景应该能保留原始场景集的均值、方差和相关性特征。这个数量是权衡求解时间和精度后定的,如果你发现缩减后的场景间差异不明显,可以把目标场景数提高到30或50。
- 概率怎么赋?场景缩减完成后,每个典型场景需要分配一个概率值,所有场景概率之和为1。目标函数中需要对各场景下的运行成本做期望运算,也就是每个场景的成本乘以对应概率再累加。这一步如果写错,求解结果会直接偏掉。
2. 系统建模:把"电-气-热"耦合关系写成数学语言
2.1 能源集线器视角下的系统架构
我构建的综合能源系统模型,核心框架采用能源集线器(Energy Hub)思想。简单说,变电站、燃气轮机组、电锅炉、燃气锅炉、储能装置这些电气设备和能源转换设备,共同构成一个多输入多输出的能量转换单元。输入端是外部电网购入电力和天然气网购入燃气,外加风光新能源出力;输出端满足电负荷、热负荷两类刚性需求。
能源集线器的输入输出关系可以写成矩阵形式:
[L_e] [η_ee η_ge] [P_e] [L_h] = [η_eh η_gh] * [P_g]其中L_e和L_h分别是电、热负荷功率,P_e和P_g分别是购入电能和购入燃气功率,η矩阵中的元素代表各条能量转换路径的效率。这个模型的可贵之处在于它把复杂的多能耦合关系压缩成矩阵运算,后续无论是写约束还是做灵敏度分析都非常方便。我在Matlab里就是按照这个思路先搭好能量转换系数矩阵,再写各个设备的详细约束。
2.2 关键设备建模与运行约束
CHP热电联产机组是综合能源系统的核心设备,它的特点是电出力P_chp和热出力Q_chp之间存在耦合关系。我用的是抽凝式机组线性化模型:
Q_chp(t) = a * P_chp(t) + b P_chp_min ≤ P_chp(t) ≤ P_chp_max -ΔP_chp ≤ P_chp(t+1) - P_chp(t) ≤ ΔP_chpa是热电比斜率,b是常数项。要注意的是,CHP机组在低负荷时热电比会变化,线性模型只能在某个工况区间内保持较高精度。如果实际项目中机组长期在部分负荷运行,建议用分段线性化处理,把可行域划分成多个线性段。
电锅炉和燃气锅炉建模相对简单:
Q_eb(t) = η_eb * P_eb(t), 0 ≤ P_eb(t) ≤ P_eb_max Q_gb(t) = η_gb * F_gb(t), 0 ≤ F_gb(t) ≤ F_gb_max其中P_eb是电锅炉消耗的电功率,F_gb是燃气锅炉消耗的燃气功率,η是各自热效率。电锅炉的价值在于消纳富余风电——在风电大发时段,如果系统向上级电网反送电不经济,就把多余电能转化为热能储存或直接供热。
储能系统我同时考虑了电储能和热储能,模型统一写成:
SOC_e(t+1) = SOC_e(t) + (η_ch * P_ch(t) - P_dis(t) / η_dis) * Δt SOC_min ≤ SOC_e(t) ≤ SOC_max 0 ≤ P_ch(t) ≤ P_ch_max * u_ch(t) 0 ≤ P_dis(t) ≤ P_dis_max * u_dis(t) u_ch(t) + u_dis(t) ≤ 1u_ch和u_dis是充放电状态二进制变量,这一步引入了整数变量,模型变成MILP问题。这也是为什么求解器需要选择Cplex或Gurobi这类商业MILP求解器的主要原因。电储能主要用来削峰填谷和应对不确定性带来的实时波动,热储能则配合CHP和电锅炉一起平滑热负荷曲线。
电气设备层面的网络约束:我没有把配电网三相潮流全部写进去,因为综合考虑电-气-热耦合和不确定性场景后,非线性潮流会严重拖慢求解速度。实际处理是在园区级尺度下采用功率平衡约束替代详细潮流,并给变压器、线路设置了最大传输容量约束。如果你的课题更侧重配电网层面,可以把DistFlow线性化潮流加进来,Matlab里用Yalmip结合Cplex也能处理,但求解时间会明显上升。
2.3 目标函数与完整约束体系
协同优化的目标是最小化系统总运行成本,包括购电费用、购气费用、设备运维费用和弃风弃光惩罚:
min Σ_s ρ_s * { Σ_t [ c_e(t)·P_grid(t) + c_g·F_gas(t) + c_om·(P_chp(t)+Q_chp(t)) + λ·(P_w_avail(t)-P_w_use(t)) ] }其中ρ_s是场景s的概率,c_e(t)是分时电价,c_g是气价,c_om是运维成本系数,λ是弃风弃光惩罚系数,P_w_avail是新能源可用出力,P_w_use是实际消纳出力。
等式约束主要是各时段的电功率平衡和热功率平衡:
电平衡:P_grid(t) + P_chp(t) + P_w_use(t) + P_dis_e(t) = P_load(t) + P_eb(t) + P_ch_e(t) 热平衡:Q_chp(t) + Q_eb(t) + Q_gb(t) + P_dis_h(t) = H_load(t) + P_ch_h(t)不等式约束包括设备出力上下限、爬坡约束、储能SOC范围、充放电状态互斥约束、上级电网交互功率限制等。这些约束全部写成矩阵形式后,用Yalmip的sdpvar和constraint组合非常方便,这也是我推荐用Yalmip而不是纯Matlab手写求解器接口的原因——代码可读性和可修改性都好很多。
3. Matlab代码架构:从场景生成到求解器的一站式实现
3.1 整体文件结构与调度流程
收到不少同学的私信问"这种代码从哪下手",我给的统一建议是先画清楚数据流。整套Matlab程序我拆成了五个脚本文件,职责边界非常清晰:
IES_Optimization/ ├── main_IES.m # 主程序,串起整个求解流程 ├── params_IES.m # 系统参数与设备参数 ├── generate_scenarios.m # 新能源出力不确定性场景生成与缩减 ├── build_model.m # 用Yalmip构建优化模型 └── plot_results.m # 结果可视化与对比分析主程序的执行顺序是:先运行params_IES.m加载参数,再调用generate_scenarios.m生成典型场景及概率,接着进入build_model.m构建决策变量、约束和目标函数,调用求解器求解后把结果传给plot_results.m画图。
有个容易忽视的点:所有脚本都不建议设置成函数形式来调用参数结构体,因为调试时你经常需要在工作区里查看中间变量。我直接把params_IES.m写成脚本,里面的变量以params结构体形式存放,例如params.chp.a、params.chp.p_max。这样在主程序里任何位置都能快速查看和修改参数,迭代效率高很多。
3.2 不确定性场景生成:蒙特卡洛抽样与同步回代缩减
场景生成是整套代码里最体现"不确定性建模"精髓的部分。我采用"典型出力曲线 + 随机扰动"的抽样方式:先定义风电和光伏的预测典型曲线,假设预测误差服从正态分布,在每个时段叠加随机噪声,生成1000个初始场景。
% 参数:初始场景数 N_scen = 1000; T = 24; % 风电典型出力曲线(标幺值) wind_base = [0.28 0.26 0.24 0.22 0.21 0.23 0.25 0.30 0.38 0.45 0.42 ... 0.36 0.33 0.35 0.30 0.26 0.24 0.28 0.35 0.42 0.48 0.45 0.38 0.30]; % 光伏典型出力曲线(标幺值) pv_base = [0 0 0 0 0 0.05 0.15 0.30 0.55 0.75 0.88 0.95 0.92 0.80 ... 0.62 0.40 0.20 0.08 0 0 0 0 0 0]; % 抽样生成初始场景矩阵:每一行是一个完整日场景 wind_scen = repmat(wind_base, N_scen, 1) .* (1 + 0.15 * randn(N_scen, T)); pv_scen = repmat(pv_base, N_scen, 1) .* (1 + 0.10 * randn(N_scen, T)); % 修正越界值 wind_scen(wind_scen < 0) = 0; wind_scen(wind_scen > 1) = 1; pv_scen(pv_scen < 0) = 0; pv_scen(pv_scen > 1) = 1; % 组装场景矩阵:把风、光场景拼接成1000×48的矩阵 scen_all = [wind_scen, pv_scen]; prob_all = ones(N_scen, 1) / N_scen;随机生成的场景数量太多,直接带入优化模型会导致变量维度过大,必须做场景缩减。我采用的是工程上最常用的同步回代缩减方法:每次迭代找一对概率距离最小的场景,删掉其中一个,同时把被删场景的概率加到距离最近的那个场景上,直到剩余场景数达到目标值。
function [scen_red, prob_red] = sbr_scenario_reduction(scen, prob, K) % scen: 原始场景矩阵, N×M % prob: 场景概率列向量, N×1 % K: 目标保留场景数 N = size(scen, 1); while N > K % 计算场景间欧氏距离矩阵 D = pdist2(scen, scen); D(D == 0) = inf; % 自身距离设为无穷 % 每个场景找最近的相邻场景 [d_min, j_idx] = min(D, [], 2); % 概率加权距离作为删除指标 cost = prob .* d_min; % 找到删除代价最小的场景 [~, i_del] = min(cost); % 将其概率累加到最近场景上,并删除该场景 prob(j_idx(i_del)) = prob(j_idx(i_del)) + prob(i_del); scen(i_del, :) = []; prob(i_del) = []; N = N - 1; end scen_red = scen; prob_red = prob; end这段代码虽然短,但有几点需要额外留意。第一,pdist2在场景数很大时内存占用可观,如果你的机器配置一般,建议用分块计算或直接写双重循环。第二,每次删除场景后要重新计算距离矩阵,所以缩减20个场景可能要迭代980次,程序会跑一小段时间,这是正常的。第三,缩减结果的稳定性和初始场景有关,建议固定随机种子rng(42),保证实验可复现。
缩减之后,我得到的典型场景可以直观理解为"晴天高光伏""阴天低光伏""大风夜""无风夜"这几类典型天气模式,每一类带上一个概率权重。这个概率分布会直接影响优化结果中储能充放电策略和CHP出力水平。
3.3 Yalmip建模与求解器调用
模型构建部分我完全依赖Yalmip工具箱,它最大的好处是让建模语法和求解器解耦——你不用关心Cplex底层的C API怎么调用,只需要用sdpvar定义决策变量、用constraint写约束、用optimize求解。下面给出核心建模代码的骨架。
%% 决策变量定义 P_grid = sdpvar(T, 1); % 购电功率 P_chp = sdpvar(T, 1); % CHP电出力 Q_chp = sdpvar(T, 1); % CHP热出力 P_eb = sdpvar(T, 1); % 电锅炉电功率 P_w_use = sdpvar(T, 1); % 实际消纳风电功率 P_ch_e = sdpvar(T, 1); % 电储能充电功率 P_dis_e = sdpvar(T, 1); % 电储能放电功率 SOC_e = sdpvar(T + 1, 1); % 电储能荷电状态 u_ch_e = binvar(T, 1); % 充电状态指示 u_dis_e = binvar(T, 1); % 放电状态指示 %% 约束集合 Constraints = []; %% 功率平衡约束 for t = 1:T Constraints = [Constraints, P_grid(t) + P_chp(t) + P_w_use(t) + P_dis_e(t) ... == P_load(t) + P_eb(t) + P_ch_e(t)]; end %% 设备运行约束 Constraints = [Constraints, params.chp.p_min <= P_chp <= params.chp.p_max, Q_chp == params.chp.a * P_chp + params.chp.b, P_eb_min <= P_eb <= P_eb_max, P_w_use >= 0, P_w_use <= sum(wind_PV_scenario, 2)]; % 注意:上面的风光伏场景是缩减后的某个典型场景,需要遍历所有场景实际代码里,因为我们要对20个场景同时建模,每个场景下都有一组决策变量和平衡约束,目标函数里对场景做期望运算。我习惯用三维数组来存放场景相关的决策变量,例如P_w_use(s, t)表示场景s下t时段的风电消纳功率,P_grid(s, t)表示场景s下t时段购电功率。这样目标函数写成:
Objective = 0; for s = 1:N_red Obj_scen = 0; for t = 1:T Obj_scen = Obj_scen + ... c_e(t) * P_grid(s, t) + ... c_gas * F_gas(s, t) + ... c_om * (P_chp(s, t) + Q_chp(s, t)) + ... lambda * (P_w_avail(s, t) - P_w_use(s, t)); end Objective = Objective + prob_red(s) * Obj_scen; end求解调用:
ops = sdpsettings('solver', 'cplex', 'verbose', 2, 'showprogress', 1); ops.cplex.mip.tolerances.mipgap = 0.01; % 设置MIP间隙 result = optimize(Constraints, Objective, ops);这里有个细节:P_w_avail(s,t)是场景缩减后已知的风光最大可用功率,它在优化前就是常数;P_w_use(s,t)是决策变量。弃风弃光量的本质就是两者差值。惩罚系数λ设置很关键,设置太小会导致模型主动弃风,设置太大则牺牲经济性保消纳。我经过试算后把λ设为上网电价的两倍左右,效果比较平衡。
4. 算例验证与结果分析:确定性调度和随机调度的差距有多大
4.1 算例系统的参数设定
我用一个典型园区综合能源系统做验证,系统包含一台CHP机组(额定电功率300kW)、一台电锅炉(200kW)、一台燃气锅炉(200kW)、电储能200kWh/100kW、热储能100kWh/50kW,配置风电150kW、光伏100kW。电负荷峰值约350kW,热负荷峰值约180kW。
| 参数类别 | 具体参数 | 数值 |
|---|---|---|
| 分时电价 | 峰时段 10:00-16:00, 19:00-22:00 | 0.85 元/kWh |
| 分时电价 | 平时段 08:00-10:00, 16:00-19:00, 22:00-24:00 | 0.55 元/kWh |
| 分时电价 | 谷时段 00:00-08:00 | 0.32 元/kWh |
| 天然气价格 | 折算热值成本 | 0.62 元/kWh |
| 弃风弃光惩罚 | 单位惩罚成本 | 1.60 元/kWh |
| CHP机组 | 热电比斜率 a / 截距 b | 1.2 / 20 kW |
| 电锅炉效率 | η_eb | 0.95 |
| 电储能 | 初始SOC / 容量 | 0.5 / 200 kWh |
风光预测典型曲线就是上一节里展示的标幺值曲线,乘以各自的额定容量即可得到功率量值。场景缩减后保留了20个典型场景,每个场景都包含24个时段的风电、光伏可用出力。
4.2 三种调度模式的结果对比
我设计了三种模式做对比:
- 模式A:确定性调度。把风光预测均值当成确定值,完全不考虑不确定性。
- 模式B:随机场景调度(本文方案)。用缩减后的20个场景做期望优化。
- 模式C:鲁棒调度。用盒式不确定集合,不确定区间取预测值的±15%,最坏情况约束。
| 调度模式 | 总运行成本(元/日) | 弃风弃光率 | CHP日发电量(kWh) | 求解时间(s) |
|---|---|---|---|---|
| 确定性A | 8726 | 5.3% | 3120 | 6.8 |
| 随机场景B | 9145 | 1.2% | 3360 | 38.5 |
| 鲁棒C | 9402 | 0.4% | 3485 | 52.1 |
表格里的数虽然只是我的算例结果,但反映的规律具有普遍性:确定性方案成本最低,但这是建立在预测完全准确的假设上,实际运行时这个成本根本守不住;随机场景方案成本略高,但优势在于它对各种可能场景都做了准备,实际运行的可靠性大幅提升;鲁棒方案最保守,适用于极端天气频发、安全要求极高的场景。
4.3 结果剖析:不确定性成本与调度策略差异
深入看CHP机组出力曲线,可以发现模式A下CHP机组午间出力会压得比较低,因为光伏出力预测较高,系统认为不需要CHP多发电。但在随机场景调度中,模型意识到午间光伏可能比预测低30%以上,因此会让CHP保持一个相对高的出力水平,同时让电储能提前预留一点容量——这就是"协同优化"体现的地方:多能互补的灵活性和设备间的协调动作,共同对冲新能源不确定性带来的风险。
另外,弃风弃光率从5.3%降到1.2%,主要贡献来自电锅炉。在随机场景中,部分场景下夜间风电出力远超预测,此时电锅炉启动,把多余风电转化为热能储存在热储能中,替代一部分燃气锅炉出力。这种"电气设备"(电锅炉、储能)与热力负荷之间的协同调度,正是综合能源系统相比单一电力系统调度的优势所在。
我在结果分析时还计算了一个指标,叫"不确定性成本"——模式B和模式A的成本差值除以模式A的成本,约4.8%。这个数字如果换算到全年运行,就是一笔相当可观的费用。做项目汇报时,把这个指标讲清楚,比单纯罗列成本数值更有说服力。
5. 我在调试这套Matlab程序时踩过的坑
5.1 场景缩减的尺度效应:缩得太多反而丢信息
一开始我把1000个场景缩减到5个,求解确实飞快,但优化结果和真实情况偏差很大。原因在于5个场景无法覆盖风光出力的相关性结构——比如"光伏高风电低"和"光伏低风电高"这两种关键模式,缩减后可能只剩一种,模型就会偏向某种特定天气,失去代表性。后来我做了敏感性分析,目标场景数从5、10、15、20、30一路往上试,发现20个场景是一个明显的拐点,再往上增加场景数,成本改善幅度很小但求解时间增长明显。这个平衡点需要针对你的具体系统参数去试,不能拍脑袋定。
5.2 Yalmip求解时最容易翻车的三个细节
第一,二进制变量初始化问题。binvar定义的变量如果没给初值,Cplex在某些版本下可能陷入很慢的branch and bound过程。建议在sdpsettings里设置好MIP gap,比如0.01,让求解器在精度达标后提前退出,而不是硬求到全局最优。
第二,约束中的数值尺度。如果某个约束里的系数相差几个数量级,比如电价是0.3而CHP容量是300000W,求解器数值稳定性会变差。经验做法是统一量纲——功率用kW、能量用kWh、费用用元,把数值控制在0.01~10000范围内,Cplex处理起来会很舒服。
第三,等式约束里的温度、SOC传递关系要特别注意时段的错位。储能SOC约束如果写成SOC(1)和SOC(T+1)的循环闭合,容易出现索引不一致导致的约束错乱。我调试时有一个晚上所有方案都退化,最后发现是SOC_e(t+1)和SOC_e(t)的索引写反了,这种低级错误排查起来特别费时间。
5.3 CHP非线性特性的线性化处理
前面提到CHP电热耦合约束Q = a*P + b,这个线性化在小范围内还好,但如果CHP机组的可行域是典型的三角形或四边形区域(由最小电出力、最大电出力、最大热出力、最小热电比等围成),只用一条直线约束会丢失可行域边界信息,导致优化结果出现在物理上不可行的工况点。
处理办法有两种。一种是把可行域拆成多个线性不等式组合,画出四个顶点然后用凸包约束表达;另一种是采用二进制变量选择工况区间,做分段线性化。我最终采用的是第一种,因为代码实现简单,只需要加三四个线性不等式约束,求解速度没有明显下降。如果你自己要在Matlab里验证CHP可行域,建议先画出P-Q平面上的可行域多边形,再反推线性约束,而不是凭空写公式。
5.4 求解时间与精度平衡的实战调参经验
这套模型求解时间是38秒左右,对于学术研究完全够用。但如果做多日滚动优化或需要嵌入实时控制,这个时间就需要压缩。我的几条经验:
- 控制整数变量数量。储能充放状态两对二进制变量、CHP启停两对二进制变量,24时段就是接近100个整数变量,规模不大但会影响求解速度。如果你不需要模拟启停过程,可以把启停二进制变量去掉,只保留充放电互斥约束,MILP退化成QP,求解时间能缩短一半。
- 设置合理的MIP gap。学术研究里gap设1%足够说明问题,没必要追求0误差。
- 减少场景数的同时用概率密度加权。有些场景虽然发生概率不高,但对应极端出力,直接删掉会影响鲁棒性,可以考虑把低概率极端场景合并进相邻高概率场景,而不是简单删掉。
6. 这套方案还能往哪些方向扩展
代码框架搭好之后,后续扩展空间其实很大。我目前正在把电转气(P2G)设备和碳排放约束加进模型,因为双碳目标下,综合能源系统协同优化不仅要算经济账,还要算碳账。添加P2G设备时,只需要在能量耦合矩阵里增加一条"电→天然气"的转换路径,在设备约束里加P2G的电功率输入范围和转换效率,目标函数里加对应的运维成本项,整个框架不需要大改。
另外,如果研究对象从园区级扩展到区域级,需要考虑多能源网络潮流约束,那么场景生成模块可以和拉丁超立方抽样或准蒙特卡洛方法结合,提高采样效率;求解器方面可以从Cplex切换到Gurobi,它在大规模MILP问题上表现更好。
最后再分享一个实际操作的体会:这套Matlab代码在Windows和Linux环境下我都跑过,最容易出问题的环节不是模型本身,而是环境配置——Yalmip把Cplex、Gurobi这些求解器路径配好后,建议先跑一个官方demo确认求解器可用,再跑综合能源系统模型。否则一旦报错,你很难分清是模型写错还是求解器接口没接好。别问我怎么知道的,我在这上面浪费过整整一天时间。