You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python的Mesa囚徒困境模型中获取邻居上一步行动?

问题分析与修复方案

核心问题

  1. 空列表触发max()报错:当所有邻居(含自身)上一步行动都是D时,best_neighbors为空,直接调用max()会抛出max() arg is an empty sequence错误。
  2. Memory记录不完整:仅在时间步0时记录行动,后续时间步未更新memory,导致后续时间步无法正确获取邻居上一步的行动(甚至触发索引越界)。
  3. 邻居范围可选调整:原代码获取邻居时包含自身(include_center=True),若你希望仅参考其他智能体,需修改该参数。

修复后的完整代码

class PDAgent(Agent):
    
    def __init__(self, pos, model, starting_move=None):
        """
        Create a new Prisoner's Dilemma agent.
            pos: (x, y) tuple of the agent's position.
            model: model
            move: C(cooperating) or D(defecting)
            score: score of the agent
        """
        super().__init__(pos, model)
        self.pos = pos
        self.score = 0
        if starting_move:
            self.move = starting_move
        else:
            self.move = self.random.choice(["C", "D"])
        self.memory = []
        # 初始化时记录初始行动(对应时间步0)
        self.memory.append(self.move)


    def step(self):
        """Get the best neighbor's move, and change own move accordingly
        if better than own score."""
        # 获取邻居:若不需要包含自己,将include_center改为False
        neighbors = self.model.grid.get_neighbors(self.pos, True, include_center=True)
        
        best_neighbors = []
        current_time = self.model.schedule.time
        
        # 时间步0:仅计算初始得分,不调整行动
        if current_time == 0:
            self.score += self.increment_score()
            return
        
        # 时间步>=1:收集上一步行动为C的邻居
        if current_time >= 1:
            # 先检查邻居的memory是否有对应时间步的记录,防止索引越界
            for neighbor in neighbors:
                if len(neighbor.memory) > current_time - 1:
                    if neighbor.memory[current_time - 1] == "C":
                        best_neighbors.append(neighbor)
        
        # 没有符合条件的邻居,直接保持当前行动
        if not best_neighbors:
            return
        
        # 找到得分最高的合作型邻居
        best_neighbor = max(best_neighbors, key=lambda a: a.score)            
        
        # 仅当邻居得分更高时,切换行动
        if best_neighbor.score > self.score:
            self.move = best_neighbor.move


    def increment_score(self):
        neighbors = self.model.grid.get_neighbors(self.pos, True)
        # 基于上一轮的行动计算得分(符合囚徒困境常规规则,可按需调整)
        moves = [neighbor.memory[-1] for neighbor in neighbors]
        return sum(self.model.payoff[(self.memory[-1], move)] for move in moves)    
    
    def advance(self):
        """每个时间步结束后,记录当前行动到memory,供下一轮参考"""
        self.memory.append(self.move)

关键修改说明

  1. 完善Memory记录:初始化时就把初始行动存入memory,新增advance()方法(Mesa框架中,step()算决策,advance()更新状态),确保每个时间步后都记录当前行动,后续能正确获取上一步的行动数据。
  2. 提前处理空列表:在调用max()前先判断best_neighbors是否为空,为空则直接返回,避免报错。
  3. 索引安全检查:增加len(neighbor.memory) > current_time -1的判断,防止因个别智能体的memory未更新导致索引越界。
  4. 得分逻辑修正:把原代码中基于当前move计算得分,改为基于上一轮行动(memory[-1]),符合囚徒困境的常规规则。
  5. 简化冗余逻辑:删除无意义的self.move = self.move语句,直接用return保持行动即可。

内容的提问来源于stack exchange,提问作者Emmina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:07:08