简介电力市场与博弈论交叉方向的课程讲义PPT面向电气工程、能源经济等专业学生及需要理解发电侧竞价逻辑的入门读者重点回答博弈论基本概念如何用于电力市场报价分析。压缩包仅含1个PPT文件大小约847KB属于轻量单文件课程资料便于课堂展示、复习翻阅和汇报前快速梳理框架。已有173人学习说明其作为概念入门材料具备一定参考价值。内容从参与人、行动、信息、战略、支付、结果与均衡等要素切入串联博弈的战略式表述、静态与动态博弈、完全与不完全信息博弈及对应纳什均衡并进一步介绍电力寡头市场的古诺、伯特兰德和供给函数均衡模型。读者可借此建立从博弈要素到市场均衡的分析路径理解发电厂商报价策略与均衡求解之间的关系适合概念速览和知识串联。1. 发电厂的报价单本质是别人战略的函数一份讲电力市场的课程资源最容易被快速翻过去的就是博弈论那几页 PPT——参与人、行动、信息、战略、支付一页一个名词看着像考前背诵的清单。可真坐到报价席上问题立刻变了味你报 320 元/兆瓦时同片区的机组报 300你的电就上不了网你把价格压到 290对方跟着压到 280你依然出局。这不是一台机组对着自己的成本曲线做单目标优化而是一群人同时被卷进同一个方程组。博弈论给的从来不是某个“最优报价”而是一个判据什么样的报价组合谁单方面改动谁吃亏。这份讲义把判据拆成了五个要素、四个象限和三个寡头模型下面一层层往下挖。2. 五要素拆解为什么支付函数里必须出现别人的战略2.1 参与人与行动集决策变量究竟是「量」还是「价」参与人是博弈里的决策主体目标是靠选行动或战略把自己的支付推到最高。落到电力市场参与人就是那些报价的发电厂商一个人控制多台机组时也可以把整个投资组合当成一个参与人处理。这里第一个容易含糊的地方在于参与人的身份边界必须和你建模的决策边界一致。如果你把同一个集团下的两台机组拆成两个参与人它们之间的内部协调就会被误当成市场竞争均衡结果会明显偏离现实。行动是参与人在某个时点的决策变量可以离散也可以连续。电力市场里最典型的行动有三类申报价格、申报电量、机组启停状态。离散化之后行动集的大小直接决定了计算规模。报价从 0 到 1000 元/兆瓦时按 1 元一档就是 1001 个行动两台机组做战略式展开组合数立刻过百万。很多人建模时随手把粒度设成 0.1 元然后抱怨求解器跑不动根子就在这里。n 个参与人各选一个行动拼起来的有序组叫行动组合。支付函数吃的就是这个组合而不是某一个参与人自己的行动。这一点是博弈和普通优化的分水岭普通优化里目标函数只依赖自己的决策变量博弈里它依赖整个向量。from itertools import product # 参与人两台机组的报价决策 players (G1, G2) # 行动集把连续报价离散成三档粒度决定了后续组合规模 actions { G1: [280, 300, 320], G2: [280, 300, 320], } # 行动组合 所有参与人行动集的笛卡尔积 profiles list(product(*(actions[p] for p in players))) print(len(profiles)) # 9两台机组各三档 print(profiles[0]) # (280, 280) # 粒度每加一档组合数按参与人数指数增长 def combo_count(players, k): return k ** len(players) print(combo_count(players, 10)) # 100 print(combo_count((G1,G2,G3,G4), 10)) # 10000这段代码只做一件事把“行动集 → 行动组合”这层关系摊开。actions是每个参与人可选的行动集合product生成的是行动组合而非战略组合静态博弈里两者恰好重合。combo_count用来看规模4 台机组、10 档报价就是 1 万种组合每种的支付都要算一遍如果把档位加到 100就是 1 亿。所以讲义里反复强调“行动可以是离散的也可以是连续的”不是啰嗦是在提醒你离散化粒度是一个必须提前算清楚的成本项。2.2 战略是相机行动方案不是一张报价单战略和行动的区分是整个讲义里最容易被读快而漏掉的一段。行动是某个时点的一个决策值战略是一份规则规定在每一个可能的信息集上该选什么行动。用讲义的原话说战略是“相机行动方案”。静态博弈里所有人同时动手、谁也看不到谁战略就退化成单个行动两个词可以混着用一旦进入动态场景混淆这两个词会直接把模型算错。举个具体的日前市场先出清实时市场再平衡。你在日前报了一个量价对在实时市场还要根据日前出清价、机组实际出力、负荷预测偏差再报一次。这时你的战略不是“日前报 300”而是“日前报 300如果日前出清价高于 320 就实时减报低于 280 就实时增报”。前者是一个数后者是一张 if-then 表。这个区分带来的计算后果是数量级的。你有 3 档行动对手先动且你能观察到他选了哪一档那么你的战略空间不是 3而是 3 的 3 次方——每一个观察到的对手行动你都要预备一个回应。这是动态博弈求解难的根本原因也是子博弈精炼这类概念存在的理由它要在一张指数膨胀的表里把不可信的回应剔除掉。from itertools import product def strategy_space(own_actions, observed_actionsNone): 静态博弈战略 行动动态博弈战略是观察结果的函数 if observed_actions is None: return [(a,) for a in own_actions] # 对对手的每一种可能行动都要指定一个自己的回应 return list(product(own_actions, repeatlen(observed_actions))) own [280, 300, 320] rival [280, 300, 320] print(len(strategy_space(own))) # 3 静态 print(len(strategy_space(own, rival))) # 27 动态指数膨胀own_actions是自己的可行行动observed_actions是能观察到的对手行动节点。静态分支直接返回单元素元组动态分支返回所有“回应组合”。第二行输出 27 这个数字值得盯一会儿机组数量再多一台或者报价档位再细一档战略空间就会膨胀到求解器无法处理。现实建模里大家会用“限制回忆长度”“只对关键节点分支”这类手段剪枝本质是在给这张表降维。2.3 完美信息与完全信息一字之差的两个假定信息是参与人关于博弈的知识尤其是关于“自然”的选择、其他参与人的特征和行动的知识。讲义把两个特别容易混的概念并排放了完美信息说的是你能准确看到别人已经做了什么完全信息说的是你对别人的特征、战略空间、支付函数有完整了解事前没有不确定性。前者管行动可见性后者管类型可知性两者可以独立成立或不成立。这个区分在电力市场里非常实在。报价保密制度下别的机组报了什么价你看不到这是不完美信息但你大致知道对方的燃料成本区间、机组容量、检修计划这可以算完全信息。反过来有些市场披露历史报价行动可见但对手的边际成本可能因为燃料长协价格不公开而无法确知那就是完美但不完全。把这两个维度搞混会直接把你送到错误的均衡概念上去。还有一个更强的假定共同知识。它指的是“所有参与人知道所有参与人知道所有参与人知道……”无限递归下去。这个假定在教科书里一句话带过在工程建模里却是一个硬约束只要有一家厂商不确定别人是否知道自己知道理性的推理链条就断了。现实中报价策略的“玄学”感很大一部分来自共同知识链条的断裂——大家并不真的确信对方和自己对规则的理解完全一致。提示建模时把“信息结构”当成一个独立参数写进配置文件别写死在代码里。同一个求解器换个信息假定就是另一个均衡概念硬编码会让复用变成灾难。3. 战略式表述与四象限均衡概念为什么要跟着信息结构走3.1 把博弈压缩成 (N, S, u) 三元组战略式表述干的事情是“抹掉时间”。它只保留三样东西参与人集合、每个人的战略空间、每个人的支付函数。所有关于“谁先动、谁看到了什么”的时序信息都被压进了战略的定义里——因为战略本身就是一份覆盖所有信息集的行动规则时序信息已经编码在规则中了。这份讲义只给了战略式表述没展开扩展式这在课程场景下是合理的取舍战略式适合静态博弈和纯策略分析扩展式适合画博弈树、讲子博弈精炼。但从工程角度看扩展式更贴近电力市场的实际决策流程因为机组启停、日前-实时两级市场天然是分阶段的。支付函数 u_i(s) 的自变量是整个战略组合 s不是 s_i。这一行符号看着平淡实际是整个理论的支点。它意味着你把自己的战略调到最优前提是别人的战略已经固定别人一改你的最优解就变了。所谓“求解”找的不是一个最优点而是一组互相咬合的点。从优化理论的角度看纳什均衡可以写成一个最优化问题的解s_i* 是在给定其他所有人选择 s_-i* 的条件下第 i 个参与人能取到的最大支付对应的战略。n 个参与人就有 n 个这样的最优化问题它们耦合在一起必须联立求解。3.2 行动顺序 × 信息完全性切出四种博弈四种均衡讲义给出的四象限是这套理论的骨架缺了它后面三个寡头模型就没法定位。信息结构静态动态完全信息纳什均衡子博弈精炼纳什均衡不完全信息贝叶斯纳什均衡精炼贝叶斯纳什均衡四格不是四套平行理论而是同一套逻辑在两种不确定性下的两次升级。静态完全信息下纳什均衡够用因为你不需要考虑“我说了要做但事后不会做”这种问题。一旦进入动态先动者可能放出一个不可信的威胁来影响后动者纳什均衡管不住它于是要用逆向归纳把不可信的部分从后往前剪掉剩下的才叫子博弈精炼。再往右一格参与人连对手的类型都不确定就得把类型先验和贝叶斯更新引进来。映射到电力市场日前市场多家机组同时申报可以按完全信息静态博弈处理找纳什均衡如果某家先公布检修计划、其余机组再报价就要按动态处理如果燃料成本属于私有信息就得走贝叶斯那条线。选错格子解出来的东西在数学上自洽在业务上却站不住。3.3 纳什均衡的不动点本质没人愿意单方面改纳什均衡的定义一句话能说完给定其他所有人的战略每个参与人选择的都是自己的最优战略。形式化就是对任意参与人 i 和任意可行战略 s_i都有 u_i(s_i*, s_-i*) ≥ u_i(s_i, s_-i*)。换句话说没有任何人存在“单方面偏离能变得更好”的动机。这个性质和“全局最优”完全是两回事。全局最优要求所有人协调起来把总支付推到最大纳什均衡只要求每个人都对别人的选择做出最优回应。囚徒困境里双方都招供是纳什均衡但显然不是联合最优——讲义里那套支付函数“依赖所有人战略”的表述讲的就是这个。从数学上看纳什均衡是最优反应映射 BR(s) (BR_1(s_-1), ..., BR_n(s_-n)) 的不动点。存在性靠角谷不动点定理只要战略空间是紧凸集、支付函数对自身战略连续拟凹这个映射就有不动点。这条定理保证了博弈至少有一个均衡可能混在混合战略里但不保证唯一也不保证一定落在纯战略上。所以在代码里暴力搜索纯策略纳什均衡时搜不到不等于模型错了可能只是均衡在混合战略里。from itertools import product def best_response(i, profile, players, actions, payoff): 固定其他人不动扫描参与人 i 的全部可行行动返回支付最高的那个 best_a, best_u None, float(-inf) for a in actions[players[i]]: cand list(profile) cand[i] a u payoff[tuple(cand)][i] if u best_u: best_a, best_u a, u return best_a def find_pure_nash(players, actions, payoff): out [] for prof in product(*(actions[p] for p in players)): # 每个人都在对别人的选择做最优回应 → 该组合是不动点 if all(best_response(i, prof, players, actions, payoff) prof[i] for i in range(len(players))): out.append(prof) return out players (G1, G2) actions {G1: [低, 中, 高], G2: [低, 中, 高]} # 支付表payoff[(a1, a2)] (u1, u2) payoff { (低, 低): (6, 6), (低, 中): (8, 3), (低, 高): (9, 1), (中, 低): (3, 8), (中, 中): (5, 5), (中, 高): (7, 2), (高, 低): (1, 9), (高, 中): (2, 7), (高, 高): (4, 4), } print(find_pure_nash(players, actions, payoff)) # [(低, 低)]best_response是定义的一比一翻译把参与人 i 的行动逐个替换进战略组合看哪个支付最高。find_pure_nash遍历所有组合用“每个人都在做最优回应”做筛选。最后输出[(低, 低)]说明这个收益结构下只有这一组是稳定的任何一方单独从“低”换到“中”或“高”收益都会掉下来。注意是严格比较如果出现收益相等的情况按定义也算最优回应但这段代码只会返回第一个遇到的遇到平台期需要额外规则——这是数值求解多解的一个常见来源。4. 古诺、伯特兰德与 SFE三种寡头模型差在哪一行一阶条件4.1 古诺把对手产量当常数反应函数怎么解出来古诺模型的本质是把对手的产量水平当作固定值再决定自己生产多少。它被称为产量竞争模型各厂商同时决策都清楚自己的产量会影响价格但都认为自己的产量决定不影响别人的产量决定。设反需求曲线 P a - bQQ 是市场总产量每家厂商边际成本为常数 c。厂商 i 的利润是 π_i P·q_i - c·q_i [a - b(q_i Q_-i)]·q_i - c·q_i其中 Q_-i 是除 i 以外所有人的产量之和。对 q_i 求一阶条件展开π_i (a - c)q_i - b q_i² - b Q_-i q_i求导dπ_i/dq_i (a - c) - 2b q_i - b Q_-i 0反应函数q_i (a - c - b Q_-i) / (2b)二阶条件 d²π_i/dq_i² -2b 0只要 b 0 就满足所以一阶条件给出的确实是最大值而不是最小值。这一步讲义专门提了一句“所以上式小于等于 0”就是在确认极大值条件很多讲义会跳过它但跳过之后你无法判断解出来的是均衡还是鞍点。对称均衡下所有厂商产量相同Q_-i (n-1)q代入反应函数解得 q* (a - c) / [b(n1)]。n 趋于无穷时 q* 趋于 0、价格趋于边际成本n 1 时退化成垄断解 (a-c)/(2b)。这两个极限正好把古诺夹在垄断和完全竞争之间是它最直观的经济含义。def cournot_symmetric(a, b, c, n): 对称古诺均衡q* (a - c) / (b * (n 1)) return (a - c) / (b * (n 1)) def cournot_price(a, b, c, n): q cournot_symmetric(a, b, c, n) return a - b * n * q # 总产量代回反需求 a, b, c 100.0, 1.0, 10.0 for n in (1, 2, 4, 10): q cournot_symmetric(a, b, c, n) p cournot_price(a, b, c, n) print(fn{n:2d} q{q:6.2f} P{p:6.2f} 单厂利润{(p - c) * q:7.2f}) # 用最优反应迭代验证不动点两家对称情形 q1 q2 0.0 for _ in range(200): q1 (a - c - b * q2) / (2 * b) q2 (a - c - b * q1) / (2 * b) print(f迭代收敛: q1{q1:.4f} q2{q2:.4f}) # 30, 30cournot_symmetric是解析解参数n是参与人数b是需求斜率越大表示价格对产量越敏感均衡产量越小。循环打印的四个 n 值展示了收敛路径n1 时价格 55、产量 45是垄断n2 时价格 40、产量 30n10 时价格已经逼近边际成本 10。第二段用最优反应迭代从 (0,0) 出发反复代入反应函数200 轮后停在 (30, 30)和解析解一致。这个迭代过程本身就是“不动点”三个字的可视化两条反应曲线在平面上交于一点从任何起点出发都会被吸过去。4.2 伯特兰德决策变量一换利润为什么塌到零伯特兰德模型把决策变量从产量换成价格生产同一产品的厂商同时定价产品之间没有差异也没有容量限制。在这个设定下只要有一家的价格高于边际成本另一家略微降价就能抢走全部市场于是价格被一路压到等于边际成本。此时每个厂商都是价格的接受者利润为零所以这个解也叫准竞争解。数学上很干脆厂商 i 面对的需求是一个阶跃函数——价格低于对手时拿走全部市场高于对手时一单没有等于对手时按某个规则分配。利润最大化的一阶条件在这种情况下退化为“定价不能高于对手也不能低于边际成本”唯一稳定的点是 P MC。这里有一个经常被忽略的前提没有容量限制。如果每家机组的装机容量加起来还不够覆盖总负荷那么价格压到边际成本时市场根本出清不了价格会被重新抬起来。电力市场的现实恰恰是容量约束、网络阻塞、启停成本三者同时存在所以纯伯特兰德均衡在电力市场里往往只能作为参照系不能直接拿来当预测。真正接近伯特兰德逻辑的是统一出清价机制下的边际机组定价——所有中标机组按最后一个满足负荷的报价结算这是规则设计出来的价格一致性而不是厂商博弈出来的。4.3 SFE报价曲线当战略为什么线性解才稳定唯一供给函数均衡模型最贴近电力市场的实际规则市场要求各发电商递交供给函数表明在不同价格下愿意提供的发电量市场价格由总需求和各家供给函数共同决定。这跟古诺报量、伯特兰德报价都不一样决策变量是一条曲线。讲义提到很多文献证明线性供给函数均衡才是稳定且唯一的。这句话背后的直觉是如果供给函数可以任意非线性厂商就有无穷多个自由度去构造“在均衡价格附近陡峭、在其他区间平缓”的形状解会变得不唯一且对扰动极其敏感。把供给函数限制成线性等于把无穷维的战略空间压成两维截距和斜率唯一性才有条件成立。推导对称线性均衡设各家的供给函数为 s_i(p) βp截距取零市场需求 D(p) A - Bp边际成本 c。对厂商 i 来说其他 n-1 家提供 (n-1)βp剩余需求是R(p) (A - Bp) - (n-1)βp A - Kp其中 K B (n-1)β反解价格p (A - q_i) / K利润π_i (p - c)q_i [(A - q_i)/K - c]·q_i一阶条件dπ_i/dq_i (A - 2q_i)/K - c 0得 q_i (A - cK)/2把 q_i 代回价格表达式得到 p* (A cK)/(2K)于是自己的供给函数斜率必须是 β q_i/p* K(A - cK)/(A cK)。而对称性又要求 β (K - B)/(n-1)。两个式子联立得到关于 K 的一元方程(K - B)/(n-1) K(A - cK)/(A cK)这个方程在有效区间内可以用数值方法解出来再回代得到 β 和均衡价格。from scipy.optimize import brentq def sfe_symmetric(A, B, c, n): 对称线性供给函数均衡 s_i(p)beta*p需求 D(p)A-B*p 不动点条件(K-B)/(n-1) K(A-cK)/(AcK)K B(n-1)*beta def f(K): return (K - B) / (n - 1) - K * (A - c * K) / (A c * K) lo, hi B * 1.0001, (A / c) * 0.9999 # 需保证 A-cK0价格为正 K brentq(f, lo, hi) beta (K - B) / (n - 1) p (A c * K) / (2 * K) q beta * p # 单厂产量 return beta, p, q A, B, c 100.0, 1.0, 10.0 for n in (2, 4, 10): beta, p, q sfe_symmetric(A, B, c, n) print(fn{n:2d} beta{beta:6.3f} P{p:6.2f} q_i{q:6.2f} 总产量{n*q:7.2f})brentq是求根器lo和hi的选择不是随便定的K 必须大于需求斜率 B否则 β 为负供给曲线向下倾斜同时必须小于 A/c否则一阶条件给出的产量为负。这两个边界正好框住可行域超出范围brentq会报错这本身就是一个有用的自检。n2 时算出 β1.5、P25、单厂产量 37.5和手算结果一致。把四个模型的数字摆在一起对比才有说服力模型决策变量均衡价格单厂产量单厂利润垄断对照总产量55452025古诺 n2产量4030900线性 SFE n2供给函数2537.5562.5伯特兰德价格10450同一套成本和需求参数下报价曲线竞争SFE比产量竞争古诺激烈得多均衡价格 25 对 40单厂利润腰斩。这个结果在电力市场分析里很关键市场规则允许报供给曲线还是只允许报一个量价对会显著改变均衡结果。规则设计者真正在调的就是这张表里的某一行。5. 建模避坑五种翻车现场与排查路径5.1 把纳什均衡当成联合最优现象模型跑出来的均衡利润比把所有机组当成一家公司统一调度时低了将近一半第一反应是求解器有 bug 或者目标函数写反了。原因纳什均衡要求的是互相最优回应不是总支付最大。每个参与人只对自己的支付负责没人有动机为了集体利益牺牲自己。囚徒困境是这个性质最纯粹的例子寡头古诺模型里价格高于边际成本但低于垄断价也是同一个道理。把均衡解和联合最优解并列一比差出来的那部分就是所谓的“竞争损失”它是理论预测的结果不是数值误差。解决在代码里同时算两个解——联合最优用单一优化器解总利润最大化均衡解用最优反应或方程联立。两者都算出来再对比一旦均衡利润高于联合最优那才是真出问题了。这个交叉验证我一般会写进回归测试因为改参数的时候特别容易把支付函数改错方向。5.2 求导时漏掉总产量里的自己现象古诺模型的反应函数斜率算出来是 -1/b而理论值应该是 -1/(2b)均衡产量比预期大了一截。原因利润函数 π_i [a - b(q_i Q_-i)]q_i 对 q_i 求导时总产量 Q 里的 q_i 也要参与求导。展开后是 (a-c)q_i - b q_i² - b Q_-i q_i三项里有两项含 q_i。很多人在纸上写的时候把 P 当常数直接乘忘了 P 本身是 Q 的函数漏掉 -bq_i 这一项一阶条件就从 a - c - 2bq_i - bQ_-i 0 退化成了 a - c - bq_i - bQ_-i 0。解决养成先展开再求导的习惯别在心算阶段直接对含 P 的表达式求导。写代码时把利润函数单独定义成一个可调用的函数用数值微分和解析导数对一遍差超过 1e-6 就说明推导有问题。这个检查只花几行代码能挡掉一大半符号错误。5.3 完美信息与完全信息混用现象动态模型里让后手观察到了先手的具体报价但求解出来的均衡和静态版本一模一样逆向归纳完全没起作用。原因信息集没有真正更新。在战略式表述里让后手“看到”先手行动意味着后手的战略空间必须从 k 个行动膨胀成 k^k 个相机行动方案如果代码里还是给后手一个固定的行动列表那么所谓“观察”只是形式上的求解器根本不知道后手有条件化选择的能力。另一个常见混淆是把“我知道你的成本”当成“我看到你的报价”前者是完全信息后者是完美信息处理方式完全不同。解决建模前先把信息结构画成一张表明确每个参与人在每个决策节点知道什么、不知道什么。代码里用strategy_space这类函数显式构造战略空间别直接用行动集顶替。求解结果和静态版本相同的时候先怀疑信息结构没生效再怀疑模型本身。5.4 伯特兰德结论直接套到电力市场现象用伯特兰德模型算某区域市场的均衡得到价格等于边际成本、所有人利润为零但实际市场出清价长期高于边际成本模型预测完全失效。原因伯特兰德的三条前提——产品同质、无容量约束、无搜索成本——在电力市场里几乎全部不成立。机组有装机容量上限输电线路有阻塞启停有成本不同机组的爬坡速率也不一样。容量约束一加上价格压到边际成本时供给不足以覆盖负荷价格必然被抬起来网络阻塞会让局部市场隔离形成节点价差。把这些前提忽略掉模型就只剩一个理论参照系的作用。解决先把伯特兰德解当成下界基准再看实际价格偏离多少偏离的部分用容量约束、阻塞、机组组合来解释。如果确实要用伯特兰德框架至少加上容量约束做成容量约束价格竞争模型或者引入产品差异化比如调频、备用等辅助服务让价格不至于塌到底。5.5 供给函数均衡解出多组系数现象非线性方程组联立求解从不同初值出发收敛到不同的 (α, β) 组合每组都满足一阶条件不知道哪个才是“真”均衡。原因一阶条件只是必要条件不是充分条件。非线性方程组的解可能对应极大值也可能对应极小值或鞍点即使都是极大值也可能存在多个局部最优。讲义里强调“线性供给函数均衡才是稳定唯一的”恰恰是在给这个问题打补丁把供给函数限制成线性可行域变成凸的一阶条件才同时是充分条件不动点才唯一。解决三板斧——检查二阶条件海森矩阵负定、从多组初值出发看是否收敛到同一点、做扰动测试把某个参数微调 1%解是否连续变化。三关都过才算数。如果三关过不了说明模型设定本身有问题该退回去检查是不是漏了容量约束或者成本函数的凸性假定。6. 怎么验证一个均衡解是真的最优反应、二阶条件与唯一性解出一个均衡和证明它真的是均衡是两件事。前者是求解器给你的数字后者需要你自己补验证。我一般会走三步第一步把解代回每个人的最优反应函数看残差是不是接近零第二步检查二阶条件确认一阶条件给的是极大值不是极小值第三步从多个不同初值重新求解看是否收敛到同一个点。第一步对离散博弈最直接。给定解出来的战略组合把每个参与人的行动逐个替换成其他可行行动如果没有任何一个替换能带来正的收益增量那这个组合就是纯策略纳什均衡。这段检查代码只有十几行但能挡掉绝大多数“求解器收敛了但解错了”的情况。def verify_nash(profile, payoff, actions, players, tol1e-9): 返回每个参与人的有利可图单边偏离全部为空才是纯策略纳什均衡 gaps {} for i, p in enumerate(players): base payoff[profile][i] better [] for a in actions[p]: cand list(profile) cand[i] a gain payoff[tuple(cand)][i] - base if gain tol: # 只记录严格改进 better.append((a, round(gain, 4))) gaps[p] better return gaps prof (低, 低) print(verify_nash(prof, payoff, actions, players)) # {G1: [], G2: []} —— 两方都没有有利可图的偏离 print(verify_nash((中, 中), payoff, actions, players)) # {G1: [(低, 1.0)], G2: [(低, 1.0)]} —— 双方都想往低走tol是数值容差浮点运算下残差不可能严格为零设太小会误报设太大会漏报1e-9 对一般量级够用。返回空列表表示该参与人没有改进空间返回非空就说明这个组合不是均衡列表里的(行动, 收益增量)直接告诉你往哪个方向偏。连续博弈的验证要换成反应函数残差。以古诺为例解出 (q1, q2) 之后把 q2 代进厂商 1 的反应函数算出理论最优产量和 q1 一比差值应该在数值精度内。这个检查比看求解器返回的successTrue可靠得多——求解器说成功只代表它没崩不代表它找到了你要的东西。最后一层是唯一性。均衡不唯一的时候“求出解”这件事本身就失去意义因为你不知道手上这个是哪一个。判断办法是从多个随机初值出发重复求解如果收敛到不同的点就要回到模型设定上去找原因是不是可行域不凸、是不是成本函数非凸、是不是供给函数允许了非线性形状。多数情况下把模型收紧线性化、加凸性假定比在求解器里调参数有效得多。从那以后我每次跑完寡头模型都会强制走一遍这三步验证哪怕解析解已经手推过——因为改参数的时候最先坏掉的往往不是求解器而是我自己对模型的假设。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
语音识别与自然语言理解的融合技术与应用 1. 语音处理与语言理解的融合现状去年我在开发一个智能客服系统时,遇到了一个典型问题:系统能准确识别用户说的每个字,却经常误解用户的真实意图。比如用户说"这个怎么用不了",系统机械地回答"请检查网络连接"… · 2026/11/3 4:22:47
自动驾驶传感器仿真建模:从噪声原理到工程实践 1. 传感器仿真建模的核心挑战在自动驾驶和机器人系统的开发过程中,传感器仿真是验证算法可靠性的关键环节。不同于理想化的数字仿真,真实的传感器数据总是伴随着各种物理缺陷和噪声干扰。以摄像头、激光雷达和毫米波雷达这三种主流传感器为例,… · 2026/11/3 4:22:47
EN 55022 EMC测试:从限值表到传导辐射测量链路 简介:EN 55022 2006A1-2007 是面向信息技术设备电磁兼容设计、预测试与检测认证人员的欧洲协调标准,围绕ITE设备的无线电干扰特性,规定传导骚扰与辐射骚扰在不同频率范围的限值、测量方法与合规判定思路,适用于计算机、打印机、服… · 2026/11/3 4:22:47
C++冒泡排序原理、优化与实战应用 1. 冒泡排序的基本原理与实现冒泡排序是计算机科学中最基础的排序算法之一,也是C初学者必须掌握的经典算法。它的核心思想就像水中的气泡一样,较小的元素会逐渐"浮"到数组的顶端(前端),而较大的元素会"… · 2026/11/3 4:55:53
城市生命线工程智慧化转型:物联网与数字孪生技术实践 1. 城市生命线工程的智慧化转型城市生命线工程就像人体的血管和神经系统,维系着现代都市的正常运转。从供水管网到燃气管线,从电力网络到交通枢纽,这些基础设施构成了城市运行的"生命线"。传统管理模式往往面临数据孤岛、响应滞后、… · 2026/11/3 4:55:53
Element Plus el-upload二次失效原因与四套生产级解决方案 1. 问题本质:不是组件“坏了”,而是状态管理被悄悄劫持了“element-plus:el-upload上传文件只能一次,第二次失效”——这个标题在Element Plus使用者的日常中出现频率极高,几乎成了前端开发群里的“暗号”。它背后根本… · 2026/11/3 4:55:53
Element Plus el-upload二次上传失效原因与解决方案 1. 问题本质与真实场景还原“element-plus:el-upload上传文件只能一次,第二次失效”——这个标题不是一句模糊抱怨,而是大量前端开发者在真实业务中反复踩坑后提炼出的精准症状。它背后往往对应着一个正在上线的内部管理系统、一个需要频繁提… · 2026/11/3 4:55:53
Grok 4.7 接入全攻略:Build、Cursor 与 API 的避坑指南 最近我身边陆续有人开始聊 Grok 4.7。有人问的是 Cursor 里能不能直接用,有人问的是 Grok Build 官网上那个聊天页面和 API 返回的结果是不是同一个模型,还有人直接甩了一张unexpected status 401 unauthorized: incorrect api key provided的报错截图过… · 2026/11/3 4:55:53
企业大额资金周转的ACS转账解决方案 1. 企业大额资金周转的痛点与解决方案在企业的日常经营中,大额资金周转一直是财务管理的核心难题。我接触过不少企业客户,他们经常面临这样的困境:一方面需要确保资金流动性,随时应对供应商付款、员工薪资发放等刚性支出ÿ… · 2026/11/3 4:54:52
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18