基于非对称纳什谈判的微电网P2P电能交易合作博弈建模与MATLAB实现

发布时间:2026/10/8 9:35:24
基于非对称纳什谈判的微电网P2P电能交易合作博弈建模与MATLAB实现 1. 项目背景与整体思路为什么要把P2P交易做成合作博弈做微网的朋友应该都有这种感觉单纯把光伏、储能、负荷凑在一起并不等于“微网”。真正的难点在于让里面的每个单元愿意配合、主动参与调节而不是各打各的小算盘。这两年P2P电能交易特别火本质上就是想用市场机制解决“怎么分钱、怎么分摊责任”的问题但我看了不少相关代码发现多数实现还停留在“统一出清”或者简单的按比例分配上成员之间的议价能力差异、交易顺序、贡献大小全被抹平了。这种方案做仿真可以放到实际项目里基本跑不通。所以我这次整理的项目核心思路是把P2P交易建模成非对称纳什谈判用合作博弈的框架去求解微网内多主体共享电能时的成交电量和成交价格。所谓“非对称”意思是各个微网成员在谈判中的地位和权重不一样——比如一个自带大储能的工商业用户跟一个只有屋顶光伏的居民用户参与共享时的议价基础完全不同谈判权重自然不该一刀切。项目用的求解工具是MATLAB模型基于YALMIP加求解器实现既能出数值结果也能画交易矩阵、收益分配曲线整个逻辑链是完整的。适合谁看如果你正在做微电网能量管理、分布式能源交易、或者毕业论文里涉及合作博弈方向的这套代码可以直接当成骨架来改。基础要求是会用MATLAB、知道YALMIP怎么装博弈论只需要懂纳什谈判的基本概念就行代码里每一步都拆开了。另一点值得说的是这个项目的价值不只是“算出一个交易结果”而是帮你理解合作博弈里最关键的事帕累托最优和个体理性怎么同时满足。谈判解必须在保证联盟总收益最大的前提下让每个成员分到的收益都不少于自己单干的收益这两条同时锁住P2P共享才不是“劫富济贫”而是“人人受益”。后文我会按模型、代码、结果、坑这四个方面展开讲。2. 非对称纳什谈判模型拆解从数学形式到物理含义2.1 谈判问题怎么变成优化问题乘积形式与权重纳什谈判解的标准形式是最大化各成员效用增量谈判收益的乘积。对称情形下所有成员的权重相同但非对称情形会在乘积里给每个成员加一个权重指数谁的权重大谁在谈判中更有话语权最终的收益分配就会向谁倾斜其他成员必须通过让渡一部分交易利益来换取谈判成立。在微网P2P共享场景里这个权重的物理解释通常是成员对联盟的贡献度、可再生能源出力的不确定性、或者负荷重要程度。比如某个成员的可调容量大、调节速度快它在维持联盟平衡中承担了更多责任那么它在收益分配中理应获得更多补偿否则下一次它就没有积极性继续参与联盟。从数学上看非对称纳什谈判问题可以写成[ \max \prod_{i \in \mathcal{N}} \left(U_i - U_i^0\right)^{w_i} ]其中(U_i)是成员i参与共享后的收益(U_i^0)是成员i不参与合作单独运行时的收益(w_i)是谈判权重满足(\sum w_i 1)。物理含义很直观只有当(U_i U_i^0)时该成员才有动机加入合作这就是个体理性约束而等式约束和不等式约束则刻画了功率平衡、传输容量、储能SOC等物理限制。2.2 为什么不能用单层优化直接求解耦合项的处理直接用上述乘积形式求解会遇到两个麻烦第一目标函数非凸YALMIP虽然能处理部分非凸问题但求解效率和稳定性都很差尤其是在成员数超过5个之后经常出现“可行域存在但找不到解”的情况第二乘积展开后会产生大量非线性交叉项比如两个决策变量相乘这就把问题变成了一个非线性规划NLP对初值极其敏感。项目里采用的处理方法是两步分解。第一步先求“社会收益最大化”问题即不考虑收益分配方式只最大化联盟总收益得到最优交易电量第二步固定交易电量再求解一个关于“转移支付”的谈判问题决定每个成员应该向联盟支付或从联盟获得多少钱。这种分解的精妙之处在于第一步保证了帕累托最优总收益最大第二步保证了分配公平个体理性成立两步合在一起就收敛到非对称纳什谈判解。关于这个过程项目中有一层“系统运营商”角色负责汇总各成员信息并协调交易但不存在一个强制性的中心定价机构——价格由谈判结果内生决定。因此模型虽然用到了集中式求解但经济机制上是去中心化的。在MATLAB实现时第一步是一个线性规划LP或二次规划QP第二步是一个凸优化问题两部分都能稳定求解。2.3 成员收益模型从电费账单到联盟收益每个成员的收益函数建模是整个系统的重要基础。项目把微网中的成员分为三种类型纯负荷型只有用电需求、光伏型有分布式光伏但可能有负荷、光储型光伏加储能具备调节能力。以购电型成员为例其收益函数为[ U_i \sum_t \left( \lambda_t^{DA} P_{i,t}^{DA} \lambda_t^{P2P} P_{i,t}^{P2P} - c_i(P_{i,t}^{G}) \right) ]其中(P_{i,t}^{DA})表示从上级电网购电日前市场购电的功率(\lambda_t^{P2P})表示P2P成交电价(P_{i,t}^{P2P})表示从其他成员买入的功率(c_i)表示本地发电成本函数光伏成本近似为零储能充放电有损耗成本。储能单元的建模也占了不少篇幅。电池不能同时充放电这是硬约束SOC状态方程必须作为全局约束参与优化。在第一步求解时储能充当的是联盟的“公共缓冲池”光伏大发时段充电晚高峰时段放电减少联盟从电网购电的总电量。到了第二步分配收益时储能单元因其调节贡献获得较高的谈判权重这正好呼应了非对称谈判的基本假设。3. MATLAB代码架构与核心模块实现3.1 代码文件结构与运行流程拿到代码后建议按照下面的逻辑顺序来读不要从主脚本开始逐行啃文件/模块功能说明关键函数main.m主脚本定义成员参数、调用优化模型、输出结果数据初始化、求解入口data_define.m定义负荷曲线、光伏出力、电价曲线、储能参数从Excel或.mat文件读入model_social.m构建社会收益最大化模型第一步目标函数、功率平衡约束model_bargain.m构建转移支付谈判模型第二步非对称权重、个体理性约束plot_results.m可视化交易电量、电价、收益分配堆叠图、柱状图、箱线图整个运行流程非常直观首先运行data_define.m加载参数再调用model_social.m求解最优电量把电量结果作为已知量传入model_bargain.m求解转移支付最后用plot_results.m把结果画出来。三个步骤之间通过结构体变量传递数据建议你在中间加disp语句打印每一步的求解状态这样能更容易定位优化失败的位置。3.2 第一步求解社会收益最大化的YALMIP实现社会收益最大化问题的目标函数是最大化所有成员收益之和等价于最小化联盟总成本包括向电网购电的成本、本地发电机组的成本、储能损耗成本。决策变量是各成员每个时段的购售电功率、储能充放电功率、P2P交易功率。我建议用YALMIP的约束列表加目标函数的形式来构建模型而不是用矩阵形式因为后者在修改约束时很容易出错。示例代码如下% 决策变量 P_DA_buy sdpvar(N_member, T, full); % 从上级电网购电 P_DA_sell sdpvar(N_member, T, full); % 向电网售电 P_P2P sdpvar(N_member, N_member, T, full); % P2P交易矩阵i-j SOC sdpvar(N_storage, T1, full); % 储能SOC % 目标函数联盟总成本最小化 objective sum(sum(lambda_DA_buy .* P_DA_buy)) ... - sum(sum(lambda_DA_sell .* P_DA_sell)) ... sum(sum(c_gen .* P_gen)); % 约束功率平衡、储能SOC、P2P交易限制 constraints []; for t 1:T constraints [constraints, P_DA_buy(:,t) sum(P_P2P(:,:,t),2) ... P_load(:,t) P_charge(:,t) - P_discharge(:,t)]; % ... 其余约束 end optimize(constraints, objective, sdpsettings(solver,gurobi,verbose,1));注意第一部分的P_P2P是成员间的物理交易电量但具体价格并不在这里决定。因为P2P交易的本质是电量从剩余方流向缺电方社会收益最大化问题的求解结果会自动让低成本的售电方多发电、高成本购电方少购电这是由目标函数驱动的自然结果而不是人为指定。这里有个很容易踩的坑P2P交易矩阵P_P2P不需要也不应该同时设置正反向。比如1号成员卖给2号成员电量在矩阵里表现为P_P2P(1,2,t)0那么P_P2P(2,1,t)必须为0否则就会出现同一时段两个方向都有功率流这在物理上等于一个成员既是买方又是卖方虽然数学上可能不违反约束但物理上是矛盾的。建议用互斥约束或者直接定义交易方向变量来规避。3.3 第二步求解非对称权重下的收益分配第二步的目标是求转移支付。此时第一步求出的最优电量(P^*)已固定各成员的总成本和总收益也确定了。第二步引入一个“转移支付向量”表示每个成员为获得这些交易电量而支付或接收的费用目标函数是最大化加权乘积形式的谈判收益。实际代码中为了数值稳定性通常不是直接对乘积求最大化而是转为对数形式因为对数函数是单调递增的且把乘积变为求和求解更容易。对数后的目标函数为[ \max \sum_{i1}^{N} w_i \ln\left(U_i - U_i^0\right) ]这个目标函数是凹函数约束条件全都是线性的整体是一个凸优化问题可以稳定求解。这个转化非常重要我在下面单独说明一下。为什么要取对数直接对乘积求最大化在数值上很容易出问题——如果某个成员的收益增量很小乘积会趋近于零导致梯度消失取对数后每个成员的收益增量都被拉到了同一数量级求解器更容易找到最优解。这是个在论文里不算起眼、但在代码实现里必须做的处理。我第一次跑这个模型时直接对原始乘积调用fmincon结果在10个成员规模下求解时间超过半小时还经常不收敛取了对数之后同样的数据几分钟就解出来了。收益分配的具体逻辑是这样的第一步求解得到联盟总收益后每个成员单独运行时的收益(U_i^0)需要单独计算一遍。这个“单独运行”是博弈论里的纳什谈判点也是判断合作是否值得的基准线如果一个成员参与合作后的收益还不如不合作那它肯定会退出谈判。在代码里单独运行的收益计算可以复用同一套优化框架只需把P2P交易的决策变量全部置零只保留与上级电网的交易即可。这样一来做的另一个好处是——你顺带得到了一个“无合作”的对照场景后面画对比图时直接能用。3.4 非对称权重如何设定经验公式与参数调节项目中非对称权重(w_i)的设定有几种常见方法代码默认采用了“基于联盟贡献度”的方式即权重正比于该成员在联盟最优解中的净供应量供应为正需求为负或者调节能力指数。具体计算公式为[ w_i \frac{\sum_t \left(P_{i,t}^{sell} - P_{i,t}^{buy}\right) \cdot \Delta t}{\sum_j \left| \sum_t \left(P_{j,t}^{sell} - P_{j,t}^{buy}\right) \cdot \Delta t \right|} ]简单说就是谁的净送电量多谁的权重就大。这种方式在直观上比较好解释——你往联盟里贡献了更多的电量自然应该在收益分配中享受更大的份额。如果所有成员的净送电量都为负即整个微网是缺电的分母的绝对值求和能保证权重归一化到[0,1]之间。当然这种权重设定并不是唯一的。如果你要模拟的是“负荷重要性”主导的谈判场景可以把权重改成预测负荷的归一化值如果要模拟“新能源消纳责任”主导的场景可以把权重改成光伏装机容量的归一化值。关键是要在论文或报告中写清楚权重的设定依据否则审稿人或者答辩评委肯定会追问。4. 仿真算例设置与结果分析4.1 算例参数数据怎么定才合理一个标准的仿真算例建议设置4到6个微网成员24小时作为一个调度周期时间分辨率取1小时。成员类型建议包含两种及以上比如两个光储型成员、一个光伏型成员、两个纯负荷型成员。这样安排的目的是覆盖所有类型的交易组合光储对负荷、光伏对负荷、储能对负荷、光伏对储能各种组合都能被覆盖到。电价曲线建议采用分时电价三段式峰时段19:00-22:00电价高、谷时段23:00-07:00电价低、平时段08:00-18:00电价中等。可再生能源出力曲线可以从典型日数据中提取或者直接使用代码中内置的demo数据。储能参数按常规锂电池标准设定即可容量2MWh额定功率500kW初始SOC 0.5SOC上下限0.1到0.9充放电效率0.95。这里我特别提醒一下负荷曲线和光伏出力曲线的时序相关性要真实一些。很多人喜欢用随机数生成负荷生成出来的曲线忽高忽低、完全没有日规律性结果P2P交易结果也会变得毫无规律根本无法做分析。建议用实测数据或者典型日数据即使稍微粗糙一点也比纯随机的数据有说服力。4.2 核心结果展示三步看图法跑完代码建议按以下三个层次来分析结果第一层看总收益对比“有P2P合作”与“无合作单独运行”两种场景下的联盟总成本或总收益计算合作带来的收益增量这个数字是整篇文章的核心结论之一。一般来说P2P交易对联盟总成本的降低幅度在8%到15%之间具体取决于各个成员的负荷特性差异和储能配置情况。第二层看个体收益检查每个成员参与合作后的收益是否都大于单独运行的收益。如果某个成员的收益增量很小甚至为负说明权重设定或约束条件设置不合理需要回头检查。这个“个体理性检查”在论文里通常用一张柱状图展示把两个场景的收益并排列出来。第三层看交易矩阵画出P2P交易电量矩阵热力图横轴是卖方纵轴是买方颜色深浅代表交易电量大小。热力图能很快看出哪些成员之间的交易最频繁、交易量最大。通常光伏型成员在午间时段作为卖方纯负荷型成员在全天作为买方储能型成员则在晚高峰时段作为卖方、光伏大发时段作为买方。另外有一个很实用的小技巧把每个时段的P2P成交电价单独画成曲线跟分时电价曲线叠加在同一张图上。你会发现一个关键规律——虽然P2P电价是内生谈判出来的不等于分时电价但它的取值范围总是在购电价和售电价之间而且峰值时段P2P电价会明显高于谷值时段这说明谈判结果间接受到了上级电网电价的影响。这个现象值得在结果分析里单独写一段它体现了“当前微网P2P交易依然以上级电网价格作为外部基准”的特点。4.3 收敛性分析权重的敏感性与稳定性非对称纳什谈判代码调试过程中权重参数对结果的敏感性可能是最大的影响因素。我做过一组对照实验在同一个算例下把权重从均匀分布逐渐调整到高压差分布观察各成员收益增量的变化。结果发现一个规律——收益增量最大的成员往往是权重最大的成员但联盟总收益基本不变。这说明第一步的社会收益最大化已经决定了“蛋糕”的大小第二步只是决定“分蛋糕”的方式权重不影响蛋糕大小只影响分配比例。这个特性有重要的实践意义如果你发现某个成员在合作中贡献了很多电量但收益分配结果却不理想那大概率是权重设置的问题而不是优化模型的问题。可以把该成员的权重适当调高重新运行第二步不必重跑第一步这样可以大幅缩减调试时间。我在实际调试中就靠这个特性节省了不少时间——先说一个结论权重只影响分配不影响总收益所以调试时直接先固定第一步的结果单独调第二步的权重就行不必每次都联调两步。另外一个需要注意的点是当权重分布过于极端时比如某个成员权重达到0.5以上优化问题可能会病态个别成员的收益增量会逼近零。此时建议对个体理性约束加上一个很小的正值下界比如(U_i - U_i^0 \geq 0.1)元避免数值问题导致的不可行。这个下界的数值单位跟成本函数一致具体大小需要根据模型尺度调整。5. 常见问题与调试实录我踩过的坑5.1 优化不可行第一步解不出来怎么办我调试这个项目时遇到的最常见问题毫无疑问是第一步的社会收益最大化模型不可行。排查顺序建议为检查功率平衡约束是否过紧。微网内部功率平衡加上P2P交易限制可能让模型在某个时段找不到可行解。尝试把功率平衡约束中的等式改为不等式允许一定的失负荷看模型是否能解出来。如果能说明原约束太紧需要调整成员参数。检查储能的SOC初值是否需要重新设置。在长时间尺度调度中如果SOC初始值设定过低而前几个时段又需要储能放电来满足平衡就可能出现无解。可以把SOC的上下限范围放宽一些比如从[0.1, 0.9]放宽到[0.05, 0.95]先排除参数设置的问题。检查P2P交易矩阵的维度是否匹配。如果成员数量是N那么P_P2P矩阵应该是(N \times N \times T)且对角线元素恒为0自己不能和自己交易。我犯过的错误是把对角线元素忘了置零导致约束表达式中出现自己买自己电量的情况模型虽然能跑但结果毫无意义。建议在初始化时直接加上P_P2P(i,i,t) 0的约束。检查求解器设置是否合理。我强烈建议把solver设置为gurobi或cplex不要用YALMIP默认的求解器。默认求解器在处理线性规划时性能很差中等规模的问题就会卡住。如果你没有安装商业求解器可以先用linprog或quadprog替代但要注意LP和QP求解器的适用场景不同不要混用。5.2 求解时间过长大规模场景如何加速当成员数量上升到10个以上、时间分辨率提高到15分钟即96个时段时模型规模会急剧膨胀求解时间可能从几秒飙升到几十分钟。我试过几种加速手段效果从高到低排列为首选启用求解器的稀疏矩阵模式。YALMIP中通过sdpsettings(solver,gurobi,gurobi.Sparse,1)可以直接生效对于含有大量零元素约束的模型稀疏模式比密集模式快3到5倍。然后是减少变量的对称冗余。P2P交易矩阵本来可以拆分为购电和售电两个方向但实际上每一对成员之间只需要定义一个方向变量即可另一半可以通过变量代换得到。这样变量数量直接减半规模小了约一半。最后是预求解裁剪。在建模之前手动加入一些约束裁剪比如储能SOC在初始值0.5、容量2MWh、24小时周期内的最大充电量有限可以提前把这个上限写入约束减少求解器搜索空间。这一项收益相对有限对某些场景可能没有改善。5.3 收益分配结果出现负增量怎么处理负增量即某个成员参与合作后的收益小于单独运行收益。这个情况在已经设定了个体理性约束的情况下仍然可能出现通常是由以下两个原因造成的第一步求解的最优解不是唯一的。社会收益最大化问题可能存在多个最优解而不同的最优解对应的P2P交易电量分布差异很大这会直接影响第二步的个体收益分配。解决办法是给第一步的目标函数加一个很小的正则项比如最小化总交易电量的平方和从而在所有最优解中挑选一个“交易成本最小”的解。第二步中的转移支付变量超出了可行范围。检查转移支付的下界约束确保其允许每个成员的收益增量足够抵消参与合作的固定成本。如果有成员存在固定成本比如储能损耗成本需要在收益函数中显式扣除这部分成本否则收益增量就会被高估或低估。5.4 YALMIP安装与求解器匹配问题不少人卡在环境配置这关。YALMIP是一个建模层它本身不求解优化问题需要搭配求解器使用。我建议的搭配方案是YALMIP Gurobi效率最高、稳定性最好或者YALMIP SDPT3开源替代处理中小型线性规划够用。需要特别注意的是Gurobi需要申请学术免费许可证安装后需要把gurobi的路径添加到MATLAB路径中并且确保版本兼容。我遇到过的情况是YALMIP版本太老无法识别新版Gurobi的调用接口导致一直报“No solver found”。解决方法很简单去YALMIP的官网下载最新版本覆盖安装即可应。如果你的系统上安装了多个求解器建议在代码开头显式指定options sdpsettings(solver,gurobi,verbose,1); optimize(constraints, objective, options);这样不会浪费时间在自动选择求解器上。6. 代码扩展方向从基础模型到进阶应用6.1 扩展方向一多微网互联这个项目目前处理的是单个微网内的P2P交易但很多实际项目面临的是多个微网互联的场景。在这种情况下角色层级会变得更加复杂每个微网内部先进行P2P交易剩余的电量需求或富余再通过微网之间的互联线路进行交易。这正好可以套用双层优化的思路——上层是微网之间的非对称纳什谈判下层是微网内部的谈判两层之间通过耦合变量微网间的交易功率链接。修改代码时你可以在现有的成员列表外层再加一个微网循环每个微网内部调用一次现有的“两步求解”函数返回该微网的总收益和总购售电需求然后把每个微网当作上层谈判的“成员”再次调用非对称纳什谈判求解。这样整个模型就变成了一个跨层的一致性优化问题代码的可复用性很高因为2.1节到2.3节的核心函数都不需要改动。6.2 扩展方向二引入不确定性——鲁棒优化和随机规划光伏出力和负荷的随机性在真实微网中不可忽略。我建议大家在基础模型跑通后接着做一步鲁棒优化。具体做法是把光伏出力表示为不确定区间比如预测值的上下15%浮动然后在功率平衡约束中引入鲁棒对等转化。YALMIP对鲁棒优化的支持相对有限但你可以自己写对等约束。如果你倾向于随机规划路线可以预设几个典型场景每个场景对应一组光伏和负荷数据然后在目标函数中对所有场景求期望。这个改动要动的地方比较多建议重构数据输入模块把场景信息独立出来。6.3 扩展方向三把谈判结果嵌入实时控制目前求解得到的交易计划和收益分配是日前的时间尺度时间分辨率一般是1小时。如果想进一步拓展到实时控制层可以把分时电价换为实时电价时间分辨率改成15分钟让储能策略依赖最新的电价信息动态调整。注意这种扩展对求解速度的挑战很大你可以考虑保存日前模型求解出的P2P交易电量然后在实时层只调整储能功率和P2P偏差量不要把所有决策变量全部重新求解一遍。这套两步分解的思路本身就是为“分层调度”准备的结构第一步相当于计划层第二步相当于结算层——计划与结算解耦在工程上更接近真实微网能量管理系统的运作方式。7. 关键心得与后续建议跑完这个项目我最大的体会有三点。第一合作博弈模型的价值不在于数学模型本身有多高明而在于它能不能还原交易主体之间的真实关系。非对称纳什谈判之所以比对称谈判更接近实际就是因为它承认了“每个成员的议价能力不同”这个基本事实。权重参数虽然只是一个数字但它所代表的贡献补偿机制才是决定合作能否持续的核心。第二MATLAB代码调试过程中最耗时的是找建模错误而不是调求解器。YALMIP虽然降低了建模门槛但约束表达式的维度错误、语义错误很难通过报错信息定位。我的经验是每次求解之前先用size(check(constraints))检查约束数量再用probing功能检查模型是否有明显问题做到提前暴露问题不要在优化失败后才开始满世界找原因。第三建议你在跑通基础版之后立刻尝试改一个参数比如把某个成员的权重翻一倍看看结果怎么变。通过这种“扰动测试”你能最快地完成对模型内部机制的直观理解。这一步是整个学习过程里收益最高的投入。最后这个小项目还可以扩展的方向挺多的比如加上碳排放约束、引入需求响应、把单目标扩展成多目标。但无论如何扩展核心的“两步分解”思路——先做帕累托最优、再做分配谈判——都是不变的。把这一步想透了后面的一切改动都只是往里填新约束和新变量而已。