
前阵子把“综合能源园区三方市场主体非合作方法”的模型迭代跑通那天我把24小时的电平衡残差曲线来回翻了三遍。从第1次迭代到第1940次迭代用电平衡偏差从接近0.9 MW慢慢压到1e-4以内热平衡也稳定在同样的量级那一刻我才敢说这个模型不只是论文里的数学游戏它是真的可以拿来做结算机制推演的。这几年做园区级综合能源项目最头疼的往往不是设备选型也不是潮流计算而是三个利益主体之间的“算账”问题综合能源服务商想赚钱用户想省钱上级配电网这边还盯着联络线功率和系统安全。每一方都有自己的计划和目标没有谁愿意把自己的内部数据全盘托出更不可能接受一个“别人替我决策”的方案。于是“非合作方法”就成了一个绕不开的探索方向。这篇文章想聊的就是围绕这类园区场景三方市场主体如何在各自优化目标的前提下通过非合作博弈达到一个稳定的市场均衡——包括为什么要用广义纳什均衡这个框架、模型怎么搭、分布式算法怎么收敛以及我实际调试时踩过的几个大坑。适合正在做综合能源园区调度、售电结算或需求响应机制设计的朋友参考哪怕你之前没怎么碰过博弈论顺着思路走一遍也能明白个七八分。1. 从园区现场矛盾说起三方主体凭什么博弈起来1.1 三方主体各自的运营痛点先说园区里这三方到底是谁。第一方是园区综合能源服务商手里管着热电联产机组、电锅炉、储能、屋顶光伏这些资产既产电也产热对外还要跟上级电网买电、跟天然气公司买气。它的核心诉求很直白在保证供能可靠的前提下让运行收益最大化或者至少让账面上的运行成本最小化。但问题是热电联产的“以热定电”特性经常让它很别扭——冬天热负荷高的时候电发多了园区自己消纳不完上网又可能受到联络线容量限制反过来要是为了多发电强撑热负荷没人用热就变成纯浪费。第二方是园区内的多能用户可能是工厂、办公楼、数据中心这类综合体。用户不关心热电联产怎么运行也不关心储能SOC是多少他们只关心一件事在满足生产生活和舒适度要求的前提下能源账单尽量低。于是用户手里就有了“柔性负荷”这张牌——可转移时段的生产用电、可微调的空调温度、可错峰的充电桩这些都是需求侧资源。问题在于用户的舒适度和生产节奏是有代价的不能为了省钱无限度地转移负荷。第三方是上级配电网。站在配网的角度园区是一个特殊的“可调节负荷分布式电源”聚合体。电网希望联络线功率平稳、不要出现尖峰倒送、更不能突破线路容量上限同时在电力市场环境下还希望通过分时电价引导园区削峰填谷。但电网没法直接指挥园区内部哪台机组开、哪个用户停只能通过价格信号和容量约束来间接影响。这三方的目标天然不一致放在同一个园区里就必然产生博弈服务商想提高热价来提高收益用户就会少用热甚至自建电锅炉用户想把负荷挪到低谷时段服务商的储能策略就得跟着变电网想压联络线峰值服务商的购电计划和用户负荷曲线又直接决定这个约束能不能满足。任何一个单方面优化都会挤压另外两方的利益空间。1.2 不合作的本质没有事前协议的多方决策这里要澄清一个常见的误解非合作博弈并不是说三方要恶意对抗、互相使绊子而是指三方之间没有一份具有约束力的合作契约。服务商不能命令用户必须几点用电电网也不能直接调度园区内每一台设备。大家各自做各自的决策但是决策结果会通过共享的电力网络、热力网络和市场价格互相影响。我做过一个对比实验同样的园区参数用集中式联合优化求解出来的总运行成本确实最低但把优化结果中的设备启停计划交给实际运行人员时没有一方真正满意。服务商说“凭什么我的储能要为了缓解电网峰值而少放电”用户说“凭什么我的产线要为了全局最优挪到凌晨三点”电网那边也觉得“你给的计划我根本没法验证真实性”。这就是联合优化的现实困境——在单业主园区里成立在多利益主体园区里落不了地。非合作博弈的价值恰恰在这里它不需要谁服从谁只需要一个公平的价格信号和一套透明的迭代规则。每一方都在给定价格和其他主体当前策略的前提下做自己最有利的决策大家反复调整最终落在一个“谁也无法单方面变得更好”的稳定点上这就是纳什均衡。落到工程语言上就是一套可执行、可解释、可结算的分布式市场机制。2. 为什么不直接做联合优化非要用非合作博弈架构2.1 三种建模范式的适用边界很多刚接触园区多能流优化的人第一反应是直接把所有设备、所有负荷、所有约束丢进一个大模型里求全局最优不行吗技术上当然行但工程上往往行不通。原因不复杂我用一张表把三种路线摆在一起看就清楚了。建模路线决策权归谁数据可见性要求利润/利益分配典型场景集中式联合优化统一调度中心各方真实成本、约束全部可见无明确的分配机制只能事后算总账单一业主、源网荷储一体化的封闭园区合作博弈各方谈判形成联盟需要一定信息共享和谈判机制按Shapley值、核仁等分配联盟收益有长期合作基础、可签订契约的多方主体非合作博弈各方独立决策只需交换价格和少量边界信息均衡价格自动决定各方收支多利益主体、信息不对称、无强制契约的市场环境这里面的关键变量是信息可见性。先看成本曲线吧服务商的天燃气采购成本、机组的效率曲线这些数据在企业内部算核心经营信息不太可能全部开放给用户去验证用户的产线价值曲线、因负荷转移造成的生产效率损失用户也不太愿意告诉服务商——毕竟一旦说出去服务商就可以在定价时“精准拿捏”。集中式优化假设所有数据都透明这在多主体园区里基本是伪命题。再看合作博弈它要求各方先承认联盟有净收益然后坐下来谈怎么分钱。园区刚投运那阵子各方连信任基础都没有更别说讨价还价的成本了。谈崩一次后面就不太愿意再谈。非合作博弈的好处是以共识的价格信号为媒介把信息暴露控制在最小范围内每次迭代只需交换“在当前价格下我的最优申报量”。这个机制在电力市场、碳排放权交易中已经被反复验证过——不需要你告诉我你的底牌只需要你按市场规则出牌。2.2 非合作博弈的代价与补偿当然非合作博弈不是没有代价。最典型的代价就是双边加价double marginalization效应上游主体在定价时加入自己的利润下游主体面对高价又减少用量最终总交易量低于联合最优水平系统整体效率受损。在园区场景里服务商如果把电价定得偏高用户就会减少购电、多用自己的分布式光伏或者干脆投资自备储能结果服务商的机组利用小时数下降双方都没占到便宜配网的潮流分布也可能更差。但这不意味着非合作博弈就不可用。工程上通常用两个手段来弥补一是引入合理的价差约束——比如热价的定价上限不能超过用户自建燃气锅炉的边际成本否则用户一定“用脚投票”二是用市场化的结算机制引导让各方在一个迭代均衡的自然出清结果里结算而不是由某一方拍脑袋定价。实际上后面要讲的影子价格出清方式在数学上可以保证均衡解满足全网的电热平衡这种“市场机制内生化”的设计比单纯的外部价格管制要顺滑得多。3. 三方非合作模型的数学骨架目标、约束与均衡3.1 决策变量与时间粒度搭建模型之前需要先把决策变量定义清楚。我做这个探索性模型时的基本设定是以1小时为调度步长滚动一个典型日24小时。服务商的决策变量包括热电联产机组的电出力 (P_{CHP,t}) 和热出力 (H_{CHP,t})电锅炉的耗电功率 (P_{EB,t})把低谷电变成热储能的充/放电功率 (P_{ESS,t})正值放电、负值充电从上级电网的购电功率 (P_{grid,t})也可以为负值表示倒送但这里先限制为不可倒送简化收敛性分析。用户的决策变量主要是可转移电负荷 (\Delta P_{L,t})正值表示比基线多用负值表示少用可调节热负荷 (\Delta H_{L,t})如果用户侧有供热锅炉或蓄热装置也可以把它看作可平移的用热计划。上级配电网的决策变量实际就落在这个园区与外界的联络线功率 (P_{grid,t})和服务商的购电功率是同一个量物理上耦合以及一个可能的可中断负荷响应量上。为了让三方边界清晰可以把这个变量归为“电网侧参与者的决策”服务商和电网在联络线上形成一对供需关系。3.2 目标函数与耦合约束如何出市场出清价格我不建议一开始就加入太复杂的非线性模型直接用二次成本函数把各方目标写清楚就够了。服务商的目标是让总运行成本最小化[ C_1 \min \sum_{t1}^{24} \left[ c_{gas}(P_{CHP,t}, H_{CHP,t}) c_{grid}(P_{grid,t}) c_{ESS}(P_{ESS,t}) c_{EB}(P_{EB,t}) \right] ]其中 (c_{gas}(\cdot)) 是天然气成本可以写成关于电出力和热出力的凸二次函数(c_{grid}(\cdot)) 是向电网购电的成本通常包含一个分时电价项加一个二次项表示购电压力(c_{ESS}) 和 (c_{EB}) 分别表示储能损耗和电锅炉运行成本。用户的目标函数是在用电舒适度损失和能源支出之间做权衡[ C_2 \min \sum_{t1}^{24} \left[ \alpha_{comf}(\Delta P_{L,t})^2 \beta_{thermal}(\Delta H_{L,t})^2 \lambda_t^(P_{L,t}^{base} \Delta P_{L,t}) \mu_t^(H_{L,t}^{base} \Delta H_{L,t}) \right] ]这里 (\lambda_t^) 和 (\mu_t^) 是迭代过程中逐步形成的电、热出清价格。换句话说用户在做决策时已经把当前市场价格当作给定参数只优化自己的负荷调整量。电网参与者的目标函数可以设为联络线功率波动惩罚与线路损耗成本之和[ C_3 \min \sum_{t1}^{24} \left[ c_{loss}(P_{grid,t}) \xi(P_{grid,t} - P_{grid,t-1})^2 \right] ]这三个目标函数并不是互相独立的它们通过两个全局平衡等式耦在一起电力平衡 [ P_{CHP,t} P_{grid,t} P_{ESS,t} P_{PV,t} P_{L,t}^{base} \Delta P_{L,t} P_{EB,t} ]热力平衡 [ H_{CHP,t} H_{EB,t} H_{ESS,t} H_{L,t}^{base} \Delta H_{L,t} ]再加上联络线容量约束 (|P_{grid,t}| \le P_{grid}^{max})这个模型就构成了一个带有耦合约束的多方博弈问题。这里有一个很关键的设计细节价格不是任何一方自己定的而是由耦合约束对应的影子价格决定的。每次迭代中协调中心先根据当前各方的申报量计算电不平衡量 (\Delta e_{ele,t})再按这个偏差更新价格 (\lambda_t)。当价格收敛后(\lambda_t) 恰好等于电力平衡约束在均衡点上的边际值也就是“让电力市场出清的那个价格”。这样就把人为定价的博弈空间压缩到最小价格本身成为各方共同认可的市场信号。3.3 广义纳什均衡的解概念由于公共耦合约束的存在这个问题不是普通的纳什博弈而是广义纳什均衡问题。普通纳什博弈里每个参与者的可行域只取决于自己的决策互不影响广义纳什博弈里一个参与者的可行策略还受制于其他参与者的决策——比如园区的用电负荷你不能凭空给一个数必须让全网的电力平衡约束成立。求解广义纳什均衡至少要保证以下几点存在性通常要求每个参与者的目标函数在自身决策上是凸的且约束满足一定正则条件稳定性纳什均衡必须是一个“无人愿意单独改变策略”的状态价格一致性由于三方共享同一个平衡约束均衡处对应的影子价格必须一致。如果各算各的拉格朗日乘子就会出现“同一个市场两个电价”的荒谬结果。在工程实践中我用的是变分不等式的框架来理解这个解把三方的KKT条件联立起来实际上就是在求解一个变分不等式问题。只要映射满足单调性条件广义纳什均衡点的存在性和部分唯一性就能保证这也为后面的分布式算法提供了理论支撑。4. 分布式求解算法从KKT条件到可跑的迭代流程4.1 求解路线的基本思路把三方模型写出来后下一步就是怎么求。最常见的做法是“中心化求解”把三个参与者的KKT条件放在一起用一个大规模求解器直接算。这种方式在小规模算例里能跑但有一个致命问题它会破坏“信息不互通”的前提。服务商的燃气成本曲线、用户的舒适度惩罚系数全都堆到同一个模型里去了这在真实市场中根本不可能实现。所以我采用了一个分布式原对偶迭代框架核心思想是“本地决策、价格协调”初始化一组电、热价格序列 (\lambda^0, \mu^0)将当前价格广播给三方主体三方面对当前价格分别求解自己的本地凸优化子问题并把最优决策量上传给协调中心协调中心汇总所有申报量计算电力不平衡量和热力不平衡量按不平衡量更新价格再回到第2步直到不平衡量小于允许误差。这个流程对应到实际系统中协调中心可以是园区能量管理平台也可以是独立的市场运营方。三方不需要把自己的完整成本曲线报给任何一方只需要申报“在当前价格下我要买/卖多少电和热”。这正是非合作博弈架构最适合工程落地的地方。4.2 实际可复用的迭代代码骨架用一套伪Python代码来描述这个迭代流程逻辑是很清楚的import numpy as np # 基础参数 T 24 alpha_price 0.02 # 电价更新步长 beta_price 0.01 # 热价更新步长 max_iter 3000 tol 1e-4 # 初始化价格取分时电价的均值附近 lam np.ones(T) * 0.65 # 元/kWh mu np.ones(T) * 0.35 # 元/kWh for k in range(max_iter): # 主体1服务商本地优化返回CHP出力、储能、购电计划 P_chp, H_chp, P_ess, P_grid, P_eb solve_service_provider(lam, mu) # 主体2用户本地优化返回可转移负荷和可调热负荷 delta_P_load, delta_H_load solve_user(lam, mu) # 主体3电网侧优化返回联络线功率这里与P_grid是同一物理量 P_grid_final, loss_flag solve_grid(P_grid) # 汇总后的电不平衡量MW # 电源出力 外购电 储能放电 - 用户负荷 - 电锅炉耗电 res_ele (P_chp P_grid P_ess - (P_load_base delta_P_load) - P_eb) # 汇总后的热不平衡量MW res_heat (H_chp H_eb - (H_load_base delta_H_load)) # 价格更新不平衡量大于0说明供大于求价格下降 lam lam alpha_price * res_ele mu mu beta_price * res_heat # 两个判据原残差和价格变化量 if np.max(np.abs(res_ele)) tol and np.max(np.abs(res_heat)) tol: print(f收敛于迭代 {k}) break if k % 200 0: print(f迭代 {k}: 最大电不平衡 {np.max(np.abs(res_ele)):.6f}, f最大热不平衡 {np.max(np.abs(res_heat)):.6f})这段代码骨架有两个要注意的地方一是solve_service_provider、solve_user、solve_grid这三个子函数内部是各自独立的凸优化问题可以并行求解并且它们的实现细节对彼此不可见二是价格更新步长 (\alpha, \beta) 的选择直接决定迭代是否收敛后面我会专门讲这个坑。4.3 收敛判据的设置经验范围从纯数学角度收敛判据就是当原残差 (|r|\to 0) 时停止。但从工程角度我建议至少加两个判据同时判断原残差判据电力、热力平衡偏差的无穷范数小于某个物理可行值。比如一个兆瓦级园区偏差压到 (10^{-4}) MW即0.1 kW已经足够小决策变化判据相邻两轮迭代中每个主体的决策量变化小于某个阈值防止“价格还在小幅震动但平衡刚好碰巧满足”的假象。只用一个判据很容易出问题。我见过有些人只写原残差判据结果某轮迭代中价格更新恰好抵消了不平衡量看起来收敛了实际下一轮又发散。所以稳妥的做法是把两者联合起来哪个先满足都要确认另一个不能超标太远。5. 实测中踩过的坑不收敛、解不唯一、价格震荡5.1 影子价格不唯一带来的结算风险第一次把模型跑通后我信心满满地看热平衡的收敛结果却意外发现一条诡异的规律即使原变量收敛到同一组解电价序列却有两种不同的收敛路径差距达到每千瓦时0.08元。一开始我以为程序写错了反复检查后才发现这是广义纳什均衡本身的结构特性——当耦合约束在均衡点处不满足严格互补松弛条件时影子价格不一定唯一。这个问题放到结算环节就是大事。同样的用能量按一条价格路径结算是15万按另一条结算就变成了16.5万。处理办法是在价格更新公式里加一个小幅度的二次正则项或者在迭代过程中对所有主体采用统一的初值和相同的步长序列。我在代码里加了很小的价格正则项后价格序列就稳定多了重复运行结果也高度一致。5.2 步长参数0.5和0.02之间的巨大鸿沟迭代算法的步长是影响收敛的第二大坑。我在一组测试里把电价更新步长从0.05改成0.5观察到的现象是0.05还能勉强收敛0.3以上直接等幅振荡0.5以上干脆发散。原因是园区电气耦合太强电价的微小变化会通过用户负荷、服务商储能策略层层放大送到下一轮又反过来放大价格偏差。经过多轮试错后我形成了一套经验规则电价的更新步长取0.01~0.02热价的更新步长取0.005~0.01如果迭代到1000轮仍然在缓慢震荡不要急着调大步长而是给价格序列做一个滑动平均或者采用步长衰减策略更好的做法是模拟“退火”前500轮用稍大步长快速进入可行域后面再把步长缩小到前者的五分之一专门做精细收敛。这套策略实践下来大部分工况都能在几百到一两千轮内达到 (1e-4) 的平衡残差。5.3 固定热电比与“以热定电”的矛盾不少热电联产机组的热电比是固定或近似固定的这意味着电出力和热出力不能独立调节。在联合优化里这个约束只是多一个等式但在三方博弈里这个约束会变成一个大麻烦服务商为了追求电收益想多发电但热负荷用不完热平衡会被打破用户那边想多用热服务商的电出力又会跟着增加导致电力供大于求。我踩过最明显的一次坑是某天热负荷高峰段用户申报了大量热需求服务商的热电联产被迫满发结果夜间低谷期电力富余到快突破联络线约束。解决思路有几个一是引入电锅炉作为热电联产的“热解耦器”——电出力多了就用电锅炉把多余电转成热相当于在热侧制造一个人为负荷二是优化储能策略让储能在电力富余时充电、在热需求高峰时能放热三是允许服务商申报负热电比调整也就是阶段性降出力让用户侧蓄热装置顶上。这些缓解措施配上储能之后模型的可收敛性和方案的经济性都有明显提升。5.4 对用户需求弹性初始值估计过于乐观很多人在建模时会把用户的舒适度惩罚系数 (\alpha_{comf}) 设得很小认为“只要价格合适用户就会积极调整负荷”。真实情况完全不是这样。我用一个实际园区数据测试时发现用户的可转移负荷比例也就10%左右而且很多工业负荷根本没有那么多弹性。如果模型里把弹性设得太高迭代过程中用户侧负载变化幅度会很大进而造成价格剧烈跳动。后来我把用户侧惩罚系数从初始值调大两倍再配合一个“申报量限幅”机制——每次迭代允许用户最大调整不超过上一轮申报量的20%——整个系统立刻稳了下来。虽然收敛轮数稍微变长了一点但不会再出现负荷曲线像锯齿一样来回抖的现象。5.5 耦合约束不是摆设联络线越限的隐性代价最后一个坑是关于约束的处理方式。有同事图省事直接把联络线功率上限写成“罚函数”一旦越限就加一笔很大惩罚。这个方法在联合优化里尚可接受但在非合作博弈里会产生副作用服务商和电网各自对“越限惩罚”的敏感度不一样外部价格的扭曲会传导到电热平衡上导致最终的纳什均衡点偏离真实的市场出清点。我在工程里用了投影法来替代罚函数每次迭代得到联络线功率后如果越限就直接投影到可行区间内再把这个投影后的值带入下一轮的价格更新。这么做不仅避免了罚系数难以调节的问题也让均衡解在机理上更干净。6. 小规模算例怎么搭参数、造数验证与扩展方向6.1 一个可以手算复现的小型园区场景说了这么多方法来一个具体的小规模算例参数方便你自己复现验证。假设园区典型日24小时基线电负荷峰值1.2 MW、低谷0.4 MW基线热负荷峰值0.8 MW、低谷0.2 MW。主要设备参数如下表设备/参数数值说明热电联产电效率0.35天然气低位热值效率热电联产热效率0.45热回收效率天然气价格2.6 元/m³折算为每千瓦时燃料成本约0.62元上级电网分时电价峰值1.1 元/kWh早高峰时段上级电网分时电价谷值0.35 元/kWh凌晨低谷时段电锅炉效率0.9电转热储能容量0.5 MWh允许放/充功率0.25 MW联络线容量上限0.8 MW禁止倒送在这个算例里我的初始价格取的是固定电价序列的加权平均值电0.65元/kWh、热0.35元/kWh迭代步长按前文建议设置。跑完后的收敛表现是约800轮后最大电不平衡降到1e-31800轮后降到1e-4热平衡收敛速度略慢最终在2200轮左右三个判据全部满足。6.2 三组对照场景的观察结果为了验证模型的有效性我在同样的基础参数上做了三组对照实验。第一组是“无储能、无需求响应”的基准场景第二组是“只加需求响应不加储能”第三组是“储能和需求响应都有”。场景服务商运行成本万元/日用户能源支出万元/日联络线峰值MW总电平衡偏差收敛轮数无储能、无需求响应3.812.940.80触顶约2600加需求响应3.722.660.74约1900储能需求响应3.552.610.68约1500这个结果并不意外但有几个细节值得注意加了需求响应后用户支出下降明显服务商成本也微降这说明需求弹性缓解了双边加价带来的效率损失再加储能后联络线峰值下来了电网侧的运行压力明显减小。对模型探索阶段来说这些结果足以说明三方非合作机制能让每个主体都受益而不是零和游戏。6.3 从模型探索走向工程机制的三个补丁模型收敛只是第一步真要把它用到园区日常运行和结算里还差三块拼图。第一块是结算偏差处理。博弈均衡得到的是目标出力曲线但实际运行中总会出现预测误差和突发故障。我通常会在模型外面再套一层考核机制偏差在允许范围内的按均衡价格结算超出的按惩罚价格结算。这样既能保留非合作机制的价格引导力又不会因为短期扰动引发价格机制崩溃。第二块是时序滚动。典型日模型算出来的是“明天怎么做”的决策但园区运行是连续的。实际部署时我会采用滚动优化每小时触发一次重新计算只执行未来第一个小时的决策后面23小时作为前瞻窗口。这样能有效对冲负荷预测误差让博弈均衡结果对实时波动保持鲁棒。第三块是碳约束的引入。现在很多园区已经逐步把碳排放指标纳入考核我在探索模型里也把碳配额当作一种额外的影子价格加进了天然气成本和购电成本中。思路不复杂给碳排放量定一个影子价格然后在三方目标函数里各加一项碳成本。碳价格高时服务商会更倾向于调整热电联产出力和储能策略用户也会更积极地进行需求响应。这相当于在原有电热市场上多了一层碳市场信号机制依然是非合作博弈框架但均衡结果会更贴近低碳运行需求。如果后面你也要做类似的探索我建议一定从最小场景开始调通再逐步加设备、加约束。先把两三个参与主体、十几个约束条件跑稳比一次性把整个园区塞进模型再慢慢排查要省太多时间。三方非合作模型在综合能源园区里的价值不在某个算法有多炫而在于它真正尊重了每个参与者的独立决策权同时还能在价格信号的引导下收敛到一个各方都能接受的稳定运行点——这对多利益主体园区来说本身就是最重要的工程属性。