Agent-Based Evolutionary Game Dynamics: Luis R. Izquierdo, Segismundo S. Izquierdo, & William H. Sandholm
Agent-Based Evolutionary Game Dynamics: Luis R. Izquierdo, Segismundo S. Izquierdo, & William H. Sandholm
EVOLUTIONARY GAME
DYNAMICS
The LibreTexts mission is to unite students, faculty and scholars in a cooperative effort to develop an easy-to-use online platform
for the construction, customization, and dissemination of OER content to reduce the burdens of unreasonable textbook costs to our
students and society. The LibreTexts project is a multi-institutional collaborative venture to develop the next generation of open-
access texts to improve postsecondary education at all levels of higher learning by developing an Open Access Resource
environment. The project currently consists of 14 independently operating and interconnected libraries that are constantly being
optimized by students, faculty, and outside experts to supplant conventional paper-based books. These free textbook alternatives are
organized within a central environment that is both vertically (from advance to basic level) and horizontally (across different fields)
integrated.
The LibreTexts libraries are Powered by NICE CXOne and are supported by the Department of Education Open Textbook Pilot
Project, the UC Davis Office of the Provost, the UC Davis Library, the California State University Affordable Learning Solutions
Program, and Merlot. This material is based upon work supported by the National Science Foundation under Grant No. 1246120,
1525057, and 1413739.
Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not
necessarily reflect the views of the National Science Foundation nor the US Department of Education.
Have questions or comments? For information about adoptions or adaptions contact [email protected]. More information on our
activities can be found via Facebook (https://facebook.com/Libretexts), Twitter (https://twitter.com/libretexts), or our blog
(http://Blog.Libretexts.org).
This text was compiled on 02/01/2024
TABLE OF CONTENTS
Licensing
1: Introduction
1.1: Introduction to evolutionary game theory
1.2: Introduction to agent-based modeling
1.3: Introduction to NetLogo
1.4: The fundamentals of NetLogo
Index
Detailed Licensing
1 https://math.libretexts.org/@go/page/123820
Licensing
A detailed breakdown of this resource's licensing can be found in Back Matter/Detailed Licensing.
1 https://math.libretexts.org/@go/page/123836
CHAPTER OVERVIEW
1: Introduction
1.1: Introduction to evolutionary game theory
1.2: Introduction to agent-based modeling
1.3: Introduction to NetLogo
1.4: The fundamentals of NetLogo
This page titled 1: Introduction is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo, Segismundo
S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts
platform; a detailed edit history is available upon request.
1
1.1: Introduction to evolutionary game theory
Evolutionary Game Theory (EGT) is a branch of a more general discipline called game theory. Therefore, to understand what EGT
is about, we believe it is useful to get familiar with the basic ideas underlying game theory first.
Figure 1. Payoff matrix of a 2-player 2-strategy game. For each possible combination of pure strategies there is a corresponding
pair of numbers (x , y) in the matrix whose first element x represents the payoff for player 1, and whose second element y represents
the payoff for player 2.
Note that the payoff matrix shown in Fig. 1 could well be used for the three examples outlined above, assuming that there is one
side of the road, one text messaging app, and one restaurant in town that is preferred, if only slightly. To be sure, let us model the
example about choosing a restaurant as a game, identifying each of its elements:
The players would be you and your partner.
Each of you may choose restaurant A or restaurant B.
Neither of you have any information about the other’s choice at the time of making your decision.
Both of you prefer eating together rather than being alone, no matter where, and you both prefer restaurant B over restaurant A.
Thus, the best possible outcome for both would be to meet at restaurant B; second best would be meeting at restaurant A; and
any lack of coordination would be equally awful.[2]
The three examples above are very different in many aspects, but they all could be modeled using the same game. This is so
because games are abstractions that are meant to capture the bare essentials of the original social interaction and, at least to some
extent, the three examples above share the same strategic backbone.
Having seen this, it may not come as a surprise that the sort of issues for which game theory can be useful is impressively broad
and diverse, including applications in international relations, resource management, network routing (of vehicles or information
packages), voting systems, linguistics, law, distributed control, evolutionary biology, design of incentive systems, and business and
environmental regulations.
1.1.1 https://math.libretexts.org/@go/page/123821
2. Traditional game theory
Game theory has nowadays various branches. Historically, the first branch to be developed was Traditional Game Theory (TGT)
(von Neumann and Morgenstern (1944), Nash (1950), Selten (1965, 1975), Harsanyi (1967, 1968a, 1968b)). TGT is also the
branch where most of the work has been focused, and the one with the largest representation in most game theory textbooks and
academic courses.[3]
In TGT, payoffs reflect preferences and players are assumed to be rational, meaning that they act as if they have consistent
preferences and unlimited computational capacity to achieve their well-defined objectives. The aim of the discipline is to study
how these instrumentally rational players would behave in order to obtain the maximum possible payoff in the formal game.
A key problem in TGT is that, in general, assuming rational behavior for any one player rules out very few actions –and
consequently very few outcomes– in the absence of strong assumptions about what players know about others’ rationality,
knowledge and actions. Hence, in order to derive specific predictions about how rational players would behave, it is often
necessary to make very stringent assumptions about everyone’s beliefs and their reciprocal consistency. If one assumes common
knowledge of rationality and consistency of beliefs, then the outcome of the game is a Nash equilibrium, which is a set of
strategies, one for each player, such that no player, knowing the other players’ strategies in that set, could improve her expected
payoff by unilaterally changing her own strategy (see Samuelson (1997, pp. 10-12) and Holt and Roth (2004) for several
interpretations). An equivalent definition is the following: A Nash equilibrium is a strategy profile (i.e. one strategy for each player
in the game) where every player is best responding to the strategies of the others.
Oftentimes, games have several Nash equilibria. As an example, the game depicted in Fig. 1 has three different Nash equilibria: the
two strategy profiles where both players choose the same action (i.e. {A, A} and {B, B}), and a third equilibrium in mixed
strategies, which means that players choose each action with a certain probability. In this third Nash equilibrium, both players
choose action A with probability ⅔ (and action B with probability ⅓), a strategy that we denote (⅔, ⅓).
The equilibrium in mixed strategies is unsatisfactory for a number of reasons. First, since both actions can be chosen with strictly
positive probability by each player, any observation of the actions actually taken by the two players would be consistent with this
Nash equilibrium. Therefore, this equilibrium cannot be falsified by observing the outcome of the game. Another disappointing
property of the Nash equilibrium in mixed strategies is the low payoff that players are expected to receive when they play it. In that
equilibrium, outcome {B, B} would occur with probability ⅓ × ⅓, outcome {A, A} would occur with probability ⅔ × ⅔, and
players would not coordinate with probability 2 × ⅓ × ⅔ , yielding a total expected payoff of ⅔ for each of them. Thus, this
equilibrium is worse than any of the other two Nash equilibria for both players. Finally, the mixed-strategy equilibrium does not
seem to be very robust. Imagine that one of the players deviates from this equilibrium only slightly, by choosing action B with a
probability marginally greater than ⅓. Then the other player’s best response would be to choose action B with probability 1, and
the deviator’s best response to that reaction would be to play B with probability 1, too. Thus, this mixed-strategy equilibrium does
not seem to be very stable.[4]
One could think that this diversity of equilibria, and the existence of the mixed-strategy equilibrium, may be partly an artifact of the
fact that the game is played just once. It seems intuitive to think that if the game was played repeatedly, rational individuals would
manage to coordinate in the (unique) Pareto optimal[5] outcome {B, B}, and the other suboptimal outcomes would not be observed
in any Nash equilibrium. However, that natural intuition turns out to be wrong. To understand this, let us briefly review how
repeated games are modeled in TGT.
In a repeated game, a certain basic game (called stage game) is played a number of rounds; the payoff obtained by each player in
the repeated game is the sum of the (potentially discounted) payoffs obtained in each of the rounds. At any round, all the actions
chosen by each of the players in previous rounds are known by everyone. A strategy in this repeated game is a complete plan of
action for every possible contingency that may occur. For instance, in our coordination game, a possible strategy for the 3-round
repeated game would be:
At initial round t = 1, play B.
At round t > 1, play B if the other player chose B at time t – 1. Otherwise play A.
Importantly, note that, even though the game is played repeatedly, the interaction only occurs once, since the strategies of the
individuals dictate what to do in every possible history of the long game. Players could send their strategies by mail, and robots
could implement them.
So, does repetition lead to sharper predictions about how rational players may interact? Not at all, rather the opposite. It turns out
that when a game is repeated, the number of Nash equilibria generally multiplies, and there is a wide range of possible outcomes
1.1.2 https://math.libretexts.org/@go/page/123821
that can be supported by them. As an example, in our coordination game, any sequence formed by combining the three Nash
equilibria of the stage game is a Nash equilibrium of the repeated game, and there are many more.[6]
The approach followed to model repeated interactions in Evolutionary Game Theory is rather different, as we explain below.
As many more individuals of each species are born than can possibly survive; and as,
consequently, there is a frequently recurring struggle for existence, it follows that any
being, if it vary however slightly in any manner profitable to itself, under the complex and
sometimes varying conditions of life, will have a better chance of surviving, and thus be
naturally selected. From the strong principle of inheritance, any selected variety will
tend to propagate its new and modified form. Darwin (1859, p. 5)
The essence of this simple and groundbreaking idea could be algorithmically summarized as follows:
IF:
More offspring are produced than can survive and reproduce, and
variation within populations:
affects the fitness (i.e. the expected reproductive contribution to future generations) of individuals, and
is heritable,
1.1.3 https://math.libretexts.org/@go/page/123821
THEN:
evolution by natural selection occurs.
The key insight that game theory contributed to evolutionary biology is that, once the strategy distribution changes as a result of the
evolutionary process, the relative fitness of the remaining strategies may also change, so previously unsuccessful strategies may
turn out to be successful in the new environment, and thus increase their prevalence. In other words, the fitness landscape is not
static, but it also evolves as the distribution of strategies changes.
An important concept developed in this research programme was the notion of Evolutionarily Stable Strategy (ESS), put forward
by Maynard Smith and Price (1973) for 2-player symmetric games played by individuals belonging to the same population.
Informally, a strategy I (for Incumbent) is an ESS if and only if, when adopted by all members of a population, it enjoys a uniform
invasion barrier in the sense that any other strategy M (for Mutant) that could enter the population (in sufficiently low proportion)
would obtain a strictly lower expected payoff in the postentry population than the incumbent strategy I. The ESS concept is a
refinement of (symmetric) Nash equilibrium.
As an example, in the coordination game depicted in Fig. 1 both pure strategies are ESSs, but the mixed strategy (⅔ , ⅓),
corresponding to the symmetric Nash equilibrium in mixed strategies, is not an ESS. The intuition for this is clear: a population
where every agent is playing strategy I = (⅔ , ⅓) would be invadable by e.g. a small fraction of mutants playing action B (i.e.
strategy (0,1)). This is so because the mutants would obtain the same payoff against the incumbents as the incumbents among
themselves (i.e. ⅔ on average), but a strictly greater payoff whenever they met other mutants (i.e. 2 for certain). Thus, natural
selection would gradually favor the mutants over the incumbents.[7]
The basic ideas behind EGT –i.e. that strategies with greater payoffs tend to spread more, and that fitness is frequency-dependent–
soon transcended the borders of biology and started to permeate many other disciplines. In economic contexts, it was understood
that natural selection would derive from competition among entities for scarce resources or market shares. In other social contexts,
evolution was often understood as cultural evolution, and it referred to dynamic changes in behavior or ideas over time (Nelson
and Winter (1982), Boyd and Richerson (1985)).
3.2. An interpretation of evolutionary game theory where strategies are explicitly selected by
individuals
Evolutionary ideas proved very useful to understand several phenomena in many disciplines, but –at the same time– it became
increasingly clear that a direct application of the principles of Darwinian natural selection was not always appropriate for the study
of (non-Darwinian) social evolution.[8] In many contexts, it seems more natural to assume that players are capable of adapting their
behavior within their lifetime, occasionally revising their strategy in a way that tends to favor strategies leading to higher payoffs
over strategies leading to lower payoffs. The key distinction is that, in this latter interpretation, strategies are selected at the
individual level (rather than at the population level). Also, in this view of selection taking place at the individual level, payoffs do
not have to represent Darwinian fitness anymore, but can perfectly well represent a preference ordering, and interpersonal
comparisons of payoffs may not be needed. Following this interpretation, the algorithmic view of the process by which strategies
with greater payoffs gradually displace strategies with lower payoffs would look as follows:
IF:
Players using different strategies obtain different payoffs, and
they occasionally revise their strategies (by e.g. imitation or direct reasoning over gathered information), preferentially
switching to strategies that provide greater payoffs,
THEN:
the frequency of strategies with greater payoffs will tend to increase (and this change in strategy frequencies may alter the
future relative success of strategies).
In this interpretation, the canonical evolutionary model typically comprises the following elements:
A population of agents,
a game that is recurrently played by the agents,
a procedure by which revision opportunities are assigned to agents, and
a revision protocol, which dictates how individual agents choose their strategy when they are given the opportunity to revise.
1.1.4 https://math.libretexts.org/@go/page/123821
Note that this approach to EGT can formally encompass the biological interpretation, since one can always interpret the revision of
a strategy as a death and birth event, rather than as a conscious decision. Having said that, it is clear that different interpretations
may seem more natural in different contexts. The important point is that the framework behind the two interpretations is the same.
To conclude this section, let us revisit our coordination example (with payoff matrix shown in Fig. 1) in a population context. We
will analyze two revision protocols that lead to different results: imitative pairwise-difference protocol and best experienced payoff
protocol.
Under the imitative pairwise-difference protocol (Helbing (1992), Hofbauer (1995), Schlag (1998)), a revising agent looks at
another individual at random and imitates her strategy only if that strategy yields a higher expected payoff than his current
strategy; in this case he switches with probability proportional to the payoff difference. It can be proved that the dynamics of
this protocol in large populations will tend to approach the state where every agent plays action B if the initial proportion of B-
players is greater than ⅓, and will tend to approach the state where every agent plays action A if the initial proportion of B-
players is less than ⅓ (Fig. 2).[9]
0:00
Simulation runs of the imitative pairwise-difference protocol in coordination game [[1 0][0 2]]
Under the best experienced payoff protocol (Osborne and Rubinstein (1998), Sethi (2000, 2019), Sandholm et al. (2019, 2020)),
a revising agent tests each of the two strategies against a random agent, with each play of each strategy being against a newly
drawn opponent. The revising agent then selects the strategy that obtained the greater payoff in the test, with ties resolved at
random. It can be proved that the dynamics of this protocol in large populations will tend to approach the state where every
agent plays action B from any initial condition (other than the state where everyone plays A; see Fig. 3).[11]
0:00
1.1.5 https://math.libretexts.org/@go/page/123821
Simulation runs of the best experienced payoff protocol in coordination game [[1 0][0 2]]
The example above shows that different protocols can lead to very different dynamics in non-trivial ways. Both protocols above
tend to favor best-performing strategies, and in both the mixed-strategy Nash equilibrium is unstable. However, given an initial
state where 80% of the population is playing strategy A, one of the protocols will almost certainly lead the population to the state
where everyone plays A, while the other protocol will lead the population to the state where everyone plays B. In this book, we will
learn a range of different concepts and techniques that will help us understand these differences.
1.1.6 https://math.libretexts.org/@go/page/123821
imitation) this link between acquired information and action is direct (e.g. in a stimulus-response fashion); in more sophisticated
learning, players use the history of the game to form expectations or beliefs about the other players’ behavior, and they then react
optimally to these inferred expectations.[13]
The interpretation of EGT which assumes that players can revise their strategy is very similar to TLG. The main differences
between these two branches are:
EGT tends to study large populations of small agents, who interact anonymously. This implies that players’ payoffs only
depend on the distribution of strategies in the population, and also that any one player’s actions have little or no effect on the
aggregate success of any strategy at the population level. In contrast, TLG is mainly concerned with the analysis of small
groups of players who repeatedly play a game among them, each of them in her particular role.
The revision protocols analyzed in EGT tend to be fairly simple and use information about the current state of the population
only. By contrast, the sort of algorithms analyzed in TLG tend to be more sophisticated, and make use of the history of the game
to decide what action to take.
1. A common misconception about game theory relates to the roots of players’ preferences. There is no assumption in game theory
that dictates that players’ preferences are formed in complete disregard of each other’s interests. On the contrary, preferences in
game theory are assumed to account for anything, i.e. they may include altruistic motivations, moral principles, and social
constraints (see e.g. Colman (1995, p. 301), Vega-Redondo (2003, p. 7), Binmore and Shaked (2010, p. 88), Binmore (2011, p.
8) or Gintis (2014, p. 7)). ↵
2. Note that there is no inconsistency in being indifferent about outcomes {A, B} and {B, A}, even if you prefer restaurant B. It is
sufficient to assume that you care about your partner as much as about yourself. ↵
3. TGT can be divided further into cooperative and non-cooperative game theory. In cooperative game theory, it is assumed that
players may negotiate binding agreements that can be externally enforced (by e.g. contract law). In non-cooperative game
theory, such agreements cannot be enforced externally, so they are relevant only to the extent that abiding by them is in each
individual's interest. ↵
4. The same logic applies if one assumes that the deviation consists in choosing action B with a probability marginally less than
⅓. In this case, the other player's best response would be to choose action A with probability 1. ↵
5. An outcome is Pareto optimal if it is impossible to make one player better off without making at least one other player worse off
↵
6. In general, any strategy profile which at every round prescribes the play of a Nash equilibrium of the stage game regardless of
history is a (subgame perfect) Nash equilibrium of the repeated game. This can be easily proved using the one-shot deviation
principle. ↵
7. Note that mutants playing action A (i.e. strategy (1,0)) would also be able to invade the incumbent population. ↵
1.1.7 https://math.libretexts.org/@go/page/123821
8. As an example, note that payoffs interpreted as Darwinian fitness are added across different players to determine the relative
frequency of different types of players (i.e. strategies) in succeeding generations. These interpersonal comparisons are inherent
to the notion of biological evolution by natural selection, and pose no problems if payoffs reflect Darwinian fitness. However, if
evolution is interpreted in cultural terms, presuming the ability to conduct interpersonal comparisons of payoffs across players
may be controversial. In this link, you can watch a video that shows how unconvinced John Maynard Smith was by direct
applications of the principles of Darwinian natural selection in Economics. ↵
9. To prove this statement, note that the mean dynamic of this revision protocol is the well-known replicator dynamic (Taylor and
Jonker, 1978) ↵
10. See exercise 5 in section 1.0 and exercise 3 in section 1.4 ↵
11. This statement is a direct application of Proposition 5.11 in Sandholm et al. (2020) ↵
12. See exercise 6 in section 1.0 and exercise 4 in section 1.4 ↵
13. Izquierdo et al. (2012) provide a succinct overview of some of the learning models that have been studied in TLG. For a more
detailed account, see chapters 11 and 12 in Vega-Redondo (2003). ↵
This page titled 1.1: Introduction to evolutionary game theory is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by
Luis R. Izquierdo, Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and
standards of the LibreTexts platform; a detailed edit history is available upon request.
1.1.8 https://math.libretexts.org/@go/page/123821
1.2: Introduction to agent-based modeling
1. What is agent-based modeling?
Agent-based modeling (ABM) is a methodology used to build formal models of real-world systems that are made up by individual units (such as e.g. atoms, cells, animals, people or
institutions) which repeatedly interact among themselves and/or with their environment.
The essence of agent-based modeling
The defining feature of the agent-based modeling approach is that it establishes a direct and explicit correspondence
between the individual units in the target system to be modeled and the parts of the model that represent these units (i.e. the agents), and also
between the interactions of the individual units in the target system and the interactions of the corresponding agents in the model (figure 1).
This approach contrasts with e.g. equation-based modeling, where entities of the target system may be represented via average properties or via single representative agents.
Figure 1. In an agent-based model, the individual units of the real-world system to be modeled and their interactions are explicitly and individually represented in the model.
Thus, in an agent-based model, the individual units of the system and their repeated interactions are explicitly and individually represented in the model (Edmonds, 2001).[1] Beyond
this, no further assumptions are made in agent-based modeling.
At this point, you may be wondering whether game theory is part of ABM, since in game theory players are indeed explicitly and individually represented in the models.[2] The key to
answer that question is the last sentence in the box above, i.e. “Beyond this, no further assumptions are made in agent-based modeling“. There are certainly many disciplines (e.g. game
theory and cellular automata theory) that analyze models where individuals and their interactions are represented explicitly. The key distinction is that these disciplines make further
assumptions, i.e. impose additional structure on their models. These additional assumptions constrain the type of models that are analyzed and, by doing so, they often allow for more
accurate predictions and/or greater understanding within their (somewhat more limited) scope. Thus, when one encounters a model that fits perfectly into the framework of a particular
discipline (e.g. game theory), it seems more appropriate to use the more specific name of the particular discipline, and leave the term “agent-based” for those models which satisfy the
defining feature of ABM mentioned above and they do not currently fit in any more specific area of study.
The last sentence in the box also uncovers a key feature of ABM: its flexibility. In principle, you can make your agent-based model as complex as you wish. This has pros and cons.
Adding complexity to your model allows you to study any phenomenon you may be interested in, but it also makes analyzing and understanding the model harder (or even sometimes
practically impossible) using the most advanced mathematical techniques. Because of this, agent-based models are generally implemented in a programming language and explored
using computer simulation. This is so common that the terms agent-based modeling and agent-based simulation are often used interchangeably. The following is a list of some features
that traditionally have been difficult to analyze mathematically, and for which agent-based modeling can be useful (Epstein and Axtell, 1996):
Agents’ heterogeneity. Since agents are explicitly represented in the model, they can be as heterogeneous as the modeler deems appropriate.
Interdependencies between processes (e.g. demographic, economic, biological, geographical, technological) that have been traditionally studied in different disciplines, and are not
often analyzed together. There is no restriction on the type of rules that can be implemented in an agent-based model, so models can include rules that link disparate aspects of the
world that are often studied in different disciplines.
Out-of-equilibrium dynamics. Dynamics are inherent to ABM. Running a simulation consists in applying the rules that define the model over and over, so agent-based models
almost invariably include some notion of time within them. Equilibria are never imposed a priori: they may emerge as an outcome of the simulation, or they may not.
The micro-macro link. ABM is particularly well suited to study how global phenomena emerge from the interactions among individuals, and also how these emergent global
phenomena may constrain and shape back individuals’ actions.
Local interactions and the role of physical space. The fact that agents and their environment are represented explicitly in ABM makes it particularly straightforward and natural to
model local interactions (e.g. via networks).
As you can imagine, introducing any of the aspects outlined above in an agent-based model often means that the model becomes mathematically intractable, at least to some extent.
However, in this book we will learn that, in many cases, there are various aspects of agent-based models that can be analytically solved, or described using formal approximation
results. Our view is that the most useful agent-based models lie at the boundaries of theoretical understanding, and help us push these boundaries. They are advances sufficiently small
so that simplified versions of them (or certain aspects of their behaviour) can be fully understood in mathematical terms –thus retaining its analytical rigour–, but they are steps large
enough to significantly extend our understanding beyond what is achievable using the most advanced mathematical techniques available.
In my personal (albeit biased) view, the best simulations are those which just peek over the rim of theoretical understanding,
displaying mechanisms about which one can still obtain causal intuitions. Probst (1999)
2. What is an agent?
In this book we will use the term agent to refer to a distinct part of our (computational) model that is meant to represent a decision-maker. Agents could represent human beings, non-
human animals, institutions, firms, etc. The agents in our models will always play a game, so in this book we will use the term agent and the term player interchangeably.
1.2.1 https://math.libretexts.org/@go/page/123822
Agents have individually-owned variables, which describe their internal state (e.g. a strategy), and are able to conduct certain computations or tasks, i.e. they are able to run instructions
(e.g. to update their strategy). These instructions are sometimes called decision rules, or rules of behavior, and most often imply some kind of interaction with other agents or with the
environment.
The following are some of the individually-owned variables that the agents we are going to implement in this book may have:
strategy (a number)
payoff (a number)
my-coplayers (the set of agents with whom this agent plays the game)
color (the color of this agent)
And the following are examples of instructions that the agents in most of our models will be able to run:
to play (play a certain game with my-coplayers and set the payoff appropriately)
to update-strategy (revise strategy according to a certain revision protocol)
to update-color (set color according to strategy)
3. A paradigmatic example
In this section we present a model that captures the spirit of ABM. The model implements the main features of a family of models proposed by Sakoda (1949, 1971) and –
independently– by Schelling (1969, 1971, 1978).[3][4] Specifically, here we present a computer implementation put forward by Edmonds and Hales (2005).[5]
In this model there are 133 blue agents and 133 orange agents who live in a 2-dimensional grid made up of 20×20 cells (figure 2). Agents are initially located at random on the grid.
The neighborhood of a cell is defined by the eight neighboring cells (i.e. the eight cells which surround it).[6]
Figure 2. Grid of Schelling-Sakoda model (20×20), with 133 blue agents, 133 orange
agents. The agents in yellow circles have 2 out of 5 neighbors of the same color.
Agents may be happy or unhappy. An agent is happy if the proportion of other agents of its same colour in its neighbourhood is greater or equal than a certain threshold (%-similar-
wanted), which is a parameter of the model; otherwise the agent is said to be unhappy. Agents with no neighbors are assumed to be happy regardless of the value of %-similar-wanted.
In each iteration of the model one unhappy agent is randomly selected to move to a random empty cell in the lattice.
As an example, the two agents surrounded by a circle in figure 2 have 2 out of 5 neighbors of the same color as them, i.e. 40%. This means that in simulation runs where %-similar-
wanted ≤ 40% these agents would be happy, and would not move. On the other hand, in simulations where %-similar-wanted > 40% these two agents would move to a random location.
Now imagine that we simulate a society where agents require at least 60% of their neighbors to be of the same color as them in order to be happy (i.e. %-similar-wanted = 60%). These
are pretty strong segregationist preferences, so one would expect a fairly clear pattern of spatial segregation at the end. The following video shows a representative run. You may wish
to run the simulations yourself downloading this model’s code.
0:00
1.2.2 https://math.libretexts.org/@go/page/123822
What is really surprising is that even with only mild segregationist preferences, such as %-similar-wanted = 40%, we still obtain fairly segregated spatial patterns (expected avg-
%similar ≈ 82.7%). The following video shows a representative run.
0:00
0:00
1. These three videos by Bruce Edmonds and Michael Price and Uri Wilensky nicely describe what ABM is about. ↵
2. The extent to which repeated interactions are explicitly represented in traditional game theoretical models is not so clear. ↵
3. Hegselmann (2017) provides a detailed and fascinating account of the history of this family of models. ↵
4. Our implementation is not a precise instance of neither Sakoda's nor Schelling's family of models, because unhappy agents in our model move to a random location. We chose this
migration regime to make the code simpler. For details, see Hegselmann (2017, footnote 124). ↵
5. Izquierdo et al. (2009, appendix B) analyze this model as a Markov chain. ↵
6. Cells on a side have five neighbors and cells at a corner have three neighbors. ↵
7. See Aydinonat (2007). ↵
8. Free online book ↵
This page titled 1.2: Introduction to agent-based modeling is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo, Segismundo S. Izquierdo, William H.
Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.
1.2.3 https://math.libretexts.org/@go/page/123822
1.3: Introduction to NetLogo
1. What is NetLogo?
NetLogo is a well-written, easy-to-install, easy-to-use, easy-to-extend, and easy-to-
publish-online environment. The entry level is simple enough and the tutorials provided in
the package are straightforward and clear enough that anyone who can read and is
comfortable using a keyboard and mouse could create their own models in a short time,
with little or no additional instruction. Sklar (2007, p. 7)
NetLogo (Wilensky, 1999) is a modeling environment designed for coding and running agent-based simulations.[1] Nowadays,
there are many languages and software platforms that can be employed to create agent-based models,[2] and at the time of writing
NetLogo is the most widely used. We recommend NetLogo and will use it throughout this book for the many reasons we outline
below.
Easy to learn
NetLogo stands out as the quickest to learn and the easiest to use. Gilbert (2007, p. 49)
The language used to code models within NetLogo –which is also called NetLogo– has been designed following a “Low Threshold,
No Ceiling” philosophy (Wilensky and Rand, 2015). All reviews of the software highlight how easy it is to learn. To be concrete,
we would estimate that an average scholar without previous coding experience can learn the basics of the language and be in a
position to write a simple agent-based model after 2-4 days of work. Someone with programming experience could reduce the
estimated time to 1-2 days.
One characteristic that makes the NetLogo language easy to learn is that it is remarkably close to natural language. As a matter of
fact, NetLogo language could perfectly be used as pseudo-code to communicate algorithms implemented in other languages.
Since NetLogo was designed to be easily readable, we believe that NetLogo code is about
as easy to read as any pseudo-code we would have used. NetLogo also has the big
advantage over pseudo-code of being executable, so the user can run and test the
examples. (Wilensky and Rand, 2015, p. xiv)
NetLogo language is definitely simpler to use than e.g. Java or Objective-C, and can often reduce programming efforts
significantly when compared with other languages.
Powerful
NetLogo has become a standard platform for agent-based simulation, yet there appears to
be widespread belief that it is not suitable for large and complex models due to slow
execution. Our experience does not support that belief. Railsback et al. (2017, abstract)
NetLogo is powerful in that it can accommodate reasonably large and complex simulations, and its execution speed is more than
acceptable for most purposes. NetLogo can easily run simulations with several tens of thousands of agents.
Excellent documentation
NetLogo is by far the most professional platform in its appearance and documentation.
Railsback et al. (2006, p. 613)
One of the reasons why NetLogo is so easy to learn is that it is very well documented. The user manual includes three tutorials to
help beginners get started, an excellent programming guide, and a comprehensive dictionary with the definitions of all NetLogo
primitives, including examples of how to use them. NetLogo also comes with an extensive library of models from different
disciplines (e.g. art, biology, chemistry, computer science, mathematics, networks, philosophy, physics, psychology, and other
social sciences) and several code examples which succinctly illustrate particular features and coding techniques.
1.3.1 https://math.libretexts.org/@go/page/123823
Possibility to interact with the model at runtime
NetLogo is designed to allow the user to interact with the model during runtime in a variety of ways:
By modifying parameter values at runtime, with immediate effect on the simulation. This feature is very convenient to assess
the impact of different assumptions in the model and conduct exploratory work.
By running commands in the middle of a run to e.g. create new agents, remove others, or make a subset of them take some
action.
By probing agents to see –and potentially set– the value of any of their individually-owned variables at any time.
This reviewer, who has used NetLogo for both research and teaching at several levels,
highly recommends it for instructors from elementary school to graduate school and for
researchers from a wide range of fields. Sklar (2007, p. 8)
Useful to conduct experiments with real people and for participatory modeling
The NetLogo release includes HubNet (Wilensky and Stroup, 1999), a technology that enables users to communicate and interact
with each other through NetLogo. Thus, Hubnet can be very useful to run participatory simulations and experiments, in which
1.3.2 https://math.libretexts.org/@go/page/123823
human users can be part of the simulation and interact among themselves and with artificial agents.
1. NetLogo was created by Uri Wilensky and is under continuous development at the Northwestern's Center for Connected
Learning and Computer-Based Modeling. It is also important to acknowledge Seth Tisue, who "worked meticulously to
guarantee the quality of the NetLogo software" (Wilensky and Rand, 2015, p. xxii) as lead developer for over a decade. ↵
2. To our knowledge, the most up-to-date and comprehensive review of agent-based simulation software has been conducted by
Abar et al. (2017), who compare 85 tools using a convenient tabular and chart format, and deem NetLogo both easy to use and
also appropriate to execute medium/large-scale simulations. Another recent review that assesses and compares NetLogo with
other platforms has been published by Kravari and Bassiliades (2015). There is also a Wikipedia page set up by Nikolai and
Madey (2009) which provides an up-to-date comparison of agent-based software toolkits. Finally, it is also possible to code
agent-based models using general-purpose programming languages directly. In the context of evolutionary game theory, Isaac
(2008) convincingly demonstrates how this can be easily done with Python. ↵
3. This can be done by uploading any NetLogo model to NetLogo Web and exporting it as HTML. ↵
4. Please, make sure you download version 6.1.1 or greater. NetLogo syntax changed significantly in version 6.0, and a little bit in
6.1. ↵
This page titled 1.3: Introduction to NetLogo is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R.
Izquierdo, Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards
of the LibreTexts platform; a detailed edit history is available upon request.
1.3.3 https://math.libretexts.org/@go/page/123823
1.4: The fundamentals of NetLogo
This section provides a succinct overview of the fundamentals of NetLogo. It is strongly based on the excellent NetLogo user manual, version 6.1.1 (Wilensky, 2019). By no means do we claim
originality on the content of this section; all credit should go to Uri Wilensky and his team. The following table provides links to the different aspects of NetLogo programming that we cover here.
Feel free to skip this section if you are already familiar with NetLogo. For future reference, you may wish to download our NetLogo quick guide, which is a 6-page pdf file containing the main
concepts outlined here.
Figure 1. Top bar of the NetLogo Interface tab, where you can select the tab you want to see.
The interface tab is used to run the model. It often contains buttons, sliders, switches, plots… Most models include a button labeled setup, which is used to initialize the model, and another button
labeled go, which is used to run the model.
The Info tab can be used to include the documentation of the model.
Finally, the code tab contains most of the code of the model. We say most because in some models part of the code is included within the plots in the interface tab.
2. Types of agents
Figure 2. The NetLogo world is made up of turtles, patches, links and the observer.
The NetLogo world is made up by four types of agents (see figure 2), i.e.:
Turtles. Turtles are agents that can move.
Patches: The NetLogo world is two-dimensional and is divided up into a grid of patches. Each patch is a square piece of “ground” over which turtles can move.
Links: Links are agents that connect two turtles. Links can be directed (from one turtle to another turtle) or undirected (one turtle with another turtle).
The observer: There is only one observer and it does not have a location. You can think of the observer as the conductor of the whole NetLogo orchestra.
Note that in many descriptions of agent-based models, the word agent is used only to refer to the turtles (i.e. the mobile agents in NetLogo), while patches and links are not considered agents (and
the observer is not even mentioned). However, when reading NetLogo documentation, it is important to remember that these four types of entities are all agents in NetLogo.
3. Instructions
Instructions tell agents what to do. Three characteristics are useful to remember about instructions:
Whether the instruction is implemented by the user (procedures), or whether it is built into NetLogo (primitives). Once you define a procedure, you can use it elsewhere in your program. The
NetLogo Dictionary has a complete list of built-in instructions (i.e. primitives). The following code is an example of the implementation of procedure to setup:
The instruction to setup is a procedure (since it is implemented by us), whereas clear-all and create-turtles are both primitives (they are built into NetLogo).
Note that primitives are nicely colored, and you can click on them and press F1 to see their syntax, functionality, and examples. You may want to copy and paste the code above to see all this for
yourself.
1.4.1 https://math.libretexts.org/@go/page/123824
Whether the instruction produces an output (reporters) or not (commands).
A reporter computes a result and reports it. Most reporters are nouns or noun phrases (e.g. “average-wealth”, “most-popular-girl”). These names are preceded by the keyword to-report. The
keyword end marks the end of the instructions in the procedure.
A command is an action for an agent to carry out. Most commands begin with verbs (e.g. “create”, “die”, “jump”, “inspect”, “clear”). These verbs are preceded by the keyword to (instead of
to-report). The keyword end marks the end of the procedure.
to go
ask turtles [
forward 1 ;; all turtles move forward one step
right random 360 ;; and turn a random amount
]
end
Note that primitive commands are colored in blue while primitive reporters are colored in purple. Keywords are colored in green.
Whether the instruction takes an input (or several inputs) or not. Inputs are values that the instruction uses in carrying out its actions.
4. Variables
Variables are places to store values (such as numbers). A variable can be a global variable, a turtle variable, a patch variable, a link variable, or a local variable (local to a procedure). To change the
value of a variable you can use the set command. If you don’t set the variable to any value, it starts out storing a value of zero.
Global variables: If a variable is a global variable, there is only one value for the variable, and every agent can access it. You can declare a new global variable either in the Interface tab –by
adding a switch, a slider, a chooser or an input box– or in the Code tab –by using the globals keyword at the beginning of your code, like this:
globals [ n-of-strategies ]
Turtle, patch, and link variables: Each turtle has its own value for every turtle variable, each patch has its own value for every patch variable, and each link has its own value for every link
variable. Turtle, patch, and link variables can be built-in or defined by the user.
Built-in variables: For example, all turtles and all links have a color variable, and all patches have a pcolor variable. If you set this variable, the corresponding turtle, link or patch changes
color. Other built-in turtle variables are xcor, ycor, and heading. Other built-in patch variables include pxcor and pycor. Other built-in link variables are end1, end2, and thickness. You can
find the complete list in the NetLogo Dictionary.
User-defined turtle, patch and link variables: You can also define new turtle, patch or link variables using the turtles-own, patches-own, and links-own keywords respectively, like this:
Local variables: A local variable is defined and used only in the context of a particular procedure or part of a procedure. To create a local variable, use the let command. You can use this
command anywhere. If you use it at the top of a procedure, the variable will exist throughout the procedure. If you use it inside a set of square brackets, for example inside an ask, then it will
exist only inside those brackets.
You can also use of to make one agent read another agent’s variable. of is written in between the variable name and the relevant agent (i.e. [reporter] of agent). Example:
Finally, a turtle can read and set the variables of the patch it is standing on directly, e.g.
1.4.2 https://math.libretexts.org/@go/page/123824
The code above causes every turtle to make the patch it is standing on red. (Because patch variables are shared by turtles in this way, you cannot have a turtle variable and a patch variable with the
same name –e.g. that is why we have color for turtles and pcolor for patches).
5. Ask
NetLogo uses the ask command to specify instructions that are to be run by turtles, patches or links. Usually, the observer uses ask to ask all turtles or all patches to run commands. Here’s an
example of the use of ask syntax in a NetLogo procedure:
to setup
clear-all ;; clear everything
create-turtles 100 ;; create 100 new turtles with random heading
ask turtles [ ;; ask them
set color red ;; to turn red and
forward 50 ;; to move 50 steps forward
]
ask patches [ ;; ask patches
if (pxcor > 0) [ ;; with pxcor greater than 0
set pcolor green ;; to turn green
]
]
end
You can also use ask to have an individual turtle, patch or link run commands. The reporters turtle, patch, link, and patch-at are useful for this technique. For example:
to setup
clear-all ;; clear the world
create-turtles 3 ;; make 3 turtles
ask turtle 0 [ fd 10 ] ;; tell the first one to go forward 10 steps
ask turtle 1 [ ;; ask the second turtle (with who number 1)
set color green ;; ... to become green
]
ask patch 2 -2 [ ;; ask the patch at (2,-2)...
set pcolor blue ;; ... to become blue
]
ask turtle 0 [ ;; ask the first turtle (with who number 0)
create-link-to turtle 2 ;; to link to turtle with who number 2
]
ask link 0 2 [ ;; ask the link between turtle 0 and 2...
set color blue ;; ... to become blue
]
ask turtle 0 [ ;; ask the turtle with who number 0
ask patch-at 1 0 [ ;; ... to ask the patch to her east
set pcolor red ;; ... to become red
]
]
end
6. Lists
In the simplest models, each variable holds only one piece of information, usually a number or a string. Lists let you store multiple pieces of information in a single variable by collecting those
pieces of information in a list. Each value in the list can be any type of value: a number, a string, an agent, an agentset, or even another list.
Constant lists
You can make a list by simply putting the values you want in the list between brackets, e.g.:
set my-list [2 4 6 8]
To make shorter or longer lists, you can use the list reporter with fewer or more than two inputs, but in order to do so, you must enclose the entire call in parentheses, e.g.:
The of primitive lets you construct a list from an agentset (i.e. a set of agents). It reports a list containing each agent’s value for the given reporter (syntax: [reporter] of agentset).
1.4.3 https://math.libretexts.org/@go/page/123824
See also: n-values, range, sentence and sublist.
See also: but-first, but-last, fput, lput, length, shuffle, position and remove-item.
The names assigned to the inputs of the procedure (i.e. input-1 and input-2 above) may be used within the code of the procedure just like you would use any other variable within scope. You can use
any name you like for these local variables (complying with the usual restrictions). An example of an anonymous procedure that implements the absolute value is:
foreach is used to run a command on each item in a list. It takes as inputs the list and the command to be run on each element of the list, e.g.:
foreach [1.2 4.6 6.1] [ n -> show (word n " rounded is " round n) ]
;; output: "1.2 rounded is 1" "4.6 rounded is 5" "6.1 rounded is 6"
map is similar to foreach, but it is a reporter (it returns a list). It takes as inputs a list and a reporter; and returns an output list containing the results of applying the reporter to each item in the input
list. As in foreach, procedures can be anonymous.
Simple uses of foreach, map, n-values, and related primitives can be written more concise.
Both foreach and map can take multiple lists as input; in that case, the procedure is run once for the first items of all input lists, once for the second items, and so on.
(map [[el1 el2] -> el1 + el2] [1 2 3] [10 20 30]) ;; returns [11 22 33]
(map + [1 2 3] [10 20 30]) ;; a shorter way of writing the same
See also: reduce, filter, sort-by, sort-on, and -> (anonymous procedure).
7. Agentsets
An agentset is a set of agents; all agents in an agentset must be of the same type (i.e. turtles, patches, or links). An agentset is not in any particular order. In fact, it’s always in a random order.[1]
What’s powerful about the agentset concept is that you can construct agentsets that contain only some agents. For example, all the red turtles, or the patches with positive pxcor, or all the links
departing from a certain agent. These agentsets can then be used by ask or by various reporters that take agentsets as inputs, such as one-of, n-of, with, with-min, max-one-of, etc. The primitive with
and its siblings are very useful to build agentsets. Here are some examples:
Once you have created an agentset, here are some simple things you can do:
Use ask to make the agents in the agentset do something.
Use any? to see if the agentset is empty.
Use all? to see if every agent in an agentset satisfies a condition.
Use count to find out exactly how many agents are in the set.
Here are some more complex things you can do:
1.4.4 https://math.libretexts.org/@go/page/123824
show mean ([wealth] of turtles with [gender = male])
;; Use of to make a list of values, one for each agent in the agentset.
show (turtles with [gender = male]) = (turtles with [wealth > 10])
;; Check whether two agentsets are equal using = or !=
if all? turtles [color = red] ;; use all? to see if every agent in the
[ show "every turtle is red!" ] ;; agentset satisfies a certain condition
ask turtles [
create-links-to other turtles-here ;; on same patch as me, not me,
with [color = [color] of myself] ;; and with same color as me.
]
8. Synchronization
When you ask a set of agents to run more than one command, each agent must finish all the commands in the block before the next agent starts. One agent runs all the commands, then the next agent
runs all of them, and so on. As mentioned before, the order in which agents are chosen to run the commands is random. To be clear, consider the following code:
ask turtles [
forward random 10 ;; move forward a random number of steps (0–9)
wait 0.5 ;; wait half a second
set color blue ;; set your color to blue
]
The first (randomly chosen) turtle will move forward some steps, she will then wait half a second, and she will finally set her color to blue. Then, and only then, another turtle will start doing the
same; and so on until all turtles have run the commands inside ask without being interrupted by any other turtle. The order in which turtles are selected to run the commands is random. If you want
all turtles to move, and then all wait, and then all become blue, you can write it this way:
Finally, you can make agents execute a set of commands in a certain order by converting the agentset into a list. There are three primitives that help you do this: sort, sort-by and sort-on.
set my-list-of-agents sort-by [[t1 t2] -> [size] of t1 < [size] of t2] turtles
;; This sets my-list-of-agents to a list of turtles sorted in
;; ascending order by their turtle variable size. For simple orderings
;; like this, you can use sort-on, e.g.: sort-on [size] turtles
to setup
create-turtles 10
1.4.5 https://math.libretexts.org/@go/page/123824
forward 1
end
If we implement this code, we obtain the following error message: “You can’t use FORWARD in an observer context, because FORWARD is turtle-only” (see figure 3).
to setup
create-turtles 10
show xcor
end
;; Here we would obtain the error:
;; "You can't use XCOR in an observer context, because XCOR is turtle-only"
to setup
create-turtles 10
show pxcor
end
;; Here we would obtain the error:
;; "You can't use PXCOR in an observer context, because PXCOR is turtle/patch-only"
Note that in the example above, NetLogo says that pxcor is “turtle/patch-only”. This is because all patch variables can be directly accessed by any turtle standing on the patch (see section Variables
above).
to setup
create-turtles 10
show end1
end
;; Here we would obtain the error:
;; "You can't use END1 in an observer context, because END1 is link-only"
10. Breeds
NetLogo allows you to have different types of turtles and different types of links. There are called breeds. Here we discuss breeds of turtles only, since breeds of links follow the same logic. Breeds
are defined with the syntax:
For instance, to define a breed of sellers and a breed of buyers, we would type the following at the top of our code:
From then onwards, we could assign different individually-owned variables to each of the breeds, using the keywords sellers-own and buyers-own. Also, there are a number of primitives that are
automatically added to the NetLogo language once you have defined a breed, such as create-sellers, hatch-sellers, sprout-sellers, sellers-here, sellers-at, sellers-on, and is-seller?.
1.4.6 https://math.libretexts.org/@go/page/123824
we set up all initial conditions (this often implies creating several agents), and
we finish with the primitive reset-ticks.
Procedure to go contains all the actions that will be executed repeatedly in the model. Some of these actions will be executed directly by the observer, while others will be run by the turtles, the
patches or the links. In any case, procedure to go is run by the observer, so it is the observer who must ask the other agents to run the appropriate instructions, using the primitive ask. Most often,
procedure to go contains the primitive tick, which advances the (discrete) NetLogo clock in one unit.
to setup
clear-all
…
setup-patches ;; procedure where patches are initialized
…
setup-turtles ;; procedure where turtles are created
…
reset-ticks
end
to go
conduct-observer-procedure
…
ask turtles [conduct-turtle-procedure]
…
ask patches [conduct-patch-procedure]
…
tick ;; this will update every plot and every pen in every plot
end
to-report a-particular-statistic
…
report the-result-of-some-formula
end
1.4.7 https://math.libretexts.org/@go/page/123824
Figure 5. Window that pops up when you inspect a turtle.
You can ask the turtle to execute instructions by typing
them on the bottom line.
The code that goes in the code tab is shown below. You can download the whole model here and take this code as a test to check whether you are ready to proceed to the next chapter. If you can
understand most of it, you are definitely prepared!
To work your way through the code, you will most likely have to use the NetLogo Dictionary intensively, and run small pieces of code in the Command Center (especially because the model
includes several NetLogo primitives that we have not seen yet). You can also inspect individual turtles and make them run (turtle) instructions such as:
You will have to type these instructions on the bottom line of the window that pops up when you inspect a turtle (see figure 5). To inspect a turtle, right-click on it, select the name of the turtle (e.g.
turtle 21), and click on “inspect”. Alternatively, you can just type the following instruction in the command center:
inspect turtle 21
Developing these skills will be useful, since programming in NetLogo most often involves looking up the dictionary very often and testing short snippets of code. Once you have understood most of
the code below we can start building our first agent-based evolutionary model in the next chapter!
;;;;;;;;;;;;;;;;;
;;; VARIABLES ;;;
;;;;;;;;;;;;;;;;;
turtles-own [
happy?
]
;;;;;;;;;;;;;;;;;;;;;;;;
;;; SETUP PROCEDURES ;;;
;;;;;;;;;;;;;;;;;;;;;;;;
to setup
clear-all
setup-agents
reset-ticks
end
to setup-agents
set-default-shape turtles "person"
ask n-of number-of-agents patches
[ sprout 1 [set color cyan] ]
ask n-of (number-of-agents / 2) turtles
[ set color orange ]
ask turtles [update-happiness]
end
;;;;;;;;;;;;;;;;;;;;;;
;;; MAIN PROCEDURE ;;;
;;;;;;;;;;;;;;;;;;;;;;
1.4.8 https://math.libretexts.org/@go/page/123824
to go
if all? turtles [happy?] [stop]
ask one-of turtles with [not happy?] [move]
ask turtles [update-happiness]
tick
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; TURTLES' PROCEDURES ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
to move
move-to one-of patches with [not any? turtles-here]
end
to update-happiness
let my-nbrs (turtles-on neighbors)
let n-of-my-nbrs (count my-nbrs)
let similar-nbrs (count my-nbrs with [color = [color] of myself])
set happy? similar-nbrs >= (%-similar-wanted * n-of-my-nbrs / 100)
end
1. If you want agents to do something in a fixed order, you can make a list of the agents instead. ↵
2. Both implementations lead to exactly the same dynamics. ↵
This page titled 1.4: The fundamentals of NetLogo is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo, Segismundo S. Izquierdo, William H. Sandholm, & William H.
Sandholm via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.
1.4.9 https://math.libretexts.org/@go/page/123824
CHAPTER OVERVIEW
This page titled 2: Our first agent-based evolutionary model is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by
Luis R. Izquierdo, Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and
standards of the LibreTexts platform; a detailed edit history is available upon request.
1
2.1: Our very first model
1. Goal
The goal of this section is to create our first agent-based evolutionary model in NetLogo. Being our first model, we will keep it
simple; nonetheless, the model will already contain the four building blocks that define most models in agent-based evolutionary
game theory, namely:
a population of agents,
a game that is recurrently played by the agents,
an assignment rule, which determines how revision opportunities are assigned to agents, and
a revision protocol, which specifies how individual agents update their (pure) strategies when they are given the opportunity to
revise.
In particular, in our model the number of (individually-represented) agents in the population will be chosen by the user. These agents
will repeatedly play a symmetric 2-player 2-strategy game, each time with a randomly chosen counterpart. The payoffs of the game
will be determined by the user. Agents will revise their strategy with a certain probability, also to be chosen by the user. The revision
protocol these agents will use is called “imitate-the-better-realization”, which dictates that a revising agent imitates the strategy of a
randomly chosen player, if this player obtained a payoff greater than the revising agent’s.
This fairly general model will allow us to explore a variety of specific questions, like the one we outline next.
2.1.1 https://math.libretexts.org/@go/page/123825
2. With probability prob-revision, individual agents are given the opportunity to revise their strategies. The revision rule –called
“imitate the better realization”– reads as follows:[1]
Look at another (randomly selected) agent and adopt her strategy if and only if her payoff was greater than yours.
The model shows the evolution of the number of agents choosing each of the two possible strategies at the end of every tick.
CODE
4. Interface design
to setup
;; empty for now
end
to go
;; empty for now
end
In the Interface tab, create a button and write setup in the “commands” box. This will make the procedure to setup run whenever
the button is pressed.
Create another button for the procedure to go (i.e., write go in the commands box) with display name go once to emphasize that
pressing the button will run the procedure to go just once.
Finally, create another button for the procedure to go, but this time tick the “forever” option. When pressed, this button will make
the procedure to go run repeatedly until the button is pressed again.
A slider to let the user select the number of players. Create a slider for global variable n-of-players. You can choose limit values 2
(as the minimum) and 1000 (as the maximum), and an increment of 1.
An input box where the user can write a string of the form [ [A00 A01] [A10 A11] ] containing the payoffs Aij that an agent playing
strategy i obtains when meeting an agent playing strategy j (i, j ∈ {0, 1}). Create an input box with associated global variable
2.1.2 https://math.libretexts.org/@go/page/123825
payoffs. Set the input box type to “String (reporter)”. Note that the content of payoffs will be a string (i.e. a sequence of
characters) from which we will need to extract the payoff numeric values.
A slider to let the user select the probability of revision. Create a slider with associated global variable prob-revision. Choose
limit values 0 and 1, and an increment of 0.01.
A plot that will show the evolution of the number of agents playing each strategy. Create a plot and name it Strategy Distribution.
Since we are not going to use the 2D view (i.e. the large black square in the interface) in this model, you may want to overlay it
with the newly created plot.
CODE 5. Code
5.1. Skeleton of the code
globals [payoff-matrix]
Next we declare a breed of agents called “players”. If we did not do this, we would have to use the default name “turtles”, which may
be confusing to newcomers.
Individual players have their own strategy (which can be different from the other agents’ strategy) and their own payoff, so we need
to declare these individually-owned variables as follows:
players-own [
strategy
payoff
]
clear-all
To transform the string of characters the user has written in the payoffs input box (e.g. “[[1 2][3 4]]”) into a list (of 2 lists) that we
can use in the code (e.g. [[1 2][3 4]]). This list of lists will be stored in the global variable named payoff-matrix. To do this
2.1.3 https://math.libretexts.org/@go/page/123825
transformation (from string to list, in this case), we can use the primitive read-from-string as follows:
To create n-of-players players and set their individually-owned variables to an appropriate initial value. At first, we set the value
of payoff and strategy to 0:[2]
create-players n-of-players [
set payoff 0
set strategy 0
]
Note that the primitive create-players does not appear in the NetLogo dictionary; it has been automatically created after defining
the breed “players”. Had we not defined the breed “players”, we would have had to use the primitive create-turtles instead.
Now we will ask a random number of players (between 0 and n-of-players) to set their strategy to 1, using one of the most
important primitives in NetLogo, namely ask. The instruction will be of the form:
random (n-of-players + 1)
To initialize the tick counter. At the end of the setup procedure, we should include the primitive reset-ticks, which resets the tick
counter to zero (and also runs the “plot setup commands”, the “plot update commands” and the “pen update commands” in every
plot, so the initial state of the model is plotted):
reset-ticks
globals [
payoff-matrix
]
players-own [
strategy
2.1.4 https://math.libretexts.org/@go/page/123825
payoff
]
to setup
clear-all
set payoff-matrix read-from-string payoffs
create-players n-of-players [
set payoff 0
set strategy 0
]
ask n-of random (n-of-players + 1) players [set strategy 1]
reset-ticks
end
to go
end
5.4. Go procedure
The procedure to go contains all the instructions that will be executed in every tick. In this particular model, these instructions
include a) asking all players to interact with another (randomly selected) player to obtain a payoff and b) asking all players to revise
their strategy with probability prob-revision.
To keep things nice and modular, we will create two separate procedures to be run by players named to play and to update-strategy.
Writing short procedures with meaningful names will make our code elegant, easy to understand, easy to debug, and easy to
extend… so we should definitely aim for that. Following this modular design, the procedure to go is particularly easy to code and
understand:
tick
2.1.5 https://math.libretexts.org/@go/page/123825
Here we want the player running this procedure (let us call her the running player) to play with some other player and get the
corresponding payoff. First, we will (randomly) select a counterpart and store it in a local variable named mate:
Now we need to compute the payoff that the running player will obtain when she plays the game with her mate. This payoff is an
element of the payoff-matrix list, which is made up of two sublists (e.g., [[1 2][3 4]]).
Note that the first sublist (i.e., item 0 payoff-matrix) corresponds to the case in which the running player plays strategy 0. We want to
consider the sublist corresponding to the player’s strategy, so we type:
In a similar fashion, the payoff to extract from this sublist is determined by the strategy of the running player’s mate (i.e., [strategy]
of mate). Thus, the payoff obtained by the running agent is:
Finally, to make the running agent store her payoff, we can write:
to update-strategy
In this procedure, which is also to be run by individual players, we want the running player to look at some other random player
(which we will call the observed-agent) and, if the payoff of the observed-agent is greater than her own payoff, adopt the observed-
agent’s strategy.
To select a random player and store it in the local variable observed-agent, we can write:
To compare the payoffs and, if appropriate, adopt the observed-agent’s strategy, we can write:
This concludes the definition of the procedure to update-strategy and, actually, of all the code in the Code tab, which by now should
look as shown below.
globals [
payoff-matrix
]
players-own [
strategy
2.1.6 https://math.libretexts.org/@go/page/123825
payoff
]
to setup
clear-all
set payoff-matrix read-from-string payoffs
create-players n-of-players [
set payoff 0
set strategy 0
]
ask n-of random (n-of-players + 1) players [set strategy 1]
reset-ticks
end
to go
ask players [play]
ask players [
if (random-float 1 < prob-revision) [update-strategy]
]
tick
end
to play
let mate one-of other players
set payoff item ([strategy] of mate) (item strategy payoff-matrix)
end
to update-strategy
let observed-agent one-of other players
if ([payoff] of observed-agent) > payoff [
set strategy ([strategy] of observed-agent)
]
end
6. Sample runs
Now that we have the model, we can investigate the question we posed at the motivation above. Let strategy 0 be “Defect” and let
strategy 1 be “Cooperate”. We can use payoffs [[1 3][0 2]]. Note that we could choose any other numbers (as long as they satisfy the
2.1.7 https://math.libretexts.org/@go/page/123825
conditions that define a Prisoner’s Dilemma), since our revision protocol only depends on ordinal properties of payoffs. Let us set n-
of-players = 100 and prob-revision = 0.1, but feel free to change these values.
If you run the model with these settings, you will see that in nearly all runs all agents end up defecting in very little time.[3] The
video below shows some representative runs.
0:00
Note that at any population state, defectors will tend to obtain a greater payoff than cooperators, so they will be preferentially
imitated. Sadly, this drives the dynamics of the process towards overall defection.
7. Exercises
You can use the following link to download the complete NetLogo model: 2×2-imitate-if-better.
2.1.8 https://math.libretexts.org/@go/page/123825
Picture by Ming Jun Tan
Exercise 3. Consider a Hawk-Dove game with payoffs [[0 3][1 2]] where strategy 0 is “Hawk” and strategy 1 is “Dove”. Do all
players tend to choose the same strategy? Reduce the number of players to 100 and observe the difference in behavior (press the
setup button after changing the number of players). Reduce the number of players to 10 and observe the difference.
P.S. You can explore this model’s (deterministic) mean dynamic approximation with this program.
Exercise 4. Create a stand-alone version of the model we have implemented in this section. To do this, you will have to upload the
model to NetLogo Web and then export it in HTML format.
CODE
Exercise 5. Reimplement the procedure to update-strategy so the revising agent uses the imitative pairwise-difference
protocol that we saw in section 0.1.
CODE Exercise 6. Reimplement the procedure to update-strategy so the revising agent uses the best experienced payoff protocol
that we saw in section 0.1.
1. This protocol has been studied by Izquierdo and Izquierdo (2013) and Loginov (2019). ↵
2. By default, user-defined variables in NetLogo are initialized with the value 0, so there is no actual need to explicitly set the initial
value of individually-owned variables to 0, but it does no harm either. ↵
3. All simulations will necessarily end up in one of the two absorbing states where all agents are using the same strategy. The
absorbing state where everyone defects (henceforth D-state) can be reached from any state other than the absorbing state where
everyone cooperates (henceforth C-state). The C-state can be reached from any state with at least two cooperators, so –in
principle– any simulation with at least two agents using each strategy could end up in either absorbing state. However, it is
overwhelmingly more likely that the final state will be the D-state. As a matter of fact, one single defector is extremely likely to
be able to invade a whole population of cooperators, regardless of the size of the population. ↵
This page titled 2.1: Our very first model is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo,
Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the
LibreTexts platform; a detailed edit history is available upon request.
2.1.9 https://math.libretexts.org/@go/page/123825
2.2: Extension to any number of strategies
1. Goal
Our goal here is to extend the model we have created in the previous section –which accepted games with 2 strategies only– to model
(2-player symmetric) games with any number of strategies.
CODE
4. Interface design
We depart from the model we developed in the previous section (so if you want to preserve it, now is a good time to duplicate it).
2.2.1 https://math.libretexts.org/@go/page/123826
Remove the “pens” in the Strategy Distribution plot. Since the number of strategies is unknown until the payoff matrix is read, we
will need to create the required number of “pens” via code. In the Interface tab, edit the Strategy Distribution plot and delete both
pens.
CODE 5. Code
5.1. Skeleton of the code
globals [
payoff-matrix
n-of-strategies
]
to setup
clear-all
set payoff-matrix read-from-string payoffs
create-players n-of-players [
set payoff 0
set strategy 0
]
ask n-of random (n-of-players + 1) players [set strategy 1]
reset-ticks
end
2.2.2 https://math.libretexts.org/@go/page/123826
Note that the code in the current setup procedure performs several unrelated tasks –namely clear everything, set up the payoffs, set
up the players, and set up the tick counter–, and now we will need to set up the graph as well (since we have to create as many pens
as strategies). Let us take this opportunity to modularize our code and improve its readability by creating new procedures with
descriptive names for groups of related instructions, as follows:
to setup
clear-all
setup-payoffs
setup-players
setup-graph
reset-ticks
update-graph
end
to setup-payoffs
The procedure to setup-payoffs will include the instructions to read the payoff matrix, and will also set the value of the global
variable n-of-strategies. We will use the primitive length to obtain the number of rows in the payoff matrix.
to setup-payoffs
set payoff-matrix read-from-string payoffs
set n-of-strategies length payoff-matrix
end
to setup-players
The procedure to setup-players will create the players and set the initial values for their individually-owned variables. The initial
payoff will be 0 and the initial strategy will be a random integer between 0 and (n-of-strategies – 1).
to setup-players
create-players n-of-players [
set payoff 0
set strategy (random n-of-strategies)
]
end
to setup-graph
The procedure to setup-graph will create the required number of pens –one for each strategy– in the Strategy Distribution plot. To
this end, we must first specify that we wish to work on the Strategy Distribution plot, using the primitive set-current-plot.
Then, for each strategy i ∈ {0, 1, …, (n-of-strategies – 1)}, we do the following tasks:
1. Create a pen with the name of the strategy. For this, we use the primitive create-temporary-plot-pen to create the pen, and the
primitive word to turn the strategy number into a string.
create-temporary-plot-pen (word i)
2. Set the pen mode to 1 (bar mode) using set-plot-pen-mode. We do this because we plan to create a stacked bar chart for the
distribution of strategies.
2.2.3 https://math.libretexts.org/@go/page/123826
set-plot-pen-mode 1
3. Choose a color for each pen. See how colors work in NetLogo.
set-plot-pen-color 25 + 40 * i
Now we have to actually loop through the number of each strategy, making i take the values 0, 1, …, (n-of-strategies – 1). There are
several ways we can do this. Here, we do it by creating a list [0 1 2 … (n-of-strategies – 1)] containing the strategy numbers and
going through each of its elements. To create the list, we use the primitive range.
range n-of-strategies
to setup-graph
set-current-plot "Strategy Distribution"
foreach (range n-of-strategies) [ i ->
create-temporary-plot-pen (word i)
set-plot-pen-mode 1
set-plot-pen-color 25 + 40 * i
]
end
to update-graph
Procedure to update-graph will draw the strategy distribution using a stacked bar chart, like the one shown in figure 3 below. This
procedure is called at the end of setup to plot the initial distribution of strategies, and then also at the end of procedure to go, to plot
the strategy distribution at the end of every tick.
Figure 3. Example of stacked bar chart showing the strategy distribution as ticks go by
We start by creating a list containing the strategy numbers [0 1 2 … (n-of-strategies – 1)], which we store in local variable strategy-
numbers.
To compute the (relative) strategy frequencies, we apply to each element of the list strategy-numbers, i.e. to each strategy number,
the operation that calculates the fraction of players using that strategy. To do this, we use primitive map. Remember that map requires
2.2.4 https://math.libretexts.org/@go/page/123826
as inputs a) the function to be applied to each element of the list and b) the list containing the elements on which you wish to apply
the function. In this case, the function we wish to apply to each strategy number (implemented as an anonymous procedure) is:
In the code above, we first identify the subset of players that have a certain strategy (using with), then we count the number of
players in that subset (using count), and finally we divide by the total number of players n-of-players. Thus, we can use the following
code to obtain the strategy frequencies, as a list:
Finally, to build the stacked bar chart, we begin by plotting a bar of height 1, corresponding to the first strategy. Then we repeatedly
draw bars on top of the previously drawn bars (one bar for each of the remaining strategies), with the height diminished each time by
the relative frequency of the corresponding strategy. The final code of procedure to update-graph will look as follows:
to update-graph
let strategy-numbers (range n-of-strategies)
let strategy-frequencies map [ n ->
count players with [strategy = n] / n-of-players
] strategy-numbers
5.4. Go procedure
The only change needed in the go procedure is the call to procedure to update-graph, which will draw the fraction of agents using
each strategy at the end of every tick:
to go
ask players [play]
ask players [
if (random-float 1 < prob-revision) [update-strategy]
]
tick
update-graph
end
2.2.5 https://math.libretexts.org/@go/page/123826
5.6. Complete code in the Code tab
The Code tab is ready!
globals [
payoff-matrix
n-of-strategies
]
players-own [
strategy
payoff
]
to setup
clear-all
setup-payoffs
setup-players
setup-graph
reset-ticks
update-graph
end
to setup-payoffs
set payoff-matrix read-from-string payoffs
set n-of-strategies length payoff-matrix
end
to setup-players
create-players n-of-players [
set payoff 0
set strategy (random n-of-strategies)
]
end
to setup-graph
set-current-plot "Strategy Distribution"
foreach (range n-of-strategies) [ i ->
create-temporary-plot-pen (word i)
set-plot-pen-mode 1
set-plot-pen-color 25 + 40 * i
]
end
to go
ask players [play]
2.2.6 https://math.libretexts.org/@go/page/123826
ask players [
if (random-float 1 < prob-revision) [update-strategy]
]
tick
update-graph
end
to play
let mate one-of other players
set payoff item ([strategy] of mate) (item strategy payoff-matrix)
end
to update-strategy
let observed-player one-of other players
if ([payoff] of observed-player) > payoff [
set strategy ([strategy] of observed-player)
]
end
to update-graph
let strategy-numbers (range n-of-strategies)
let strategy-frequencies map [n -> count players with [strategy = n] / n-of-players]
6. Sample run
Now that we have implemented the model, we can explore the behavior of a population who are repeatedly matched to play a Rock-
Paper-Scissors game. To do that, let us use payoff matrix [[0 -1 1][1 0 -1][-1 1 0]], a population of 500 agents and a 0.1 probability of
revision. The following video shows a representative run with these settings.
2.2.7 https://math.libretexts.org/@go/page/123826
0:00
Note that soon in the simulation run, one of the strategies will get a greater share by chance (due to the inherent randomness of the
model). Then, the next strategy (modulo 3) will enjoy a payoff advantage, and thus will tend to be imitated. For example, if “Paper”
is the most popular strategy, then agents playing “Scissors” will tend to get higher payoffs, and thus be imitated. As the fraction of
agents playing “Scissors” grows, strategy “Rock” becomes more attractive… and so on and so forth. These cycles get amplified until
one of the strategies disappears. At that point, one of the two remaining strategies is superior and finally prevails. The three strategies
have an equal change of being the “winner” in the end, since the whole model setting is symmetric.
7. Exercises
You can use the following link to download the complete NetLogo model: nxn-imitate-if-better.
This page titled 2.2: Extension to any number of strategies is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis
R. Izquierdo, Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards
of the LibreTexts platform; a detailed edit history is available upon request.
2.2.8 https://math.libretexts.org/@go/page/123826
2.3: Noise and initial conditions
1. Goal
Our goal is to extend the model we have created in the previous section by adding two features that will prove very useful:
The possibility of setting initial conditions explicitly. This is an important feature because initial conditions can be very relevant for the
evolution of a system.
The possibility that revising agents select a strategy at random with a small probability. This type of noise in the revision process may
account for experimentation or errors in economic settings, or for mutations in biological contexts. The inclusion of noise in a model
can sometimes change its dynamical behavior dramatically, even creating new attractors. This is important because dynamic
characteristics of a model –such as attractors, cycles, repellors, and other patterns– that are not robust to the inclusion of small noise
may not correspond to relevant properties of the real-world system that we aim to understand. Besides, as a positive side-effect, adding
small amounts of noise to a model often makes the analysis of its dynamics easier to undertake.
2.3.1 https://math.libretexts.org/@go/page/123827
Figure 1. Interface design
The new interface (see figure 1 above) requires a few simple modifications:
Create an input box to let the user set the initial number of players using each strategy. In the Interface tab, add an input box with
associated global variable n-of-players-for-each-strategy. Set the input box type to “String (reporter)”.
Note that the total number of players (which was previously set using a slider with associated global variable n-of-players) will now be
computed totaling the items of the list n-of-players-for-each-strategy. Thus, we should remove the slider, and include the global variable
n-of-players in the Code tab.
globals [
payoff-matrix
n-of-strategies
n-of-players
]
Add a monitor to show the total number of players. This number will be stored in the global variable n-of-players, so the monitor must
show the value of this variable. In the Interface tab, create a monitor. In the “Reporter” box write the name of the global variable n-of-
players.
Create a slider to choose the value of parameter noise. In the Interface tab, create a slider with associated global variable noise. Choose
limit values 0 and 1, and an increment of 0.001.
CODE
5. Code
5.1. Skeleton of the code
2.3.2 https://math.libretexts.org/@go/page/123827
Figure 2. Skeleton of the code
to setup-players
Since the content of parameter n-of-players-for-each-strategy is a string, the first we should do is to turn it into a list that we can use in our
code. To this end, we use the primitive read-from-string and store its output in a new local variable named initial-distribution, as follows:
Next, we can check that the number of elements in the list initial-distribution matches the number of possible strategies (i.e. the number of
rows in the payoff matrix stored in payoff-matrix), and issue a warning message otherwise, using primitive user-message. Naturally, this is
by no means compulsory, but it is a thoughtful touch that will make our program more user-friendly. To this end, we can use the code
below.
2.3.3 https://math.libretexts.org/@go/page/123827
;; It is not necessary to show the user
;; the value of n-of-players-for-each-strategy
;; and payoffs again,
;; but when creating an error message,
;; it is good practice to give the user
;; as much information as possible,
;; so the error can be easily corrected.
Now, let us create as many players using each strategy as indicated by the values in the list initial-distribution. For instance, if initial-
distribution is [5 10 15], we should create 5 players with strategy 0, 10 players with strategy 1, and 15 players with strategy 2. Since we
want to perform a task for each element of the list, primitive foreach will be handy.
Besides going through each element on the list using foreach, we would also like to keep track of the position being read on the list, which
is the corresponding strategy number. For this, we create a counter i which we start at 0:
let i 0
foreach initial-distribution [ j ->
create-players j [
set payoff 0
set strategy i
]
set i (i + 1)
]
The line above concludes the definition of procedure to setup-players, and the implementation of the user-chosen initial conditions.
to update-strategy
let observed-player one-of other players
if ([payoff] of observed-player) > payoff [
set strategy ([strategy] of observed-player)
]
end
We can implement the noise feature using primitive ifelse, whose structure is
ifelse CONDITION
[ COMMANDS EXECUTED IF CONDITION IS TRUE ]
[ COMMANDS EXECUTED IF CONDITION IS FALSE ]
In our case, the CONDITION should be true with probability noise. Bearing all this in mind, the final code for procedure to update-
strategy could be as follows:
to update-strategy
ifelse random-float 1 < noise
2.3.4 https://math.libretexts.org/@go/page/123827
;; the condition is true with probability noise
[ ;; code to be executed if there is noise
set strategy (random n-of-strategies)
]
[ ;; code to be executed if there is no noise
let observed-player one-of other players
if ([payoff] of observed-player) > payoff [
set strategy ([strategy] of observed-player)
]
]
end
globals [
payoff-matrix
n-of-strategies
n-of-players
]
players-own [
strategy
payoff
]
to setup
clear-all
setup-payoffs
setup-players
setup-graph
reset-ticks
update-graph
end
to setup-payoffs
set payoff-matrix read-from-string payoffs
set n-of-strategies length payoff-matrix
end
to setup-players
let initial-distribution read-from-string n-of-players-for-each-strategy
if length initial-distribution != length payoff-matrix [
user-message (word "The number of items in\n"
"n-of-players-for-each-strategy (i.e. "
length initial-distribution "):\n"
n-of-players-for-each-strategy
2.3.5 https://math.libretexts.org/@go/page/123827
"\nshould be equal to the number of rows\n"
"in the payoff matrix (i.e. "
length payoff-matrix "):\n"
payoffs
)
]
let i 0
foreach initial-distribution [ j ->
create-players j [
set payoff 0
set strategy i
]
set i (i + 1)
]
set n-of-players count players
end
to setup-graph
set-current-plot "Strategy Distribution"
foreach (range n-of-strategies) [ i ->
create-temporary-plot-pen (word i)
set-plot-pen-mode 1
set-plot-pen-color 25 + 40 * i
]
end
to go
ask players [play]
ask players [
if (random-float 1 < prob-revision) [update-strategy]
]
tick
update-graph
end
to play
let mate one-of other players
set payoff item ([strategy] of mate) (item strategy payoff-matrix)
end
to update-strategy
ifelse random-float 1 < noise
[ set strategy (random n-of-strategies) ]
[
let observed-player one-of other players
if ([payoff] of observed-player) > payoff [
set strategy ([strategy] of observed-player)
]
]
2.3.6 https://math.libretexts.org/@go/page/123827
end
to update-graph
let strategy-numbers (range n-of-strategies)
let strategy-frequencies map [ n ->
count players with [strategy = n] / n-of-players ]
strategy-numbers
6. Sample run
Now that we have implemented the model, we can use it to answer the question posed above: Will adding a bit of noise change the
dynamics of the Rock-Paper-Scissors game under the “imitate-the-better-realization” revision protocol? To do that, let us use the same
setting as in the previous section, i.e. payoffs = [[0 -1 1][1 0 -1][-1 1 0]] and prob-revision = 0.1. To have 500 agents and initial conditions
close to random, we can set n-of-players-for-each-strategy = [167 167 166]. Finally, let us use noise = 0.01. The following video shows a
representative run with these settings.
0:00
As you can see, noise dampens the amplitude of the cycles, so the monomorphic states where only one strategy is chosen by the whole
population are not observed anymore.[1] Even if at some point one strategy went extinct, noise would bring it back into existence. Thus, the
model with noise = 0.01 exhibits an everlasting pattern of cycles of varying amplitudes. This contrasts with the model without noise, which
necessarily ends up in one of only three possible final states.
7. Exercises
You can use the following link to download the complete NetLogo model: nxn-imitate-if-better-noise.
2.3.7 https://math.libretexts.org/@go/page/123827
Exercise 1. Consider a Prisoner’s Dilemma with payoffs [[2 4][1 3]] where strategy 0 is “Defect” and strategy 1 is “Cooperate”. Set
prob-revision to 0.1 and noise to 0. Set the initial number of players using each strategy, i.e. n-of-players-for-each-strategy, to [0 200], i.e.,
everybody plays “Cooperate”. Press the setup button and run the model. While it is running, move the noise slider slightly rightward to
introduce some small noise. Can you explain what happens?
Exercise 2. Consider a Rock-Paper-Scissors game with payoff matrix [[0 -1 1][1 0 -1][-1 1 0]]. Set prob-revision to 0.1 and noise to 0.
Set the initial number of players using each strategy, i.e. n-of-players-for-each-strategy, to [100 100 100]. Press the setup button and run the
model for a while. While it is running, click on the noise slider to set its value to 0.001. Can you explain what happens?
Exercise 3. Consider a game with payoff matrix [[1 1 0][1 1 1][0 1 1]]. Set prob-revision to 0.1, noise to 0.05, and the initial number of
players using each strategy, i.e. n-of-players-for-each-strategy, to [500 0 500]. Press the setup button and run the model for a while (then
press the setup button again to change the initial conditions). Can you explain what happens?
Exercise 4. Consider a game with n players and s strategies, with noise equal to 1. What is the infinite-horizon probability distribution of
the number of players using each strategy?
CODE
Exercise 5. Imagine that you’d like to run this model faster, and you are not interested in the plot. This is a common scenario when
you want to conduct large-scale computational experiments. What lines of code could you comment out?
CODE
Exercise 6. Note that you can modify the values of parameters prob-revision and noise at runtime with immediate effect on the
dynamics of the model. How could you implement the possibility of changing the number of players in the population with immediate
effect on the model?
1. In this model with noise, every state will be observed at some point if we wait for long enough, but long enough might be a really long
time (e.g. centuries). ↵
This page titled 2.3: Noise and initial conditions is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo,
Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts
platform; a detailed edit history is available upon request.
2.3.8 https://math.libretexts.org/@go/page/123827
2.4: Interactivity and efficiency
1. Goal
Our goal in this section is to improve the interactivity and the efficiency of our model.
By interactivity we mean the possibility of changing the value of parameters at runtime, with immediate effect on the dynamics of the model. This
feature is very convenient for exploratory work. In this section, we will implement the necessary functionality to let the user change the number of agents
in the population at runtime.
By efficiency we mean implementing the model in such a way that it can be executed using as little time and memory as possible. In this section, we will
modify the code of our model slightly to make it run significantly faster.
Oftentimes there is a trade-off between interactivity and efficiency: making the model more interactive generally implies some loss of efficiency.
Nonetheless, sometimes we can find ways of implementing a model more efficiently without compromising its interactivity.
It is also important to be aware that –most often– there is also a trade-off between efficiency and code readability. The changes required to make our
model run faster will frequently make our code somewhat less readable too. Uri Wilensky –the creator of NetLogo– and William Rand do not recommend
making such comprises:
However, it is important that your code be readable, so others can understand it. In the end, computer time
is cheap compared to human time. Therefore, it should be noted that, whenever there is a possibility of
trade-off, clarity of code should be preferred over efficiency. Wilensky and Rand (2015, pp 219–20)
Our personal opinion is that this decision is best made case by case, taking into account the objectives and constraints of the whole modelling exercise in
the specific context at hand. Our hope is that, after reading this book, you will be prepared to make these decisions by yourself in any specific situation
you may encounter.
CODE
4. Skeleton of the code
CODE
2.4.1 https://math.libretexts.org/@go/page/123828
CODE
5. Interactivity
Note that we can already modify the value of parameters prob-revision and noise at runtime, with immediate effect on the dynamics of the model. This is
so because the values of these variables are used directly in the code. Parameter prob-revision is used only in procedure to go, in the following line:
And parameter noise is used only in procedure to update-strategy, in the following line:
Whenever NetLogo reads the two lines of code above, it uses the current values of the two parameters. Because of this, we can modify the parameters’
values on the fly and immediately see how that change affects the dynamics of the model.
By contrast, changing the value of parameter n-of-players-for-each-strategy at runtime will have no effect whatsoever. This is so because parameter n-of-
players-for-each-strategy is only used in procedure to setup-players, which is executed at the beginning of the simulation –triggered by procedure to
setup– and never again.
To enable the user to modify the population size at runtime, we should create a slider for the new parameter n-of-players. Before doing so, we have to
remove the declaration of the global variable n-of-players in the Code tab, since the creation of the slider implies the definition of the variable as global.
globals [
payoff-matrix
n-of-strategies
;; n-of-players <== We remove this line
]
After creating the slider for parameter n-of-players, we could also remove the monitor showing n-of-players from the interface, since it is no longer
needed. Another option (see figure 1 below) is to use that same monitor to display the value of the ticks that have gone by since the beginning of the
simulation. To do this, we just have to write the primitive ticks (instead of n-of-players) in the “Reporter” box of the monitor.
to update-n-of-players
let diff (n-of-players - count players)
2.4.2 https://math.libretexts.org/@go/page/123828
if diff != 0 [
ifelse diff > 0
[ repeat diff [ ask one-of players [hatch-players 1] ] ]
[ ask n-of (- diff) players [die] ]
]
end
Note the use of primitives hatch-players and die to clone and kill agents respectively. The difference between primitives hatch-players and create-players
is important. Hatching is an action that only individual agents (i.e. “turtles” and breeds of “turtles”, in NetLogo parlance) can execute. By contrast, only
the observer can run create-turtles and create-<breeds> primitives.
Finally, we should include the call to the new procedure at the beginning of to go.
to go
update-n-of-players ;; <== New line
ask players [play]
ask players [
if (random-float 1 < prob-revision) [update-strategy]
]
tick
update-graph
end
And with this, we’re ready to go! Give it a try, and enjoy the good progress you are making!
CODE
6. Efficiency
Naturally, to make a model run faster, one can always untick the “view updates” box on the Interface tab.[1] This is a must in models that do not make use
of the view, like the ones we are programming in this chapter, since it implies a significant speed-up at no cost. But beyond this simple piece of advice, in
general, how can we know whether our model can run faster? A good first step is to try to identify inefficiencies in our code. These inefficiencies often
take one of two possible forms:
Computations that we conduct but we do not use at all.
Computations that we conduct several times despite knowing that their outputs will not change.
Let us see an example of each of these inefficiencies in our current code.
to go
update-n-of-players
;; ask players [play] <== We remove this line
ask players [
if (random-float 1 < prob-revision) [update-strategy]
]
tick
update-graph
end
to update-strategy
let observed-player one-of other players
2.4.3 https://math.libretexts.org/@go/page/123828
if ([payoff] of observed-player) > payoff [
set strategy ([strategy] of observed-player)
]
end
These changes will make simulations with low prob-revision run much faster. [2]
6.2. Example of computations that we conduct several times when once would do
Let us now focus on the second type of inefficiency pointed out above. Can you identify a computation that we repeatedly conduct in every tick, even
though its result does not change?
Note that we undertake the computation:
other players
several times in every tick, but we could conduct it just once for each agent in each simulation. To be sure, we conduct that operation every time an agent
computes her payoff in to play:
This computation may not sound very expensive, but if the number of agents is large, it may well be (see exercise 3 below). To make the model run
faster, we could create an individually-owned variable named e.g. other-players, as follows
players-own [
strategy
payoff
other-players
]
And then we should set the new individually-owned variable other-players to the appropriate value only once at the beginning of each simulation (at the
end of procedure to setup-agents).
Since we may change the number of players at runtime, we should also include the line above in the block of code where we clone or kill agents in
procedure to update-n-of-agents, i.e.
to update-n-of-players
let diff (n-of-players - count players)
if diff != 0 [
ifelse diff > 0
[ repeat diff [ ask one-of players [hatch-players 1] ] ]
[ ask n-of (- diff) players [die] ]
ask players [set other-players other players]
]
end
Once we have done that, in the two lines of code where we had the code
other players
we should write other-players instead. These changes will make simulations with many players run faster.
2.4.4 https://math.libretexts.org/@go/page/123828
6.3. Measuring execution speed of different parts of the code
There are two simple ways to measure execution speed in NetLogo. One is using primitives reset-timer and timer. For instance, to time how long it takes
to have every agent carry out the operation:
other players
to-report time-other-players
reset-timer
ask players [let temporary-var other players]
report timer
end
A second –more advanced– way of measuring execution speed involves the Profiler Extension, which comes bundled with NetLogo. This extension
allows us to see how many times each procedure in our model is called during a run and how long each call takes. The extension is simple to use and well
documented here. To use it in our model, we should include the extension at the beginning of our code, as follows:
extensions [profiler]
Then we could execute the following procedure, borrowed from the Profiler Extension documentation page.
to show-profiler-report
setup ;; set up the model
profiler:start ;; start profiling
repeat 1000 [ go ] ;; run something you want to measure
profiler:stop ;; stop profiling
print profiler:report ;; print the results
profiler:reset ;; clear the data
end
Once the procedure is implemented, you can run it by typing its name in the Command Center.
The profiler report includes the inclusive time and the exclusive time for each procedure. Inclusive time is the time the simulation spends running the
procedure, i.e. since the procedure is entered until it finishes. Exclusive time is the time passed since the procedure is entered until it finishes, but does
not include any time spent in other user-defined procedures which it calls. An example of the output printed by show-profiler-report follows:
2.4.5 https://math.libretexts.org/@go/page/123828
UPDATE-GRAPH 1000 231.718 231.718 0.232
UPDATE-N-OF-PLAYERS 1000 2.480 2.480 0.002
END PROFILING DUMP
players-own [
strategy
payoff
other-players
]
to setup
clear-all
setup-payoffs
setup-players
setup-graph
reset-ticks
update-graph
end
to setup-payoffs
set payoff-matrix read-from-string payoffs
set n-of-strategies length payoff-matrix
end
to setup-players
let initial-distribution read-from-string n-of-players-for-each-strategy
if length initial-distribution != length payoff-matrix [
user-message (word "The number of items in\n"
"n-of-players-for-each-strategy (i.e. "
length initial-distribution "):\n" n-of-players-for-each-strategy
"\nshould be equal to the number of rows\n"
"in the payoff matrix (i.e. "
length payoff-matrix "):\n"
payoffs
)
]
2.4.6 https://math.libretexts.org/@go/page/123828
let i 0
foreach initial-distribution [ j ->
create-players j [
set payoff 0
set strategy i
]
set i (i + 1)
]
set n-of-players count players
ask players [set other-players other players]
end
to setup-graph
set-current-plot "Strategy Distribution"
foreach (range n-of-strategies) [ i ->
create-temporary-plot-pen (word i)
set-plot-pen-mode 1
set-plot-pen-color 25 + 40 * i
]
end
to go
update-n-of-players
ask players [
if (random-float 1 < prob-revision) [update-strategy]
]
tick
update-graph
end
to play
let mate one-of other-players
set payoff item ([strategy] of mate) (item strategy payoff-matrix)
end
to update-strategy
ifelse (random-float 1 < noise)
[ set strategy (random n-of-strategies) ]
[
let observed-player one-of other-players
play
ask observed-player [play]
if ([payoff] of observed-player) > payoff [
set strategy ([strategy] of observed-player)
]
]
end
to update-graph
let strategy-numbers (range n-of-strategies)
let strategy-frequencies map
[n -> count players with [strategy = n] / n-of-players]
strategy-numbers
2.4.7 https://math.libretexts.org/@go/page/123828
set-current-plot "Strategy Distribution"
let bar 1
foreach strategy-numbers [ n ->
set-current-plot-pen (word n)
plotxy ticks bar
set bar (bar - (item n strategy-frequencies))
]
set-plot-y-range 0 1
end
to update-n-of-players
let diff (n-of-players - count players)
if diff != 0 [
ifelse diff > 0
[ repeat diff [ ask one-of players [hatch-players 1] ] ]
[ ask n-of (- diff) players [die] ]
ask players [set other-players other players]
]
end
8. Sample run
Now that we can change the population size at runtime, we can easily explore the question posed above: How does population size affect the dynamics of
the “imitate-the-better-realization” revision protocol with noise in the Rock-Paper-Scissors game? To do that, let us use the same setting as in the
previous sections (i.e. payoffs = [[0 -1 1][1 0 -1][-1 1 0]] and prob-revision = 0.1), start with a small population of 60 agents (n-of-players-for-each-
strategy = [20 20 20]), and then, increase n-of-players up to 2000 at runtime. The following video shows a representative run with these settings, where
we increased the population size from 60 to 2000 at tick 4000.
0:00
As you can see, when the number of agents is small, the population consistently follows cycles of large amplitude among the three strategies. The cycles
are so wide that sometimes one or even two strategies go extinct for a while. In stark contrast, when the population is large, the cycles get much smaller
and the population tends to linger around the state where each strategy is used by approximately a third of the population.[3]
9. Exercises
You can use the following link to download the complete NetLogo model: nxn-imitate-if-better-noise-efficient.
2.4.8 https://math.libretexts.org/@go/page/123828
CODE
Exercise 2. In this section we have reduced the number of times procedure to play is called (as long as prob-revision is less than 0.5). To
illustrate this, compare the number of times this procedure is called in a 1000-tick simulation with 600 agents and prob-revision 0.1, before and after our
efficiency improvement. Can you compute the number of times procedure to play is called in the general case?
CODE Exercise 3. In this section we have reduced the number of times the computation other players is conducted by creating an individually-
owned variable (named other-players). To compare these two approaches, write a short NetLogo program where 10000 agents conduct this operation.
CODE
Exercise 4. In this section we have reduced the number of times procedure to play is called (as long as prob-revision is less than 0.5). However, it
is still possible that some players will execute procedure to play more than once in the same tick, specially if prob-revision is high. Can you think of a
way to reduce the number of calls to procedure to play even further?
1. This action is equivalent to pushing the speed slider –situated in the middle of the interface toolbar– to its rightmost position and can also be done via
code using primitive no-display ↵
2. Note, however, that the new model is not exactly the same as the old one. In the new –efficient– version of the model, agents switch strategies
sequentially, since all relevant payoffs are computed just before any single revision takes place, using the strategy distribution at the time of the
revision. In constrast, in the old version all revisions within the same tick made use of the payoffs computed at the beginning of the tick, using the
strategy distribution at the beginning of the tick. It is not difficult to define an efficient and totally equivalent version of the old model by defining a
new players-own variable to store players' strategy after the revision. We chose not to do so here for pedagogical reasons. ↵
3. The state where all strategies are equally represented is a globally asymptotically stable state of the mean dynamics of this model (which provides a
good approximation for models with large populations). See solution to Exercise 1.2.2. ↵
This page titled 2.4: Interactivity and efficiency is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo, Segismundo S.
Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is
available upon request.
2.4.9 https://math.libretexts.org/@go/page/123828
2.5: Analysis of these models
1. Two complementary approaches
Agent-based models are usually analyzed using computer simulation and/or mathematical analysis.
The computer simulation approach consists in running many simulations –i.e. sampling the model many times– and then, with the
data thus obtained, trying to infer general patterns and properties of the model.
Mathematical approaches do not look at individual simulation runs, but instead analyze the rules that define the model directly,
and try to derive their logical implications. Mathematical approaches use deductive reasoning only, so their conclusions follow
with logical necessity from the assumptions embedded in the model (and in the mathematics employed).
These two approaches are complementary, in that they can provide fundamentally different insights on the same model. Furthermore,
there are synergies to be exploited by using the two approaches together (see e.g. Izquierdo et al. (2013, 2019), Seri (2016), García
and van Veelen (2016, 2018) and Hindersin et al. (2019)).
Here we provide several references to material that is helpful to analyze the agent-based models we have developed in this chapter of
the book, and illustrate its usefulness with a few examples. Section 2 below deals with the computer simulation approach, while
section 3 addresses the mathematical analysis approach.
Figure 1. Average proportion of 1-strategists in an experiment of 1000 simulation runs. Orange error bars show the minimum and
maximum values observed across the 1000 runs. Payoffs [[1 0][0 2]]; prob-revision 0.01; noise 0; initial conditions [500 500].
To set up the computational experiment that will produce the data required to draw figure 1, we just have to go to Tools (in the upper
menu of NetLogo) and then click on BehaviorSpace. The new experiment can be set up as shown in figure 2.
2.5.1 https://math.libretexts.org/@go/page/123829
Figure 2. Experiment setup in BehaviorSpace
In this particular experiment, we are not changing the value of any parameter, but doing so is straightforward. For instance, if we
wanted to run simulations with different values of prob-revision –say 0.01, 0.05 and 0.1–, we would just write:
If, in addition, we would like to explore the values of noise 0, 0.01, 0.02 … 0.1, we could use the syntax for loops, [start increment
end], as follows:
If we made the two changes described above, then the new computational experiment would comprise 33000 runs, since NetLogo
would run 1000 simulations for each combination of parameter values (i.e. 3 × 11).
The original experiment shown in figure 2, which consists of 1000 simulation runs only, takes a couple of minutes to run. Once it is
completed, we obtain a .csv file with all the requested data, i.e. the fraction of 1-strategists in every tick for each of the 1000
simulation runs – a total of 1001000 data points. Then, with the help of a pivot table (within e.g. an Excel spreadsheet), it is easy to
plot the graph shown in figure 1. A similar graph that can be easily plotted is one that shows the standard error of the average
computed in every tick (see figure 3).[2]
2.5.2 https://math.libretexts.org/@go/page/123829
Figure 3. Average proportion of 1-strategists in an experiment of 1000 simulation runs. Orange error bars show the standard error.
Payoffs: [[1 0][0 2]]; prob-revision: 0.01; noise 0; initial conditions [500 500].
3.1. Markov analysis of 2-strategy evolutionary processes where agents switch strategies sequentially
In this section we study 2-strategy evolutionary processes where agents switch strategies sequentially. For simplicity, we will asume
that there is one revision per tick, but several revisions could take place in the same tick as long as they ocurred sequentially.[5] These
processes can be formalized as birth-death chains, a special type of Markov chains for which various analytical results can be derived.
An example of such a process is the one simulated in section 2 above.
2.5.3 https://math.libretexts.org/@go/page/123829
only three possible transitions: one implies increasing by , another one implies decreasing by , and the other one leaves the
state unchanged. Let us denote the transition probabilities as follows:
Thus, the probability of staying at the same state after one tick is:
This Markov chain has two important properties: the state space is endowed with a linear order and all transitions
move the state one step to the left, one step to the right, or leave the state unchanged. These two properties imply that the Markov
chain is a birth-death chain. Figure 4 below shows the transition diagram of this birth-death chain, ignoring the self-loops.
In our evolutionary process, the transition probabilities and are determined by the revision protocol that agents use. Let us see
how this works with a specific example. Consider the coordination game defined by payoffs [[1 0][0 2]], played by agents who
sequentially revise their strategies according to the the imitate-the-better-realization rule (without noise). This is the model we have
simulated in section 2 above. [6]
Let us derive . Note that the state increases by if and only if the revising agent is using strategy 0 and
he switches to strategy 1. In the game with payoffs [[1 0][0 2]], this happens if and only if the following conditions are satisfied:
the agent who is randomly drawn to revise his strategy is playing strategy 0 (an event which happens with probability ),
the agent that is observed by the revising agent is playing strategy 1 (an event which happens with probability ; note that there
are agents using strategy 1 and the revising agent observes another agent, thus the divisor ), and
the observed agent’s payoff is 2, i.e. the observed agent –who is playing strategy 1– played with an agent who was also playing
strategy 1 (an event which happens with probability ; note that the observed agent plays with another agent who is also
playing strategy 1).
Therefore:
Note that, in this case, the payoff obtained by the revising agent is irrelevant.
2.5.4 https://math.libretexts.org/@go/page/123829
We can derive in a similar fashion. Do you want to give it a try before reading the solution?
Computation of
With the formulas of and in place, we can write the transition matrix of this model for any given . As an example, this is the
transition matrix for :
And here’s a little Mathematica® script that can be used to generate the transition matrix for any :
n = 10;
p[x_] := (1 - x) (x n/(n - 1)) ((x n - 1)/(n - 1))
q[x_] := x (((1 - x)n)/(n - 1))^2 ((1 - x)n - 1)/(n - 1)
P = SparseArray[{
{i_, i_} -> (1 - p[(i - 1)/n] - q[(i - 1)/n]),
{i_, j_} /; i == j - 1 -> p[(i - 1)/n],
{i_, j_} /; i == j + 1 -> q[(i - 1)/n]
}, {n + 1, n + 1}];
MatrixForm[P]
Thus, we can easily compute the transient distribution simply by multiplying the initial conditions by the th power of the
transition matrix :
2.5.5 https://math.libretexts.org/@go/page/123829
As an example, consider the evolutionary process we formalized as a Markov chain in the previous section, with imitate-the-
better-realization agents playing the coordination game [[1 0][0 2]]. Let us start at initial state , i.e. ,
where the solitary 1 lies exactly at the middle of the vector (i.e. at position ). Figure 5 shows the distributions
and .
Figure 5. Probability mass function of at different ticks. Number of agents . Initial conditions .
®
To produce figure 5, we have computed the transition matrix with the previous Mathematica script (having previously set the
number of agents to 100) and then we have run the following two lines:
a0 = UnitVector[n + 1, 1 + n/2];
ListPlot[Table[a0.MatrixPower[N@P, i], {i, 100, 500, 100}], PlotRange -> All]
Looking at the probability distribution of , it is clear that, after 500 revisions, the evolutionary process is very likely to be at a
state where most of the population is using strategy 1. There is even a substantial probability (~6.66%) that the process will have
reached the absorbing state where everyone in the population is using strategy 1. Note, however, that all the probability distributions
shown in figure 5 have full support, i.e. the probability of reaching the absorbing state where no one uses strategy 1 after 100, 200,
300, 400 or 500 is very small, but strictly positive. As a matter of fact, it is not difficult to see that, given that and
(i.e. initially there are 50 agents using strategy 1), a_k(0) = \mathbb{P}(X_k = 0 \,|\, X_0=0.5) 0" class="ql-img-inline-formula quicklatex-auto-
format" height="18" style="vertical-align: -4px;" title="Rendered by QuickLaTeX.com" width="256"
src="/@api/deki/files/108430/quicklatex.com-2e2201cc319aeea97a34b91c08c8505e_l3.png"> for any .
Finally, to illustrate the sensitivity of transient dynamics to initial conditions, we replicate the computations shown in figure 5, but
with initial conditions (figure 6) and (figure 7).
2.5.6 https://math.libretexts.org/@go/page/123829
Figure 6. Probability mass function of at different ticks. Number of agents . Initial conditions .
Figure 7. Probability mass function of at different ticks. Number of agents . Initial conditions .
Besides the probability distribution of at a certain , we can analyze many other interesting properties of a Markov chain, such
as the expected hitting time (or first passage time) of a certain state , which is the expected time at which the process first reaches
state . For general Markov chains, this type of results can be found in any of the references mentioned at the beginning of section 3.
For birth-death chains specifically, Sandholm (2010, section 11.A.3) provides simple formulas to compute expected hitting times and
hitting probabilities (i.e. the probability that the birth-death chain reaches state before state ).
2.5.7 https://math.libretexts.org/@go/page/123829
align: -3px;" title="Rendered by QuickLaTeX.com" width="54" src="/@api/deki/files/108441/quicklatex.com-
8aa23c021787fc8fb7af37a505c4bc3c_l3.png"> for some ), then the Markov chain is irreducible and aperiodic.
If there exists a positive integer such that (P^m)_{ij} 0" class="ql-img-inline-formula quicklatex-auto-format" height="20"
style="vertical-align: -6px;" title="Rendered by QuickLaTeX.com" width="84" src="/@api/deki/files/108443/quicklatex.com-
39ed3317dd0ab52a09eae4c8277dda17_l3.png"> for all and , then the Markov chain is irreducible and aperiodic.
If one sees the transition diagram of a Markov chain (see e.g. Figure 4 above) as a directed graph (or network), the conditions above
can be rewritten as:
The network contains more than two nodes and there is a directed link from every node to every other node.
The network is strongly connected and there is at least one loop.
There exists a positive integer such that there is at least one walk of length
from any node to every node (including itself).
The 2-strategy evolutionary process we are studying in this section is not necessarily irreducible if there is no noise. For instance, the
coordination game played by imitate-the-better-realization agents analyzed in section 3.1.2 is not irreducible. That model will
eventually reach one of the two absorbing states where all the agents are using the same strategy, and stay in that state forever. The
probability of ending up in one or the other absorbing state depends on initial conditions (see Figure 8).[7]
Figure 8. Probability of ending up in each of the two absorbing states for different initial states , in the coordination game [[1 0][0 2]]
played by imitate-if-better agents.
However, if we add noise in the agents’ revision protocol –so there is always the possibility that revising agents choose any strategy–,
then it is easy to see that the second sufficient condition for irreducibility and aperiodicity above is fulfilled.[8]
Generally, in irreducible and aperiodic Markov chains with state space (henceforth IAMCs), the probability mass function of
approaches a limit as tends to infinity. This limit is called the limiting distribution, and is denoted here by , a vector with
components which denote the probability of finding the system in state in the long run. Formally, in IAMCs the following
limit exists and is unique (i.e. independent of initial conditions):
0\;\text{ for all }i \in S." class="ql-img-inline-formula quicklatex-auto-format" height="18"
\lim_{k \to \infty}\mathbb{P}(X_k = i) = \mu(i)
2.5.8 https://math.libretexts.org/@go/page/123829
where the value of is derived by imposing that the elements of must add up to 1. This formula can be
easily implemented in Mathematica®:
Note that the formula above is only valid for irreducible and aperiodic birth-death chains. An example of such a chain would be the
model where a number of imitate-the-better-realization agents are playing the coordination game [[1 0][0 2]] with noise. Thus, for this
model we can easily analyze the impact of noise on the limiting distribution. Figure 9 illustrates this dependency.
Figure 9. Limiting distribution for different values of noise in the coordination game [[1 0][0 2]] played by imitate-the-
better-realization agents.
Figure 9 has been created by running the following Mathematica® script:
n = 100;
μs = Map[Normalize[
FoldList[Times, 1, Table[p[(j-1)/n, #] / q[j/n, #], {j, n}]]
, Total]&, {0.01, 0.1, 0.2, 0.3, 0.4, 0.5}];
The limiting distribution of birth-death chains can be further characterized using results in Sandholm (2007).
2.5.9 https://math.libretexts.org/@go/page/123829
3.2.1. Deterministic approximations of transient dynamics when the population is large. The mean dynamic
When the number of agents is sufficiently large, the mean dynamic of the process provides a good deterministic approximation to the
dynamics of the stochastic evolutionary process over finite time spans. In this section we are going to analyze the behavior of our
evolutionary process as the population size becomes large, so we make this dependency on explicit by using superscripts for ,
and .
Let us start by illustrating the essence of the mean dynamic approximation with our running example where imitate-the-better-
realization agents are playing the coordination game [[1 0][0 2]] without noise. Initially, half the agents are playing strategy 1 (i.e.
). Figures 10, 11 and 12 show the expected proportion of 1-strategists against the number of revisions
(scaled by ), together with the 95% band for , for different population sizes.[12] Figure 10 shows the transient dynamics for
, figure 11 for and figure 12 for . These figures show exact results, computed as explained in section 3.1.2.
Figure 10. Expected proportion of agents playing strategy 1 and its 95% band (in yellow). Model: coordination game [[1 0][0 2]] played
by imitate-the-better-realization agents. Initially, half the population is using strategy 1.
Figure 11. Expected proportion of agents playing strategy 1 and its 95% band (in yellow). Model: coordination game [[1 0][0 2]] played
by imitate-the-better-realization agents. Initially, half the population is using strategy 1.
2.5.10 https://math.libretexts.org/@go/page/123829
Figure 12. Expected proportion of agents playing strategy 1 and its 95% band (in yellow). Model: coordination game [[1 0][0 2]] played
by imitate-the-better-realization agents. Initially, half the population is using strategy 1.
Looking at figures 10, 11 and 12 it is clear that, as the number of agents gets larger, the stochastc evolutionary process gets
closer and closer to its expected motion. The intuition is that, as the number of agents gets large, the fluctuations of the evolutionary
process around its expected motion tend to average out. In the limit when goes to infinity, the stochastic evolutionary process is
very likely to behave in a nearly deterministic way, mirroring a solution trajectory of a certain ordinary differential equation called the
mean dynamic.
To derive the mean dynamic of our 2-strategy evolutionary process, we consider the behavior of the process over the next
time units, departing from state . We define one unit of clock time as ticks, i.e. the time over which every agent is expected to
receive exactly one revision opportunity. Thus, over the time interval , the number of agents who are expected to receive a revision
opportunity is . Of these agents who revise their strategies, are expected to switch from strategy 0 to strategy 1 and
are expected to switch from strategy 1 to strategy 0. Hence, the expected change in the number of agents that are using
strategy 1 over the time interval is . Therefore, the expected change in the proportion of agents using strategy 1,
i.e. the expected change in state at , is
Note that the transition probabilities and may depend on . This does not represent a problem as long as this dependency
vanishes as gets large. In that case, to deal with that dependency, we take the limit of and as goes to infinity since,
after all, the mean dynamic approximation is only valid for large . Thus, defining
and
As an illustration of the usefulness of the mean dynamic to approximate transient dynamics, consider the simulations of the
coordination game example presented in section 2. We already computed the transition probabilities and for this model in
section 3.1.1:
where stands for the fraction of 1-strategists. The solution of the mean dynamic with initial condition is shown in figure 13
below. It is clear that the mean dynamic provides a remarkably good approximation to the average transient dynamics plotted in
2.5.11 https://math.libretexts.org/@go/page/123829
figures 1 and 3.[13] And, as we have seen, the greater the number of agents, the closer the stochastic process will get to its expeted
motion.
Figure 13. Trajectory of the mean dynamic of the example in section 2, showing the proportion of 1-strategists as a function of time
(rescaled to match figures 1 and 3).
Naturally, the mean dynamic can be solved for many different initial conditions, providing an overall picture of the transient dynamics
of the model when the population is large. Figure 14 below shows an illustration, created with the following Mathematica® code:
Plot[
Evaluate[
Table[
NDSolveValue[{x'[t] == x[t] (x[t] - 1) (x[t]^2 - 3 x[t] + 1),
x[0] == x0}, x, {t, 0, 10}][ticks/100]
, {x0, 0, 1, 0.01}]
], {ticks, 0, 1000}]
Figure 14. Trajectories of the mean dynamic of the example in section 2, showing the proportion of 1-strategists as a function of time
(rescaled to match figures 1 and 3) for different initial conditions.
The cut-off point that separates the set of trajectories that go towards state from those that will end up in state is easy to
derive, by finding the rest points of the mean dynamic:
2.5.12 https://math.libretexts.org/@go/page/123829
The three solutions in the interval are , and .
In this section we have derived the mean dynamic for our 2-strategy evolutionary process where agents switch strategies sequentially.
Note, however, that the mean dynamic approximation is valid for games with any number of strategies and even for models where
several revisions take place simultaneously (as long as the number of revisions is fixed as goes to infinity or the probability of
revision is ).
It is also important to note that, even though here we have presented the mean dynamic approximation in informal terms, the link
between the stochastic process and its relevant mean dynamic rests on solid theoretical grounds (see Benaïm & Weibull (2003),
Sandholm (2010, chapter 10) and Roth & Sandholm (2013)).
Finally, to compare agent-based simulations of the imitate-the-better-realization rule and its mean dynamics in 2×2 symmetric games,
you may want to play with the purpose-built demonstration titled Expected Dynamics of an Imitation Model in 2×2 Symmetric
Games. And to solve the mean dynamic of the imitate-the-better-realization rule in 3-strategy games, you may want to use this
demonstration.
where stands for the fraction of 1-strategists, i.e. “Hawk” agents.[14] Solving the mean dynamic reveals that most large-population
simulations starting with at least one “Hawk” and at least one “Dove” will tend to approach the state where half the population play
“Hawk” and the other play “Dove”, and stay around there for long. Figure 15 below shows several trajectories for different initial
conditions.
Figure 15. Trajectories of the mean dynamic of an imitate-the-better-realization Hawk-Dove game, showing the proportion of “Hawks”
as a function of time for different initial conditions. One unit of time corresponds to revisions.
Naturally, simulations do not get stuck in the half-and-half state, since agents keep revising their strategy in a stochastic fashion (see
figure 16). To understand this stochastic flow of agents between strategies near equilibria, it is necessary to go beyond the mean
dynamic. Sandholm (2003) shows that –under rather general conditions– stochastic finite-population dynamics near rest points can be
2.5.13 https://math.libretexts.org/@go/page/123829
approximated by a diffusion process, as long as the population size is large enough. He also shows that the standard deviations of
the limit distribution are of order .
To illustrate this order , we set up one simulation run starting with 10 agents playing “Hawk” and 10 agents playing “Dove”. This
state constitutes a so-called “Equilibrium”, since the expected change in the strategy distribution is zero. However, the stochasticity in
the revision protocol and in the matching process imply that the strategy distribution is in perpetual change. In the simulation shown
in figure 16, we modify the number of players at runtime. At tick 10000, we increase the number of players by a factor of 10 up to
200 and, after 10000 more ticks, we set n-of-players to 2000 (i.e., a factor of 10, again). The standard deviation of the fraction of
players using strategy “Hawk” (or “Dove”) during each of the three stages in our simulation run was: 0.1082, 0.0444 and 0.01167
respectively. As expected, these numbers are related by a factor of approximately .
Figure 16. A simulation run of an imitate-the-better-realization Hawk-Dove game, set up with 20 agents during the first 10000 ticks,
then 200 agents during the following 10000 ticks, and finally 2000 agents during the last 10000 ticks. Payoffs: [[2 1][3 0]]; prob-
revision: 0.01; noise 0; initial conditions [10 10].
As a matter of fact, Izquierdo et al. (2019, example 3.1) use the diffusion approximation to show that in the large limit, fluctuations
of this process around its unique interior rest point are approximately Gaussian with standard deviation .
2.5.14 https://math.libretexts.org/@go/page/123829
3.2.4 A final example
A fundamental feature of these models, but all too often ignored in applications, is that the
asymptotic behavior of the short-run deterministic approximation need have no connection
to the asymptotic behavior of the stochastic population process. Blume (1997, p. 443)
Consider the Hawk-Dove game analyzed in section 3.2.2, played by imitate-the-better-realization agents with noise = 10-10,
departing from an initial state where 28 agents are playing Hawk. Even though the population size is too modest for the mean
dynamic and the diffusion approximations to be accurate, this example will clarify the different time scales at which each of the
approximations is useful.
Let us review what we can say about this model using the three approximations discussed in the previous sections:
Mean dynamic. Figure 15 shows the mean dynamic of this model without noise. The noise we are considering here is so small
that the mean dynamic looks the same in the time interval shown in figure 15.[17] So, in our model with small noise, for large ,
the process will tend to move towards state , a journey that will take about revisions for our initial conditions
. The greater the , the closer the stochastic process will be to the solution trajectory of its mean dynamic.
Diffusion approximation. Once in the vicinity of the unique interior rest point , the diffusion approximation tells us that –
for large – the dynamics are well approximated by a Gaussian distribution with standard deviation .
Stochastic stability. Finally, we also know that, for a level of noise low enough (but strictly positive), the limiting distribution is
going to place most of its mass on the unique stochastically stable state, which is . So, eventually, the dynamics will approach
its limiting distribution, which –assuming the noise is low enough– places most of its mass on the monomorphic state .[18]
Each of these approximations refers to a different time scale. In this regard, we find the classification made by Binmore and
Samuelson (1994) and Binmore et al. (1995) very useful (see also Samuelson (1997) and Young (1998)). These authors distinguish
between the short run, the medium run, the long run and the ultralong run:
By the short run, we refer to the initial conditions that prevail when one begins one’s
observation or analysis. By the ultralong run, we mean a period of time long enough for the
asymptotic distribution to be a good description of the behavior of the system. The long run
refers to the time span needed for the system to reach the vicinity of the first equilibrium in
whose neighborhood it will linger for some time. We speak of the medium run as the time
intermediate between the short run [i.e. initial conditions] and the long run, during which
the adjustment to equilibrium is occurring. Binmore et al. (1995, p. 10)
Let us see these different time scales in our Hawk-Dove example. The following video shows the exact transient dynamics of this
model, computed as explained in section 3.1.2. Note that the video shows all the revisions up until , but then it moves faster
and faster. The blue progress bar indicates the number of revisions already shown.
0:00
Transient dynamics of a model where imitate-the-better-realization agents are playing a Hawk-Dove game, with noise= .
Each iteration corresponds to one revision.
In the video we can distinguish the different time scales:
The short run, which is determined by the initial conditions .
The medium run, which in this case spans roughly from to . The dynamics of this adjustment process towards
the equilibrium can be characterized by the mean dynamic, especially for large .
2.5.15 https://math.libretexts.org/@go/page/123829
The long run, which in this case refers to the dynamics around the equilibrium , spanning roughly from to
. These dynamics are well described by the diffusion approximation, especially for large .
The ultra long run, which in this case is not really reached until . It is not until then that the limiting distribution becomes a
good description of the dynamics of the model.
It is remarkable how long it takes for the infinite horizon prediction to hold force. Furthermore, the wait grows sharply as increases
and also as the level of noise decreases.[19] These long waiting times are typical of stochastic stability analyses, so care must be taken
when applying the conclusions of these analyses to real world settings.
In summary, as grows, both the mean dynamic and the difussion approximations become better. For any fixed , eventually, the
behavior of the process will be well described by its limiting distribution. If the noise is low enough (but strictly positive), the limiting
distribution will place most of its mass on the unique stochastically stable state . But note that, as grows, it will take
exponentially longer for the infinite-horizon prediction to kick in (see Sandholm and Staudigl (2018)).
Note also that for the limiting distribution to place most of its mass on the stochastically stable state, the level of noise has to be
sufficiently low, and if the population size increases, the maximum level of noise at which the limiting distribution concentrates
most of its mass on the stochastically stable state decreases. As an example, consider the same setting as the one shown in the video,
but with . In this case, the limiting distribution is completely different (see figure 17). A noise level of 10-10 is not enough for
the limiting distribution to place most of its mass on the stochastically stable state when .
Figure 17. Limiting distribution of a model where imitate-the-better-realization agents are playing a Hawk-Dove game, with
noise = 10-10.
Figure 17 has been created by running the following Mathematica® script:
n = 50;
noise = 10.^-10;
μ = Normalize[
FoldList[Times, 1, Table[p[(j-1)/n, noise] / q[j/n, noise], {j, n}]]
, Total];
4. Exercises
2.5.16 https://math.libretexts.org/@go/page/123829
Exercise 1. Consider the evolutionary process analyzed in section 3.1.2. Figure 5 shows that, if we start with half the population
using each strategy, the probability that the whole population will be using strategy 1 after 500 revisions is about 6.66%. Here we ask
you to use the NetLogo model implemented in the previous section to estimate that probability. To do that, you will have to set up and
run an experiment using BehaviorSpace.
Exercise 2. Derive the mean dynamic of a Prisoner’s Dilemma game for the imitate-the-better-realization protocol.
Exercise 3. Derive the mean dynamic of the coordination game discussed in section 0.1 (with payoffs [[1 0][0 2]]) for the imitative
pairwise-difference protocol.
Exercise 4. Derive the mean dynamic of the coordination game discussed in section 0.1 (with payoffs [[1 0][0 2]]) for the best
experienced payoff protocol.
1. This is the model implemented in the previous section. It can be downloaded here. Note that in this model agents switch strategies
sequentially, even when several revisions take place in the same tick. This is so because all relevant payoffs are computed just
before any single revision takes place, using the strategy distribution at the time of the revision. ↵
2. The standard error of the average equals the standard deviation of the sample divided by the square root of the sample size. In our
example, the maximum standard error was well below 0.01. ↵
3. This result can be easily derived using a "stars and bars" analogy. ↵
4. As an example, in a 4-strategy game with 1000 players, the number of possible states (i.e. strategy distributions) is
.↵
5. Note that the implementation of procedure to update-strategy in the model implemented in the previous section implies that agents
switch strategies sequentially. This is so because all relevant payoffs are computed just before any single revision takes place,
using the strategy distribution at the time of the revision. ↵
6. The only difference is that now we are asuming that there is exactly one revision per tick, while in the model simulated in section
2 agents sequentially revise their strategies with probability 0.01 in every tick. This difference is really just about what we decide
to call "tick". ↵
7. These probabilities are sometimes called "fixation probabilities". ↵
8. In terms of the transition probabilities and , adding noise implies that p(x)0" class="ql-img-inline-formula quicklatex-
auto-format" height="18" style="vertical-align: -4px;" title="Rendered by QuickLaTeX.com" width="66"
src="/@api/deki/files/108506/quicklatex.com-55b4009716026af0482010b65ecbae68_l3.png"> for (i.e. you can always move
one step to the right unless already equals 1), q(x)0" class="ql-img-inline-formula quicklatex-auto-format" height="18"
style="vertical-align: -4px;" title="Rendered by QuickLaTeX.com" width="65" src="/@api/deki/files/108508/quicklatex.com-
c20d07a68c98d93a4f2bb1b9e026f6a1_l3.png"> for x0" class="ql-img-inline-formula quicklatex-auto-format" height="12"
style="vertical-align: 0px;" title="Rendered by QuickLaTeX.com" width="43" src="/@api/deki/files/108509/quicklatex.com-
4d0528f1c8d6265b2860f59b7575cf72_l3.png"> (i.e. you can always move one step to the left unless already equals 0) and
for all (i.e. you can always stay where you are). ↵
9. Formally, the occupancy of state is defined as:
where denotes the number of times that the Markov chain visits state over the time span .↵
10. The second-largest eigenvalue modulus of the transition matrix determines the rate of convergence to the limiting distribution.
↵
11. For the derivation of this formula, see e.g. Sandholm (2010, example 11.A.10, p. 443). ↵
12. For each value of , the band is defined by the smallest interval that leaves less than 2.5% probability at both sides, i.e.
and \mathbb{P}(X_k j \,|\, X^N_0=0.5)<0.025" class="ql-img-inline-formula quicklatex-auto-format"
height="20" style="vertical-align: -5px;" title="Rendered by QuickLaTeX.com" width="230"
src="/@api/deki/files/108517/quicklatex.com-d7d682ed2c25cf72d936d285727d242b_l3.png">, with .↵
13. Note that one unit of clock time in the mean dynamic is defined in such a way that each player expects to receive one revision
opportunity per unit of clock time. In the model simulated in section 2, prob-revision = 0.01, so one unit of clock time corresponds
to 100 ticks (i.e. 1 / prob-revision). ↵
14. For details, see Izquierdo and Izquierdo (2013) and Loginov (2019). ↵
15. There are a number of different definitions of stochastic stability, depending on which limits are taken and in what order. For a
discussion of different definitions, see Sandholm (2010, chapter 12). ↵
16. To be precise, here we are considering stochastic stability in the small noise limit, where we fix the population size and take the
limit of noise to zero (Sandholm, 2010, section 12.1.1). The proof can be conducted using the concepts and theorems put forward
2.5.17 https://math.libretexts.org/@go/page/123829
by Ellison (2000). Note that the radius of the state where everyone plays Hawk is 2 (i.e. 2 mutations are needed to leave its basin
of attraction), while its coradius is just 1 (one mutation is enough to go from the state where everyone plays Dove to the state
where everyone plays Hawk). ↵
17. The only difference is that, in the model with noise, the two trajectories starting at the monomorphic states eventually converge to
the state , but this convergence cannot be appreciated in the time interval shown in figure 15. ↵
18. Using the analytic formula for the limiting distribution of irreducible and aperiodic birth-death chains provided in section 3.1.3, we
have checked that \mu(1)0.9" class="ql-img-inline-formula quicklatex-auto-format" height="18" style="vertical-align: -4px;"
title="Rendered by QuickLaTeX.com" width="80" src="/@api/deki/files/108519/quicklatex.com-
cec115c901c1ab72019d844e3444a6f7_l3.png"> for and noise = 10-10. ↵
19. Using tools from large deviations theory, Sandholm and Staudigl (2018) show that –for large population sizes – the time required
to reach the boundary is of an exponential order in . ↵
This page titled 2.5: Analysis of these models is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo,
Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the
LibreTexts platform; a detailed edit history is available upon request.
2.5.18 https://math.libretexts.org/@go/page/123829
CHAPTER OVERVIEW
This page titled 3: Spatial interactions on a grid is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R.
Izquierdo, Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards
of the LibreTexts platform; a detailed edit history is available upon request.
1
3.1: Spatial chaos in the Prisoner's Dilemma
1. Goal
The goal of this chapter is to learn how to build agent-based models with spatial structure. In models with spatial structure, agents do not interact with
all other agents with the same probability, but they interact preferentially with those who are nearby.[1]
More generally, populations where some pairs of agents are more likely to interact with each other than with others are called structured populations.
This contrasts with the random matching models developed in the previous chapter, where all members of the population were equally likely to
interact with each other.[2] The dynamics of an evolutionary process under random matching can be very different from the dynamics of the same
process in a structured population. In social dilemmas in particular, population structure can play a crucial role (Gotts et al. (2003), Hauert (2002,[3]
2006), Roca et al. (2009a, 2009b)).[4]
3.1.1 https://math.libretexts.org/@go/page/123830
Choose the dimensions of the world by clicking on the “Settings…” button on the top bar, or by right-clicking on the 2D view and choosing Edit.
A window will pop up, which allows you to choose the number of patches by setting the values of min-pxcor, max-pxcor, min-pycor and max-
pycor. You can also determine the patches’ size in pixels, and whether the grid wraps horizontally, vertically, both or none (see Topology section).
You can choose these parameters as in figure 2 below:
CODE
5. Code
5.1. Skeleton of the code
3.1.2 https://math.libretexts.org/@go/page/123830
5.2. Global variables and individually-owned variables
We will not need any global variables besides those defined with the sliders in the interface.
Note that in this model there is a one-to-one correspondence between our immobile players and the patches they live in. Thus, there is no need to
create any turtles (i.e. NetLogo mobile agents) in our model. We can work only with patches, and our code will be much simpler and readable.
Thus, we can make the built-in “patches” be the players, identifying each patch with one player. These patches already exist in NetLogo, making up
the world, so we do not need to create them. Having said that, we do need to associate with each patch all the information that we want it to carry.
This information will be:
Whether the patch is a C-player or D-player. For efficiency and code readability we can use a boolean variable to this end, which we can call C-
player? and which will take the value true or false.
Whether the patch will be a C-player or a D-player after its revision. For this purpose, we may use the boolean variable C-player?-after-revision.
This is needed because we want to model synchronous updating, i.e. we want all patches to change their strategy at the same time. To do this, first
we will ask all patches to compute the strategy they will adopt after the revision and, once all patches have computed their next strategy, we will
ask them all to switch to it at the same time.
The total payoff obtained by the patch playing with its neighbours. We can call this variable payoff.
For efficiency, it will also be useful to endow each patch with the set of neighbouring patches plus itself. The reason is that this set will be used
many times, and it never changes, so it can be computed just once at the beginning and stored in memory. We will store this set in a variable
named my-nbrs-and-me.
The following variable is also defined for efficiency reasons. Note that the payoff of a patch depends on the number of C-players and D-players in
its set my-nbrs-and-me. To spare the operation of counting D-players, we can calculate it as the number of players in my-nbrs-and-me (which does
not change in the whole simulation) minus the number of C-players. To this end, we can store the number of players in the set my-nbrs-and-me of
each patch as an individually-owned variable that we naturally name n-of-my-nbrs-and-me.
Thus, this part of the code looks as follows:
patches-own [
C-player?
C-player?-after-revision
payoff
my-nbrs-and-me
n-of-my-nbrs-and-me
]
clear-all
2. Set initial values for the variables that we have associated to each patch. We can set the payoff to 0,[5] and both C-player? and C-player-last? to
false (later we will ask some patches to set these values to true). To set the value of my-nbrs-and-me, NetLogo primitives neighbors and patch-set
are really handy.
ask patches [
set payoff 0
set C-player? false
set C-player?-after-revision false
set my-nbrs-and-me (patch-set neighbors self)
set n-of-my-nbrs-and-me (count my-nbrs-and-me)
]
3. Ask a certain number of randomly selected patches to be C-players. That number depends on the percentage initial-%-of-C-players chosen by the
user and on the total number of patches, and it must be an integer, so we can calculate it as:
3.1.3 https://math.libretexts.org/@go/page/123830
To randomly select a certain number of agents from an agentset (such as patches), we can use the primitive n-of (which reports another –usually
smaller– agentset). Thus, the resulting instruction will be:
4. Color patches according to the four possible combinations of values of C-player? and C-player?-after-revision. The color of a patch is controled by
the NetLogo built-in patch variable pcolor. A first (and correct) implementation of this task could look like:
ask patches [
ifelse C-player?-after-revision
[
ifelse C-player?
[set pcolor blue]
[set pcolor lime]
]
[
ifelse C-player?
[set pcolor yellow]
[set pcolor red]
]
]
However, the following implementation, which makes use of NetLogo primitive ifelse-value is more readable, as one can clearly see that the only
thing we are doing is to set the patch’s pcolor.
ask patches [
set pcolor
ifelse-value C-player?-after-revision
[ifelse-value C-player? [blue] [lime]]
[ifelse-value C-player? [yellow] [red]]
]
patches-own [
C-player?
C-player?-after-revision
payoff
my-nbrs-and-me
n-of-my-nbrs-and-me
]
to setup
clear-all
3.1.4 https://math.libretexts.org/@go/page/123830
setup-players
ask patches [update-color]
reset-ticks
end
to setup-players
ask patches [
set payoff 0
set C-player? false
set C-player?-after-revision false
set my-nbrs-and-me (patch-set neighbors self)
set n-of-my-nbrs-and-me (count my-nbrs-and-me)
]
ask n-of (round (initial-%-of-C-players * count patches / 100)) patches [
set C-player? true
set C-player?-after-revision true
]
end
to go
end
to update-color
set pcolor
ifelse-value C-player?-after-revision
[ifelse-value C-player? [blue] [lime]]
[ifelse-value C-player? [yellow] [red]]
end
5.4. Go procedure
The procedure to go contains all the instructions that will be executed in every tick. In this particular model, we will ask each player (i.e. patch):
1. To play with its neighbours in order to calculate its payoff. For modularity and clarity purposes, we should do this in a new procedure named to
play.
2. To compute the value of its next strategy and store it in the variable C-player?-after-revision. In this way, the variable C-player? will keep the
strategy with which the current payoff has been obtained, and we can update the value of C-player?-after-revision without losing that information,
which will be required by neighboring players when they compute their next strategy. To keep our code nice and modular, we will do this
computation in a new procedure called to update-strategy-after-revision.
3. To update its color according to their C-player? and C-player?-after-revision values, using the procedure to update-color.
4. To update its strategy (i.e. the value of C-player?). We will do this in a separate new procedure called to update-strategy.
We should also mark the end of the round, or tick, after all players have updated their strategies, using the primitive tick, which increases the tick
counter by one, and updates the graph on the interface. Thus, by now the code of procedure to go should look as follows:
to go
ask patches [ play ]
ask patches [
update-strategy-after-revision
;; here we are not updating the agent's strategy yet
update-color
]
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
tick
end
3.1.5 https://math.libretexts.org/@go/page/123830
5.5 Other procedures
to play
In procedure to play we want patches to calculate their payoff. This payoff will be the number of C-players in the set my-nbrs-and-me times the
payoff obtained with a C-player, plus the number of D-players in the set times the payoff obtained with a D-player.
We will store the number of C-players in the set my-nbrs-and-me in a local variable that we can name n-of-C-players. The number can be computed
as follows:
Note that if the calculating patch is a C-player, the payoff obtained when playing with another C-player is CC-payoff, and if the calculating patch is a
D-player, the payoff obtained when playing with a C-player is DC-payoff. Thus, in general, the payoff obtained when playing with a C-player can
then be obtained using the following code:
Taking all this into account, we can implement procedure to play as follows:[6]
to play
let n-of-C-players count my-nbrs-and-me with [C-player?]
set payoff n-of-C-players *
(ifelse-value C-player? [CC-payoff] [DC-payoff]) +
(n-of-my-nbrs-and-me - n-of-C-players) *
(ifelse-value C-player? [CD-payoff] [DD-payoff])
end
to update-strategy-after-revision
In this procedure, which will be run by individual patches, we want the patch to compute its next strategy, which will be the strategy used by one of
the patches with the maximum payoff in the set my-nbrs-and-me. To select one of these maximum-payoff patches, we may use primitives one-of and
with-max as follows:
Now remember that strategy updating in this model is synchronous, i.e. every player revises his strategy at the same time. Thus, we want each patch
to adopt the strategy that was used by the selected maximum-payoff patch when it played the game, i.e. before any strategy revision may have taken
place. This strategy is stored in variable C-player?. With this, we conclude the code of procedure to update-strategy-after-revision.
to update-strategy-after-revision
set C-player?-after-revision [C-player?] of one-of my-nbrs-and-me with-max [payoff]
end
Another (equivalent) implementation of this procedure, which makes use of primitive max-one-of is the following.
to update-strategy-after-revision
set C-player?-after-revision [C-player?] of max-one-of my-nbrs-and-me [payoff]
end
to update-strategy
This is a very simple procedure where the patch just updates its strategy (stored in variable C-player?) with the value of C-player?-after-revision. This
update is not conducted right after having computed the value of C-player?-after-revision to make the strategy updating synchronous.
3.1.6 https://math.libretexts.org/@go/page/123830
to update-strategy
set C-player? C-player?-after-revision
end
patches-own [
C-player?
C-player?-after-revision
payoff
my-nbrs-and-me
n-of-my-nbrs-and-me
]
to setup
clear-all
setup-players
ask patches [update-color]
reset-ticks
end
to setup-players
ask patches [
set payoff 0
set C-player? false
set C-player?-after-revision false
set my-nbrs-and-me (patch-set neighbors self)
set n-of-my-nbrs-and-me (count my-nbrs-and-me)
]
ask n-of (round (initial-%-of-C-players * count patches / 100)) patches [
set C-player? true
set C-player?-after-revision true
]
end
to go
ask patches [ play ]
ask patches [
update-strategy-after-revision
;; here we are not updating the agent's strategy yet
update-color
]
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
tick
end
to play
let n-of-C-players count my-nbrs-and-me with [C-player?]
set payoff n-of-C-players * (ifelse-value C-player? [CC-payoff] [DC-payoff]) +
(n-of-my-nbrs-and-me - n-of-C-players) * (ifelse-value C-player? [CD-payoff] [DD-payoff])
end
3.1.7 https://math.libretexts.org/@go/page/123830
to update-strategy-after-revision
set C-player?-after-revision [C-player?] of one-of my-nbrs-and-me with-max [payoff]
end
to update-strategy
set C-player? C-player?-after-revision
end
to update-color
set pcolor
ifelse-value C-player?-after-revision
[ifelse-value C-player? [blue] [lime]]
[ifelse-value C-player? [yellow] [red]]
end
6. Sample runs
We can use the model we have implemented to shed some light on the question that we posed at the motivation above. We will use the same
parameter values as Nowak and May (1992), so we can replicate their results: CD-payoff = DD-payoff = 0, CC-payoff = 1, DC-payoff = 1.85, and
initial-%-of-C-players = 90.[7] An illustration of the sort of patterns that this model generates is shown in the video below.
0:00
As you can see, both C-players and D-players coexist in this spatial environment, with clusters of both types of players expanding, colliding and
fragmenting. The overall fraction of C-players fluctuates around 0.318 for most initial conditions (Nowak and May, 1992). Thus, we can see that
adding spatial structure can make cooperation be sustained even in a population where agents can only play C or D (i.e. they cannot condition their
actions on previous moves).
3.1.8 https://math.libretexts.org/@go/page/123830
Incidentally, this model is also useful to see that a simple 2-player 2-strategy game in a two-dimensional spatial setting can generate chaotic and
kaleidoscopic patterns (Nowak and May, 1993). To illustrate this, let us use the same payoff values as before, but let us start with all agents playing C,
i.e. initial-%-of-C-players = 100.
When you click on setup, the whole world should look blue, since all agents are C-players. If you now click on go, nothing should happen, since all
agents are playing the same strategy and the strategy updating is imitative. To make things interesting, let us ask the agent at the center to play D. You
can do this by typing the following code at the Command Center (i.e. the line at the bottom of the NetLogo screen) after clicking on setup:
If you now click on go, you should see the following beautiful patterns:
0:00
7. Exercises
You can use the following link to download the complete NetLogo model: 2×2-imitate-best-nbr.
Exercise 1. Let us run a (weak) Prisoner’s Dilemma game with payoffs DD-payoff = CD-payoff = 0, CC-payoff = 1 and DC-payoff = 1.7. Set the
initial-%-of-cooperators to 90. Run the model and observe the evolution of the system as you gradually increase the value of DC-payoff from 1.7 to 2.
If at any point all the players adopt the same strategy, press the setup button again to start a new simulation. Compare your observations with those in
fig. 1 of Nowak and May (1992). Note: To use the same dimensions as Nowak and May (1992), you can change the location of the NetLogo world’s
origin to the bottom left corner, and set both the max-pxcor and the max-pycor to 199. You may also want to change the patch size to 2.
CODE
Exercise 2. Create a button to make the patch at 0 0 be a D-player. You may want to label it make agent at 0 0 play D. This button will be
useful to replicate some of the experiments in Nowak and May (1992, 1993).
Exercise 3. Replicate the experiment shown in figure 3 of Nowak and May (1992). Note that you will have to make the NetLogo world be a 99 ×
99 square lattice.
CODE
Exercise 4. Implement the following extension to Nowak and May (1992)‘s model, proposed by Mukherji et al. (1996):
With a small probability ε, each player errs and chooses evenly between strategies C and D; with
probability 1-ε, the player follows the Nowak and May update rule.
You may wish to rerun the sample run above with a small value for ε. You may also want to replicate the experiment shown in Mukherji et al. (1996,
fig. 1).
CODE Exercise 5. Implement the following extension to Nowak and May (1992)‘s model, proposed by Mukherji et al. (1996):
During each period, players fail to update their previous strategy with a small probability, θ.
You may wish to rerun the sample run above with a small value for θ. You may also want to replicate the experiment shown in Mukherji et al. (1996,
fig. 1).
CODE
Exercise 6. Implement the following extension to Nowak and May (1992)‘s model, proposed by Mukherji et al. (1996):
After following the Nowak and May update rule, each cooperator has a small independent probability, ϕ,
of cheating by switching to defection.
You may wish to rerun the sample run above with a small value for ϕ. You may also want to replicate the experiment shown in Mukherji et al. (1996,
fig. 1).
1. Note that in most evolutionary models there are two types of neighborhoods for each individual agent A:
the set of agents with whom agent A plays the game, and
the set of agents that agent A may observe at the time of revising his strategy.
Most often these two sets coincide for each individual agent, but that is not necessarily the case (see e.g. Ohtsuki et al. (2007a, b). ↵
2. Populations where all members are equally likely to interact with each other are sometimes called well-mixed populations. ↵
3. See Roca et al. (2009b) for an important and illuminating discussion of this paper. ↵
3.1.9 https://math.libretexts.org/@go/page/123830
4. Christoph Hauert has an excellent collection of interactive tutorials on this topic at his site EvoLudo (Hauert 2018). ↵
5. By default, user-defined variables in NetLogo are initialized with the value 0, so there is no actual need to explicitly set the initial value of
individually-owned variables to 0, but it does no harm either. ↵
6. The parentheses around the first ifelse-value block are necessary since NetLogo 6.1.0 (see
https://ccl.northwestern.edu/netlogo/docs/transition.html#changes-for-netlogo-610). ↵
7. Some authors make CD-payoff = DD-payoff, so they can parameterize the game with just one parameter, i.e. DC-payoff. Note, however, that the
resulting game lies at the border between a Prisoner's Dilemma and a Hawk-Dove (aka Chicken or Snowdrift) game. Making CD-payoff = DD-
payoff is by no means a normalization of the Prisoner's Dilemma, but a restriction which reduces the range of possibilities that can be studied. ↵
This page titled 3.1: Spatial chaos in the Prisoner's Dilemma is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo,
Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts platform; a
detailed edit history is available upon request.
3.1.10 https://math.libretexts.org/@go/page/123830
3.2: Robustness and fragility
1. Goal
Our goal in this section is to extend the model we have created in the previous section by adding three features that will prove very useful:
Noise, i.e. the possibility that revising agents select a strategy at random with a small probability.
Self-matching, i.e. the possibility to choose whether agents are matched with themselves to play the game or not.
Asynchronous strategy updating, i.e. the possibility that agents revise their strategies sequentially –rather than simultaneously– within the same tick.[1]
These three features will allow us to assess the robustness of our previous computational results.
CODE
4. Interface design
We depart from the model we developed in the previous section (so if you want to preserve it, now is a good time to duplicate it).
CODE
5. Code
3.2.1 https://math.libretexts.org/@go/page/123831
5.1. Skeleton of the code
to update-strategy-after-revision
set C-player?-after-revision [C-player?] of one-of my-nbrs-and-me with-max [payoff]
end
To implement the choice of a random strategy with probability noise by revising agents, we can use NetLogo primitive ifelse-value as follows:[2]
to update-strategy-after-revision
set C-player?-after-revision ifelse-value (random-float 1 < noise)
[ one-of [true false] ] ;; this is run with probability noise
[ [C-player?] of one-of (my-nbrs-and-me with-max [payoff]) ]
end
The noise extension is now ready, so you may want to explore the impact of noise in this model.
3.2.2 https://math.libretexts.org/@go/page/123831
It will also be convenient to define another patch variable named n-of-my-coplayers, which will store the cardinality of my-coplayers for each patch. This
is just for the same (efficiency) reasons we defined n-of-my-nbrs-and-me in the previous model. Now that we have variables my-coplayers and n-of-my-
coplayers, patch variable n-of-my-nbrs-and-me will no longer be needed. Thus, the definition of patch-own variables in the Code tab will look as follows:
patches-own [
C-player?
C-player?-after-revision
payoff
my-nbrs-and-me
my-coplayers ;; <== new variable
n-of-my-coplayers ;; <== new variable
;; n-of-my-nbrs-and-me <== not needed anymore
]
Now we have to set the value of the two new patch-own variables. Since these values will not change during the course of the simulation and they pertain
to the individual players, the natural place to set them is in procedure to setup-players.
to setup-players
ask patches [
set payoff 0
set C-player? false
set C-player?-after-revision false
set my-nbrs-and-me (patch-set neighbors self)
Finally, we have to modify procedure to play so patches play with agentset my-coplayers, rather than with agentset my-nbrs-and-me.
to play
let n-of-C-players count my-coplayers with [C-player?]
set payoff n-of-C-players * (ifelse-value C-player? [CC-payoff] [DC-payoff]) +
(n-of-my-coplayers - n-of-C-players) * ifelse-value C-player? [CD-payoff] [DD-payoff]
end
Note also that we have to replace the variable n-of-my-nbrs-and-me with n-of-my-coplayers when computing the payoff. You can now explore the
consequences of not forcing agents to play the game with themselves!
to go
ifelse synchronous-updating?
[
ask patches [ play ]
3.2.3 https://math.libretexts.org/@go/page/123831
ask patches [
update-strategy-after-revision
;; here we are not updating the agent's strategy yet
update-color
]
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
]
[
;; this is where we have to place the code
;; for asynchronous strategy updating
]
tick
end
The implementation of sequential updating requires that every patch (in a random order) goes through the whole cycle of playing and updating its
strategy without being interrupted. Note that, at the time of revising the strategy, agents will compare their payoff with their coplayers’ payoffs, so before
calling procedure update-strategy-after-revision we have to make sure that all these payoffs have been properly computed, i.e. we must ask the revising
agent and her coplayers to play the game. So basically, each patch, in sequential order, must:
play the game,
ask its coplayers to play the game (so their payoffs are updated),
run update-strategy-after-revision to compute its next strategy (C-player?-after-revision),
update its color (now that we have access both to the current strategy C-player? and to the next strategy C-player?-after-revision)
update its strategy, i.e. set the value of C-player? to C-player?-after-revision. This is done in procedure update-strategy.
Taking all this into account, the code in the procedure to go looks as follows:
to go
ifelse synchronous-updating?
[
ask patches [ play ]
ask patches [
update-strategy-after-revision
;; here we are not updating the agent's strategy yet
update-color
]
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
]
[
ask patches [
play
ask my-coplayers [ play ]
;; since your coplayers' strategies or
;; your coplayers' coplayers' strategies
;; could have changed since the last time
;; your coplayers played
update-strategy-after-revision
update-color
update-strategy
]
]
tick
end
3.2.4 https://math.libretexts.org/@go/page/123831
5.5. Complete code in the Code tab
The Code tab is ready! Congratulations! You have implemented three important generalizations of the model in very little time.
patches-own [
C-player?
C-player?-after-revision
payoff
my-nbrs-and-me
my-coplayers
n-of-my-coplayers
]
to setup
clear-all
setup-players
ask patches [update-color]
reset-ticks
end
to setup-players
ask patches [
set payoff 0
set C-player? false
set C-player?-after-revision false
set my-nbrs-and-me (patch-set neighbors self)
set my-coplayers ifelse-value self-matching? [my-nbrs-and-me] [neighbors]
set n-of-my-coplayers (count my-coplayers)
]
ask n-of (round (initial-%-of-C-players * count patches / 100)) patches [
set C-player? true
set C-player?-after-revision true
]
end
to go
ifelse synchronous-updating?
[
ask patches [ play ]
ask patches [
update-strategy-after-revision
;; here we are not updating the agent's strategy yet
update-color
]
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
]
[
ask patches [
play
ask my-coplayers [ play ]
;; since your coplayers' strategies or
;; your coplayers' coplayers' strategies
;; could have changed since the last time
;; your coplayers played
3.2.5 https://math.libretexts.org/@go/page/123831
update-strategy-after-revision
update-color
update-strategy
]
]
tick
end
to play
let n-of-cooperators count my-coplayers with [C-player?]
set payoff n-of-cooperators * (ifelse-value C-player? [CC-payoff] [DC-payoff]) +
(n-of-my-coplayers - n-of-cooperators) * ifelse-value C-player? [CD-payoff] [DD-payoff]
end
to update-strategy-after-revision
set C-player?-after-revision ifelse-value (random-float 1 < noise)
[ one-of [true false] ]
[ [C-player?] of one-of (my-nbrs-and-me with-max [payoff]) ]
end
to update-strategy
set C-player? C-player?-after-revision
end
to update-color
set pcolor
ifelse-value C-player?-after-revision
[ifelse-value C-player? [blue] [lime]]
[ifelse-value C-player? [yellow] [red]]
end
6. Sample runs
Now that we have implemented the extended model, we can use it to answer the questions posed in the motivation above. Let us see how the simulation
we ran in the previous section (with CD-payoff = DD-payoff = 0, CC-payoff = 1, DC-payoff = 1.85, and initial-%-of-C-players = 90 in a 81×81 grid) is
affected by each of the changes outlined in the motivation, one by one. We will refer to this parameterization as the baseline setting.
0:00
Therefore, it turns out that playing with oneself is a necessary condition to obtain some cooperation in the baseline setting.
3.2.6 https://math.libretexts.org/@go/page/123831
What happens if strategy updating is asynchronous, rather than synchronous?
The impact of synchronous-updating? on cooperation is also clear. If agents update their strategies sequentially, rather than simultaneously, no
cooperation whatsoever can be sustained in the baseline setting. This observation was pointed out by Huberman and Glance (1993). As a matter of fact,
to eliminate cooperation in this setting, it is sufficient that only a small fraction of the population (~15%) do not synchronize (Mukherji et al., 1996).[4]
0:00
Discussion
In this section we have discovered that the emergence of cooperation observed in the sample run of the previous section is not robust at all. Any of the
four modifications we have explored is sufficient to destroy cooperation altogether. Having said that, the emergence of cooperation in the spatially
embedded Prisoner’s Dilemma is much more robust for lower values of DC-payoff (see Nowak et al. (1994a, 1994b, 1996)). As an example, consider a
simulation with DC-payoff = 1.3, where we include the four modifications we have investigated, i.e. noise = 0.05, self-matching? = false, synchronous-
updating? = false, and DD-payoff = 0.1. The other parameter values are the same as in our baseline simulation, i.e. CD-payoff = 0, CC-payoff = 1, and
the grid is 81×81. Cooperation in this setting can indeed emerge and be sustained. The video below shows an illustrative run with initial conditions
initial-%-of-C-players = 25. The long-run proportion of cooperators in this setting is greater than 50%.
0:00
In section 2.3 we will see that there is another assumption in this model that has a very important (positive) influence in the emergence of cooperation:
the use of the “imitate the best neighbor” protocol. But for now, let us take a step back and think about what we have learned in this section in general
terms, i.e. beyond the specifics of this particular model.
In this section we have learned that assumptions that may seem irrelevant at first sight can actually play a crucial role in the dynamics of our models.
Furthermore, there are often complex interactions between the effects of different assumptions. We have also learned that small changes in one parameter
can lead to big changes in the dynamics of our models (see exercise 1 below for a striking example). Unfortunately, this sensitivity to seemingly small
details is not the exception but the rule in agent-based models. For this reason, it is of utmost importance to always check the robustness of our
computational results, to explore the parameter space adequately, and to keep our conclusions within the scope of what we have actually investigated, not
beyond.
7. Exercises
You can use the following link to download the complete NetLogo model: 2×2-imitate-best-nbr-extended.
3.2.7 https://math.libretexts.org/@go/page/123831
Photo by Tyler Easton on Unsplash
Exercise 1. Roca et al. (2009a, fig. 10; 2009b, fig. 2) report a counterintuitive singularity that we can replicate with our model. To do so, modify the
baseline setting (CD-payoff = DD-payoff = 0, CC-payoff = 1) by choosing self-matching? = false, make the world 100×100 with periodic (or ‘wrap-
around’) boundaries, and set initial conditions initial-%-of-C-players = 50. Now compare the long-run fraction of cooperators for values of DC-payoff
equal to 1.3999, 1.4 and 1.4001. What do you observe?
To understand this curious phenomenon, you may also want to run simulations with initial conditions initial-%-of-C-players = 100 and make use of our
button labeled make agent at 0 0 play D.
P.S. One may wonder whether this singularity could be an artifact due to floating-point errors, since (1.4 + 1.4 + 1.4 + 1.4 + 1.4) ≠ 7 in the IEEE754
floating-point standard (which is the standard used in most programming languages, and in NetLogo in particular).[6] You can check that the singularity is
not due to floating-point errors choosing an equivalent parameterization that is not prone to floating-point errors. Can you come up with an equivalent
parameterization that uses only integers when computing payoffs?
Exercise 2. Consider the simulation run from the previous section which produced the beautiful kaleidoscopic patterns. How does each of the four
modifications outlined in the motivation affect its dynamics?
Exercise 3. How can we parameterize our model to replicate the results shown in figure 2 of Killingback and Doebeli (1996, p. 1138)?
CODE Exercise 4. What changes should we make in the code to be able to replicate figure 3 of Killingback and Doebeli (1996, p. 1139)? Note that in
the model used to produce that figure, individual patches do not update their strategy with 5% probability.
CODE
Exercise 5. In section “Sample runs”, when we added some noise to the baseline setting, we stated that the percentage of cooperators in the
regime where cooperators and defectors coexist is about ~15% if noise = 0.04. Try to corroborate this estimation using BehaviorSpace.
CODE
Exercise 6. In our model, changing the value of noise has an immediate effect on the dynamics of the model at runtime. The same occurs with
synchronous-updating?, but not with self-matching?. How can you make the model respond immediately to changes in self-matching? ? Try to do it in a
way that does not affect the execution speed.
1. There are different ways one can implement asynchronicity. Here we implement what Cornforth et al. (2005) call "Random Asynchronous Order".
Under this scheme, at each tick all agents revise their strategy in a random order. ↵
2. We could also implement the noise extension using the NetLogo primitive ifelse, but the use of ifelse-value makes it clear that the only thing we are
doing in this procedure is to set the value of the patch variable C-player?-after-revision. ↵
3. The model with low noise seems to have two regimes, one where most agents are defecting and another one where cooperators and defectors coexist.
Simulations that start with a low percentage of initial cooperators tend to move first to the mostly-defection regime, while simulations that start with
higher proportions of initial cooperators tend to move to the coexistence regime. Note, however, that transitions from one regime to the other are
always possible with noise, and therefore they will occur if we wait for long enough. Having said that, the time we would have to wait to actually see
these transitions may be extremely long in some settings. Note also that the model with noise can be seen as an irreducible and aperiodic Markov
chain (see sufficient conditions for irreducibility and aperiodicity). This means that the long-run dynamics of this model are independent of initial
conditions. ↵
4. Newth and Cornforth (2009) analyze various other updating schemes in this model. ↵
5. If DD-payoff 0.58, no clusters of initial cooperators can survive, even in the absence of noise. ↵
6. Note that in our implementation of procedure to play we do not add individual payoffs but we multiply them, so we would not compute (1.4 + 1.4 +
1.4 + 1.4 + 1.4) but instead 5*1.4, which is indeed exactly equal to 7 in IEEE754 floating-point arithmetic. For more on the potential impact of
floating-point errors on agent-based models, see Polhill et al. (2006) and Izquierdo and Polhill (2006). ↵
This page titled 3.2: Robustness and fragility is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo, Segismundo S.
Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is
available upon request.
3.2.8 https://math.libretexts.org/@go/page/123831
3.3: Extension to any number of strategies
1. Goal
Our goal here is to extend the model we have created in the previous section –which accepted games with 2 strategies only– to model (2-player
symmetric) games with any number of strategies.
Hawk (H) -1 2 -1
Dove (D) 0 1 1
Retaliator (R) -1 1 1
Let us consider the population game where agents are matched to play the normal form game with payoffs as above.[1] The only Evolutionarily Stable
State (ESS; see Thomas (1984) and Sandholm (2010, section 8.3)) of this population game is the state (½H + ½D), with half the population playing Hawk
and the other half playing Dove (Maynard Smith (1982, appendix E), Binmore (2013)). Also, note that Retaliators are weakly dominated by Doves: they
get a strictly lower expected payoff than Doves in any situation, except in those population states with no Hawks whatsoever (at which retaliators get
exactly the same payoff as Doves).
Figure 1 below shows the best response correspondence of this game. Population states are represented in a simplex, and the color at any population state
indicates the strategy that provides the highest expected payoff at that state: orange for Hawk, green for Dove, and blue for Retaliator. As an example, the
population state where the three strategies are equally present, i.e. (⅓H + ⅓D +⅓R), which lies at the barycenter of the simplex, is colored in green,
denoting that the strategy that provides the highest expected payoff at that state is Dove.
Fig. 1. Best response correspondence for the Hawk-Dove-Retaliator game. Color indicates the strategy with the highest expected payoff
at each population state. Arrows are just a visual aid that indicate the direction of the best response. The yellow line indicates that both
Dove and Hawk are best response. The purple line indicates that both Dove and Retaliator are best response. All three strategies are best
response at the white circle at (⅔D +⅓R). Finally, the unique ESS (½H + ½D) is indicated with a red circle.
We would like to study the dynamic stability of the unique ESS (½H + ½D) in spatial contexts. In unstructured populations, ESSs are asymptotically
stable under a wide range of revision protocols (see e.g. Sandholm (2010, theorem 8.4.7)), and in particular under the best response protocol. Therefore,
one might be tempted to think that in our spatial model with the “imitate the best neighbor” protocol (including some noise to allow for the occasional
entry of any strategy), simulations will tend to spend most of the time around the unique (½H + ½D) and Retaliators would hardly be observed. This
hypothesis may be further supported by the fact that the area around the unique ESS where Retaliators are suboptimal is quite sizable. In no situation can
Retaliators obtain a higher expected payoff than Doves, and departing from the unique ESS, at least one half of the population would have to be replaced
(i.e. all the Hawks) for Retaliators to get the same expected payoff as Doves.
3.3.1 https://math.libretexts.org/@go/page/123832
Having seen all this, it may come as no surprise that if we simulate this game with the random-matching model we implemented in the previous chapter,
retaliators tend to disappear from any interior population state. The following video shows an illustrative simulation starting from a situation where all
agents are retaliators (and including some noise to allow for the entry of any strategy).[2]
0:00
So, will space give Retaliators any chance of survival? Let’s build a model to explore this question!
CODE
4. Interface design
We depart from the model we developed in the previous section (so if you want to preserve it, now is a good time to duplicate it).
CODE 5. Code
3.3.2 https://math.libretexts.org/@go/page/123832
5.1. Skeleton of the code
globals [
payoff-matrix
n-of-strategies
n-of-players
]
Now we focus on the patches-own variables. We are going to need each individual patch to store its strategy and its strategy-after-revision. These two
variables replace the previous C-player? and C-player?-after-revision. Thus, the code for patches-own variables looks as follows now:
patches-own [
;; C-player? <== no longer needed
;; C-player?-after-revision <== no longer needed
strategy ;; <== new variable
strategy-after-revision ;; <== new variable
3.3.3 https://math.libretexts.org/@go/page/123832
payoff
my-nbrs-and-me
my-coplayers
n-of-my-coplayers
]
to setup
clear-all
setup-players
ask patches [update-color]
reset-ticks
end
Clearly we will have to keep this code, but additionally we will have to set up the payoffs and set up the graph (since the number of pens to be created
depends on the payoff matrix now). To do this elegantly, we should create separate procedures for each set of related tasks; to setup-payoffs and to setup-
graph are excellent names for these new procedures. Thus, the code of procedure to setup should include calls to these new procedures:
to setup
clear-all
setup-payoffs ;; <== new line
setup-players
setup-graph ;; <== new line
reset-ticks
Note that we have also included a call to another new procedure named to update-graph, to plot the initial conditions.[3] The code of procedure to setup in
this model looks almost identical to the code of the same procedure in the model we developed in the previous chapter. As a matter of fact, we will be
able to reuse much of the code we wrote for that model. Let us now implement procedures to setup-payoffs, to setup-graph and to update-graph. We will
also have to modify procedures to setup-players and to update-color.
to setup-payoffs
The procedure to setup-payoffs will include the instructions to read the payoff matrix, and will also set the value of the global variable n-of-strategies.
Looking at the implementation of the same procedure in the model we developed in the previous chapter, can you implement procedure to setup-payoffs
for our new model?
Implementation of procedure to setup-payoffs.
to setup-players
The current procedure to setup-players looks as follows:
to setup-players
ask patches [
set payoff 0
set C-player? false
set C-player?-after-revision false
set my-nbrs-and-me (patch-set neighbors self)
set my-coplayers ifelse-value self-matching? [my-nbrs-and-me] [neighbors]
set n-of-my-coplayers (count my-coplayers)
]
ask n-of (round (initial-%-of-C-players * count patches / 100)) patches [
set C-player? true
3.3.4 https://math.libretexts.org/@go/page/123832
set C-player?-after-revision true
]
end
This procedure will have to be modified substantially. In particular, the lines in bold in the code above include variables that do not exist anymore. But
don’t despair! Once again, to modify procedure to setup-players appropriately, the implementation of the same procedure in the model we developed in
the previous chapter will be invaluable. Using that code, can you try to implement procedure to setup-players in our new model?
Implementation of procedure to setup-players.
to setup-graph
The procedure to setup-graph will create the required number of pens –one for each strategy– in the Strategy Distribution plot. Looking at the
implementation of the same procedure in the model we developed in the previous chapter, can you implement procedure to setup-graph for our new
model?
Implementation of procedure to setup-graph.
to update-graph
Procedure to update-graph will draw the strategy distribution using a stacked bar chart, just like in the model we implemented in the previous chapter (see
figure 3 in section 1.1). This procedure is called at the end of setup to plot the initial distribution of strategies, and will also be called at the end of
procedure to go, to plot the strategy distribution at the end of every tick.
Looking at the implementation of the same procedure in the model we developed in the previous chapter, can you implement procedure to update-graph
for our new model?
Implementation of procedure to update-graph.
to update-color
Note that in the previous model, patches were colored according to the four possible combinations of values of C-player? and C-player?-after-revision.
Now that there can be many strategies, it seems more natural to use one color for each strategy. It also makes sense to use the same color legend as in the
Strategy Distribution plot (see procedure to setup-graph). Can you try and implement the new version of to update-color?
Implementation of procedure to update-color.
5.4. Go procedure
The current go procedure looks as follows:
to go
ifelse synchronous-updating?
[
ask patches [ play ]
ask patches [
update-strategy-after-revision
;; here we are not updating the agent's strategy yet
update-color
]
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
]
[
ask patches [
play
ask my-coplayers [ play ]
;; since your coplayers' strategies or
;; your coplayers' coplayers' strategies
;; could have changed since the last time
;; your coplayers played
update-strategy-after-revision
update-color
update-strategy
]
3.3.5 https://math.libretexts.org/@go/page/123832
]
tick
end
In the previous version of the model, the call to update-color had to be done in between the calls to update-strategy-after-revision and update-strategy.
Now that the patches’ color only depends on their (updated) strategy, we should ask patches to run update-color at the end of procedure to go, after every
patch has updated its strategy.
Finally, recall that we also have to run update-graph at the end of procedure to go, to plot the strategy distribution at the end of every tick. Thus, the code
of procedure to go will be as follows:
to go
ifelse synchronous-updating?
[
ask patches [ play ]
ask patches [ update-strategy-after-revision ]
;; here we are not updating the agent's strategy yet
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
]
[
ask patches [
play
ask my-coplayers [ play ]
;; since your coplayers' strategies or
;; your coplayers' coplayers' strategies
;; could have changed since the last time
;; your coplayers played
update-strategy-after-revision
update-strategy
]
]
tick
update-graph ;; <== new line
ask patches [update-color] ;; <== new line
end
Thus, we just have to run this little function for each value of i ∈ {0, 1, …, (n-of-strategies – 1)} . This can be easily done using primitive n-values:
The code above produces a list with the number of coplayers that are using each strategy. Let us store this list in local variable n-of-coplayers-with-
strategy-?:
Now note that the relevant row of the payoff-matrix is the one at position strategy. We store this row in local variable my-payoffs:
3.3.6 https://math.libretexts.org/@go/page/123832
let my-payoffs (item strategy payoff-matrix)
Finally, the payoff that the patch will get for each coplayer playing strategy i is the i-th element of the list my-payoffs, so we only have to multiply the
two lists (my-payoffs and n-of-coplayers-with-strategy-?) element by element, and add up all the elements in the resulting list. To multiply the two lists
element by element we use primitive map:
to play
let n-of-coplayers-with-strategy-? n-values n-of-strategies [ i ->
count my-coplayers with [strategy = i] ]
let my-payoffs (item strategy payoff-matrix)
set payoff sum (map * my-payoffs n-of-coplayers-with-strategy-?)
end
to update-strategy-after-revision
Right now, procedure to update-strategy-after-revision is implemented as follows:
to update-strategy-after-revision
set C-player?-after-revision ifelse-value (random-float 1 < noise)
[ one-of [true false] ]
[ [C-player?] of one-of (my-nbrs-and-me with-max [payoff]) ]
end
to update-strategy
Right now, procedure to update-strategy is implemented as follows:
to update-strategy
set C-player? C-player?-after-revision
end
globals [
payoff-matrix
n-of-strategies
n-of-players
]
patches-own [
strategy
strategy-after-revision
payoff
my-nbrs-and-me
my-coplayers
n-of-my-coplayers
]
3.3.7 https://math.libretexts.org/@go/page/123832
to setup
clear-all
setup-payoffs
setup-players
setup-graph
reset-ticks
update-graph
ask patches [update-color]
end
to setup-payoffs
set payoff-matrix read-from-string payoffs
set n-of-strategies length payoff-matrix
end
to setup-players
let initial-distribution read-from-string n-of-players-for-each-strategy
if length initial-distribution != length payoff-matrix [
user-message (word "The number of items in\n"
"n-of-players-for-each-strategy (i.e. "
length initial-distribution "):\n" n-of-players-for-each-strategy
"\nshould be equal to the number of rows\n"
"in the payoff matrix (i.e. "
length payoff-matrix "):\n"
payoffs
)
]
3.3.8 https://math.libretexts.org/@go/page/123832
to setup-graph
set-current-plot "Strategy Distribution"
foreach (range n-of-strategies) [ i ->
create-temporary-plot-pen (word i)
set-plot-pen-mode 1
set-plot-pen-color 25 + 40 * i
]
end
to go
ifelse synchronous-updating?
[
ask patches [ play ]
ask patches [ update-strategy-after-revision ]
;; here we are not updating the agent's strategy yet
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
]
[
ask patches [
play
ask my-coplayers [ play ]
;; since your coplayers' strategies or
;; your coplayers' coplayers' strategies
;; could have changed since the last time
;; your coplayers played
update-strategy-after-revision
update-strategy
]
]
tick
update-graph
ask patches [update-color]
end
to play
let n-of-coplayers-with-strategy-? n-values n-of-strategies [ i ->
count my-coplayers with [strategy = i] ]
let my-payoffs (item strategy payoff-matrix)
set payoff sum (map * my-payoffs n-of-coplayers-with-strategy-?)
end
to update-strategy-after-revision
set strategy-after-revision ifelse-value (random-float 1 < noise)
[ random n-of-strategies ]
[ [strategy] of one-of my-nbrs-and-me with-max [payoff] ]
end
to update-strategy
set strategy strategy-after-revision
end
to update-graph
let strategy-numbers (range n-of-strategies)
3.3.9 https://math.libretexts.org/@go/page/123832
let strategy-frequencies map [ n ->
count patches with [strategy = n] / n-of-players ] strategy-numbers
to update-color
set pcolor 25 + 40 * strategy
end
6. Sample runs
Now that we have implemented the model we can explore the dynamics of the spatial Hawk-Dove-Retaliator game! Will Retaliators survive in a spatial
context? Let us explore this question using the parameter values shown in figure 2 above. Get ready… because the results are going to blow your mind!
0:00
Unbelievable! Retaliators do not only survive, but they are capable of taking over about half the population. Is this observation robust? If you modify the
parameters of the model you will see that indeed it is. The following video shows an illustrative run with noise = 0.05, synchronous-updating? = false and
self-matching? = false.
0:00
The greater level of noise means that more Hawks appear by chance. This harms Retaliators more than it harms Doves, but Retaliators still manage to
stay the most prevalent strategy in the population. How can this be?
First, note that even though the state where the whole population is choosing Retaliator is not an ESS, it is a Neutrally Stable State (Sandholm, 2010, p.
82). And, crucially, it is the only pure state that is Nash (i.e. the only pure strategy that is best response to itself). Note that in spatial contexts neighbors
face similar situations when playing the game (since their neighborhoods overlap). Because of this, it is often the case that neighbors choose the same
strategy, and therefore clusters of agents using the same strategy are common. In the Hawk-Dove-Retaliator game, clusters of Retaliators are more stable
than clusters of Doves (which are easily invadable by Hawks) and also more stable than clusters of Hawks (which are easily invadable by Doves). This
partially explains the amazing success of Retaliators in spatial contexts, even though they are weakly dominated by Doves.
7. Exercises
3.3.10 https://math.libretexts.org/@go/page/123832
You can use the following link to download the complete NetLogo model: nxn-imitate-best-nbr.
Can you implement the same functionality using the primitive map instead of n-values?
CODE
Exercise 5. Reimplement the procedure to update-strategy-after-revision so the revising agent uses the imitative pairwise-difference protocol
adapted to networks, i.e. the revising agent looks at a random neighbor and copies her strategy only if the observed agent’s average payoff is higher than
the revising agent’s average payoff; in that case, the revising agent switches with probability proportional to the payoff difference.
1. The payoff function of the associated population game is , where denotes the population state and denotes the payoff matrix of the
normal form game. This population game can be obtained by assuming that every agent plays with every other agent. ↵
2. The fact that the simulation tends to linger around the ESS is a coincidence, since the imitate-the-better-realization protocol depends only on ordinal
properties of the payoffs. What is not a coincidence is that Retaliators (which are weakly dominated by Doves) are eliminated in the absence of noise
(Loginov, 2019). ↵
3. There is some flexibility in the order of the lines within procedure to setup. For instance, the call to procedure setup-graph could be made before or
after executing reset-ticks. ↵
This page titled 3.3: Extension to any number of strategies is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R. Izquierdo,
Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts platform; a
detailed edit history is available upon request.
3.3.11 https://math.libretexts.org/@go/page/123832
3.4: Other types of neighborhoods and other revision protocols
1. Goal
Our goal in this section is to extend the model we have created in the previous section by adding two features that are crucial to assess the impact of
space on evolutionary models:
The possibility to model different types of neighborhoods of arbitrary size. Besides Moore neighborhoods, we will implement Von Neumann
neighborhoods, and both of them of any size.
The possibility to model other revision protocols besides the “imitate the best neighbor” protocol. In particular, we will implement the imitative
pairwise-difference protocol, the imitative positive-proportional protocol, and the imitative logit protocol.[1]
In what concerns the Prisoner’s Dilemma, the above results also prove that the promotion of cooperation in
this game is not robust against changes in the update rule, because the beneficial effect of spatial lattices
practically disappears for rules different from unconditional imitation, when seen in the wider scope of the
ST plane. Roca et al. (2009b, p. 9)
In this section we are going to implement several revision protocols. This will allow us to replicate Roca et al.’s (2009a, 2009b) results… and many
others (see the proposed exercises).
CODE
4. Interface design
We depart from the model we developed in the previous section (so if you want to preserve it, now is a good time to duplicate it).
3.4.1 https://math.libretexts.org/@go/page/123833
Figure 1. Interface design.
In the new interface (see figure 1 above), we have to add:
One chooser for new parameter neighborhood-type (with possible values “Moore” and “Von Neumann“), and a slider for parameter neighborhood-
range (with minimum = 1 and increment = 1).
One chooser for new parameter protocol (with possible values “best-neighbor“, “imitative-pairwise-difference“, “imitative-positive-proportional-m”
and “imitative-logit-m“), and a slider for parameter m (with minimum = 0 and increment = 0.1).
We have also added a button (labeled show player’s neighborhood) to see any patch’s neighborhood on the 2D view and another button (labeled clear) to
clear the display of the neighborhood.
CODE 5. Code
5.1. Skeleton of the code
The skeleton of the code for procedures to setup and to go is the same as in the previous model. In this section we will modify mainly the following two
procedures:
procedure to setup-players, to set the players’ neighborhoods according to parameters neighborhood-type and neighborhood-range (see figure 2).
3.4.2 https://math.libretexts.org/@go/page/123833
5.2. Extension I. Implementation of different neighborhoods
Recall that patches have the following two individually owned variables:
my-coplayers, which contains the set of agents with whom the patch plays the game (and is affected by parameter self-matching?), and
my-nbrs-and-me, which is the set of agents the player considers when revising its strategy.
These two agentsets are the same if self-matching? is true, and differ only in the focal patch if self-matching? is false. We will keep this distinction for
any type of neighborhood.
To implement the different neighborhoods, primitive at-points will be very useful. This primitive reports a subset of a given agentset that includes only
the agents on the patches at the given coordinates (relative to the calling agent). As an example, the following code gives a patch’s Von Neumann
neighborhood of range 1 (including the patch itself):
And the following code gives a patch’s Moore neighborhood of range 1 (including the patch itself):
Thus, the key is to implement procedures that report the appropriate lists of relative coordinates.[9] Let’s do this!
Below we provide some examples of what reporter to-report moore-offsets should produce:
If r = 1 and include-center? is true:
[[-2 -2] [-2 -1] [-2 0] [-2 1] [-2 2] [-1 -2] [-1 -1] [-1 0] [-1 1] [-1 2] [0 -2] [0 -1] [0 0] [0
Note that the effect of input include-center? is just to include or exclude [0 0] from the output list, so we can worry about that at the end of the
implementation. To produce the list of Moore offsets for range r, we can start building the list l = [ –r, –r+1, …, r-1, r ] and then build 2-item lists which
each element of the list l together with each element of the same list l. Thus, let us build the list l = [ –r, –r+1, …, r-1, r ]:
To build 2-items lists with first element el1 and second element each of the elements of list l, we can use primitive map as follows:
And now we should make el1 be each of the elements of list l. For this we can use primitive map again:
The only problem now is that we have several nested lists. For example, the code above for l = [ -1, 0, 1 ] produces:
[[[-1 -1] [-1 0] [-1 1]] [[0 -1] [0 0] [0 1]] [[1 -1] [1 0] [1 1]]]
3.4.3 https://math.libretexts.org/@go/page/123833
Note that the outmost list contains three sublists, each of which contains three 2-item lists. We can get rid of the extra lists using primitives reduce and
sentence:
let result reduce sentence map [ el1 -> map [el2 -> list el1 el2] l] l
The code above creates the list of required offsets, including [0 0]. Now we just have to remove [0 0] if and only if input include-center? is false. Thus,
the final code for reporter to-report moore-offsets is as follows:
Note that, for any given r and include-center?, the list of offsets for a Von Neumann neighborhood is a subset of the list of offsets for the corresponding
Moore neighborhood. In particular, the list of Von Neumann offsets is composed of the elements [el1 el2] in the list of Moore offsets that satisfy the
condition |el1| + |el2| ≤ r . Thus, we can create the corresponding list of Moore offsets and filter those coordinates that satisfy the condition using
primitive filter. Do you want to give it a try?
Implementation of procedure to-report von-neumann-offsets
to setup-players
let initial-distribution read-from-string n-of-players-for-each-strategy
if length initial-distribution != length payoff-matrix [
user-message (word "The number of items in\n"
"n-of-players-for-each-strategy (i.e. "
length initial-distribution "):\n" n-of-players-for-each-strategy
"\nshould be equal to the number of rows\n"
"in the payoff matrix (i.e. "
length payoff-matrix "):\n"
payoffs
)
]
3.4.4 https://math.libretexts.org/@go/page/123833
ask patches [set strategy false]
let i 0
let offsets ifelse-value (neighborhood-type = "Von Neumann")
[ von-neumann-offsets neighborhood-range self-matching? ]
[ moore-offsets neighborhood-range self-matching? ]
Note that variable my-coplayers may or may not contain the patch itself (depending on the value of parameter self-matching?), but variable my-nbrs-and-
me will always contain it, since we are setting its value to (patch-set my-coplayers self). This is perfectly fine even if my-coplayers already contains the
patch itself, since agentsets do not contain duplicates. Adding an agent a to an agentset that already contains that agent a has no effect whatsoever.[10]
to show-neighborhood
if mouse-down? [
ask patch mouse-xcor mouse-ycor [
ask my-coplayers [set pcolor white]
]
]
display
end
You may want to read the documentation for primitives mouse-down?, mouse-xcor and mouse-ycor. Basically, this procedure paints in white the patches
contained in the variable my-coplayers of the patch you click with your mouse. However, for this to work, the procedure must be running all the time. To
do this, we can run this procedure within the button labeled show player’s neighborhood in the interface, and make this button be a “forever” button.
Insert the following code within the button labeled show player’s neighborhood:
with-local-randomness [show-neighborhood]
The use of primitive with-local-randomness guarantees that this piece of code does not interfere with the generation of pseudorandom numbers for the
rest of the model.
To clear the white paint, insert the following code within the button labeled clear (which should not be a “forever” button):
Figure 4 shows a patch’s Von Neumann neighborhood of range 5 (excluding the patch itself) painted in white.
3.4.5 https://math.libretexts.org/@go/page/123833
Figure 4. The 2D view shows in white a patch’s set my-coplayers. Relevant parameters: neighborhood-type = “Von Neumann“, neighborhood-range =
5, and self-matching? = false.
to update-strategy-after-revision
ifelse (random-float 1 < noise)
[ set strategy-after-revision random n-of-strategies ]
[
;; code to set strategy-after-revision
;; using the revision protocol indicated by the user
;; through parameter protocol
]
end
To make the implementation of revision protocols elegant and modular, we should implement a different procedure for each revision protocol. Let us call
these procedures: best-neighbor-protocol, imitative-pairwise-difference-protocol, imitative-positive-proportional-m-protocol and imitative-logit-m-
protocol. With these procedures in place, the code for procedure to update-strategy-after-revision would just look as follows:
to update-strategy-after-revision
ifelse (random-float 1 < noise)
[ set strategy-after-revision random n-of-strategies ]
[ (ifelse
protocol = "best-neighbor"
[ best-neighbor-protocol ]
protocol = "imitative-pairwise-difference"
[ imitative-pairwise-difference-protocol ]
protocol = "imitative-positive-proportional-m"
[ imitative-positive-proportional-m-protocol ]
protocol = "imitative-logit-m"
[ imitative-logit-m-protocol ]
)
]
end
Note that primitive ifelse can work with multiple conditions, just like switch statements in other programming languages.[11]
Now we just have to implement the procedures for each of the four revision protocols. Do you want to give it a try? The first one is not very difficult.
3.4.6 https://math.libretexts.org/@go/page/123833
Implementation of procedure to best-neighbor-protocol
The implementation of procedure to imitative-pairwise-difference-protocol is significantly more difficult than the previous one, but if you have managed
to read this book until here, you certainly have what it takes to do it!
Implementation of procedure to imitative-pairwise-difference-protocol
To implement procedure to imitative-positive-proportional-m-protocol, there is an extension that comes bundled with NetLogo which will make our life
much easier: extension rnd. To use it, you just have to add the following line at the beginning of your code
extensions [rnd]
Having loaded the rnd extension, you can use primitive rnd:weighted-one-of, which will be very handy. With this information, you may want to try to
implement this short procedure yourself.
Implementation of procedure to imitative-positive-proportional-m-protocol
The implementation of procedure to imitative-logit-m-protocol is not extremely hard after having seen the implementation of to imitative-pairwise-
difference-protocol, and realizing that .
Implementation of procedure to imitative-logit-m-protocol
globals [
payoff-matrix
n-of-strategies
n-of-players
max-payoff-difference ;; <== New line
]
patches-own [
strategy
strategy-after-revision
payoff
my-nbrs-and-me
my-coplayers
n-of-my-coplayers
]
to setup
clear-all
setup-payoffs
setup-players
setup-graph
reset-ticks
update-graph
ask patches [update-color]
end
to setup-payoffs
set payoff-matrix read-from-string payoffs
set n-of-strategies length payoff-matrix
3.4.7 https://math.libretexts.org/@go/page/123833
if protocol = "imitative-positive-proportional-m"
[ check-payoffs-are-non-negative ]
end
to setup-players
let initial-distribution read-from-string n-of-players-for-each-strategy
if length initial-distribution != length payoff-matrix [
user-message (word "The number of items in\n"
"n-of-players-for-each-strategy (i.e. "
length initial-distribution "):\n" n-of-players-for-each-strategy
"\nshould be equal to the number of rows\n"
"in the payoff matrix (i.e. "
length payoff-matrix "):\n"
payoffs
)
]
to setup-graph
set-current-plot "Strategy Distribution"
foreach (range n-of-strategies) [ i ->
create-temporary-plot-pen (word i)
set-plot-pen-mode 1
set-plot-pen-color 25 + 40 * i
]
3.4.8 https://math.libretexts.org/@go/page/123833
end
to go
ifelse synchronous-updating?
[
ask patches [ play ]
ask patches [ update-strategy-after-revision ]
;; here we are not updating the agent's strategy yet
ask patches [ update-strategy ]
;; now we update every agent's strategy at the same time
]
[
ask patches [
play
ask my-coplayers [ play ]
;; since your coplayers' strategies or
;; your coplayers' coplayers' strategies
;; could have changed since the last time
;; your coplayers played
update-strategy-after-revision
update-strategy
]
]
tick
update-graph
ask patches [update-color]
end
to play
let n-of-coplayers-with-strategy-? n-values n-of-strategies [ i ->
count my-coplayers with [strategy = i] ]
let my-payoffs (item strategy payoff-matrix)
set payoff sum (map * my-payoffs n-of-coplayers-with-strategy-?)
end
to update-strategy-after-revision
ifelse (random-float 1 < noise)
[ set strategy-after-revision random n-of-strategies ]
[ (ifelse
protocol = "best-neighbor"
[ best-neighbor-protocol ]
protocol = "imitative-pairwise-difference"
[ imitative-pairwise-difference-protocol ]
protocol = "imitative-positive-proportional-m"
[ imitative-positive-proportional-m-protocol ]
protocol = "imitative-logit-m"
[ imitative-logit-m-protocol ]
)
]
end
to best-neighbor-protocol
set strategy-after-revision
[strategy] of one-of my-nbrs-and-me with-max [payoff]
end
3.4.9 https://math.libretexts.org/@go/page/123833
to imitative-pairwise-difference-protocol
let observed-player one-of other my-coplayers
set strategy-after-revision
ifelse-value (random-float 1 < (payoff-diff / max-payoff-difference))
[ [strategy] of observed-player ]
[ strategy ]
;; If your strategy is the better, payoff-diff is negative,
;; so you are going to stick with it.
;; If it's not, you switch with probability
;; (payoff-diff / max-payoff-difference)
end
to imitative-positive-proportional-m-protocol
let chosen-nbr rnd:weighted-one-of my-nbrs-and-me [ payoff ^ m ]
;; https://ccl.northwestern.edu/netlogo/docs/rnd.html#rnd:weighted-one-of
set strategy-after-revision [strategy] of chosen-nbr
end
to imitative-logit-m-protocol
let observed-player one-of other my-coplayers
set strategy-after-revision
ifelse-value (random-float 1 < (1 / (1 + exp (- m * payoff-diff))))
[ [strategy] of observed-player ]
[ strategy ]
end
to update-strategy
set strategy strategy-after-revision
end
to update-graph
let strategy-numbers (range n-of-strategies)
let strategy-frequencies map [ n ->
count patches with [strategy = n] / n-of-players ] strategy-numbers
3.4.10 https://math.libretexts.org/@go/page/123833
set-plot-y-range 0 1
end
to update-color
set pcolor 25 + 40 * strategy
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; SUPPORTING PROCEDURES ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to show-neighborhood
if mouse-down? [
ask patch mouse-xcor mouse-ycor [
ask my-coplayers [set pcolor white]
]
]
display
end
to check-payoffs-are-non-negative
if min reduce sentence payoff-matrix < 0 [
user-message (word
"Since you are using protocol = imitative-positive-proportional-m, all elements in the payoff m
payoffs
"\nshould be non-negative numbers.")
]
end
;;;;;;;;;;;;;;;;
;;; Matrices ;;;
;;;;;;;;;;;;;;;;
3.4.11 https://math.libretexts.org/@go/page/123833
6. Sample runs
Revision protocols
Now that we have implemented the model, we can explore the impact of the revision protocol on the promotion of cooperation in the spatially embedded
Prisoner’s Dilemma. Let us explore this question using the parameter values shown in figure 1 above. We start with the “imitate the best neighbor”
protocol. The simulation below shows a representative run.
0:00
As you can see in the video above, with the “imitate the best neighbor” protocol, high levels of cooperation are achieved (i.e. about 90% of the patches
cooperate in the long run). But, how robust is this result to changes in the revision protocol? To explore this question, let us run the same simulation with
the other three revision protocols we have implemented. The simulation below shows a representative run with the “imitative-pairwise-difference”
protocol.
0:00
With the “imitative-pairwise-difference” protocol, there is no cooperation at all in the long run. Let us now try the “imitative-positive-proportional-m”
protocol with m = 1:[12]
0:00
We do not observe any cooperation at all with the “imitative-positive-proportional-m” (with m = 1) either. Finally, let us try the “imitative-logit-m”
protocol with m = 1 (or any other positive value, for that matter):[13]
0:00
And we observe universal defection again! Clearly, as Roca et al. (2009a, 2009b) point out, the “imitate the best neighbor” protocol seems to favor
cooperation in the Prisoner’s Dilemma more than other revision protocols.
Neighborhoods
What about if we change the type of neighborhood? You can check that the simulations shown in the videos above do not change qualitatively if we use
Von Neumann neighborhoods rather than Moore neighborhoods. However, what does make a difference is the size of the neighborhood. Note that if the
size is so large that agents’ neighborhoods encompass the whole population, we have a global interaction model (i.e. a model without population
structure). Thus, the size of the neighborhood allows us to study the effect of population structure in a gradual manner. Having seen this, we can predict
3.4.12 https://math.libretexts.org/@go/page/123833
that, for the “imitate the best neighbor” protocol, if we increase the size of the neighborhood enough, at some point cooperation will disappear. As an
exercise, try to find the minimum neighborhood-range (for both types of neighborhood) at which cooperation cannot be sustained anymore, with the other
parameter values as shown in figure 1.
Critical neighborhood size at which cooperation does not emerge in the simulation parameterized as in figure 1.
Discussion
We would like to conclude this section emphasizing that the influence of population structure on evolutionary dynamics generally depends on many
factors that may seem insignificant at first sight, and whose effects interact in complex ways. This may sound discouraging, since it suggests that a simple
general theory of the influence of population structure on evolutionary dynamics cannot be derived. On a more positive note, it also highlights the
importance of the skills you are learning with this book. Without the aid of computer simulation, it seems impossible to explore this type of questions.
But using computer simulation we can gain some understanding of the complexity and the beauty of these apparently simple –yet surprisingly intricate–
systems. The following quote from Roca et al. (2009b) nicely summarizes this view.
To conclude, we must recognize the strong dependence on details of evolutionary games on spatial networks.
As a consequence, it does not seem plausible to expect general laws that could be applied in a wide range of
practical settings. On the contrary, a close modeling including the kind of game, the evolutionary dynamics
and the population structure of the concrete problem seems mandatory to reach sound and compelling
conclusions. With no doubt this is an enormous challenge, but we believe that this is one of the most
promising paths that the community working in the field can explore. Roca et al. (2009b, pp. 14-15)
7. Exercises
You can use the following link to download the complete NetLogo model: nxn-imitate-best-nbr-extended.
[ (ifelse
protocol = "best-neighbor"
[ best-neighbor-protocol ]
protocol = "imitative-pairwise-difference"
[ imitative-pairwise-difference-protocol ]
protocol = "imitative-positive-proportional-m"
[ imitative-positive-proportional-m-protocol ]
3.4.13 https://math.libretexts.org/@go/page/123833
protocol = "imitative-logit-m"
[ imitative-logit-m-protocol ]
)
]
1. The names given to the different protocols follow Izquierdo et al. (2019). ↵
2. Recall that the set of patches that a patch plays with also depends on the value of self-matching?. ↵
3. Roca et al. (2009a, 2009b) call this revision protocol "unconditional imitation" and Hauert (2002) calls it "best takes over". Also, note that Hauert
(2002) resolves ties differently. ↵
4. See Roca et al. (2009b) for an important and illuminating discussion of this paper. ↵
5. Roca et al. (2009a, 2009b) call this revision protocol "replicator rule or proportional imitation rule", though their implementation is not exactly the
same as ours. They use total payoffs and we use average payoffs. The two implementations differ only if it is possible that two agents have different
number of neighbors (e.g. as with non-periodic boundary conditions). Note, however, that Roca et al. (2009a, 2009b)'s experiments have periodic
boundary conditions, i.e. all agents have the same number of neighbors, so for all these cases the two implementations are equivalent. Hauert (2002)
calls this revision protocol "imitate the better". ↵
6. It may make more sense to use average rather than total payoffs. We use total payoffs here to be able to replicate Nowak et al.'s (1994a, b)
experiments. To use average payoffs, the change in the code is minimal. ↵
7. Roca et al. (2009a, 2009b) call this revision protocol with m = 1 "Moran rule". Their implementation is not exactly the same as ours, since they do
allow for negative payoffs by introducing a constant. Note, however, that the two implementations are equivalent if payoffs are non-negative. Hauert
(2002) calls this revision protocol with m = 1 "proportional update". ↵
8. Roca et al. (2009a, 2009b) and other authors (see e.g. Traulsen and Hauert (2009), Perc and Szolnoki (2010) and Adami et al. (2016)) call this
revision protocol the "Fermi rule". Note also that some authors (e.g. Szabó and Tőke (1998)) use total payoffs rather than average payoffs. ↵
9. Our implementation is heavily based on code example titled "Moore & Von Neumann Example", which you can find in NetLogo models library.
Note, however, that this code example does not compute the correct neighborhoods if the center of the world lies at the edge or at a corner of the
world (at least in version 6.1 and previous ones). ↵
10. For instance, the following code reports true.
↵
11. This functionality was added in NetLogo 6.1. ↵
12. As long as m ≤ 5, results are very similar, but for greater values of m (i.e. greater intensity of selection) cooperation starts to emerge. ↵
13. In contrast with what happens under the "imitative-positive-proportional-m" protocol, parameter m does not seem to have a great influence in this
case. This changes if self-matching? is turned on. In that case, for high values of m, cooperation can emerge. ↵
14. Figures 1 and 2 in Nowak et al. (1994a) are the same as figures 1 and 2 in Nowak et al. (1994b). ↵
This page titled 3.4: Other types of neighborhoods and other revision protocols is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Luis R.
Izquierdo, Segismundo S. Izquierdo, William H. Sandholm, & William H. Sandholm via source content that was edited to the style and standards of the LibreTexts
platform; a detailed edit history is available upon request.
3.4.14 https://math.libretexts.org/@go/page/123833
Index
Detailed Licensing
Overview
Title: Agent-Based Evolutionary Game Dynamics (Izquierdo, Izquierdo, and Sandholm)
Webpages: 26
All licenses found:
CC BY 4.0: 65.4% (17 pages)
Undeclared: 34.6% (9 pages)
By Page
Agent-Based Evolutionary Game Dynamics (Izquierdo, 2.2: Extension to any number of strategies - CC BY
Izquierdo, and Sandholm) - CC BY 4.0 4.0
Front Matter - Undeclared 2.3: Noise and initial conditions - CC BY 4.0
TitlePage - Undeclared 2.4: Interactivity and efficiency - CC BY 4.0
InfoPage - Undeclared 2.5: Analysis of these models - CC BY 4.0
Table of Contents - Undeclared 3: Spatial interactions on a grid - CC BY 4.0
Licensing - Undeclared 3.1: Spatial chaos in the Prisoner's Dilemma - CC BY
1: Introduction - CC BY 4.0 4.0
1.1: Introduction to evolutionary game theory - CC 3.2: Robustness and fragility - CC BY 4.0
BY 4.0 3.3: Extension to any number of strategies - CC BY
1.2: Introduction to agent-based modeling - CC BY 4.0
4.0 3.4: Other types of neighborhoods and other revision
1.3: Introduction to NetLogo - CC BY 4.0 protocols - CC BY 4.0
1.4: The fundamentals of NetLogo - CC BY 4.0 Back Matter - Undeclared
2: Our first agent-based evolutionary model - CC BY 4.0 Index - Undeclared
Glossary - Undeclared
2.1: Our very first model - CC BY 4.0
Detailed Licensing - Undeclared
1 https://math.libretexts.org/@go/page/123837