1. 双层博弈这种结构是怎么从电价“上升问题”里长出来的1.1 先把我说的“二元平衡问题”定义清楚严格来说中文优化圈更常见的叫法是“双层均衡问题”但这个标题里的“二元”我理解成决策层的二元上层是一个博弈方下层是另一个博弈方谁也不能单独说了算。放在电力市场里这个结构特别典型。很多刚接触这个模型的人会问为什么不能把电力市场的出清问题写成一个大优化直接把所有条件揉进去答案是电力市场的价格不是某个人拍脑袋定出来的它来自市场成员报价之后系统调度员按照经济调度原则出清的结果。上层成员可以决定自己的报价策略、投资容量、补偿预期下层调度员按照目标函数最优去安排机组出力和节点电价。两层之间的变量互相嵌套你解上层必须知道下层会怎么反应解下层又必须先给定上层的报价这就是“二元”。我习惯打一个生活比方房东定租金租客决定租不租、租多少。租金定高了没人租定低了房东亏租客的决策是基于房东的价格做出的房东的决策又必须预期租客的反应。你单独解一边都得不到稳定的结果只有两边同时成立才叫均衡。电力市场里的“市场上升问题”恰好就是这种结构的产物。所谓电价上升不只是普通的需求增长更多是指高峰时段和供应紧张时段出现的持续抬价现象。这里既有物理学上的原因装机不足、输电受限也有策略上的原因某几家大机组边际定价时拥有抬价空间。如果你把价格当成外生给定的常数去优化那就是默认抬价现象不存在建模一开始就错了。1.2 电力市场上升问题的准确建模位置在哪我参与过几个涉及容量补偿机制评估的项目最深刻的感受是电价上升问题不能只在单层模型里讨论。比如你要评估“需求响应补偿”能不能压低高峰价格单层模型会告诉你“如果把负荷削掉多少边际机组换成哪台价格就降了”但真实市场里补偿金额一变负荷侧参与者的行为就变了随之报价策略也变了最终出清价格和机组组合全都会变。这是典型的“上层决策改变下层输入下层输出反过来决定上层收益”的循环。所以在建模时市场上升问题必须放在均衡框架里表达上层市场成员或监管者决定报价上限、容量补偿单价、投资补贴下层调度中心在给定这些参数后做机组组合和经济调度得到节点电价和机组出力均衡约束上层设定的补偿和投资必须让下层出清的价格和电量反过来支撑上层目标两层同时成立。这里有个关键点补偿成本不是事后一笔勾销的财务科目它要进下层出清的约束里直接改变边际机组的排序。比如你给储能一个峰时容量补偿下层的安全约束和报价排序就会相应变化峰时电价会被压住但系统总成本里多了补偿支出。这一升一降只有均衡模型能同时算清楚。1.3 “精确求解”到底是在求什么东西学术界和工程界对“精确”的定义不太一样。仿真软件跑一万次叫“统计意义上的观察”启发式算法找到局部不错的结果也叫“可行解”但我们要讨论的精确求解指的是把上层目标函数和下层均衡条件同时纳入一个数学规划借助混合整数规划、强对偶重构或者KKT条件转化最终用求解器给出全局最优解并且这个解能被对偶变量和互补条件验证。这个要求的代价是模型复杂度成倍上升。因为下层问题一旦写出最优性条件原本一个线性规划几十个约束的事会变成带大量二进制变量和互补条件的混合整数问题。但反过来只有这么做你才敢对监管方说这个补偿标准下市场均衡结果是多少和没有补偿时相比电价上升被抑制到什么程度。2. 补偿机制和市场上升问题模型里的两股力量如何拉锯2.1 补偿放哪个位置决定了模型的性质“带补偿”这三个字看起来简单实际建模时第一件事就是决定补偿往哪儿放。我见过三类常见做法第一种补偿作为参数直接进下层成本项。比如可再生能源度电补贴补贴单价固定下层调度时会把补贴后的净报价参与排序。这类模型相对好解因为参数固定后下层只是一个带参数的优化问题。第二种补偿作为上层决策变量同时通过约束影响下层出清。比如容量补偿单价由监管者决定但这个单价要满足下层出清后投资者能回收固定成本。这时补偿既是上层变量又通过投资约束穿过两层模型结构复杂得多。第三种补偿作为下层约束的右侧项。比如给需求响应设置一个最低补偿价参与削减的负荷才能进入市场。这种约束的互补条件写出来之后会给模型增加大量整数变量。我自己的建议是做研究时可以按需求选第一种做实际政策评估尽量用第二种因为容量补偿和价格上限这类机制本质就是上层用“规则变量”干预下层出清天然适合放进均衡模型。2.2 补偿能不能压住涨价要看它进的是哪一条约束讲个我实际算过的例子。某区域峰荷时段容量紧张我建了一个简化双层模型上层是监管者决策给燃气机组的容量补偿单价下层是调度中心做两时段出清。直觉判断是补偿提高了机组收益投资意愿上升容量充裕度增加峰时电价应该下降。但模型跑出来的结果比直觉复杂。补偿单价较低时燃气机组固定成本回收不足投资变量不成立峰时电价依然高企补偿几乎没有效果补偿单价超过某个阈值后投资成立峰时价格确实下降但系统总成本里多了一大笔补偿支出折算到终端用户头上整体账单未必下降。那个让电价下降恰好又不导致总成本暴涨的补偿区间就是精确求解的用武之地。这个现象的原因在于补偿和电价在均衡模型里是此消彼长的关系。补偿进下层成本后边际机组的报价排序会改变而边际机组一变节点电价就变。二者通过下层出清的影子价格相互耦合。你看单层结果只会得到“补偿越高电价越低”的线性结论但在双层均衡里这个关系是非线性的、带跳跃的。2.3 四种常见补偿机制的模型角色对比补偿类型典型建模位置对均衡的影响需要注意的坑容量补偿上层投资约束 下层固定成本回收改变长期装机决策影响峰时边际价格补偿单价过低时投资约束不起作用可再生能源度电补贴下层报价成本项压低中标顺序影响低谷时段价格补贴过高会造成“负价”和弃电并存需求响应补偿下层负荷侧约束高峰可削减负荷压低峰时出清价最低补偿价和用户响应量需要同时内生价格上限调整下层价格约束直接封住高价但可能引发抬价博弈上限设太低会导致收益不足投资退出这几类机制单独拎出来都能写一篇论文但放在“电力市场上升问题”这个框架里它们的共同点是都会穿过上层决策和下层出清之间的交互界面任何一个参数变了均衡结果都跟着变。3. 精确求解的三条主要技术路线3.1 总览把两层问题变成单层混合整数规划精确求解的主流思路是把下层优化问题转化为它的最优性条件然后塞进上层模型。下层如果是线性规划转化后的条件包括原始可行性、对偶可行性、平稳性条件和互补松弛条件。其中互补松弛条件是非线性的需要用大M法搭配二进制变量线性化最后整个问题变成一个混合整数线性规划MILP。这一步做完之后交给Gurobi或者SCIP这类求解器理论上能拿到全局最优解。我先把一般形式写出来min F(x, y) s.t. G(x, y) ≤ 0 y ∈ S(x)其中S(x)是下层问题的解集min f(x, y) s.t. H(x, y) ≤ 0这里x是上层变量y是下层变量两个问题共享了耦合变量。要精确求解核心就是处理“y ∈ S(x)”这个隐式条件。3.2 路线一枚举法只适合小规模最简单粗暴的办法是把上层变量可能取的值全部列出来对每个取值解一次下层问题拿到下层反应之后回代上层算目标值再挑最优的。问题是上层变量如果是连续的枚举空间直接爆炸。我第一次带学生做这个方向时试过枚举容量补偿单价从0到100元每千瓦步长0.5元每个值解一次下层机组组合一个两节点三机组的例子跑了快半个小时。这个方法不是不能用它适合做代码验证和小规模机理分析不适合任何实际规模的市场。所以后面我们基本不再建议。3.3 路线二KKT条件重构最通用下层是线性规划或者凸二次规划时KKT条件是充要条件可以无损精确转化。写出来大概是∇_y f(x, y) ∑ μ_i ∇_y h_i(x, y) 0 μ_i ≥ 0 h_i(x, y) ≤ 0 μ_i · h_i(x, y) 0前面三行都是线性的麻烦在最后一行的互补条件。处理手法是给每个约束配一个二进制变量δ再用大M把非线性的乘积展开h_i(x, y) ≤ M · (1 - δ_i) μ_i ≤ M · δ_i大M选值是个技术活我后面专门讲。这一套做完下层被等价嵌入上层求解器返回的就是满足所有博弈方最优性条件的解不是仿真观察值。3.4 路线三强对偶重构速度快但要小心条件如果下层问题满足Slater条件也可以不用KKT直接用下层原问题目标函数等于对偶问题目标函数这个等式来代替互补条件。这样处理的好处是避免显式引入所有对偶变量和二进制变量模型规模小一圈求解速度往往快不少。但强对偶替换有个前提下层必须是凸问题。一旦下层本身带整数变量比如机组启停状态原问题和对偶问题之间会有对偶间隙等号不成立这条路就走不通。实际电力市场出清问题里机组组合是混合整数规划下层非凸强对偶严格来说不适用。解决思路是把下层机组组合扯出来单独枚举或者用整数变量的特殊结构做凸包松弛这些就比较进阶了。3.5 我的方法选型建议落到实际项目里我通常先问三个问题下层有没有整数变量有优先KKT加大M或者考虑对整数变量做Benders分解。模型规模大到什么程度超过几千个约束的建议先把下层单独求解验证凸性再决定要不要强对偶。精度要求多高政策评估这类场景要求可解释性宁可模型复杂也要全局最优如果是企业内部快速测算有时候启发式也能接受。这套判断逻辑我一直在用适用范围比单纯背公式要广得多。4. 一个带补偿的两时段市场算例从建模到精确解4.1 算例背景还是拿储能补贴来说明。假设一个简化电力市场两个时段峰时段和谷时段。有两台常规机组一个储能投资候选项目。上层是市场监管者要决定储能容量补偿单价γ同时决定是否批准这个储能项目投建0-1变量。下层是调度中心在给定γ和储能投建状态后做两时段经济调度出清得到各时段电价。储能项目的固定投资成本是F投建后可以在谷时充电、峰时放电但电池容量有限充放电效率η。储能运营不追求独立利润最大化它只是出清模型里的一个灵活资源因为我的目的是看补偿和电价之间的均衡关系。4.2 写出完整模型上层目标函数是终端用户支付总成本最小化包括能量费用加上补偿支出min W ∑_t (D_t · p_t) - γ · C_storage s.t. 补偿单价非负 储能投资回报约束这里p_t是下层出清得到的时段电价D_t是时段需求。投资回报约束我写成储能投建后通过套利获取的收益加上补偿收入必须能回收固定成本F。这个约束是上下层的耦合纽带因为它把下层出清变量和上层投资决策绑在了一起。下层调度问题min ∑_t ∑_g c_g · q_{g,t} s.t. 各时段供需平衡 机组出力上下限 储能充电、放电功率约束 储能电量平衡约束储能收益来自“谷时买低谷电峰时卖高峰电”的差价这个差价是下层出清对偶变量的函数。投资回报约束写成γ · C_storage ∑_t (p_t · (q_dis_t - q_ch_t)) ≥ F · z如果z等于1且这个约束不满足上层方案就不可行。4.3 转成单层混合整数问题下层是线性规划用KKT条件替换互补条件用大M线性化。注意投资变量z本身是0-1变量它又通过储能约束影响下层。所以最终模型里有三类整数变量储能投建变量以及每个互补条件的辅助二进制变量。我实际求解时储能容量设成100兆瓦时充放电功率50兆瓦效率0.9固定投资F折合到日成本为5万元。补偿单价γ的搜索区间设置在0到200元每兆瓦时。用Gurobi求解跑到1%的MIP Gap稳定停下得到的结果是γ最优解落在接近但略低于峰谷价差倒推值的区间储能项目投建峰时电价相比不投建时下降了约12%但终端用户总账单只下降了4%。这个差异恰恰说明补偿支出抵消了一部分电价下降红利。4.4 求解代码思路示例这里给一个可运行的思路技术栈是Python加Gurobi不是完整代码但框架是能抄的# 下层问题的KKT条件构造 m gp.Model(bilevel_equilibrium) # 上层变量 gamma m.addVar(lb0, ub200, namecompensation) z m.addVar(vtypegp.GRB.BINARY, nameinvestment) # 下层变量的原始变量 q m.addVars(T, G, namedispatch) theta m.addVars(T, namedual_price) # 对偶变量 # 大M互补条件辅助 delta m.addVars(len(ineq_constraints), vtypegp.GRB.BINARY) # 目标上层总成本 m.setObjective(..., gp.GRB.MINIMIZE) # 约束下层KKT 投资回收耦合约束 上层可行性 m.addConstrs(...) m.optimize()关键一步是不要忘记把“储能收益”表达为对偶变量和充放电量的乘积这个乘积是非线性的要先线性化。我的做法是把p_t写成对偶变量直接加入上层目标再用McCormick或者大M处理乘积项具体取舍看问题规模。4.5 解出来的结果怎么读这个算例最有价值的输出不是γ的数值而是三条几乎平行的曲线γ从零增大时储能投资先不成立峰时电价居高不下γ跨过一个临界值投资变量翻转成1峰时电价骤降继续增大γ电价不再明显下降但补偿支出线性上涨。那个临界值就是所谓“刚好激励投资”的补偿水平也是精确求解最应该提供给决策者的点。这让我想到一个很容易犯的错误只算“电价下降多少”就写结论不看补偿支出。均衡模型必须把两个数一起报出来否则政策建议一定是偏的。5. 实战中把“精确”做成可复现结果的几个关键要领5.1 大M的取值是最大的坑互补条件线性化时大M太大会让数值条件数恶化求解器在互补变量上频繁出现微小扰动太小又会错误砍掉可行的最优解。我见过有人习惯性把所有M统一设成1e6结果模型跑出来一个“最优解”实际是对偶变量被数值误差压在了错误的边界上。我的做法是分约束找M对每个互补条件先把外层模型大概求解一遍记录该约束对应松弛变量可能达到的最大量级再把这个量级放大50%设成M。这样既保证不砍可行域又不会让求解器被大数折磨。5.2 补偿参数的量纲和数值范围会影响收敛这个坑容易被忽视。容量补偿电价是几百元每兆瓦时电量收益是几十元每兆瓦时投资固定成本是几百万元三个量级差到十万倍。直接塞进一个模型Hessian数值基本没法看。建议把所有补偿和成本折算到同一量纲比如统一按“日成本万元”计数再放大系数让目标函数各项数量级接近。我踩过一次很惨的坑某次算可再生补偿度电补贴0.42元每千瓦时下层出力几千兆瓦目标函数里补偿项的量级是百万级而投资约束里的固定成本是十亿级求解器跑了四个小时没进展。后来把单位改成亿元每十万千瓦时模型半小时就收敛了。数值条件对求解器的影响比绝大多数人想象的大。5.3 下层存在多个均衡时怎么处理下层问题可能不只一个最优解尤其当调度模型存在degeneracy时互补条件并不能唯一确定y。这会导致上层目标值对不同的下层均衡解产生不同的结果。处理手段一般有两种一种是把上层偏好的某种性质作为辅助目标加入下层比如要求储能在最优调度中尽量多充电破坏均衡的唯一性另一种是引入所谓 pessimistic 或者 optimistic 设定——前者假设下层在多个均衡里选一个最不利于上层的解后者假设选最有利于上层的解。我建议在报告里至少给出这两个极端的区间很多政策结论的置信度要靠这个区间体现。5.4 做完求解之后必须做的验证动作精确求解不等于模型正确。我每次出结果之前都会做三件验证把求解出来的上层变量带回原始下层模型重新优化检查下层目标差值是否在容差内观察互补条件的残差如果大量约束的μ乘以h明显偏离零说明大M有问题对补偿参数做灵敏度扫描确认目标函数曲线连续、没有异常跳变。这三步做完我才敢把结果拿出去给别人看。准确说“精确”两个字不是求解器的功劳而是建模、数值处理和结果验证三者共同撑起来的。5.5 最后分享一个关于补偿机制的经验判断我做过不少补偿相关的双层均衡模型总结下来带补偿的市场均衡问题最容易出现“表面上精确、实际上失真”的场景往往不是因为算法不对而是补偿的边界条件没设好。比如补偿只发给新建机组不发给存量机组或者补偿上限和缺电惩罚挂钩却忘了设惩罚本身是影子价格函数这些都会让补偿进入模型的方式和真实机制不一致。建模型之前先把补偿的“支付触发条件”用自然语言写清楚再翻译成约束比直接写公式可靠得多。这个提醒也适用于所有双层均衡问题下层出清机制的真实规则永远是模型的第一约束条件。