数据驱动多离散场景分布鲁棒优化在电热综合能源系统中的应用

发布时间:2026/10/13 17:18:09
数据驱动多离散场景分布鲁棒优化在电热综合能源系统中的应用 “数据驱动”“多离散场景分布鲁棒”“电热综合能源系统优化”这三个词组合在一起我第一眼看到就知道这是个高热点算法方向。最近做课题和写论文的朋友十有八九都在审视这类题目。我花了一段时间用 Matlab 把整套流程完整跑通过包括场景生成、分布鲁棒建模、热电耦合约束、求解器对接每一步都有踩坑记录。这篇博文不绕弯子直接从模型定位讲到代码结构再到调试经验希望能给正在做综合能源调度、鲁棒优化、以及打算用数据驱动方法做系统运行研究的人一点参考。看完你至少能把“数据驱动多离散场景分布鲁棒”这套逻辑和你自己的电热系统模型对上号知道该在哪里发力、哪里最容易翻车。1. 项目定位先搞清楚这个模型到底在解决什么问题1.1 一个典型的电热综合能源系统长什么样电热综合能源系统和纯电力系统最大的区别在于电和热被“拧”在了一起。我经常用一句话跟别人解释它既要保证每一时刻电功率平衡又要保证热功率平衡而这两个平衡本身又通过热电联产机组、电锅炉、储热罐这些设备强耦合。典型系统里通常包含这样几个角色热电联产机组CHP是核心电源兼热源燃料成本跟它输出的电功率和热功率都相关风电场或光伏电站提供波动性可再生能源但预测误差无法回避电锅炉可以把多余的电转化成热储热罐像一个缓冲水池热多的时候存起来热少的时候放出来外部电网作为备用电源系统可以向上级电网买电。这样一套拓扑在园区的能源站、区域供能系统、微电网示范工程里都能见到。你要做的调度决策是提前一天或提前几个小时给每台设备分配出力让系统在满足电、热负荷的前提下运行成本最低。这个看似简单的目标一旦碰上“风电出力不准”“负荷预测有偏差”就得重新定义是接受一个最有可能的方案还是准备一个即使遇到最坏天气也能应付的方案这个问题的答案决定了你要用哪一类优化算法。1.2 为什么确定性优化和随机规划都不够用不少初接触这个方向的人会问直接用预测值做确定性优化不就行了把风电的预测值当成真实值列完约束求最小成本编程简单、结果好看。但真实运行里预报和实际能差出十几甚至几十个百分点。确定性模型给出来的调度计划往往过度依赖单一预测点一旦实际出力偏小系统就不得不临时高价买电或切负荷。随机规划是把不确定性考虑得更细一点的方法。它假设风电出力有若干个已知概率的场景然后求期望成本最小。这个思路看起来合理但有一个致命前提你精确知道场景发生的概率分布。现实情况是我们手头只有一段历史样本样本数量不够的时候随机规划很容易“过拟合”到历史分布上把概率小的极端情况低估。传统鲁棒优化则走向另一个极端。它要求在给定不确定集合范围内所有可能的风电出力都能被满足结果通常特别保守成本高得吓人。用过鲁棒模型的人都知道最坏情况出现的概率本来就很低你却要让整个系统为它过度预留备用经济效益上很难看。1.3 三批人最需要这个模型这个题目天然适合三种人。第一种是研究生正在选论文方向或者准备毕业设计需要一个“有理论深度、有数据支撑、有代码验证”的完整框架第二种是做园区能量管理的工程师手头有历史运行数据想用更精细的模型替代拍脑袋的调度规则第三种是对优化算法本身感兴趣的研究者想找一个有实际约束、有数据、可验证的算法测试场景。数据驱动分布鲁棒优化恰好把这三类需求串起来了它不假设精确分布只有一群历史场景它不无限抬高保守度用模糊集半径来控制风险偏好它能形成清晰的 min-max 结构理论上有充分的数学表达空间。方法对不确定性的假设保守程度数据需求主要缺陷确定性优化预测值等于实际值最低少忽略风险结果常不可行随机规划已知精确概率分布中等大量样本分布假设过强传统鲁棒优化不确定量落在规定区间最高少方案过度保守分布鲁棒优化真实分布属于含样本分布的模糊集可由半径调节历史样本场景缩减建模和求解更复杂2. 数据驱动、多离散场景与分布鲁棒的三层结构2.1 数据驱动到底驱动了什么很多人一听“数据驱动优化”以为是神经网端预测或者机器学习回归。其实在分布鲁棒优化语境里数据驱动的含义更朴素也更直接用历史样本支撑一个包含可能概率分布的集合这个集合叫模糊集。为什么不能直接“用一个分布”因为真实分布不可知你手里只有一批观测样本。与其拍脑袋说风电出力服从正态分布不如说真实分布应该离这些经验样本不远但具体长什么样不清楚。于是你把“所有与历史样本分布距离不超过某个半径的分布”放进一个集合找一个在所有这类分布上都表现不差的解。模糊集的构造方法很多。一种是矩模糊约束分布的均值和协方差在一个可控球内一种是范数模糊约束概率向量到名义概率向量的距离还有一种是Wasserstein球用最优传输距离度量分布之间的距离。Wasserstein球在数据驱动里尤其受关注因为它对样本维数有较好的适应能力而且可以推导出可求解的对偶形式。我最终在代码里用的就是Wasserstein距离构造的模糊集。2.2 多离散场景从哪里来电热系统里的不确定性源比如风电功率、电负荷、热负荷本质上是连续随机变量。但连续分布没法直接写进线性规划所以要把它们离散成若干个代表场景。第一步是场景生成。常见的做法是用历史数据拟合一个参数模型比如用风电预测误差的经验分布做蒙特卡洛采样生成几百个甚至上千个初始场景。如果有比较规整的历史样本也可以直接抽取窗口片段生成场景。这一层我不建议用太高级的深度学习生成模型原因是后面还有场景削减初始场景只要采样足够充分就行。第二步是场景削减。几百个场景直接塞进分布鲁棒模型计算量会爆炸。行业里常用同步回代消减SBR或者K-means聚类把初始场景浓缩成几十个典型场景并给每个典型场景分配一个出现概率。我实际序列里常用的数量级是初始采样500到1000个场景削减后保留25到40个。这个量级既能体现多离散场景的丰富性也不会让优化模型大得跑不动。“多离散场景分布鲁棒”这个名字里的“多离散场景”含义就在这里名义分布是一个由多个离散场景及其概率构成的离散分布模糊集则围绕着这个离散名义分布展开。削减后的场景质量直接影响模型结果。场景削减做得不好哪怕模糊集半径设得再合理结果也会有系统性偏差。2.3 分布鲁棒优化的核心逻辑分布鲁棒优化DRO的行事风格可以概括为一句大白话我不完全相信历史场景给出的分布假定真实分布藏在距离它不远的一圈候选分布里我选择让这些候选分布中“最坏那一个”带来的期望成本尽可能低。用数学语言简单表达它在求解这样一个问题[ \min_{x \in X} ; \max_{\mathbb{Q} \in \mathcal{B}} ; \mathbb{E}_{\mathbb{Q}}[f(x,\xi)] ]其中 (x) 是第一阶段的调度决策(\xi) 是风电等不确定量(\mathcal{B}) 是以历史离散场景为圆心、以给定半径为半径的模糊集。外层是正常的经济调度目标内层是搜索“最坏情况分布”。这比随机规划多了一个内层max又比传统鲁棒优化多了一层“分布允许变化”的弹性。模糊集的半径在代码里就是一个参数可以把它想象成“对历史样本的信任程度”半径越小越信任历史场景结果接近随机规划半径越大越警惕未知分布结果趋于保守。2.4 把 min-max 结构变成可求解的问题很多人卡在分布鲁棒优化的求解上就是不知道该怎么把内层max消掉。好消息是对Wasserstein模糊集支撑的线性或凸优化问题内层可以用线性规划对偶定理转换成一些额外变量和约束从而变成了一个单层的、可交给通用求解器处理的优化问题。我在代码里没有手工推导对偶公式而是借助 YALMIP 把对偶过程包装起来但我也建议至少亲手推一遍简单形式的对偶知道每一组对偶变量对应哪条原始约束。否则出了问题你只能盯着“infeasible”发呆根本不知道是半径设得太大、场景概率算错还是对偶约束方向写反了。对偶转换还有一个工程好处它能把目标函数里原本非光滑的取期望项等价转化为线性不等式约束整个模型仍然是线性规划或混合整数线性规划求解效率和稳定性都会好很多。这也是我坚持不用非线性启发式算法的原因。3. 电热综合能源系统的物理约束怎么建模3.1 系统拓扑和建模颗粒度我不建议一上来就建一个包含热网管道动态的全尺寸模型那样复杂度高到代码根本没法快速验证。实际项目里先按静态能量平衡来做也就是认为热网管道对热功率没有延迟损耗管容效应用一个简化系数折算。把精力集中在 CHP 机组可行域、储热罐状态和电热耦合关系上才能在代码阶段快速迭代。系统里至少要有三类变量设备出力变量比如 CHP 的电功率与热功率、电锅炉产热、储热罐充放热状态变量主要指储热罐容量以及交换变量比如系统向外部电网购电功率、弃风功率。3.2 电热耦合约束是核心难点电热耦合中最容易写错、也最值得花时间的是 CHP 机组的运行可行域。一个简单的建模方式是把它看成一个双输入双输出设备电功率和热功率落在定义可行域的多边形区域内。常用形式是电功率上下限(P_{\min} \le P_{CHP} \le P_{\max})热功率上下限(H_{\min} \le H_{CHP} \le H_{\max})电热耦合约束(bP aH \le c) 这样的线性不等式组表达的是机组在“以热定电”和“以电定热”之间的机动空间这些约束共同画出一个凸多边形凡是落在这个多边形内的点都是机组可以稳定运行的出力组合。注意这里我故意用线性不等式而不是非线性效率曲线是为了让模型保持 MILP 结构。电锅炉的建模就简单很多本质是一个线性转换器(H_{EB} \eta \cdot P_{EB})其中 (\eta) 是电转热效率(P_{EB}) 是电锅炉消耗的电功率。它和 CHP 的热出力相加共同满足热负荷。储热罐的动态约束是另一个容易掉坑的地方。储热罐的容量变化满足[ S(t1) S(t) H_{cha}(t) - H_{dis}(t) ]充放热功率有上下限罐容量有上下限同时要考虑一个周期结束时的容量回到初始值或者保持在一个合理区间否则模型会“抖机灵”把前期热负荷全甩给储热罐末期再猛放热算出一种运行上根本没法执行的调度计划。3.3 平衡约束与目标函数系统电平衡约束为外部购电 风电出力 - 弃风 CHP 电出力 - 电锅炉耗电 - 电负荷 0。这里要特别注意电锅炉的耗电是被写在等式左边作为负载项很多初写模型的人容易漏掉。系统热平衡约束为CHP 热出力 电锅炉产热 储热罐放热 - 储热罐充热 热负荷。如果模型考虑热网损耗可以在等式右侧乘一个大于1的损耗系数但调度类研究常用一个固定效率系数。目标函数则是最小化系统总运行成本CHP 机组的燃料成本通常表示成电出力和热出力的线性或二次函数向上级电网购电的成本弃风电量的惩罚成本储热罐操作成本通常是一个很小的常数主要用来防止频繁切换可能有人会问为什么目标函数里没有收益项。在运行成本最小化模型里负荷是固定的购电和燃料都是支出所以目标是纯成本最小化如果你把模型扩展到参与电力现货市场目标就要改成净收益最大那就会多出售电收入项。扩展的内容我放在后面讲。3.4 不确定性到底作用在哪里这个模型里的不确定性最常作用在风电出力上。传统做法是让风电在预测值附近波动分布鲁棒做法是让每一时刻的风电出力根据历史离散场景变化但模型要求不管真实分布落在模糊集里的哪个位置系统都能通过第二阶段的调整保证功率平衡和热平衡不越界。分布鲁棒模型通常会设计成两阶段结构第一阶段是“看预测值做决策”决定机组启停、储热罐初步状态第二阶段是“场景揭晓后微调”通过调整购电、弃风和储热罐充放热来吸收偏差。我的 Matlab 代码把这两个阶段拆分得很清楚主函数里先定义第一阶段变量再用一个循环或批量方法把第二阶段的调整变量和约束加进去。4. Matlab 代码实现从建模到可运行工程的完整路线4.1 环境准备你真的只需要三样东西真正动手写代码前别急着堆功能先把环境搭好。我的组合是Matlab YALMIP 一个可用的商业求解器。YALMIP 是建模工具箱负责把目标函数和约束传给底层求解器求解器负责真正做优化计算。Matlab 自带的 linprog 能处理纯线性规划但遇到混合整数变量就会吃力所以我还是建议准备好商业求解器比如业界常用的 CPLEX 或 Gurobi。安装完成后在命令行执行 yalmiptest看到所有求解器状态正常再往下写代码。提示不同版本Matlab对YALMIP的兼容性有差异旧版本有可能在定义sdpvar时出现奇怪的报错。先把YALMIP和求解器升级到相对新的版本能省掉很多无意义的排查时间。4.2 代码目录怎么组织才有复现价值好代码不是说写一个巨大的 main.m 把所有约束堆在一起而是要让别人打开目录就知道每一步在干什么。我最终采用的目录结构是这样的project/ ├── data/ # 历史数据和负荷数据 ├── scenarios/ │ ├── generate_scenarios.m # 初始场景采样 │ └── reduce_scenarios.m # 场景削减与概率计算 ├── model/ │ ├── build_uncertainty_set.m # Wasserstein模糊集半径与对偶变换 │ ├── electric_thermal_model.m # 设备约束集合 │ └── solve_dro.m # 主优化模型求解 ├── utils/ # 数据归一化、结果画图等公共函数 └── main.m # 汇总入口为什么强调场景削减单独放一个文件因为场景削减的参数比如削减后保留多少场景、聚类方法选K-means还是SBR几乎一定是要做敏感性分析的。单独放一个脚本你可以一次跑完所有场景数量把结果表格汇总出来而不用反复改主代码。4.3 核心代码结构示范主函数的第一件事是读取数据并作归一化。我坚持先把风电、负荷的数据都转换到标幺值或同一量纲这样目标函数的数值范围大概在几百到几千不便TG solver。等到求解完再换回物理量用于画图和分析。这个习惯帮我避开了好多数值病态问题。确定决策变量用一个简单例子示意T 24; % 调度周期 nCHP 1; P_CHP sdpvar(nCHP, T, full); % CHP电出力 H_CHP sdpvar(nCHP, T, full); % CHP热出力 P_EB sdpvar(1, T, full); % 电锅炉耗电功率 H_EB sdpvar(1, T, full); % 电锅炉热出力 S_TES sdpvar(T1, 1, full); % 储热罐状态 % 购电和弃风变量 P_buy sdpvar(1, T, full); P_cur sdpvar(1, T, full);约束条件就是把我前面说的平衡方程逐条写进 YALMIP。比如电平衡Constraint [Constraint, P_buy P_wind_base - P_cur P_CHP - P_EB P_load];热平衡Constraint [Constraint, H_CHP H_EB H_TES_dis - H_TES_cha H_load];这里有一点非常重要当分布鲁棒引入多场景时第二阶段约束必须对每一个场景都写一遍。YALMIP 支持用循环或者大批量方式添加约束循环方式更直观。例如对于每个离散场景 (i)风电实际出力不同就需要对应的补充调整变量 (P_{cur,i})、(P_{buy,i}) 和平衡约束。这个循环写起来并不复杂但却是整个代码运行时间的最大瓶颈。我的经验是尽量把需要循环的场景数控制在40以内否则 YALMIP 构建模型的时间会明显变长。目标函数长这样Objective sum(sum(fuel_cost_CHP)) sum(price_buy .* P_buy) big_penalty * sum(P_cur);其中 fuel_cost_CHP 是 CHP 的燃料成本矩阵big_penalty 是弃风惩罚系数设得足够大但不至于让求解器产生数值警告。4.4 求解控制与性能优化求解时我用这一句ops sdpsettings(solver, gurobi, verbose, 2); Result optimize(Constraints, Objective, ops);solveyalmip 返回结果后第一件事不是看目标函数值而是检查 Result.problem 是不是0。如果 Result.problem 不是0再顺手打印 Result.info。这一步能帮你把“模型不可行”“求解器未找到”“数值问题”这类错误分类节省大量排查时间。如果模型规模偏大我会先关闭 verbose改用分段求解。比如先固定一部分离散变量把问题当成纯LP求解再放开离散变量用上一轮解做热启动。这样能把求解时间从十几分钟压到两三分钟。这条经验在场景数超过30、T24的模型上特别有效。5. 调试经验与常见问题速查5.1 问题一结果数值诡异先检查单位我见过最多的错误就是单位混用。建模时有人把风电数据写成 kWCHP 参数写成 MW热负荷又用 GJ/h。最后算出来的“最优解”要么是各物理量差了好几个数量级要么直接不可行。解决方法是统一单位。我习惯在数据入口处做一次检查把所有功率数据统一换算成 MW所有能量统一换算成 MWh热量和电量的时间尺度对齐到小时。给每个设备参数写注释的时候把单位写清楚比如“出力上限/MW”而不是只写“上限”。5.2 问题二场景数一多内存直接爆炸有些同学一上来就把场景保留到200个结果YALMIP构建模型都要五六分钟求解器内存占用几个G。这时不是电脑不行而是你没注意模型结构。200个离散场景意味着一堆第二阶段变量和约束而分布鲁棒模糊集本身还要引入对偶变量规模膨胀是必然的。解决方法是先做场景削减把典型场景降到25到40个同时把 DRO 的模糊集半径设在一个合理范围不要过大。如果仍嫌大可以把24小时调度周期拆成几个时间段分别求解或者把阶段二约束写成稀疏矩阵而不是用YALMIP的循环逐条添加。症状可能原因排查方法模型不可行场景概率没归一化或约束方向写反检查场景概率和每一类平衡等式目标值异常大单位不一致统一单位后重跑求解器内存不足场景数过多、对偶变量太多削减场景数量、简化模糊集结果振荡每次场景削减结果差异大典型场景太少增加削减后场景数量结果对模糊集半径极不敏感半径本身设得太小把半径从小往大试几组看目标变化5.3 问题三模糊集半径怎么选才合理模糊集半径是很多人睡不着的根源。太小等于没加分布鲁棒太大成本高得没谱。比较实用的办法是用样本数量 (N) 和置信度 (\beta) 来定一个参考尺度。Wasserstein球半径有个常用公式样本量越大半径应该越小置信度要求越高半径应该越大。工程实践里我一般先把半径设成一个很小的值比如0.01逐步增加到0.2画出成本曲线观察哪里开始出现拐点。拐点附近的半径往往就是既体现风险又不至于过保守的位置。我在调试时还发现半径和场景数量会互相影响。场景削减到25个时0.05的半径就已经有明显效果场景削减到50个时同样半径的鲁棒性会显得更“温和”。所以敏感性分析不应该只扫半径一个变量最好把场景数也一起扫了最后画一张二维表格放在论文里非常有说服力。5.4 问题四数学上可行物理上不合理有一类结果特别阴间目标函数很漂亮但调出来的储热罐状态曲线像个锯齿CHP 出力忽大忽小。这种问题通常是因为目标函数里没有给设备爬坡约束或爬坡约束只写了范围没写相邻时间耦合。调度类问题几乎必须加爬坡约束形式是相邻两时刻出力差不超过限值。加完之后曲线就平滑多了。还有一种物理不合理是热负荷满足但热网供回水温度完全不在可行范围。如果模型已经包含热网管道温度变量得加上供回水温度和流量的耦合关系。如果暂时不想做热网动态模型可以在论文里明确说明本文热网采用静态能量平衡近似不考虑管道延迟。这个声明能挡掉很多审稿追问。6. 这个模型还能往哪些方向升级6.1 升级方向一加入碳交易与需求响应当前模型目标函数只有运行成本如果要把研究做到更贴近现实碳交易机制是很好的一层扩展。给CHP机组加上碳排放系数和碳配额购碳价格纳入目标函数就能分析碳约束对调度策略的影响。需求响应则可以释放负荷侧灵活性把一部分可平移电负荷作为决策变量系统在电价高峰时调整用电曲线收益会明显增加。我把这两个扩展都试过难度不大但对模型结构的影响很直接。碳交易会让 CHP 的出力向更高效、更低碳的运行区间偏移需求响应则会显著影响不同场景下第二阶段的调整量分布鲁棒模型的价值更容易体现出来。6.2 升级方向二从单园区到多园区或多主体单园区模型只有一个优化主体全局最优就是运行目标。多园区会把系统拆成几个子网各自有决策权和信息交换。这个场景下可以用交替方向乘子法或者分布式优化思想把集中式模型拆解成多个子问题。分布鲁棒部分同样可以保留只是模糊集需要针对每个园区的数据单独构建。这个方向比较适合做论文的“创新点”。6.3 升级方向三参与电力市场与现货交易如果系统园区的余电可以卖回电网目标函数就得从“成本最小化”改成“收益最大化”。这要引入售电收入、实时市场价格波动甚至还要区分日前市场和实时平衡市场。不确定性源也会从风电功率扩展到市场价格、负荷预测误差。结合数据驱动分布鲁棒后模型会变成一种更复杂的多阶段决策问题但求解思路仍然可以沿用 Wesserstein 模糊集 和 两阶段鲁棒优化的框架。6.4 写好这个项目的几个实用建议论文或课题报告里实验设置一定要写清楚三件事历史样本数量、场景削减方法、模糊集半径选取依据。这三点是分布鲁棒模型能被复现的关键。我建议做一组对比实验分别对比确定性模型、随机规划、分布鲁棒模型在场景外样本上的表现用“样本外期望成本”和“最坏情况成本”两个指标来评价。这两个指标一对比分布鲁棒的价值立刻可见也是审稿人最认可的分析方式。最后再分享一点我自己的体会做这类项目最难的不是数学推导也不是代码调试而是你能不能把“模糊集半径”“场景概率”“运行成本”这三者之间的关系讲清楚。给学生讲的时候我经常问一句话“你的模型凭什么比随机规划更稳又凭什么比传统鲁棒更省钱”如果答案清晰那么这个项目基本就成了。我建议你也用这句话自测一下自己的模型。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询