三年前我第一次拿到“基于Stackelberg模型的智能楼宇群协同能量管理”这个题目时,脑子里其实是懵的。博弈论我只在课堂上听过纳什均衡,MathJax公式看得懂,但真要拿Matlab去仿真一个主从博弈,心里完全没底。后来前前后后调试了两个月,从最开始的单楼宇单时段,一步步做到多楼宇24小时滚动优化,中间踩过的坑、推翻重来的模型、以及最终跑出收敛曲线的那一刻,到现在都记得很清楚。这篇博文就把这段实现之旅完整记录下来,包括模型怎么建、算法怎么选、代码怎么组织、以及那些文档里根本不会告诉你的调试经验。
如果你现在正准备开题、做课程设计或者做工程仿真,恰好也在纠结Stackelberg博弈怎么落地成Matlab代码,这篇内容应该能帮你少走一大半弯路。
1. 项目整体设计与思路拆解
1.1 为什么楼宇群能量管理需要博弈论
先说一个最基础的问题:一栋楼自己做能量调度,和一堆楼放在一起协调调度,本质差别在哪?
单栋楼宇的能量管理,核心是“用电成本最小化”。屋顶光伏发了电自己用,储能低谷充电高峰放电,柔性负荷(空调、热水器、电动车)挪到电价低的时段,这一步用线性规划或者混合整数规划就能解决。但是当多栋楼宇组成一个社区、一个园区,甚至一个虚拟电厂的时候,问题就变了。
每栋楼都有自己的光伏、储能和用电偏好,它们之间共享变压器容量,共同面对电网的分时电价,同时还有一个上层管理者(园区运营商或者聚合商)想要降低整体购电成本、削减峰值功率。这时候传统集中式优化的尴尬就出现了:如果上层直接下发指令让每栋楼怎么用电,楼宇用户会抵触——凭什么牺牲我的舒适度?如果完全让每栋楼自己决策,各顾各的,又容易造成负荷“撞车”,低谷时段大家一起充、高峰时段大家一起放,反而制造新的尖峰。
这个本质矛盾——个体利益和整体利益的冲突——恰恰是博弈论发挥作用的地方。不需要硬性指令,只需要一个巧妙设计的博弈规则,让每栋楼在追逐自身利益的过程中,客观上实现整体最优。这就是我最终选择Stackelberg模型做这个项目的原因。
1.2 Stackelberg模型:天然契合的主从博弈结构
博弈论里有多种模型,但用在楼宇群能量管理上,Stackelberg模型是最自然的选择。为什么?
Stackelberg博弈有一个核心特征:先动者优势。领导者先做决策,跟随者观察领导者的决策后再做自己的最优响应,而领导者做决策时已经预见到跟随者会怎么反应。这个结构跟楼宇群能量管理的现实几乎一模一样。
上层管理者(领导者)先公布一个内部交易电价——比如楼宇群内部光伏富余时,楼宇之间可以按这个电价互相买卖电力;下层每栋楼宇(跟随者)根据这个电价,优化自己的购售电量和储能充放电策略。上层要知道自己定的电价会导致什么用电结果,下层也知道自己的用电行为会影响上层下一步怎么调价。一来一回,最终收敛到Stackelberg均衡。
这个结构比集中式优化高明在什么地方?我自己的体会是三个点:
- 尊重自主性:每栋楼不需要暴露自己的所有隐私数据(比如负荷构成、舒适度偏好),只需要上报对价格的反应,也就是做决策的响应曲线。
- 价格引导而非指令控制:上层不直接制定每栋楼的用电曲线,而是通过调节内部交易电价来引导行为,现实中的接受度高得多。
- 数学可解:下层只要是一个凸优化问题,就可以用KKT条件或者迭代算法去求解,工程可落地性非常强。
对比一下,如果用的是普通纳什博弈(多家楼宇同时决策,谁都不知道谁先动),模型会变成一类广义纳什均衡问题,求解复杂度陡增,而且不一定收敛。Stackelberg模型这种上下层级结构反而是最好处理的。
1.3 为什么用Matlab做实现
这个项目用Matlab,其实不是随便选的。我知道现在很多学校和企业推崇Python+Gurobi,但我的实际感受是,这个场景Matlab有不可替代的优势。
Matlab的Optimization Toolbox提供fmincon、quadprog、linprog、intlinprog这些成熟的求解器,哪怕是一个没有编程功底的能源工程背景学生,也能快速把优化模型搭起来。更重要的是调试体验——Matlab的工作区可视化、断点调试、矩阵直接观察,对搞物理模型出身的人来说远比Python顺手。写博弈迭代算法时,我需要反复检查每一轮迭代中每条约束是否满足,矩阵维度有没有对不上,Matlab的调试器帮了我大忙。
另外从工程复现的角度说,楼宇能量管理往往要跟Simulink里的光伏模型、储能模型、楼宇热模型做联调,Matlab生态天然一体。我之前见过不少同行用Python搭完优化模型,结果到物理仿真环节还得把数据倒腾回Matlab,中间环节极易出错。所以我倾向于整个项目都在Matlab里完成,模型、算法、仿真、可视化,一条链路走完。
2. 核心数学模型构建:领导者和跟随者如何互动
2.1 楼宇群的物理组成和基本假设
模型不是越复杂越好。刚开始做的时候谁都想把所有因素都塞进去——三相不平衡、谐波、电池老化、舒适度PMV指标……但把这些全部放进博弈模型,求解器直接瘫掉。我的建议是,先把基础版做出来跑通,再逐步加复杂度。
这个项目里我用了最经典的配置:一个楼宇群由N栋智能楼宇组成,每栋楼配备以下设备:
- 光伏阵列:出力曲线按日前预测给定,不再细分辐照度模型;
- 储能电池:有容量上限、充放电功率上限、充放电效率,同时满足电能平衡方程;
- 可控负荷:可以偏移时段的柔性负荷(比如电动车充电、洗衣机),但必须在一个调度周期内完成;
- 基础负荷:不可调的刚性负荷,给定即可。
楼宇之间通过一个“虚拟母线”连接,只跟上层管理者进行电量和价格交互。所有楼宇共享一台变压器,总的购电功率不能超过变压器容量。
时段方面取24小时为单位,调度步长为1小时。这个时间粒度既能体现分时电价对行为的引导,又不会让优化模型因为时段数过多而变成求解灾难。
2.2 上层领导者:价格制定者的优化目标
上层管理者的决策变量,是每栋楼每个时段的内部交易电价 (\lambda_{i,t})。注意,这个电价是楼群内部结算价,跟外部电网的分时购电价 (\pi_t^{grid}) 是两层价格体系。
上层管理者的目标函数,是让整个楼宇群的运行总成本最小,具体拆成三项:
- 从电网购电的费用:(\sum_{t}\pi_t^{grid} \cdot P_t^{buy}),这个由所有楼宇的总购电需求决定;
- 内部售电的收入:楼宇之间互相交易时,管理者从交易电量中收取一定服务费,服务费率设为常数;
- 峰值惩罚:为了抑制群内负荷尖峰,设置一个惩罚项,超过设定阈值的购电量按更高价格计费。
可以写成这样一个紧凑形式: [ \min_{\lambda} \quad \sum_{t} \pi_t^{grid} P_t^{buy} + \sum_t c_{peak} \max(0, P_t^{buy} - P_{th}) ]
这个目标背后有一个关键的博弈意识:管理者不是高压行政命令楼宇怎么用电,而是通过 (\lambda_{i,t}) 这个价格信号,让楼宇自觉“避峰填谷”——高峰时段楼宇群的内部电价会升高,高到让楼宇宁愿用储能放电也不从电网买电。
2.3 下层跟随者:每栋楼宇的响应策略
每栋楼宇在给定电价 (\lambda_{i,t}) 后,目标函数是自己一天的净成本最小化。净成本包括三大块:
- 从群内购电的费用或向群内售电的收入(按内部交易电价 (\lambda_{i,t}) 结算);
- 储能充电带来的额外损耗(因为充放电效率不是100%,这部分损耗最终体现在成本上);
- 柔性负荷调度带来的舒适度惩罚(把某时段负荷刻意挪开,用二次型惩罚函数量化)。
对第i栋楼宇来说,决策变量包括:储能充放电功率 (P_{i,t}^{ch})、(P_{i,t}^{dis}),向群内的购/售电量 (P_{i,t}^{in})、(P_{i,t}^{out}),柔性负荷在各时段的安排 (P_{i,t}^{flex})。
约束条件包括: [ P_{i,t}^{pv} + P_{i,t}^{dis} + P_{i,t}^{in} = P_{i,t}^{base} + P_{i,t}^{flex} + P_{i,t}^{ch} + P_{i,t}^{out} ] 这是功率平衡方程,左边是电源侧(光伏+储能放电+购入),右边是负荷侧(基础负荷+柔性负荷+储能充电+向外售出)。
储能约束: [ SOC_{i,t+1} = SOC_{i,t} + \eta_c P_{i,t}^{ch} - \frac{P_{i,t}^{dis}}{\eta_d} ] [ 0 \le P_{i,t}^{ch} \le P_{ch}^{max}, \quad 0 \le P_{i,t}^{dis} \le P_{dis}^{max} ] [ SOC^{min} \le SOC_{i,t} \le SOC^{max} ]
这个下层问题是一个标准的二次规划,做代码实现时直接用quadprog就能解,数学性质很好。这一步是整个模型能跑起来的技术基石——如果下层问题不是凸的,后面的KKT替换和迭代算法全都无从谈起。
2.4 两层模型的耦合关系
Stackelberg博弈的核心就是这层耦合关系:上层通过电价 (\lambda) 影响下层的决策变量,下层的决策结果又反过来决定上层目标函数里的购电总量 (P_t^{buy})。
(\lambda) 定高了,楼宇会减少从群内买电、多用自己光伏或储能,上层售电服务费收入下降;(\lambda) 定低了,楼宇一窝蜂买电,群内负荷尖峰又会让上层的变电站超载,产生高额惩罚费用。上层就是在这一高一低之间找一个最优价格序列,让楼宇“不自觉地”配合整体削峰填谷。
这个结构性耦合,用数学语言叫双层规划(Bilevel Programming),更具体的说是一个下层带参数优化问题的主从博弈。在Matlab里直接对这一大坨用fmincon去解,基本是死路一条,因为嵌套优化问题的数值特性太差。这就引出了下一部分的核心问题:怎么把这个双层问题变成Matlab能高效求解的形式。
3. 求解算法设计:从双层优化到可计算问题
3.1 方法一:KKT条件转化法(单层化)
双层优化第一个经典的求解思路,是把下层优化问题“压缩”到上层,方法是给下层问题写KKT条件。
只要下层问题是凸的且满足约束规格(Slater条件),KKT条件就是原问题的充要条件。于是下层优化的最优性条件变成一组带互补约束的等式不等式方程组,整个问题转化为一个单层的数学规划带互补约束问题(MPCC)。
在Matlab里实现时,难点不在转化本身,而在互补约束的处理。KKT条件里的互补松弛条件形如 (\mu \cdot g(x) = 0),其中 (\mu) 是对偶变量,(g(x)) 是不等式约束。这是一个强非线性项,直接丢给fmincon,很多内点法实现会因为Jacobian奇异而直接报错。
我的做法是采用罚函数法处理互补约束。把互补条件 (\mu g(x)=0) 从约束中拿出来,变成目标函数里的惩罚项: [ \min \quad F_{upper} + M \cdot \sum \mu_i g_i(x) ] (M) 是一个很大的惩罚系数。先用较小的(M)求解获得一个可行的初解,然后逐步增大(M)迭代,迫使互补间隙趋近于零。这其实是很多商业求解器内部处理MPCC的标准做法,在Matlab里需要手动实现。
这条路的风险是:变量数会爆炸。每栋楼每个时段的KKT方程里包含对偶变量,24个时段N栋楼,变量量级直接到几千,fmincon跑非常慢,而且对初值极其敏感。我个人建议只有在楼宇数量≤3的时候用这条路线,当验证性研究还可以;一旦规模上来了,立刻切到迭代法。
3.2 方法二:分布式迭代求解算法(工程首选)
实际项目中我最终采用的方法,是迭代求解主从博弈,这是工程界公认最稳定也最好实现的一种路线。
核心思路特别朴素:上层先给一版电价,下层各自求解自己的优化问题,把购售电量反馈给上层;上层根据结果调整电价,再发给下层;如此往复,直到电价和电量都不再变化。具体流程如下:
- 初始化电价:用外部分时电价 (\lambda_{i,t}^{(0)} = \pi_t^{grid}) 作为初始值;
- 下层求解:每栋楼宇以当前电价带入各自的
quadprog,求解得到最优购售电量和储能充放电计划; - 上层聚合:汇总所有楼宇的购电量 (P_t^{buy} = \sum_i P_{i,t}^{in}),评估峰值惩罚和服务费收入;
- 价格更新:利用次梯度或者启发式规则调整电价——若某个时段总购电量超过阈值,则提高该时段电价,抑制购电;若低于阈值,则适当降低电价;
- 收敛判定:检查电价变化量是否小于设定的容差(比如 (10^{-4})),满足则停止,否则回到第2步。
价格更新的规则,我采用的是最典型的“边际价格修正法”,本质上是一个次梯度迭代: [ \lambda_{i,t}^{(k+1)} = \lambda_{i,t}^{(k)} + \alpha \cdot \frac{\partial L}{\partial \lambda_{i,t}} ] 其中步长 (\alpha) 的选取很关键,太大容易振荡不收敛,太小收敛极慢。我实际调试下来的经验值是取 (0.1 \sim 0.3) 之间,具体需要根据电价量级做归一化。
迭代法最大的优势是数值稳定,每一轮只需要解N个独立的小规模二次规划,运算时间可控,而且天然支持分布式计算——理论上每栋楼的优化可以并行跑,虽然我在Matlab里用的是一个单纯循环。
3.3 Matlab工具箱选型与求解器配置
这一部分直接关系到代码能不能跑通。我测试过三位选手:fmincon、quadprog、intlinprog。
quadprog:解决下层问题的最优选择。下层问题目标函数是二次的(储能损耗和舒适度惩罚都是二次项),约束是线性的,quadprog用的内点法很快很稳定。建议直接调用'interior-point-convex'算法。唯一要注意的是变量初值的维度必须对好,否则报错信息会看得人一头雾水。fmincon:处理上层问题。上层目标没有解析梯度,我直接用数值差分梯度,问题不大因为上层变量只有 (N \times 24) 个。要注意的是设置Display为'iter',观察每轮迭代过程,这对判断是否收敛非常直观。intlinprog:如果未来给你的模型加入不连续决策(比如储能的最小充放电时间),就得用它。但无论谁做这个项目,第一版千万不要碰整数变量——计算规模会呈指数级恶化。
工具箱方面,Matlab的Optimization Toolbox完全够用,不需要额外安装CVX或者YALMIP。虽然YALMIP这类建模语言确实能让双层优化的表达变简洁,但引入外部依赖之后,换一台机器跑不起来的问题会让你怀疑人生。我的原则是:能用原生工具箱解决的,绝不上第三依赖。
4. 仿真算例设计:5栋楼宇的24小时协同
4.1 算例场景与参数设置
模型建得再好,参数一乱全部白搭。我在这个项目中设计的标准算例是5栋楼宇、24个时段的协同调度场景。这个规模不算大,但足够把博弈动态展示清楚。
楼宇配置采用“混合模式”,而不是清一色复制五遍:
- 楼宇A:大屋顶光伏(装机60kW)+大容量储能(200kWh),代表“产能型”用户;
- 楼宇B:光伏小(20kW)+储能无,代表“纯消纳型”用户;
- 楼宇C、楼宇D:中等光伏、中等储能,区别在于C负荷白天高(办公楼),D负荷晚上高(住宅楼),正好可以观察互补效应;
- 楼宇E:没有光伏,但有储能,主要测试纯储能套利策略。
分时电网电价设计为三段式:峰时(10:00-16:00、19:00-22:00)电价1.2元/kWh;平时(7:00-10:00、16:00-19:00)电价0.8元/kWh;谷时(0:00-7:00、22:00-24:00)电价0.4元/kWh。内部交易电价的范围约束在0.2到1.5元/kWh之间,保证楼宇群内部电价始终低于电网零售价,这样楼宇才有动力参与内部交易。
光伏出力做一个典型的夏季晴天曲线,正午峰值约为额定容量的80%左右。负荷曲线用正态随机生成基础值,再加上各自的时段偏好。这些参数我没用真实数据,但量纲和量级都对照了真实园区项目的统计数据,跑出来的结果才有参考意义。
4.2 Matlab代码组织与核心实现
整个项目代码组织成五个脚本/函数模块,这是我反复重构后定下的结构,值得抄作业:
main_stackelberg.m % 主脚本:参数设置、迭代循环、结果可视化 load_data_gen.m % 数据生成:负荷、光伏、储能参数的批量生成 upper_problem.m % 上层目标函数与约束,供fmincon调用 lower_problem_i.m % 下层单楼宇优化函数,内部调用quadprog price_update.m % 电价次梯度更新函数主循环的骨架代码大概是这样的(关键部分):
% main_stackelberg.m 核心迭代逻辑 for iter = 1:max_iter % 1. 下层求解:每栋楼宇响应当前电价 for i = 1:N [P_in(i,:), P_out(i,:), P_ch(i,:), P_dis(i,:), obj_i(i)] = ... lower_problem_i(lambda(i,:), data_struct(i)); end % 2. 上层聚合总购电量 P_buy_total = sum(P_in, 1); % 3. 检查收敛条件 lambda_new = price_update(lambda, P_buy_total, threshold, alpha); error = max(abs(lambda_new(:) - lambda(:))); fprintf('iter %d, error = %.6f, cost = %.2f\n', ... iter, error, sum(sum(lambda .* P_in)) + peak_penalty); if error < tol break; end lambda = lambda_new; end下层单楼宇的问题封装在lower_problem_i.m里,里面构造quadprog的标准形式:
function [P_in, P_out, P_ch, P_dis, obj] = lower_problem_i(lambda, data) % 变量定义:x = [P_in; P_out; P_ch; P_dis; P_flex; SOC] % 目标函数:x'*H*x/2 + f'*x % 调用 quadprog(H, f, Aineq, bineq, Aeq, beq, lb, ub, x0, options) options = optimoptions('quadprog', 'Algorithm', 'interior-point-convex', ... 'Display', 'off', 'OptimalityTolerance', 1e-8); [x_opt, obj] = quadprog(H, f, Aineq, bineq, Aeq, beq, ... lb, ub, x0, options); % 从 x_opt 里拆回各变量 P_in = x_opt(1:24); P_out = x_opt(25:48); % ... end这里有一个特别容易踩的坑:初始值(x_0)的选取。quadprog虽然不需要好的初值也能求解,但如果给一个违背功率平衡的初值,内点法有时候会陷入数值困难。我的习惯是直接用当前时段的负荷值初始化各决策变量,相当于假设储能不动作,这让求解一开始就在一个可行的物理状态附近。
4.3 结果分析与对比
跑完24小时调度,把结果整理成三组对比:无协同模式(每栋楼直接面对电网电价独立优化)、Stackelberg协同模式(本项目实现)、集中式最优模式(虚构一个理想管理者直接控制所有楼宇的决策,作为理论下界)。
我的典型运行结果显示了三个关键现象:
- 总购电成本下降:Stackelberg协同相比无协同模式,整体成本下降了大约13%。这个数值在集中式最优(理论下界)和无协同之间,证明博弈机制确实能逼近理想调度效果。
- 群内互济显著:白天楼宇A的光伏富余不再是单纯卖给电网,而是以低于电网回购价的内部价格卖给楼宇B,买卖双方都获益。楼宇A的售电收入比直接弃光或低价卖电网高,楼宇B的购电成本比从电网买便宜。
- 负荷削峰有效:变电站峰值负荷从无协同的430kW降到协同后的355kW。这个效果完全是通过电价信号引导出来的,不是行政指令。迭代过程中能看到上层电价在高峰时段上升、低谷时段下降,这种趋同变化正是Stackelberg均衡的信号。
还有一个让我印象很深的细节:不同楼宇对同一条电价曲线的响应完全不同。楼宇A(有光伏储能)几乎不受影响,储能充放电策略基本不变;楼宇B(纯负荷)则对电价极度敏感,晚上谷时段的负荷占比大幅提升。这正是博弈论里所说的“异质性响应”——同一条价格信号,不同参与者的最优反应各不相同,而整体协调恰恰利用这种差异做平衡。这个观察不是理论推导出来的,是仿真跑完后逐楼宇看曲线才看清的。
5. 常见问题与调试技巧实录
5.1 求解不收敛:次梯度振荡的根源与对策
迭代法最经常遇到的现象是电价在两条曲线之间来回跳,误差一直降不下去,到了最大迭代次数还在振荡。这里的主要原因往往不是算法本身,而是步长(\alpha)选得不对。
次梯度法对步长的要求很苛刻:太大发散,太小收敛极慢。我的经验做法是给步长加一个衰减因子,每轮迭代都缩小步长,类似模拟退火的思路: [ \alpha_{k} = \frac{\alpha_0}{1 + \beta \cdot k} ] (\alpha_0)取值0.3,(\beta)取0.02~0.05,这样前期步长大能快速接近最优区域,后期步长小收敛稳定。
另一个很隐蔽的问题是上层目标不光滑造成的振荡。如果目标函数里有(P_t^{buy})的绝对值项或者max函数(比如峰值惩罚),这个非光滑项会在某些点上导致次梯度方向剧烈变化。解决办法是把峰值惩罚从目标函数里改成约束+影子价格来处理,或者用光滑近似代替max函数。
5.2 结果不合理:问题可能在参数量纲
有一回我把楼宇数量从3改成5之后,结果亮了红灯——某些楼宇的购电量出现负数,也就是突然变成巨大的售电方,把群内总购电量压成了负值。排查了很久,最终发现是储能效率参数写错了:放电效率(\eta_d)误填成大于1的值,导致储能变成了“能量放大器”,这当然会让优化器疯狂利用“漏洞”套利。
这一类参数量纲和物理边界问题,是Matlab优化项目中最隐蔽的坑。我的排错方法是给所有决策变量加上物理边界检查——凡是功率量纲的变量,必须落在(-P^{max})到(P^{max})区间;SOC必须落在0到1之间。每次迭代后做一次断言检查,一旦越界就抛出警告。这比跑完24小时之后对着结果发呆高效得多。
5.3 仿真时间过长:让计算提速的三个实用招数
当楼宇数量增加到10栋以上,迭代法每轮要解10个二次规划,外层还要迭代几十甚至上百次,总时长会让人焦虑。实测中我的原始版本跑10栋楼300次迭代,花了将近20分钟。优化三步后压到了2分钟以内:
- 热启动:每轮迭代中,下层问题的初值用上一轮的最优解代替默认零向量。因为相邻两轮之间电价变化不大,最优解也不会跑太远,
quadprog内点法二次迭代就收敛了,效率提升极其可观。 - 限制约束规模:检查是否有冗余约束。比如储能功率上限约束本来就应该自动满足容量约束,但在建模时如果你同时加了“储能SOC大于0”和“充电功率上限”,某些情况下会把同样一条物理限制表达两次,白白增加求解规模,内点法的计算量随约束数是近似平方增长的。
- 收敛判据放宽:一开始我用(10^{-6})做收敛容差,后来发现对于双层博弈这个精度没有实际意义,电价差(10^{-4})对楼宇决策的影响已经微乎其微。把容差放宽两个数量级,迭代次数直接少三分之一,最终成本差异不到0.1%。
5.4 一个特别提醒:秒懂收敛曲线的判读
仿真跑完,第一件事不是看成本,而是看电价和购电量的迭代收敛曲线。这个曲线隐藏着整个博弈是否健康的全部信息:
- 理想曲线:前10轮快速下降,之后平缓趋近0,误差单调递减;
- 如果曲线是先下降后抬升,大概率是步长太大触发了非光滑区;
- 如果误差长期横盘不动,大概率是收敛判据过严,或者步长太小被困在次优区域。
我习惯把每一轮的电价曲线动画化绘制出来,视觉上看“电价波形”怎么一步步从初始分时电价变换到均衡价格。这个动画过程跑几遍之后,你对Stackelberg均衡的理解会完全不一样——不再是一个数学定义,而是一个活生生的动态过程。
一点个人体会
整个项目做完,我最深的感触是:Stackelberg模型用在智能楼宇群协同能量管理上,不是理论研究者拍脑袋想出来的炫技套路,而是确确实实命中了一个真实工程痛点——如何在不牺牲参与者自主权的前提下实现系统层面的优化。Matlab作为实现平台,最大的贡献不是它的求解器有多强,而是让我能够快速试错、直观调试、反复验证每一条物理约束和博弈逻辑。如果你也要做类似的课题,我的建议是不要一上来就追求数学模型的天花板,先跑通最简单的两楼宇、单时段版本,哪怕只考虑一台储能和一条电价曲线,然后一步步加复杂度。博弈模型的层级逻辑本身已经足够烧脑,把基础版本吃透后,再往里面加光伏消纳率、储能寿命损耗、碳排放约束这些工程细节,都会是顺理成章的事。