Grid Agent

 Grid Agent

Grid Agent is the default agent component in grid topology simulations constructed by RepastPy. It acts as template from which agents in the simulation are constructed. Grid Agent contains has the ability to work with grid topologies, such as finding neighbors and so on. It also has methods for playing cooperation type games with other Grid Agents. There are all explained in more detail below.

Parent Component

Grid Model. Grid Agent must be added only to a Grid Model.

Properties

Properties are the items that appear in the property pane when you click on a component in the project tree. For more information of properties, see here.

Name     Description
Actions See the section on Actions and editing them if you are unfamiliar with Actions. The Actions property is where you specify the behavior of your agent.

Grid Agent defines one action by default.

  • step. The step action is where you define the behavior of your agents. Of course, you can have your step action call other actions, but the step action of every agent created from your agent component is by default executed every iteration of your simluation.
Group Name The name of the Default Group into which all the agents created from this Agent Component will be put. This group becomes an implicit field in the model. See the section on Agent Groups in the model documentation.
Initial Location This property determines the initial location of every agent of the type created by this agent component. The initial location can be:
  • Random The agents are placed by RepastPy at random locations on the grid.

  • Manual You are responsible for placing the agents at some location on the grid. You would typically do this in your model's initAgents action with something like:

    for agent as Agent in self.agents:
      agent.setX(x)
      agent.setY(y)

    where x and y are some valid coordinates that are different for each agent.

Name The name of the agent. This property is used internally by RepastPy and must not contain any spaces or quote characters. The name of the agent will be used in any errors associated with the agent's code. You can use this to name your agent's type to something more descriptive of its function. For example, if the agent's are neighbors playing a cooperation-type game, then you set the name property to Neighbor.
Number of Agents The initial number of agents created in this model. That number of agents will be created and placed in the DefaultGroup named by the group name property. If you have selected an initiali location of Random then the agents will be placed randomly in the space.
Fields See the the Fields section of the help docs for information on creating and editing parameters. Here you can define any parameters you want your agent to have.
Schedule See the schedule help and tutorial 3 for more information on the schedule property. The schedule property defines the execution schedule for any actions defined in your agent. By default the step action is scheduled to execute every tick.
Type Grid Agent can be of two types.

  1. Plain. The plain type grid agent contains methods for working with grid topologies, finding neighbors and so on. See the Java Parent Class and Usage section below for more information.

  2. Game. The game type agent contains methods for working with grid topologies, finding neighbors and playing cooperation type games with other game agents. See the Java Parent Class and Usage section below for more information.



Implicit Fields

Fields are variables that the component exposes for your use in code. For example, if there is a field named agentList, you can refer to that field with self.agentList in your NQPy code.

Name     Description
Color The color of the agent when displayed. The field type is Color (a java class).

self.color = Color.GREEN

Model Every agent has a reference to the model with which it is associated. You can use this in your own code as self.model.
Shape The shape of the agent when displayed. The shape can either be a RECT or a CIRCLE. For example,

self.shape = self.CIRCLE
self.shape = self.RECT

Space The space field variable is an Object2DGrid (a Repast java class) that represents the grid or torus topology. You can reference this from within your NQPy code with self.space. The Object2DGrid has a variety of methods which are explained in the RePast API documentation. Grid Agent itself has a variety of methods for dealing with the grid, and so working with with the space field directly is often not necessary. However, for convenience, the most important space methods are described below.

getMooreNeighbors( int x , int y , boolean ) : Vector - a vector of objects (and possibly nulls) ordered by row starting with the "NW corner" and ending with the "SE corner."
Gets the Moore neighbors of the object at x, y. Objects are returned by row starting with the "NW corner" and ending with the "SE corner." The Object at x, y is not returned.

getMooreNeighbors( int x , int y , int xExtent , int yExtent , boolean ) : Vector - a vector of objects (and possibly nulls) ordered by row starting with the "NW corner" and ending with the "SE corner."
Gets the extended Moore neighbors of the object at x, y. The extension in the x and y direction are specified by xExtent and yExtent. Objects are returned by row starting with the "NW corner" and ending with the "SE corner." The Object at x,y is not returned.

getObjectAt( int x , int y ) : Object
Gets the object at (x,y)

getSizeX( ) : int
Gets the size of the x dimension.

getSizeY( ) : int
Gets the size of the y dimension.

getValueAt( int x , int y ) : double
Gets the double value at (x,y) if possible

getVonNeumannNeighbors( int x , int y , boolean ) : Vector - a vector of objects (and possibly nulls) in west, east, north, south order
Gets the von Neumann neighbors of the object at x, y. Objects are returned in west, east, north, south order. The object at x, y is not returned.

getVonNeumannNeighbors( int x , int y , int xExtent , int yExtent , boolean ) : Vector - a vector of objects (and possibly nulls) in west, east, north, south order with the most distant object first.
Gets the extended von Neumann neighbors of the object at x, y. The extension in the x and y direction are specified by xExtent and yExtent. Objects are return in west, east, north, south order.The most distant objects are returned first, that is, all the objects to the west starting with the most distant, then those to the east and so on. The Object at x,y is not returned.

putObjectAt( int x , int y , Object ) :
Puts the specified object at (x,y)

putValueAt( int x , int y , double ) :
Puts the specified double at (x,y)



Java Parent Class

Many of the RepastPy components are based on Java code. What this means is that these components come with built-in fields and methods inherited from their Java parent classes. The docs below describe these built in fields and methods.

Grid Agents of the plain type are built upon the Java class DefaultGridAgent which contains method for moving around the grid topology, getting neighbors and so on. Grid Agents of the game type are also built on DefaultGridAgent and on GridGameAgent which provides methods for playing cooperation type games.

The methods or actions of a Java parent class can be used just as if they were actions in your own grid agent. For example, self.moveIfEmpty(x, y) and so on. The list of methods below is divided into two sections. The first deals with methods common to both types of grid agents -- plain and game --, and the second with methods only for games type grid agents. The format used below is

method name(argument types, if any) : return type - an optional explanation of the return type
description

where the return type is a Java class type.

Java Parent Class Methods (Actions)
getMooreNeighbors( ) : List
Returns a List of the agents that are the Moore neighbors of this grid agent. The Moore neighborhood is constituted by the 8 grid agents in the cells surrounding this grid agent. The neighbors are returned by row starting with the "NW corner" and ending with the "SE corner."

getMooreNeighbors( int extent ) : List
Returns a List of the agents that are the extended Moore neighbors of this grid agent. The extent of the neighborhood is specified by the extent parameters. For example, a Moore neighborhood of extent 1 contains the 8 grid agents in the cells surrounding this grid agent. A neighborhood of extent 2 contains the 24 grid agents in the cells surrournding this one. The neighbors are returned by row starting with the "NW corner" and ending with the "SE corner."

getVonNeumannNeighbors( ) : List
Returns a List of the agents that are the VonNeumann neighbors of this grid agent. The VonNeumann neighborhood is constituted by the 4 grid agents in the north, south, east and west cells surrounding this grid agent. The grid agents are returned in west, east, north, south order.

getVonNeumannNeighbors( int extent ) : List
Returns the List of the agents that are the extended VonNeumann neighbors of this grid agent. The extent of the neighborhood is specified by the extent parameter. For example, a VonNeumann neighborhood of extent 1 is constituted by The VonNeumann neighborhood is constituted by the 4 grid agents in the north, south, east and west cells surrounding this grid agent. A neighborhood of extent 2 is constituted by 8 grid agents (the four making up the 1 extent neighborhood and those one step beyond.) The grid agents are returned in west, east, north, south order with the further being returned first. That is, all the agents to the west are returned first beginning with the most distant, then those to the east and so on.

getX( ) : int
Gets the x coordinate of this grid agent. The x coordinate is position of this grid agent on the grid space along the x axis.

getY( ) : int
Gets the y coordinate of this grid agent. The y coordinate is position of this grid agent on the grid space along the y axis.

move( int newX , int newY ) :
Moves this grid agent to the specified newX, newY coordinates on the grid space. Note that this does not check if the cell specified by these coordinates is empty. If it is not, the grid agent in that cell is removed from that cell and this one is added.

moveIfEmpty( int newX , int newY ) : boolean
Moves this grid agent to the new coordinates, if the cell at those coordinates is empty. Returns true if this grid gant has successfully moved and false if not.

setColor( Color ) :
Sets the color of this grid agent.

setDrawAsCircle( ) :
Sets this grid agent to be displayed as a circle.

setDrawAsRect( ) :
Sets this grid agent to be displayed as a circle.


  Game Type Grid Agent Methods

Grid agent's game related methods make heavy use of three other java classes. These are GameChoice, PayoffMatrix and Strategy.

  1. GameChoice. GameChoice merely represents the player's (the grid agent's) possible choices in the game. The two options are GameChoice.COOPERATE and GameChoice.DEFECT. For example,


    self.calculateNextMove(GameChoice.DEFECT)


    will calculate this grid agent's next move when the opponents last move was defect.


    self.getLastMove()


    will return this grid agent's last move, either GameChoice.COOPERATE or GameChoice.DEFECT.

  2. PayoffMatrix. PayoffMatrix represents the typical cooperation game type payoff matrix. For example,


    matrix = PayoffMatrix(2, 2)
    matrix.setPayoff(0, 0, 3, 3)
    matrix.setPayoff(0, 1, 0, 5)
    matrix.setPayoff(1, 0, 5, 0)
    matrix.setPayoff(1, 1, 1, 1)

    defines a 2x2 payoff matrix, and set the payoffs for each player in each row and column of the matrix. In the above, the matrix cell 0, 1 contains a payoff of 0 for the row player and 5 for the column player.

  3. Strategy. Strategy represents the decision strategy used by the game agent to determine whether that agent will cooperate or defect. RepastPy comes with four pre-defined strategies AlwaysCooperate, AlwaysDefect, TitForTat and AntiTitForTat.
See the Usage section below for more information how to use these together with a game agent to actually play cooperation type games.

calcNextMove( GameChoice opponentLastMove ) :
Calculates this grid agent's next move (GameChoice.COOPERATE or GameChoice.DEFECT) using the game agent's current strategy and the opponents last move (the GameChoice method argument).

getAvgPayoff( ) : double
Returns the current payoff total for this game agent divided by the number of times this GridGameAgent has played. If this game agent has not played at all then this returns Double.NEGATIVE_INFINITY such that not playing at all is equivalent to achieving the worst possible payoff.

getLastMove( ) : GameChoice
Returns the last move (GameChoice.COOPERATE or GameChoice.DEFECT) played by this game agent.

getMatrix( ) : PayoffMatrix
Returns the PayoffMatrix used by this game agent.

getPayoff( ) : double
Returns the current payoff accumulated by this grid agent between calls to self.initialize().

getStrategy( ) : Strategy
Returns the current strategy used by this grid agent.

initialize( )
Initialize this grid agent for a round play by setting its payoff and current number of plays to 0.

play( GridGameAgent ) :
Plays the other agent by getting the results from the payoff matrix given the two players current strategies. This game agent is the row player. If we want to update the payoff of the other agent that game agent needs to play as well. This also remembers the other players last move.

setMatrix( PayoffMatrix ) :
Sets the payoff matrix used by this game agent.

setPayoff( double ) :
Sets the current payoff for this agent.

setStrategy( Strategy ) :
Sets the strategy for this game agent.


Usage

The usage of a plain grid agent is fairly straightforward. For example,

neighbors = self.getVonNeumannNeighbors()

for neigh as MyAgent in neighbors:
  if (neigh.getZoneType() != self.getZoneType()):
    newX = Random.uniform.nextIntFromTo(0, self.space.getSizeX() - 1)
    newY = Random.uniform.nextIntFromTo(0, self.space.getSizeY() - 1)
    moved = self.moveIfEmpty(newX, newY)

This code fragment gets a list of neighbors and illustrates how to iterate through that list. If a neighbor is not of this grid agent's (self's) zone type then this grid agent attempts to move to some random location on the space. Note that this assume you have created the ZoneType field.

The schelling segregation (schelling.sbp) example SimBuilder project is a good example of using plain grid agents. It can be found in the samples directory.

Working with grid agents of the game type is more complicated. In this case, some setup is required. This setup entails creating a payoff matrix and assigning each agent a strategy. At that point, the agents can begin to play each other. Setup is done in your model's initAgents action and would typically look something like:

...
matrix = PayoffMatrix(2, 2)
matrix.setPayoff(0, 0, 3, 3)
matrix.setPayoff(0, 1, 0, 5)
matrix.setPayoff(1, 0, 5, 0)
matrix.setPayoff(1, 1, 1, 1)

for agent as Player in self.agentList:
  agent.setStrategy(AlwaysCooperate.getInstance())
  agent.setMatrix(matrix)

(The elipses here is meant to indicate the elided presence of other model setup code.) Here, we first create our payoff matrix, then we iterate through the list of agents associated with this model and assign each one a strategy and the payoff matrix. In this case, for purposes of illustration, each agent is assigned the AlwaysCooperate strategy. As mentioned above, SimBuilder comes with four predefined strategies. They are each created and assigned in the same way:

agent.setStrategy(AlwaysCooperate.getInstance())
agent.setStrategy(AlwaysDefect.getInstance())
agent.setStrategy(TitForTat.getInstance())
agent.setStrategy(AntiTitForTat.getInstance())

Once setup has been completed, having the agents play each other is fairly simple. For example,

self.neighbors = self.getVonNeumannNeighbors()
for neighbor as Player in self.neighbors:
  self.calcNextMove(neighbor.getLastMove())
  neighbor.calcNextMove(self.lastMove)

  self.play(neighbor)
  neighbor.play(self)

This code would typically appear in the agent's step action. The important pieces here are having the game agent represented by self calculate its next move based on its opponents last move, and then for the opponent to caculate its next move based on self's last move. The agents then play each other via self.play and neighbor.play. The agents themselves will keep track of their cumulative payoff total as well as their last move. In the above example, the self grid agent plays each of its Von Neumann neighbors.

Lastly, the prisonners dilemma (prionners_dilemma.sbp) example RepastPy project is a good example of using game type grid agents. It can be found in the projects directory.