
说实话刚拿到这个题目的时候我第一反应是微电网容量优化配置直接建个混合整数线性规划不就完事了吗为什么要上非合作博弈后来真正把模型跑起来才明白问题没那么简单。风、光、氢三个主体如果背后的投资运营方不是同一个利益体那集中式优化算出来的“全局最优解”在实际执行阶段可能压根落不了地谁都不愿意接受一个让自己吃亏的方案。这篇文章我想把基于非合作博弈的风-光-氢微电网容量优化配置这件事从原理、建模、Matlab实现到实际踩坑完整拆开讲清楚。内容主要面向正在做微电网规划方向的硕博生、从事综合能源系统设计的技术人员以及想用博弈论但不知道怎么落地的Matlab玩家整体偏应用但原理部分也会讲到“为什么”不是纯代码堆砌。1. 这个题目到底在解决什么问题1.1 微电网容量配置的基本矛盾微电网容量优化配置本质上是回答“装多少风机、装多少光伏板、配多大的电解槽、储氢罐要不要搞、搞多大”这几个问题。但这个问题之所以复杂就是因为它不是一个简单的工程量计算而是要在多个维度之间找平衡投资成本是一次性的运维成本是每年的发电量是跟着天气波动的负荷曲线又是跟着生产和生活节奏走的。你装机装多了前期投入巨大闲置率也高装少了供电缺口大系统可靠性和经济性双双不达标。传统做法通常是把所有设备打包成一个整体设定一个统一的目标函数比如最小化年综合费用然后丢给优化求解器去跑。这种集中式优化在数学上是漂亮的因为目标函数是全局的约束是统一的求解结果就是一个“全局最优解”。但它隐含了一个前提所有设备属于同一个投资主体所有决策由同一个运营中心统一制定。如果这个前提不成立集中式优化出来的容量配置就是一张废纸。1.2 为什么单一主体假设站不住脚实际工程中风电、光伏、氢储能这三块的投资运营主体往往不是同一拨人。风电可能是新能源开发商出资建的光伏可能是园区自己投的氢能部分可能又是另一个能源公司运营的。每个主体都有自己的利益诉求风电运营商想多发点电、多挣点电费氢储能运营商想低价买电、高价售氢光伏运营商则希望自己的发电量尽可能被消纳、少弃光。这些诉求之间天然存在冲突。举个简单的例子电解槽是耗电大户它希望从电网拿到的电价越低越好。但如果风电运营商为了追求自身收益最大化把多余的电能卖给电网而不是以低价卖给电解槽那么氢储能系统的收益就会受损。反过来如果氢储能运营商掌握了定价权把购电价压得很低风电运营商的利润空间就被挤掉了。这种互相影响、互相牵制的关系就是典型的博弈关系。1.3 非合作博弈在此处的定位非合作博弈解决的正是“多个决策主体各自追求自身利益最大化”的问题。它不追求全局最优而是寻找一个“纳什均衡”状态在这个状态下任何一个主体单独改变策略都不可能获得更高收益。这个均衡解在现实中反而比集中式优化解更容易被各方接受因为它尊重了每个主体的理性决策。放在微电网容量配置这个场景里就是每个主体先根据其他主体的容量配置和运行策略求解自己的最优容量配置然后循环迭代直到所有主体的容量配置都不再变化即达到纳什均衡。这套思路可以理解为“相互博弈之后的稳态结果”而不是“某个强权中心拍板定的方案”。注意这里说的“非合作”不是指互相纯粹对抗而是指决策时只考虑自身利益最大化不指望对方配合。合作博弈研究的是结盟和收益分配非合作博弈研究的是竞争和均衡两者建模思路完全不同。2. 非合作博弈建模的思路拆解2.1 博弈三要素参与者、策略集、收益函数任何博弈模型都有三个基本要素参与者Player、策略集Strategy Set、收益函数Payoff Function。放在这个题目里参与者是三个风电运营商、光伏运营商、氢储能运营商。为了简化问题一般把氢储能系统电解槽、储氢罐、燃料电池打包成一个参与者因为它背后的投资运营主体可以视为一个整体。策略集是每个参与者的可选方案。在这个问题里每个参与者的策略就是自己的设备容量配置即风电装机容量、光伏装机容量、电解槽额定功率、储氢罐容量、燃料电池额定功率。每个策略都有一个可行范围比如装机容量不能超过土地或屋顶面积允许的上限电解槽功率要匹配制氢需求规模等。收益函数是每个参与者需要最大化的目标。风电运营商的收益是售电收入减去风电设备投资成本和运行维护成本光伏运营商类似氢储能运营商的收益是售氢收入加上燃料电池发电收入减去电解槽耗电成本、储氢罐投资成本和设备运维成本。建模时我建议把三个收益函数写成如下形式伪代码风格方便后面对照Matlab实现F_wind Revenue_wind_sale(P_wind) - Cost_wind_invest(C_wind) - Cost_wind_om(C_wind) F_pv Revenue_pv_sale(P_pv) - Cost_pv_invest(C_pv) - Cost_pv_om(C_pv) F_hydrogen Revenue_h2_sale(E_h2) Revenue_fc_sale(P_fc) - Cost_electrolyzer_invest(C_el) - Cost_tank_invest(C_tank) - Cost_fc_invest(C_fc) - Cost_h2_om(C_h2)2.2 收益函数与成本模型怎么定博弈模型的难点在于收益函数必须能真实反映各主体之间的利益冲突。如果三个主体的收益函数互不相干那就不存在博弈各自独立优化就行了。所以必须找到利益交叉点。在实际系统中最重要的交叉点有两个。第一个交叉点是售电关系。风电和光伏发的电一部分卖给电网一部分供给氢储能系统的电解槽。卖给电网的价格是由上网电价决定的相对固定供给电解槽的价格则是内部协商电价是可以调节的。这个内部交易电价正是风电、光伏与氢储能之间的博弈焦点风电和光伏希望对氢储能的售电价格高一点氢储能则希望购电价格低一点。这个电价一旦定下来各方的收益函数就耦合在一起了。第二个交叉点是弃电惩罚。如果风电光伏发电过剩而电网消纳能力有限多余的电只能弃掉。弃电对风电和光伏运营商来说是一种损失。氢储能系统如果配置得足够大可以消纳这部分多余的电减少弃电损失但氢储能的设备投资成本也更高。这又是一个权衡关系风电光伏希望氢储能配大一点好帮自己消纳弃电氢储能则希望自己的投资能换来足够多的低价电不然成本收不回来。成本模型方面核心是设备投资成本与容量的关系。通常采用如下形式C_invest c_unit * C_capacity * r / (1 - (1 r)^(-life))其中 c_unit 是单位容量投资成本C_capacity 是设备安装容量r 是折现率life 是设备寿命。这一项是把全生命周期的一次性投资折算成每年等额支付的年金成本这样和每年的运行费用可以放在同一个口径下比较。很多初学者容易忽略这个折算过程直接拿一次性投资和年收益相减导致结果严重失真。运行成本相对简单主要是维护费用一般按设备容量的比例估算比如风电年运维成本为装机成本的3%~5%光伏为1%~2%电解槽和燃料电池因为存在催化剂衰减和维护复杂的问题比例会更高一些可能需要6%~8%。2.3 目标函数和约束条件的数学表达明确了收益函数的组成接下来就是把各参与者的优化问题完整写出来。以氢储能运营商为例它的决策变量是电解槽额定功率 P_el、储氢罐容量 V_tank、燃料电池额定功率 P_fc收益函数为max F_hydrogen p_h2 * E_h2_year p_elec * E_fc_year - C_invest_el - C_invest_tank - C_invest_fc - C_om_hydrogen约束条件则包括电解槽输入功率约束0 P_el(t) P_el_rated燃料电池输出功率约束0 P_fc(t) P_fc_rated储氢罐容量约束SOC_min SOC(t) SOC_max氢平衡约束储氢罐的氢气量变化 电解槽产氢量 - 燃料电池耗氢量 - 对外售氢量功率平衡约束整个微电网层面风电出力 光伏出力 燃料电池发电 电网购电 负荷 电解槽耗电风电运营商和光伏运营商的优化问题类似只是约束条件更简单主要是功率上下限约束和容量上限约束。提示这里我把售氢价格、内部交易电价作为已知外生参数处理实际工程中这些价格往往也是博弈的产物。如果想做得更精细可以把内部交易电价也作为策略变量形成双层博弈结构。不过对于硕士课题或者工程初设阶段设定为固定参数已经够用了。3. Matlab实现的关键路径3.1 求解思路为什么用迭代搜索而不是一次性规划非合作博弈的求解思路是“迭代找均衡”一开始给三个参与者设定一组初始容量配置方案然后每个参与者根据自己的收益函数把别人的策略视为已知重新求解自身的最优容量配置所有参与者同时或先后更新策略反复迭代直到策略不再变化就认为收敛到了纳什均衡。这种做法在思路上非常直观每个参与者都在“穷举自己容量-在给定他人策略下算自身收益-取收益最大者”的这个框架下做决策。因为每个参与者的收益函数需要调用完整的微电网运行模拟来计算所以整体的计算量并不小。有人可能会问为什么不用KKT条件直接求纳什均衡理论上可行但实际做起来非常痛苦。因为每个参与者的收益函数不是简单的凸函数内部还有运行模拟的时序过程强行求KKT条件容易掉进非线性互补问题的深坑里。相比之下迭代搜索实现简单、鲁棒性更好而且数学性质在Scarf的收敛条件满足时可以得到保证。工程上用的最多的就是这样做。3.2 整体流程与核心代码框架我这边把整体流程梳理成以下几个步骤每一步对应一段Matlab代码步骤一初始化参数。定义风、光、氢三个参与者的设备可选范围、成本参数、电价参数、负荷时序数据、风电光伏出力系数时序数据等。步骤二初始化策略。给三个参与者设置初始容量方案比如根据经验值先给一个基础配置。步骤三进入迭代循环。在每一轮迭代中依次求解三个参与者的最优策略。求解时把其他参与者的策略固定为当前最新值在自己的策略空间范围内搜索能最大化自身收益的容量方案。步骤四检查收敛性。如果本轮迭代中各参与者的容量配置与上一轮相比变化幅度小于预设阈值就认为达到纳什均衡跳出循环否则更新策略继续下一轮迭代。步骤五输出结果。绘制收敛曲线输出最优容量配置方案和各参与者的收益明细。核心迭代逻辑的Matlab伪代码如下% 初始化 C_wind C_wind_init; C_pv C_pv_init; C_h2 C_h2_init; max_iter 50; tol 1e-3; for iter 1:max_iter % 记录上一轮策略 C_wind_old C_wind; C_pv_old C_pv; C_h2_old C_h2; % 1. 风电运营商在给定光伏和氢储能容量下优化 C_wind optimize_wind(C_pv, C_h2); % 2. 光伏运营商在给定风电和氢储能容量下优化 C_pv optimize_pv(C_wind, C_h2); % 3. 氢储能运营商在给定风电和光伏容量下优化 C_h2 optimize_hydrogen(C_wind, C_pv); % 检查收敛性 if max(abs(C_wind - C_wind_old)) tol ... max(abs(C_pv - C_pv_old)) tol ... max(abs(C_h2 - C_h2_old)) tol disp(纳什均衡找到); break; end end在这个框架里optimize_wind、optimize_pv、optimize_hydrogen这三个函数是核心。每个函数内部做的事情本质上是一样的在策略空间中搜索最优容量。3.3 策略搜索用枚举还是智能算法每个参与者的策略搜索可以选用枚举法、遗传算法、粒子群等。我这里根据实际使用经验给出建议如果策略空间比较小比如容量取值范围离散化后只有几十到几百个可选值直接用枚举法最省事也最好调试如果策略空间很大可以用粒子群或遗传算法加速搜索。我在自己的项目里容量变量不多就用的是枚举加网格搜索。虽然慢一点但结果稳定而且很直观。要注意的是在迭代博弈主体时我需要反复调用内部的运行模拟函数来计算某个特定容量方案下该主体全年的收益所以这个模拟函数必须写得高效最好用向量化计算避免在循环里逐小时进行时序模拟。举个例子计算某容量方案下风电运营商的全年收益核心代码可以写成这样function profit calc_wind_profit(C_wind, P_wind_series, price_grid, price_h2, C_h2) % 计算风电年发电量 E_wind_total sum(P_wind_series * C_wind / C_wind_ref) * dt; % 风电卖给氢储能的部分简化假设优先卖给氢储能内部电价 E_to_h2 min(E_wind_total, max_h2_consumption(C_h2, price_h2)); % 风电卖给电网的部分 E_to_grid E_wind_total - E_to_h2; % 收益计算 revenue E_to_h2 * price_h2 E_to_grid * price_grid; cost annualized_invest(C_wind) om_cost(C_wind); profit revenue - cost; end注意这里我用了“简化假设风电优先卖给氢储能”的做法。实际项目中卖不卖给氢储能取决于内部电价和电网电价的相对高低这是一个逻辑判断需要在模拟中加入条件分支。我建议在初期建模时先简化处理跑通整个框架后再逐步增加细节避免一步到位把代码写死。3.4 收益函数中的时序模拟怎么写时序模拟是非合作博弈框架里最耗时、也最容易写错的部分。简单来说就是给定容量配置和一年或一个代表日的风速、光照、负荷数据逐小时或逐15分钟模拟整个微电网的运行计算每个时刻的功率平衡、储能状态、交易电量最后汇总成全年/代表期内的总收益和总成本。一个典型的时序模拟循环是for t 1:T % 风电光伏出力 P_wind_t P_wind_series(t) * C_wind / C_wind_ref; P_pv_t P_pv_series(t) * C_pv / C_pv_ref; % 电解槽消纳逻辑优先用风光发电不足时从电网购电 P_el_t min(P_el_rated, max(0, P_wind_t P_pv_t - P_load_t)); % 或者根据电价策略决定是否用电网低价电制氢 % 氢储罐状态更新 SOC_t SOC_{t-1} eta_el * P_el_t * dt - (P_fc_t / eta_fc) * dt - h2_sell_t * dt; % 记录各时刻电量 end这段逻辑看着简单但实际写的时候有几个坑第一电解槽的启动特性和部分负荷效率。电解槽在低负荷时效率会明显下降如果强行假设效率恒定会导致氩储能收益被高估。建议用效率随负荷率变化的曲线来修正哪怕用分段线性近似也行。第二储氢罐的SOC不能简单等效成电池。氢气的存储有时间尺度差异日调节和跨季节调节的储氢罐容量需求完全不同。如果负荷数据只有几天算出来的储氢罐容量可能只是满足日调节根本体现不出季节性吞吐的需求。第三弃电的精细化处理。弃电不能只看“总发电量大于总负荷”还要看具体时刻的实时功率情况。逐时模拟的意义就在这里一天之内可能上午弃光严重下午却要从电网购电如果不做时序模拟这些信息都会被平均掉。3.5 收敛判据怎么设置更稳妥收敛判据不能只看单一变量的变化幅度。我见过有人只看风电容量变化结果风电收敛了但光伏和氢储能还没稳定程序就提前跳出循环了。建议用三个参与者的容量变化量共同判断并且加上一个最小迭代次数限制比如至少迭代5次再判断收敛避免刚起步就出现“假收敛”。还有一个经验不要只依赖一范数或无穷范数收敛判据。有时候容量变化很小但收益还在明显波动。稳妥的做法是同时检查容量变化和收益变化两个都满足阈值才算收敛。if max(abs(C_wind - C_wind_old)) tol ... max(abs(C_pv - C_pv_old)) tol ... max(abs(C_h2 - C_h2_old)) tol ... abs(F_wind - F_wind_old) tol_benefit ... abs(F_pv - F_pv_old) tol_benefit ... abs(F_h2 - F_h2_old) tol_benefit % 收敛 end另外如果迭代了二三十轮还不收敛多半是模型有问题比如收益函数写错、数值尺度不一致成本和收益差了好几个数量级、或者内部价格设置不当。这时候不要急着去调收敛阈值先检查代码。4. 案例演示一个典型算例的全过程4.1 场景与基础数据为了让整个实现路径更具体我这里给出一组供参考的基础数据。假设某园区的微电网需要满足一个中等规模的综合负荷典型日负荷峰值约为5MW日用电量约80MWh。风电和光伏的资源条件取典型水平风电年利用小时数约为2000小时光伏年利用小时数约为1200小时。设备成本参数可以参考当前行业平均水平但注意这类参数更新很快实际项目时要查最新的造价数据。参数取值说明风电单位容量投资6500元/kW含安装、接入光伏单位容量投资3500元/kW含支架、逆变器电解槽单位投资5000元/kW碱性电解槽储氢罐单位投资3000元/kg按储氢量折算燃料电池单位投资6000元/kW含功率变换风电年运维费率4%占投资成本比例光伏年运维费率2%占投资成本比例氢系统年运维费率6%占投资成本比例折现率8%统一经济性口径设备寿命风20光25氢15年均化折算内部交易电价是博弈的焦点初始可以设一个0.35元/kWh左右的水平然后观察博弈结果。电网购电电价按0.6元/kWh设计上网电价按0.4元/kWh设计。4.2 初始化与第一轮迭代初始方案我按经验值给一个基础配置风电5MW光伏5MW电解槽2MW储氢罐500kg燃料电池1MW。这个配置不一定合理但它作为博弈起点是有意义的因为后续各参与者会从它开始逐步“调”出自己的最优策略。第一轮迭代风电运营商发现在光伏5MW、氢储能2MW电解槽的配置下自己的风电容量增加到6.5MW时收益最高于是把策略更新为6.5MW。光伏运营商观察到风电变成6.5MW后重新计算自己的最优容量发现光伏增加到7MW更划算于是更新为7MW。氢储能运营商看到风电光伏都增加了弃电量会变大低价电解负荷的机会也多了于是把电解槽容量提高到3MW储氢罐容量提高到800kg。4.3 迭代收敛过程与均衡结果后续迭代就是重复这个过程。我实际跑下来的收敛曲线显示前期容量振荡比较明显因为每个参与者都在响应别人的变化迭代到第8轮左右风电容量围绕6.3~6.6MW振荡到第15轮之后三个参与者的容量配置变化幅度已经小于1%收益变化也趋于稳定可以认为达到了近似纳什均衡。最终的纳什均衡配置大约为风电容量6.4MW光伏容量7.2MW电解槽功率3.2MW储氢罐容量900kg燃料电池功率1.5MW。从中可以看出一个有意思的现象光伏和氢储能之间存在明显的互补关系光伏容量较大因为它白天出力正好配合电解槽制氢风电则因为夜间出力和冬季出力更能弥补光伏的不足也有一定的配置规模。对比一下集中式优化的结果集中式最优方案给出的总成本更低因为它强制让风电运营商在某种情况下让利给氢储能牺牲了风电的个体收益换取了系统整体收益最大化。但问题在于风电运营商凭什么要让利如果它是独立决策者这个“全局最优解”根本无法强制执行。非合作博弈均衡解的总系统收益略低于集中式最优但每个参与者的个体收益都高于集中式方案中该参与者的收益水平这才是在多投资主体场景下真正可落地的方案。4.4 结果分析的关键视角看博弈结果不能只盯着最终的容量数值还要关注几个关键指标各方收益是否都为正博弈均衡中任何一个参与者的收益如果为负它完全可以退出博弈均衡就不成立。内部电价对均衡结果的影响内部交易电价越高风电光伏越有动力多装但氢储能的成本越高、装得越少。这个价格弹性可以用灵敏度分析画出来。与集中式优化的差距这个差距就是“竞争导致的效率损失”。如果差距过大说明市场机制设计有问题可能需要引入合作机制或价格机制来改进。5. 常见问题与调试经验5.1 模型不收敛的排查思路博弈迭代不收敛是这类模型最高频的故障。我踩过几次坑之后总结出一套排查顺序先检查收益函数内部是否有“突变”。如果某个价格机制导致收益随容量变化呈现跳变或者多峰迭代时就会在多个局部最优之间反复横跳。解决办法是检查电价分段逻辑和约束边界试着平滑处理。再检查参数尺度是否统一。成本如果是万元收益如果是元那就差了四个数量级数值优化算法会直接失灵。建议所有金额统一用万元电量统一用MWh容量统一用MW。最后检查收敛阈值是否太苛刻。有些模型本身有随机性比如用了蒙特卡洛模拟风光出力收益天然有抖动此时收敛阈值需要适当放宽或者改用滑动平均后的收益来判断收敛。5.2 结果对初始值敏感怎么办博弈模型对初始值依赖性强这是非合作博弈在工程应用中的固有难点。同一个模型从不同的初始容量配置出发可能收敛到不同的纳什均衡。这不是程序bug而是博弈模型本身存在多重均衡的可能性。解决办法是跑多组初始值观察最终收敛结果。如果不同初始值收敛到了同一个均衡那说明这个均衡是稳健的如果收敛到了不同均衡就要进一步分析哪些均衡是合理的哪些是病态的比如某个参与者收益为负或者严重偏离工程约束。没有统一的标准答案但通过多初始值对比可以给出更有说服力的结论。5.3 运算速度太慢怎么优化容量优化配置离不开运行模拟运行模拟如果有8760小时的数据每一次收益函数计算都要做8760次循环外层再套博弈迭代速度自然受不了。我建议三个优化方向第一用代表日替代全年时序。选夏季典型日、冬季典型日、过渡季典型日三个或四个代表日乘以对应的天数权重基本能覆盖全年特征计算量可以降一个数量级以上。这是工程上最常见的做法。第二向量化运行模拟。尽可能把逐时循环改成矩阵运算。比如风电出力可以通过容量系数矩阵直接乘容量参数得到储氢罐状态可以通过累加函数计算不用写for循环。第三合理设置策略搜索网格。先粗粒度搜一遍找出最优区域再在最优区域附近细粒度搜索。这个方法简单有效比直接上智能算法更可控。5.4 写代码阶段的几条实用建议Matlab实现这个模型我的体会是代码组织比算法本身更重要。因为整个框架涉及参数定义、收益计算、策略搜索、迭代控制、结果绘图等多个功能模块如果全部堆在一个脚本里后面调参会变得非常痛苦。建议按函数模块拆分数据加载与预处理一个函数、成本参数定义一个脚本、单主体收益计算三个独立函数、策略搜索三个独立函数、主迭代循环一个脚本、结果分析一个脚本。这样调试任何一个环节都可以单独跑通。另外建议把关键中间结果打印出来比如每轮迭代的容量变化方便追踪模型行为。我用的是在每次迭代后打印一行摘要信息fprintf(Iter %2d: C_wind%.2f, C_pv%.2f, C_el%.2f, F_wind%.1f, F_pv%.1f, F_h2%.1f\n, ... iter, C_wind, C_pv, C_el, F_wind, F_pv, F_h2);调模型的时候有一份完整的迭代日志能省下大把排查时间。5.5 关于Matlab环境本身的一点建议最后提一下仿真环境的问题。这类模型对Matlab版本没有太苛刻的要求2020b以上的版本跑这个模型基本没什么障碍。需要用到的主要是基础矩阵运算、优化工具箱的函数如果采用fmincon或ga做策略搜索、以及绘图函数。我建议尽量用2019以后的版本因为早期的Matlab在矩阵运算效率上不如新版特别是处理长时序数据时差异更明显。如果你的Matlab环境没装优化工具箱也不要慌张用枚举法做策略搜索其实不需要优化工具箱纯基础功能就可以跑通。就是计算时间会长一些可以先缩小策略空间测试逻辑确认无误后再扩大搜索范围。我个人在实际操作中的体会是博弈论类模型最大的门槛不在数学推导而在把博弈逻辑“翻译”成可运行的代码。很多时候卡住不是因为不会写代码而是博弈模型本身没想清楚不同参与者之间的耦合关系、收益函数的边界条件这些没理透就直接上手写代码写出来的东西能跑但不能解释。建议先花半天时间把三个参与者的收益函数和约束条件在纸上写清楚再开始动手写Matlab这个前期投入非常值得。