How can I access the previous step in a Mesa model in Python?

112 Views Asked by At

I have a Mesa model which represents the Prisoners dilemma. I want the agents to make a decision about their own move based on the moves of their neighbors in the previous step.

But I can't figure out how to access the moves of the neighbors in the previous step. I tried something with self.model.schedule.time, but I can't figure out how to use that properly. This is the code for the agent model i have right now:

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 = []


    def step(self):
        """Get the best neighbor's move, and change own move accordingly
        if better than own score."""

        neighbors = self.model.grid.get_neighbors(self.pos, True, include_center=True)
        
        best_neighbors = []
        if self.model.schedule.time == 0:
            self.memory.append(self.move)
            self.score += self.increment_score()
            return
        if self.model.schedule.time >= 1:
            for neighbor in neighbors:
                if neighbor.memory[self.model.schedule.time-1] == "C":
                    best_neighbors.append(neighbor)
        if not best_neighbors:
            self.move = self.move
                
              
    
        best_neighbor = max(best_neighbors, key=lambda a: a.score)            
        
        if best_neighbor.score == self.score:  # if not higher than own score, stick to agents' own move
            self.move = self.move
        else:
            self.move = best_neighbor.move


    def increment_score(self):
        neighbors = self.model.grid.get_neighbors(self.pos, True)
        moves = [neighbor.move for neighbor in neighbors]
        return sum(self.model.payoff[(self.move, move)] for move in moves)     # payoff is defined in the Model class

The error that occurs is: "max() arg is an empty sequence". I believe this means, that the best_neighbors list is empty, which tells me that no neighbors are being added to the list. I want all the cooperating neighbors (so not the defecting ones) to be put into a list, so the agent can base his own move on only the cooperating neighbors and ignore the defecting neighbors.

1

There are 1 best solutions below

0
diviquery On

I am not completely sure what the Mesa model is, I can figure out that the best_neighbors list would be empty if at time 0, the move is not C.

Basically, the problem is in this if condition:

if neighbor.memory[self.model.schedule.time-1] == "C":

If the move appended to self.memory at self.model.schedule.time is not "C", then the best_neighbors list will be empty.

You should handle this corner case as well - what gets appended if the first move is not C.