三人博弈MATLAB实战:纳什均衡与Shapley值代码解析 简介这份资源面向博弈论初学者、高校学生及对策略分析感兴趣的IT从业者聚焦3个参与者的非合作博弈与合作博弈的MATLAB实现帮助读者把抽象理论落到可运行的代码上。压缩包为zip格式整体约10.44MB包内以MATLAB脚本与函数文件为主用于构建支付矩阵、迭代求解纳什均衡并涉及合作博弈中的联盟结构与Shapley值分配等计算同时可能包含零和、非零和及完全信息等博弈类型的示例代码。已有977人学习下载说明其在同类资料中具备一定参考价值。读者可借助这些脚本理解博弈模型的建模思路、均衡求解流程与结果验证方法并在此基础上修改参数、扩展参与者数量或替换支付矩阵用于课程作业、课题研究或算法复现是一份偏实践导向的博弈论学习素材。1. 三个参与者的博弈代码包从纳什均衡到 Shapley 值这份 MATLAB 资源能跑出什么三人博弈是博弈论里一个尴尬的分水岭。两人博弈有成熟的矩阵博弈解法画个收益矩阵就能手算纳什均衡参与者一旦变成三个收益结构从二维矩阵变成三维张量纯手算基本歇菜必须借助数值工具。这个压缩包解决的正是这个痛点它用 MATLAB 把三个参与者的非合作博弈和合作博弈都实现了一遍非合作侧聚焦纳什均衡的迭代求解合作侧覆盖联盟博弈和 Shapley 值分配。适合正在做演化博弈、机制设计、资源分配建模的研究生和工程师也适合想用代码验证课本结论的自学者。它不教你博弈论入门它给你一套能改参数、能换收益矩阵、能直接出图的工程化脚本。下面按“资源是什么、怎么跑、坑在哪”的顺序拆开讲。2. 非合作博弈的 MATLAB 落地三人收益张量与纳什均衡迭代2.1 三人博弈为什么不能照搬两人矩阵两人博弈的收益天然是一张二维表行是玩家 A 的策略列是玩家 B 的策略查表即得。三人博弈的收益是三维的玩家 1 选策略 i、玩家 2 选策略 j、玩家 3 选策略 k收益落在 (i, j, k) 这个坐标上。MATLAB 里表示它的自然结构是三维数组而不是矩阵。很多人第一次写三人博弈代码习惯性用两个二维矩阵拼结果在找最优反应时索引错位跑出来的“均衡”根本不自洽。常见做法是用zeros(n1, n2, n3)建张量三个维度分别对应三个参与者的策略数每个格点存一个长度为 3 的收益向量或者干脆建三个同尺寸张量分别存三人的收益。这样在计算某个参与者的最优反应时固定另外两个维度沿自己的维度取max逻辑清晰不易错。2.2 用最优反应迭代逼近纳什均衡纳什均衡的定义是给定其他参与者的策略没有人能通过单方面改变策略提高收益。工程上最直接的求法是最优反应迭代——轮流让每个参与者对自己的策略做一次最优反应循环直到策略组合不再变化。下面是一段可直接运行的最小实现收益张量用随机数占位替换成你自己的数据即可。% 三人非合作博弈最优反应迭代求纯策略纳什均衡 rng(1); n1 3; n2 3; n3 3; % 三个参与者的策略数 % 三个收益张量U{p}(i,j,k) 是参与者 p 在策略组合 (i,j,k) 下的收益 U cell(1,3); for p 1:3 U{p} rand(n1, n2, n3) * 10; % 占位数据替换为真实收益 end s [1 1 1]; % 初始策略组合 maxIter 100; for iter 1:maxIter sOld s; for p 1:3 % 固定其他两人的策略沿参与者 p 的维度找最优反应 idx num2cell(s); % 当前策略组合 switch p case 1 payoff squeeze(U{p}(:, s(2), s(3))); case 2 payoff squeeze(U{p}(s(1), :, s(3))); case 3 payoff squeeze(U{p}(s(1), s(2), :)); end [~, s(p)] max(payoff); % 取收益最大的策略索引 end if isequal(s, sOld) fprintf(第 %d 轮收敛纳什均衡策略组合: [%d %d %d]\n, iter, s); break; end end if iter maxIter fprintf(达到最大迭代次数仍未收敛可能存在混合策略均衡\n); end逻辑说明外层循环控制迭代轮次内层for p 1:3依次让每个参与者做最优反应。squeeze的作用是把固定两个维度后剩下的那一维抽出来变成向量再取max。num2cell(s)那行是为后续扩展成混合策略预留的索引写法纯策略场景下用s(2)、s(3)直接索引也行。参数上n1/n2/n3改成你的实际策略数U{p}换成真实收益张量maxIter一般设 100 到 500 足够纯策略均衡通常几十轮内收敛。如果跑满maxIter还没收敛大概率这个博弈没有纯策略纳什均衡需要转向混合策略用线性规划或支持枚举法求解这是三人博弈里最常见的翻车点。2.3 混合策略均衡的补充思路纯策略不收敛时混合策略是退路。三人混合策略纳什均衡的求解比两人复杂得多两人可以用线性规划Lemke-Howson 算法三人一般用支持枚举support enumeration或非线性方程求解。常见做法是枚举每个参与者的策略子集作为“支持集”在该支持集上令各策略的期望收益相等解方程组再验证非支持集策略的收益不超过均衡收益。MATLAB 里可以用fsolve解这个非线性方程组但要注意初值敏感多试几组初值。压缩包里如果带了混合策略脚本重点看它怎么构造期望收益矩阵和怎么处理支持集组合爆炸——三人各 3 个策略支持集组合就有 (2^3-1)^3 343 种规模再大就得换算法。3. 合作博弈的 MATLAB 落地联盟特征函数与 Shapley 值计算3.1 联盟博弈的特征函数怎么建合作博弈的核心是联盟特征函数 v(S)它定义每个可能的联盟 S 能创造多少总收益。三个参与者时可能的联盟有单人联盟 {1}{2}{3}、双人联盟 {1,2}{1,3}{2,3}、大联盟 {1,2,3}共 7 个非空联盟。特征函数必须满足超可加性两个不相交联盟合并后的收益不低于各自收益之和否则合作没有意义。在 MATLAB 里最省事的表示是一个长度为 2^3 - 1 7 的向量按二进制位映射联盟成员。下面这段代码演示怎么建特征函数并检查超可加性。% 三人合作博弈特征函数与超可加性检查 n 3; % v 的索引用二进制表示联盟1{1}, 2{2}, 3{1,2}, 4{3}, 5{1,3}, 6{2,3}, 7{1,2,3} v [10, 12, 30, 8, 26, 28, 50]; % 占位数据替换为真实特征函数 % 检查超可加性任意两个不相交联盟 S、Tv(S)v(T) v(S∪T) for S 1:7 for T 1:7 if bitand(S, T) 0 % 不相交 ST bitor(S, T); if v(S) v(T) v(ST) 1e-9 fprintf(违反超可加性: v(%d)v(%d)%g v(%d)%g\n, ... S, T, v(S)v(T), ST, v(ST)); end end end end fprintf(超可加性检查完成\n);逻辑说明用二进制位表示联盟成员bitand(S,T)0判断两个联盟不相交bitor(S,T)得到合并后的联盟索引。1e-9是浮点容差避免因舍入误差误报。参数上v向量按你的实际问题填索引顺序要固定好否则后面算 Shapley 值会错位。这段代码跑完如果没有任何输出说明特征函数满足超可加性合作有理论依据如果有违反要么数据有问题要么这个场景本身不适合用合作博弈建模。3.2 Shapley 值的三种算法与代码实现Shapley 值回答的是“每个参与者对联盟的边际贡献平均是多少”是合作博弈里最常用的公平分配方案。三人场景下公式展开是φ_i Σ_{S⊆N{i}} [|S|! (n-|S|-1)! / n!] × [v(S∪{i}) - v(S)]直接按公式枚举所有子集即可三人只有 7 个联盟计算量可忽略。下面给出直接枚举的实现。% 三人 Shapley 值按定义直接枚举子集 n 3; v [10, 12, 30, 8, 26, 28, 50]; % 与上节一致的特征函数 phi zeros(1, n); for i 1:n others setdiff(1:n, i); % 除 i 外的参与者 % 枚举 others 的所有子集 for mask 0:(2^length(others)-1) S []; % 联盟 S 的成员 for b 1:length(others) if bitand(mask, 2^(b-1)) S [S, others(b)]; end end s length(S); % 联盟 S 的二进制索引 idxS 0; for m S idxS idxS 2^(m-1); end % 联盟 S∪{i} 的二进制索引 idxSi idxS 2^(i-1); vS 0; if idxS 0, vS v(idxS); end vSi v(idxSi); weight factorial(s) * factorial(n - s - 1) / factorial(n); phi(i) phi(i) weight * (vSi - vS); end end fprintf(Shapley 值: φ1%.4f, φ2%.4f, φ3%.4f\n, phi(1), phi(2), phi(3)); fprintf(Shapley 值之和 %.4f, 大联盟收益 %.4f\n, sum(phi), v(7));逻辑说明外层遍历每个参与者 i内层用位掩码枚举其余参与者的所有子集 S。idxS和idxSi分别算出 S 和 S∪{i} 在特征函数向量里的索引。权重factorial(s)*factorial(n-s-1)/factorial(n)就是 Shapley 公式里的组合系数。跑完检查sum(phi)是否等于v(7)这是 Shapley 值的有效性公理如果不等说明特征函数或索引有误。参数上v向量必须和上一节一致n改成实际参与者数后这段代码也能扩展到更多人但枚举量随 n 指数增长n 超过 10 就得换蒙特卡洛近似或排列采样法。3.3 合作博弈的稳定性核心与夏普利值的配合Shapley 值给出一个公平分配但不保证这个分配落在“核心”里。核心是指没有任何联盟能通过脱离大联盟获得更好收益的分配集合。三人场景下核心是一组线性不等式约束可以用linprog检查某个分配是否在核心内。常见做法是先算 Shapley 值再把它代入核心约束验证如果不在核心内说明这个博弈的公平分配和稳定分配存在冲突需要引入其他解概念如核仁 nucleolus。压缩包里如果带了核心计算脚本重点看它怎么把联盟约束写成A*x b的形式这是合作博弈代码里最容易写错的部分。4. 避坑与排查三人博弈代码跑不通的五个血泪经验4.1 现象最优反应迭代震荡不收敛原因存在混合策略均衡或循环最优反应三人博弈里纯策略纳什均衡不一定存在。如果迭代在几个策略组合之间来回跳不是代码写错了是这个博弈本身没有纯策略均衡。解决办法是转向混合策略求解或者检查收益张量是否满足某些存在性条件比如超模博弈。我一般会先跑一遍纯策略迭代不收敛就直接切混合策略脚本不在这上面浪费时间。4.2 现象Shapley 值之和与大联盟收益对不上原因特征函数索引映射错误Shapley 值必须满足有效性公理和等于大联盟收益。对不上几乎一定是索引问题要么v向量的顺序和二进制映射不一致要么idxSi计算时漏了某个位。排查方法是手动算一个两人的简单例子逐步打印每个联盟的索引和取值对一遍就清楚了。这个坑我踩过不止一次后来养成习惯特征函数建好后先跑超可加性检查再跑 Shapley 值两步都过了才信结果。4.3 现象squeeze之后维度不对原因某一维长度为 1 时被压掉squeeze会删掉所有长度为 1 的维度。如果某个参与者的策略数恰好是 1squeeze后的向量维度会和你预期的不一样导致max取错方向。解决办法是用reshape显式指定目标维度或者用U{p}(:, s(2), s(3))这种带冒号的索引直接取不用squeeze。这个坑在策略数动态变化时特别隐蔽建议代码里加一句assert检查维度。4.4 现象混合策略fsolve不收敛或解出负概率原因初值不当或方程组欠定三人混合策略均衡的方程组可能有多个解fsolve对初值敏感。解出负概率说明约束没加对需要在方程组里加入概率非负和求和为 1 的约束或者用lsqnonlin带边界求解。常见做法是多跑几组随机初值取满足所有约束的解再验证是否真的是均衡。4.5 现象合作博弈核心为空但 Shapley 值照常算出原因没做核心存在性检查Shapley 值总是能算出来但核心可能为空。核心为空意味着不存在任何分配能同时满足所有联盟的理性约束合作博弈的稳定性没有保障。排查方法是构造核心的线性不等式组用linprog找可行解如果无可行解就说明核心为空。这时候 Shapley 值只能作为参考不能当作稳定分配方案用。5. 进阶技巧把三人博弈脚本改造成可复用的参数化工具跑通单个案例只是第一步真正省时间的是把脚本改造成参数化函数换一组收益数据就能直接出结果。我一般会把非合作和合作两部分封装成两个函数nash3(U)接收收益张量返回纯策略均衡和收敛信息shapley3(v)接收特征函数返回 Shapley 值和核心检查结果。这样在批量实验时外层只需要循环换数据不用每次改代码。验证结果是否正确除了前面说的有效性公理和超可加性检查还有一个实用手段用已知解析解的经典博弈做回归测试。比如三人囚徒困境、三人公共品博弈这些有文献给出的均衡结果拿你的代码跑一遍对答案对上了再跑自己的数据。这个习惯帮我省了很多次返工。参数化时注意几个边界策略数不要硬编码成 3用size(U{1})动态取特征函数向量的长度用2^n - 1算别写死 7Shapley 值的枚举在 n 超过 8 之后明显变慢提前想好要不要换蒙特卡洛近似。还有一个容易忽略的点MATLAB 的factorial在 n 较大时会溢出n 超过 170 直接返回 Inf虽然三人场景碰不到但改造成通用工具时最好换成gammaln做对数运算再取指数。从那以后我每次拿到新的博弈数据都强制先跑超可加性检查和有效性验证两步都过了才看具体数值。这个习惯让我少走了很多弯路。希望帮到你。本文还有配套的精品资源点击获取