ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

综合能源系统主从博弈与碳交易机制优化调度全解析

综合能源系统主从博弈与碳交易机制优化调度全解析 综合能源系统、主从博弈、碳交易机制这三个词放在一起看起来像是论文标题里拆出来的概念组合实际上它是当前园区综合能源系统IES优化调度里最常用的一套建模框架。我最近完整跑了一轮这个方向的仿真程序从上下层博弈建模、阶梯碳价嵌入到电、热、气三类负荷联动的综合需求响应数学刻画再到MATLABYalmipCplex下的程序实现整个链路走下来踩了不少坑也沉淀出一些能直接复用的参数和写法。这篇文章把从模型设计、公式拆解到程序实现、结果分析的完整思路一次说清楚重点是讲明白为什么调度问题要改写成“上层能源服务商定价、下层用户响应”的主从博弈形式碳交易费用怎么搬进优化目标以及代码里KKT条件转换、Big-M线性化这些关键环节怎么落地。这个内容适合三类人看正在做IES优化调度方向、需要仿真结果支撑论文的研究生接手园区综合能源项目、需要快速搭建可运行程序的工程师以及想理解碳排放成本如何影响售能定价和用户用能行为的产品或运营人员。没有太多复杂的数学推导我把每一步背后的“为什么这样做”也一并写了哪怕你之前只做过单一能源系统的调度顺着这套逻辑也能把模型跑起来。1. 这个题目到底在解决什么问题1.1 为什么调度问题会从“单层优化”变成“主从博弈”传统的综合能源系统优化调度一般是将系统内所有设备出力、储能充放、购能计划放在一个集中式优化模型里以系统总运行成本最小为目标函数一次性求解。这种方式在单一运营主体、没有外部价格反馈的场景下完全够用但放到真实的园区环境里就会遇到一个很现实的矛盾能源服务商和用户的目标是不一致的。服务商想提高售能价格、多卖能量、增加收入用户想降低用能成本、保持用能舒适度两边存在利益冲突。如果只用一个集中式目标函数不管怎么加权都没办法真正反映“服务商定价”和“用户响应”之间的互动关系。这时候就需要引入主从博弈框架也叫Stackelberg博弈。上层是综合能源服务商先决策售电价格、售热价格、激励价格下层是用户或负荷聚合商看到价格后再优化自己的用能行为。下层的最优反应会反过来影响上层的实际收益最终形成一个博弈均衡点。这种分层建模不是学术上的炫技它反映的是实际业务逻辑服务商确实拥有定价权但定价不是拍脑袋定的用户会用脚投票。把这种互动关系结构化就是主从博弈模型的核心价值。1.2 碳交易机制到底“动”了谁的利润碳交易机制在这个模型里不是简单加一个碳价常数而是给服务商的成本和碳排放之间建立了一个经济锚点。综合能源系统的主要碳排放来源包括外购电力的间接排放、燃气轮机和燃气锅炉燃烧天然气的直接排放。碳交易机制要求服务商持有足额碳排放配额如果实际排放超过免费配额就需要在碳市场购买配额如果配额富余则可以出售获利。在实际仿真中这意味着碳交易成本要作为一个独立成本项进入上层服务商的目标函数。碳价越高、超额量越大这一项对定价和设备出力的影响就越明显。服务商会主动调整机组组合——减少外购高排放电力、优化燃气轮机出力、提高热泵等高效电转热设备的利用率最终形成一个“碳排放成本倒逼设备结构优化”的链条。需要注意的是如果不加碳交易机制大多数调度结果一定是优先选择低运行成本的供能设备不管排放高低。加碳交易之后碳排放变成了一项“可量化的成本资源”低碳设备可能在综合成本上更有优势这个变化是观察程序正确与否的重要指标。1.3 综合需求响应如何把用户侧“捏”进模型传统需求响应一般只针对电负荷做削峰填谷综合需求响应则是把电、热、气三类负荷放进同一个用户优化模型里统一考虑。用户的参与方式主要有三类可转移负荷比如电动汽车充电、洗衣机的用电时段移动、可削减负荷比如空调温度上调、照明减半、可替代负荷比如电价低谷时用户从用气供暖切换为热泵供暖。这些行为最终都会变成用户侧优化问题的变量和约束。用户不是被动接受价格的“刚性负荷”而是会基于价格信号主动调整用能曲线。这样一来上层服务商调价格下层用户调负荷主从博弈的反馈回路就完整了。综合需求响应的“综合”二字还体现在能源品种的耦合上——用户调整用电的同时也可能影响热负荷或者气负荷这在建模时需要用设备模型和转换效率来衔接。2. 主从博弈模型的分层设计与目标函数拆解2.1 谁当领导、谁当跟随角色分配的逻辑主从博弈的第一步是划定参与者和决策顺序。在综合能源系统调度场景里最自然的角色分配是上层为综合能源服务商或称为IES运营商、能源枢纽运营商下层为用户或负荷聚合商。上层决策变量包括各时段的售电价格、售热价格、需求响应激励价格。这些变量直接影响下层的用能成本和响应意愿。下层决策变量则包括各时段购电量、购热量、可转移负荷的平移量、可削减负荷的削减量以及用户侧储能或分布式设备的出力。为什么不让用户当上层因为用户通常不具备定价权只能接受市场价格并调整用能行为。如果用户侧还包含产消者比如装了屋顶光伏和储能既能买电也能卖电这种情况可以扩展为“产消者博弈”但基础版本建议先用“服务商定价、用户响应用能”的结构跑通。另外实际场景中用户往往不止一个这就变成一对多主从博弈每个下层用户独立求解自己的优化问题上层利润是所有用户购能费用的总和。程序上多用户意味着KKT条件的数量和变量维度成倍增加调试复杂度明显上升。我建议刚开始做仿真时先用单用户聚合模型跑通后再扩展成多用户。2.2 上层目标函数怎么拆项上层服务商的目标函数可以从利润最大化的角度来写骨架如下上层目标 售能收入 激励服务节省费用 - 外购电力成本 - 天然气购气成本 - 设备运行维护成本 - 碳交易成本其中售能收入包含售电收入和售热收入分别用售电价格乘以售电量、售热价格乘以售热量表示。这里的“售电量”不是服务商单方面确定的它是下层用户优化后的购电结果这正好体现了博弈的耦合关系。外购电力成本通常按分时电价计算天然气购气成本按天然气的热值折算。设备运行维护成本用各机组的出力乘以运维成本系数来线性累加。碳交易成本单独成项因为它的计算依赖排放核算和阶梯碳价逻辑比较独立。目标函数写出来之后还需要给决策变量加边界约束。售电价格和售热价格不能无限高上限往往参考电网售电价格或用户的替代能源价格不然下层用户会选择不买服务商的热、电转而从电网购电或者自行产热。价格下限则要覆盖运行成本否则服务商卖一份亏一份均衡结果没有现实意义。这种边界条件的设定是程序能求解出合理均衡的前提。2.3 下层用户的目标函数与约束条件下层用户的核心逻辑不是“成本最小”四个字能概括的更合理的表达是“用户净效用最大化”。用户从用能中获得效用同时缴纳购能费用如果参与了负荷削减还会获得激励补偿但削减负荷本身会带来舒适度损失。下层目标函数可以写成用户净效用 用能满意度收益 - 购电费用 - 购热费用 - 负荷削减舒适度损失 需求响应激励补偿用能满意度收益可以用二次效用函数来刻画二次项系数的物理意义是用户对价格变化的敏感程度。这个系数直接影响需求响应的弹性——系数越大用户在价格高时越愿意削减或转移负荷。下层约束包括每个时段的电力平衡、热力平衡、可转移负荷的能量守恒约束、可削减负荷的上下限约束、用户侧储能的SOC荷电状态递推约束等。需要特别注意的是可转移负荷的建模一定要有时间耦合约束例如“一天内所有时段转移前后的负荷总量保持不变”。如果漏写这个约束模型会出现“能量凭空产生或消失”的问题仿真结果完全失真。2.4 为什么必须做KKT条件转换主从博弈的精确求解路径里最常用的是把下层的优化问题通过Karush-Kuhn-TuckerKKT条件转换为一组约束条件替换掉原来的下层问题。这样做的好处是原本嵌套式的博弈问题变成了一个单层数学规划问题可以直接交给求解器。但KKT转换不是没有代价。它引入两类新困难一是上层目标函数里出现“价格乘以销量”的双线性项因为销量本质上是下层购电量的函数两个变量相乘导致模型非线性二是KKT条件中包含互补松弛条件比如“对偶变量乘以约束的松弛变量等于0”这种形式也是非线性的。处理双线性项的手段是强对偶定理当用户侧问题是凸优化时可以用下层问题的对偶目标来替换原目标从而把双线性项消掉。处理互补松弛条件的手段是Big-M法引入一个足够大的正数M和0-1整数变量把互补条件拆成两组线性不等式。到这里整个模型就变成了混合整数线性规划MILP可以交给Cplex或者Gurobi求解。这套转换逻辑实际上是整个程序仿真中最核心的工程能力点后面第5部分我会再展开。3. 碳交易机制与阶梯碳价的数学建模3.1 碳排放核算边界与配额分配碳交易机制建模的第一步是算清楚“排了多少碳”。综合能源系统里的碳排放一般分两部分核算一是外购电力隐含的间接排放计算方法是用外购电量乘以电网排放因子二是系统内燃烧天然气产生的直接排放包括燃气轮机和燃气锅炉计算方法是用天然气消耗量乘以单位热值含碳量再乘以氧化率。免费配额怎么给园区场景常用基准线法即先确定一个单位供电/供热的综合排放基准再乘以系统实际供出的电量或热量得到免费配额。如果实际碳排放量低于免费配额服务商可以把富余配额拿到碳市场出售高于免费配额的部分则必须按碳市场价格购买。这里有一个建模细节容易忽略外购电的排放因子不是固定不变的实际电网中不同时段的电源结构不同但在常规仿真里通常简化成一个年均值。如果你想做更精细的场景可以考虑分时排放因子比如夜间负荷低谷时段外购电的排放因子更高或更低这会影响储能的充放电策略。3.2 阶梯碳价模型与线性化固定碳价机制建模最简单但研究价值有限因为现实碳市场的价格是随配额供需变化的超额越多、价格越贵。所以很多文献采用阶梯碳价模型将超额排放量分成若干区间每个区间对应一个递增的碳价。举个例子超额量在0-20吨时按50元/吨结算20-50吨部分按80元/吨超过50吨的部分按120元/吨。这个分段函数是非线性的嵌入MILP需要做分段线性化。做法是把超额排放量拆成多个分段变量每个分段变量有上下限同时引入0-1整数变量标记当前激活的分段确保分段按顺序占满。比如如果实际超额90吨那么第一段0-20要占满第二段20-50也要占满第三段50-90部分占满。这个“分段顺序占满”的约束是阶梯碳价建模里最容易写错的地方。如果只是简单地把超额量分成三段而不加“前一段必须填满才能用后一段”的逻辑优化器可能会只使用价格最低的区间来“逃避”高碳价完全扭曲碳交易的成本约束。添加分段约束时需要用辅助0-1变量保证顺序并在边界处设置很小的容差来避免数值震荡。3.3 碳交易机制如何改变设备出力给模型加入碳交易机制之后设备出力结果会发生一系列在工程上完全合理的变化。燃气轮机虽然发电效率有限但它同时供热综合能效高而且燃料是天然气碳排放强度显著低于外购煤电因此在碳价上升时会获得一定的调度优先级。但优先级不是无限的天然气购气成本和直接排放会同时上升所以在高碳价场景下燃气轮机的出力不会无节制增加。另一个明显变化是外购电的占比下降。电网电力的间接排放要计入总排放碳价越高外购电的实际成本越高服务商会尽量减少从电网买电转而让更高效率的本地机组出力。这时候热泵的价值会凸显出来——热泵COP一般能做到3.0左右消耗1千瓦时电可以产生3千瓦时热用这种方式替代燃气锅炉供热时虽然增加了用电量但如果电力来自光伏或燃气轮机自产电整体碳排放反而下降。储能设备的充放策略也会被碳成本“挤压”。服务商在电价低谷充电、尖峰放电的操作会因为碳成本而改变如果低谷时段外购电是高排放电力充电时段就相当于“存储了高碳电”在碳价高的场景下服务商会减少这类充电操作转而更多依赖低排放本地电源。这些设备出力变化都可以在仿真曲线里清晰观察到是做结果分析时的重要抓手。4. 综合需求响应的数学刻画与程序化表达4.1 可转移、可削减、可替代三类负荷建模综合需求响应把用户侧负荷分成多种柔性类型在数学上需要分别刻画。可转移负荷的特征是“总能量不变、时段移动”。比如电动汽车充电用户一天需要充入的总电量是固定的但可以选择在深夜充电还是在晚间高峰充电。建模时设一个转移变量表示某个时段原本的负荷被移动到其他时段然后加一个全天所有时段转移前后的总负荷平衡约束。这就是时间耦合约束的典型写法。可削减负荷的特征是“某个时段允许减少一部分用能”。比如空调在高峰时段可以适当调低功率通过牺牲一点舒适度来降低负荷。建模时设削减量变量并设置上下限同时削减会带来舒适度损失在目标函数里用惩罚项体现。通常这个惩罚项做成二次函数削弱程度越大、边际舒适度损失越高这样模型不会一股脑把负荷削到零。可替代负荷的特征是“能源品种之间可以转换”。比如用户家里既有天然气壁挂炉又有热泵当电价较低时用户可能选择热泵供暖减少天然气消耗。建模时需要设备转换效率参数和负荷平衡约束来支撑这种替代关系。三种类型的核心区别在于可转移改变的只是时间分布不改变总能量可削减改变的是总用能量需要支付激励补偿或产生舒适度损失可替代改变的是能源品种结构和不同能源的购买量。4.2 价格型与激励型响应同时并存需求响应的实现机制可以分成价格型和激励型两类实际模型中两者通常是同时作用的。价格型需求响应体现在用户目标函数的购能费用项里。售电价格提高用户自然减少购电这就是价格信号引导行为。激励型需求响应则体现在上层给出的激励单价上用户参与负荷削减或转移会获得额外补偿补偿标准由上层控制。在程序实现上上层同时优化售能价格和激励单价下层在这两类价格信号下统一做用能决策。这种方式的好处在于贴近实际两者不是替代关系而是协同作用。价格型响应是普遍、自动发生的激励型响应则是针对特定可调控负荷的深度互动。仿真结果里如果只设价格型响应用户侧弹性通常较小加入激励型响应后用户参与削减的意愿明显增强系统削峰深度和碳排放下降幅度都会提高。4.3 用户侧约束的预处理技巧用户侧模型在程序调试阶段容易出现的坑主要集中在三类约束上。第一类是储能约束最常见的问题是电储能不能同时充放。如果不加约束优化器会利用“同时充放”的漏洞凭空创造利润导致结果失真。解决方法是引入0-1变量区分充电状态和放电状态或者用线性化的互补条件来表达。第二类是热负荷的动态约束。建筑的室内温度变化可以用一阶等效热参数模型来刻画室内温度变化率与当前室内温度、室外温度、供热量有关。如果简化成静态热平衡虽然模型好解但需求响应的“短期调温”行为就刻画不出来。在做综合需求响应时至少要保留一个简单热惯性模型否则用户削减热负荷的约束会过于激进。第三类是削减量的平滑性约束。实际设备调控不能做到每个时段独立、大幅跳动所以需要加梯度约束限制相邻时段削减量的变化幅度。这个约束不加上仿真结果里可能出现前后两个时段负荷突变的情况既不现实也会让求解结果的可信度打折。建模时建议按“先LP后MILP”的顺序递进先把所有能写成线性约束的写进去跑通纯线性版本再逐步加入整数变量储能状态、阶梯碳价分段等这样排查错误要容易得多。5. 程序仿真设计从数学模型到可运行代码5.1 工具选型MATLABYalmipCplex组合我在这个方向上一路实测下来最顺手的组合是MATLABYalmipCplexGurobi也可以。Yalmip的建模语法非常接近数学表达式本身写约束时基本可以照着论文公式翻译成代码不必自己手工处理矩阵维度。Cplex/Gurobi处理大规模MILP问题的性能可靠尤其是Cplex内置的割平面和启发式算法在很多IES调度算例里表现很稳。如果你更喜欢全Python方案PyomoPandasGurobi也可以但个人感受是MATLABYalmip对初学者更友好Yalmip里变量维度不匹配时会直接报出中文可读性比较强的错误调试省心。但如果你后续要做负荷预测、大量数据清洗或机器学习模块Python的生态优势就体现出来了。这里没有“必须用哪个”的答案取决于你后续要接什么流程、团队里惯用什么工具。5.2 求解路线怎么选KKT、迭代算法还是智能算法主从博弈的求解路线主要有三种各有适用条件。第一种是KKT条件转换加MILP求解适用于下层问题是凸优化的情况特点是精确、稳定求解一次到位不需要外部迭代。这也是本领域文献里最主流的做法推荐优先掌握。第二种是迭代求解上下层交替优化上层给定价格下层求解用户模型把结果返回上层更新价格反复迭代直到收敛。这种方法的好处是实现简单不需要做复杂的KKT推导但如果两层问题之间存在多个纳什均衡或下层约束强非凸迭代过程可能振荡不收敛需要设置步长限制和收敛判据。第三种是智能算法嵌套比如粒子群算法设计上层的价格策略下层用数学规划求解用户响应。这种方法能处理下层非凸问题但计算量大、每次运行结果可能不同需要多次运行取统计值。很多论文用这种方法是因为模型不能做KKT转换但对工程实践来说不建议优先选择。我的建议非常明确能做KKT就做KKT。只有在用户模型里存在本质非凸约束比如用户侧包含多个产消者之间的非合作博弈时才需要退回到迭代或智能算法。KKT转换的工作量虽然在前期的数学推导上但后面求解过程的稳定性会给你省下大量时间。5.3 Yalmip建模核心代码骨架下面给出一个简化版的Yalmip代码骨架重点展示结构不包含全部参数。注意Yalmip默认求解方向是最小化上层目标是最大化时需要加负号处理。% 定义变量 P_sell sdpvar(24, 1); % 售电价格24小时 H_sell sdpvar(24, 1); % 售热价格 I_inc sdpvar(24, 1); % 需求响应激励价格 P_user sdpvar(24, 1); % 用户购电量 H_user sdpvar(24, 1); % 用户购热量 P_shift sdpvar(24, 1); % 用户可转移负荷平移量 P_cut sdpvar(24, 1); % 用户可削减负荷量 z binvar(24 * K, 1); % Big-M法用的0-1变量K取决于互补条件的数量 % 目标函数上层最大化取负号转为最小化 Objective -( sum(P_sell .* P_user) sum(H_sell .* H_user) ... - sum(C_buy_e .* P_net) - sum(C_gas .* G_consump) ... - sum(OM_cost) - CarbonCost ); % 约束集合 Constraints []; % 价格边界 Constraints [Constraints, P_sell_min P_sell P_sell_max]; Constraints [Constraints, H_sell_min H_sell H_sell_max]; % 下层用户购电量与负荷调整之间的关系 Constraints [Constraints, P_user P_base_load - P_shift - P_cut P_dis - P_ch]; % 下层KKT条件示意互补松弛用Big-M线性化 % 假设dual_1是某约束的对偶变量slack_1是该约束的松弛变量 Constraints [Constraints, slack_1 0, dual_1 0]; Constraints [Constraints, slack_1 M * (1 - z(1))]; Constraints [Constraints, dual_1 M * z(1)]; % ... 后续继续添加其余约束 % 求解设置 ops sdpsettings(solver, cplex, savesolveroutput, 1); optimize(Constraints, Objective, ops);这段代码骨架看上去不复杂实际调试时重点检查三处。第一处是维度对齐所有sdpvar变量的长度要一致尤其是涉及24小时逐时变量和常数向量相乘时。第二处是检查是否还有双线性项残留比如P_sell和P_user都是变量它们相乘就是非线性项Cplex会直接报错。如果看到“Nonlinear constraints”之类的提示优先检查目标函数和约束里所有“变量乘变量”的地方。第三处是Big-M的取值M不能取太小否则会错误地关闭可行域也不能取太大否则会造成数值病态求解器在互补条件上可能给出错误判定。一般经验是取当前约束量级的100-1000倍然后做敏感性测试。5.4 算例参数怎么设计才合理仿真参数是直接影响结果可信度的关键。我建议先用一个典型日24小时作为基本算例系统规模用3节点或5节点就足够说明问题不用一上来就建大规模区域模型。基础参数包括分时购电价、天然气价格与热值、燃气轮机发电效率与热电比、燃气锅炉效率、电锅炉效率、热泵COP、蓄电和蓄热罐容量、初始SOC、各类负荷基线曲线。下面给出一组我在算例里常用的参考数值参数参考值说明外购电峰谷电价0.8 / 0.4 元/kWh参考一般工商业分时电价设置天然气价格2.5 元/m³标准天然气热值约35.6 MJ/m³燃气轮机发电效率0.35热电比取1.2燃气锅炉效率0.9天然气供热的主要设备电锅炉效率0.95电转热热泵COP3.0消耗1 kWh电产生3 kWh热碳配额基准0.2 t/MWh按单位供能量折算免费配额阶梯碳价50 / 80 / 120 元/t对应超额区间递增用户价格弹性-0.3 ~ -0.5二次效用函数系数换算而来参数设置完成后不要急着做复杂场景先在基准参数下把程序跑通再逐项做敏感性分析。比如固定其他参数仅改变碳价水平观察碳排放总量和调度成本的变化曲线。每个参数只动一个这样结果里的变化能够准确归因。程序稳定之后再做30天或更长时间的季度仿真验证策略在负荷波动和天气变化下是否依然稳定。6. 仿真结果如何看从设备出力曲线到减排效果6.1 标准场景对照组的设置方法仿真结果分析最怕的是“只有一个场景不知道结果好坏”。建议至少设计四组对照把碳交易机制和综合需求响应两个因素的影响单独拆开场景碳交易机制综合需求响应目的Case 1无无基准场景只看基础设备调度Case 2有无单独看碳交易对调度和设备出力影响Case 3无有单独看需求响应对负荷曲线影响Case 4有有完整机制下的系统最优结果这四组场景跑完之后再横向对比关键指标就能清晰拆解两个机制各自的贡献。比如Case 2对比Case 1可以看出碳交易带来的碳减排效果和成本变化Case 3对比Case 1可以看出需求响应对峰谷差和用户费用的影响Case 4对比Case 2和Case 3可以看出两个机制叠加时是协同还是互斥。6.2 收敛性判断与求解质量检查用KKT转换后的单层MILP模型理论上求解一次就能得到均衡解不需要外部迭代。这时候收敛性主要看求解器报告的MIP gap。如果Cplex/Gurobi报告的gap一直收不敛停在比如2%以上通常有两个原因。第一个原因是Big-M值设置不恰当导致LP松弛质量很差割平面效率低。解决办法是尽量收紧M的数值不要为了“绝对安全”设一个天文数字。第二个原因是模型中的数值尺度差异太大比如碳交易成本是几十块量级售电收入是几千块量级目标函数里各项数量级差了好几个零求解器数值状态会变差。解决办法是把单位统一价格用“千元/MWh”或“百元/GJ”来定义让目标函数的各项数量级接近Cplex的求解表现会有明显改善。6.3 结果分析的标准套路看仿真结果时我习惯按三个层次逐层推进。第一层看总指标系统总运行成本、碳排放总量、用户总费用、负荷削峰填谷率。这些数字用于横向对比四个场景直接回答“碳交易和需求响应带来了多大改善”。第二层看设备出力曲线重点观察燃气轮机、燃气锅炉、电锅炉、热泵、电储能和热储能的24小时出力变化。在碳交易场景下热泵和燃气轮机的出力时段会怎样移动、储能的充电时间集中在哪个时段这些都能直观反映碳成本对调度决策的影响。第三层看用户负荷曲线对比需求响应前后的用电、用热曲线验证高峰时段是否明显削减、低谷时段是否出现负荷填充。如果做了可转移负荷建模还可以单独画一张“转移前后负荷叠加图”展示负荷从高峰转移到低谷的具体幅度。记住一条经验图不能为了画而画每张图都要对应一个你事前想验证的判断。比如你要验证“碳交易会减少外购电”那就画一张不同碳价水平下外购电量的柱状图你要验证“需求响应能降低用户费用”就画用户费用在各场景下的对比图。带着假设去看结果分析效率会高得多。7. 常见报错、异常结果与参数调试经验7.1 求解器报infeasible怎么排查遇到“infeasible problem”是仿真调试里最常让人头疼的情况。我的排查方法非常固定先从最简版本开始去掉碳交易、去掉需求响应、去掉储能只保留最基本的能量平衡约束和设备出力约束确认这个简单模型可以求解。然后一层层加回复杂度每加一层就跑一次。如果加回碳交易后无解大概率是碳排放约束和陈旧参数冲突比如燃气轮机最大出力下排放量超过了配额上限同时又设置了不能外购电的约束两者叠加就会出现死锁。如果加回需求响应后无解最容易出问题的是可转移负荷的总能量守恒约束转移出去的负荷总量必须等于转移进来的负荷总量任何一侧变量维度不匹配或者漏掉了某个时段都会让整个模型不可行。遇到无解时还可以利用Yalmip提供的diagnostics工具查看约束类型结合Cplex给出的冲突分析conflict refinement功能定位是哪些约束之间产生了冲突。这个功能比肉眼检查代码高一个量级强烈推荐学会用。7.2 下层反应函数导致的均衡不稳定在主从博弈模型里如果采用迭代求解路线而不是KKT单层化会出现均衡点振荡的问题。典型表现是上层调整价格下层响应负荷但这个负荷响应又导致上层继续加大价格调整来回震荡无法收敛。处理办法之一是给上层价格加上步长限制每轮迭代变化幅度不超过上一轮的一定比例比如5%或10%。办法之二是直接放弃迭代法改用KKT单层化让Cplex在同一个模型里同时处理上下层约束。实测下来KKT单层化的收敛稳定性远高于外部迭代这也是为什么前面我反复强调优先做KKT转换的原因。如果已经用了KKT单层化结果仍然异常比如求解出的价格严重偏离合理区间优先检查对偶变量的符号。KKT条件里的对偶变量符号必须与下层问题的“标准化形式”对应比如下层是最大化效用问题对偶变量符号的正负要求就和最小化成本问题相反。符号写反会出现“价格越高用户买得越多”这种反直觉结论但目标函数数值可能仍然正常极具迷惑性。7.3 几步快速验证模型合理性程序跑完之后即使没有报错、目标函数收敛正常也要做合理性检查。我整理了一份自查清单变量上下界检查所有购能变量、出力变量、储能功率变量都应有有限上下界否则求解器可能给出“unbounded”的警告。单位统一检查功率、能量、价格、碳排放量四个维度的单位最乱。功率是kW还是MW能量是kWh还是MWh价格是元/kWh还是千元/MWh碳排量是kg还是t任何一处没对齐结果里的数据都会偏得离谱。目标函数符号检查上层利润最大化在Yalmip里要转成负号最小化KKT条件转换过程中用到的对偶变量符号也要符合标准形式。储能SOC闭合检查一天仿真结束时储能SOC要回到初始状态附近否则长时间仿真的能量积累会导致结果失真。通常加上首末时段SOC相等的约束。可转移负荷守恒检查全部时段转移进出负荷的代数和应为0非零则有模型疏漏。Big-M敏感性检查将M增大10倍和减小10倍最优解应基本不变。如果结果对M取值非常敏感说明M的选择不当。这套检查做完之后模型结果才算真正可信后续做敏感性分析、场景对比才有意义。实际跑完这套程序我最深的感受是主从博弈加碳交易加需求响应模型本身没有想象中难真正难的是把每一项成本、每一条约束、每一处单位、每一个对偶变量符号全部对齐。只要有一处单位没统一或者互补松弛方向写反结果就会在某处用极隐蔽的方式出错表面上看起来一切正常实际结论全靠不住。建议新手严格按照“先基准场景、再加碳交易、再加需求响应、最后耦合全部机制”的顺序搭模型每加一层就跑一遍对照数据问题定位速度会快很多。后面如果想把这套仿真接进实际项目最关键的工作是参数校准把分时电价、气价、碳价、负荷基线全部换成项目所在地的真实数据模型才能从“展示效果好”变成“真正支撑调度决策”。
返回列表