The Abm Template Models a Reformulation with Reference Implementations

This paper refines a well-known set of template models for agent-based modeling and offers new reference implementations. It also addresses issues of design, flexibility, and ease of use that are relevant to the choice of an agent-based modeling platform.

This paper has two core objectives: to refine a well-known set of template models for agent-based modeling, and to offer a new reference implementation.In pursuing these goals, we address issues of design, flexibility, and ease of use that are relevant to the choice of an agent-based modeling platform.
The use of agent-based models (ABMs) has been growing rapidly in many fields, including evolutionary biology, ecology, economics, epidemiology, game theory, political science, and sociology.Popular ABM platforms include NetLogo (http://ccl.northwestern.edu/netlogo/),Swarm and Java Swarm (http: //www.swarm.org),Repast (http://repast.sourceforge.net),and MASON (http://www.cs.gmu.edu/%7Eeclab/projects/mason/). Each of these platforms has benefits and limitations that have been explored in the literature (Tobias and Hofmann, 2004; Railsback et al., 2006).The most popular of these platforms remains NetLogo, which is renowned for its combination good graphical capabilities, reasonable flexibility, and excellent of ease of use.Railsback et al. (2006) also judge NetLogo to be the most professional platform in terms of appearance and documentation.The most common complaint against NetLogo is its failure to adopt an open source license, which some researchers view as a crucial component of scientific ABM research.Railsback et al. (2006) discuss a collection of sixteen template models, which they designed as tools to introduce and explore agent-based modeling (ABM) platforms.(Railsback et al. (2005) provide the full model specifications.)The template models are intended to be "ridiculously simplified".They illustrate general modeling considerations required by many different real-world applications and do not constitute an attempt to implement a specific real-world application.These template models have already proved their usefulness.They are used in teaching and are chosen as a point of reference for introductory presentations of new ABM platforms.Nevertheless, in this paper we propose to remove certain ambiguities, tighten certain specifications, remove from the specification some implementation details, highlight additional learning goals, and draw a clearer distinction between general programming goals and goals focused on the visual display of information.Railsback et al. (2005) provide reference implementations of the template models for a few popular platforms.The template-model reference implementations are intended to be "simple and intuitive" rather than clever or fast.As might be expected, the reference implementations clarify the intent of certain parts of the specifications and highlight some of their limitations.The simplest and least verbose are the NetLogo reference implementations.Robertson (2005) notes that, as an ABM platform, NetLogo excels at ease of use and compactness of representation.This makes the NetLogo reference implementations particularly relevant as a point of comparison for other ABM platforms.
In this paper we provide new reference implementations.The reference implementations use the Python programming language.After modest initial start-up costs, our Python implementations of the template models prove simple, readable, and short.That is, they are useful as reference implementations.We show how use of a simple gridworld module allows for Python implementations that usually approach and often exceed the simplicity of NetLogo, while providing improved readability and power.Following the intent of the original reference implementations, our code emphasizes readability and ease of use (rather than speed or generality).We also suggest a few advantages and disadvantages of using Python as an ABM platform.Since NetLogo consistently receives high marks on these criteria, we take it as our primary point of comparison.

Template Model 1: Spatial Movement of Agents
The first template model provides a basic introduction to ABM platforms.The core programming goal is to implement the random movement of agents in a simple two-dimensional space.That is, we must implement a specified behavior for a base agent type that is spatially situated.
The background needed to attempt the first template model is platform dependent, but generally it requires a modest introduction to programming on the chosen ABM platform.Required skills include the use of basic built-in functions, definition and use of new functions, some understanding of variable scope (local vs. global), use of a looping construct, iteration over a collection (of agents), and simple randomization using built-in facilities. 1 With this background, we can attempt the specification of the first template model.

World
• a 100 x 100 toroidal grid of possible agent positions Setup • create an iterable collection of 100 agents • give each agent a unique, random position on the grid Iteration • each time step, each agent moves to a random, unoccupied neighboring location Stopping Condition • Not part of the specification.

Supplementary Detail
• agent positions are characterized by integer pairs (locations on the grid) • no two agents share a position, not even initially • agent movement is constrained to a Moore neighborhood of radius 4 -an agent must change position unless all neighboring locations are occupied the new position is a "random" selection from the unoccupied neighboring locations (no particular algorithm or PRNG is specified) the move action must terminate, even if all neighboring locations are occupied • the order in which agents move is unspecified, but agents must move sequentially (i.e., one at a time) • a "time step" is one iteration through the model schedule Display Suggestions • position: display each agent on screen at a position corresponding to its grid position • shape: display agents as circles • color: use a red fill color for agents • size: make sure adjacent agents are easily distinguishable • update: display once each iteration Despite its simplicity, the original specification contained some minor ambiguities.The emphasized text in our specification constitutes clarifying additions.We specify that the initial positions of agents are chosen randomly subject to the constraint that locations are not shared.This addition is not very consequential (and matches the NetLogo reference implementation).We also add that agents should be members of an iterable collection.Most ABM platforms support iterable collections for each agent type, so this too is not very consequential.More substantively, we explicitly specify that agents move sequentially.(This matches the reference implementations.)Sequential movement ensures that two agents do not move to the same location, and as Kahn (2007) notes, violation of this constraint can affect outcomes in later template models.
Finally, we explicitly specify that the move action must terminate.While this is the natural reading of the original specification, it conflicts with the reference implementations. 2 As Kahn (2007) notes, the reference implementations use a simple loop that makes repeated random draws from the entire neighborhood until a vacant cell is found.If there are no vacant cells, the program never escapes this loop.(Admittedly, this is a low probability event in the first template model.)However we do not augment the specification to require a specific algorithm, since the ease of any particular approach can be platform specific.
It is notable that the display suggestions have no essential relationship to the model specification.In fact, one drawback of the original template model specifications is the lack of a clean separation of core modeling goals and visual display considerations.We cannot address this fully without diverging substantially from the original specifications, but a natural supplement to the template models is a cleaner separation of these concerns.We will provide this on a template by template basis.One other drawback or the original specification is the unnecessary narrowness of original interpretive framework.The authors of the original template model specifications presumed an ecological emphasis and somewhat light-heartedly referred to their agents as "bugs".Our interest encompasses the social sciences, and we therefore stick with the more generic term 'agents'.

Procedural Implementation
To implement the first template model, we need a description of the agents and a description of the "world" in which the agents reside.The template models also make visual display suggestions, and we will implement these as well.With such limited needs, we have many different options.Starting from scratch is entirely feasible. 3Free and open source game development toolkits are also options: pygame (http://www.pygame.org) and pyglet (http://www.pyglet.org)are fairly simple and very powerful.For the purposes of this paper, however, we take a minimalist approach: we use a small gridworld module that provides a basic grid topology, "patches", and agents.Since Python 2.6, this approach provides ABM facilities that approach the simplicity of NetLogo.
The properties of an Agent resemble those of a NetLogo "turtle", which is the base NetLogo agent type. 4We will care primarily about the ability of these agents to report a current position and move to a new location.We will access and set the position of an agent via its position attribute.A position is an x,y pair of numbers, interpreted as Cartesian coordinates in a plane.(Generally, the coordinates can be floating point numbers, but for the template models they will be integers.) To facilitate comparison with NetLogo, we consider a preliminary version of the first template model that is procedurally oriented.Our world will be a GridWorldGUI from the gridworld module; this class handles a little grid-related accounting for us.For example, if myworld is a GridWorldGUI instance, we can determine whether a location is unoccupied as myworld.isempty(location).With this background, we get the following implementation of the first template model.(For completeness, we are including the entire file.)Since this is our first model implementation, we will explicate the code.Readers with a little Python programming experience may be able to simply read through the code and then skip ahead to the more objectoriented implementation.(This invitation should not be taken for granted: it is a reasonable suggestion because readability is an explicit Python language design goal.) The source file begins with a documentation string.(Python docstrings are conventionally triple quoted; triple quoted strings can include line breaks.)Immediately following the docstring are three import statements.The first imports the random module from the standard library, giving us access to Python's random number facilities.The other two import useful objects from the gridworld module.We import Agent and GridWorldGUI, two classes that will be useful for our simulation.After import, names are available for use anywhere in our program (i.e., they are in our module's global namespace).We also import the moore neighborhood function, which can produce a Moore neighborhood of any specified radius, along with the Torus class, which characterizes a rectangular grid that wraps at its boundaries.
Our approach will be to define a collection of functions that we can use to implement the simulation. 5Our first function simply initializes an agent.This initialization focuses on the visual display of the agent: we set its shape, size, and color. 6We then attack the core of the first template model: the detailed description of how an agent moves.We define a move function, which chooses a new location and then moves the agent there.Location choice is delegated to a choose location function.Movement to a new location is handled simply by assigning a new value to the agent's position attribute.
Let us consider the body of the choose location function, which does the real work of the first template model.We generate a Moore neighborhood of radius 4 around the agent's current position as as moore neighborhood(radius=4,center=old position), which returns a list of eighty (x,y) locations.An agent must move to a random location in its neighborhood, so we shuffle (in place) the locations with the random.shufflefunction.We sequentially consider each location as a possible new position (thereby avoiding the error in the reference implementations, discussed above).If the location is empty, we choose it.Note that a gridworld.Agent has a world attribute.(When a world creates agents it sets this attribute.)To determine whether a location is empty, an agent queries its world's is empty method.If no new location is empty, the agent chooses its current position.The choose location function returns a location, and the move function sets the agents position to this location.
We have completed the hardest and most essential part of the first template model.Our schedule function is relatively simple: it applies our move function to each of our agents.We will call schedule once per iteration as long as the model is running.
We are now ready to set up and run the model.Following the specification, we create our 100 by 100 grid as mytorus = Torus(shape=(100,100)).We then create our world as myworld = GridWorldGUI(grid=mytorus), initializing our world with our torus topology.We then populate the world with 100 agents: a GridWorldGUI also has a create agents convenience method, so we need only specify the number and type of agents that we want.(Since we do not specify positions, the agents are positioned randomly when they are created.)We then use our initialize function to prepare the agents for our simulation.
Running the model is essentially a matter of calling the schedule function repeatedly.However we also perform a subsidiary, display-related task: we turn off screen updating before we start moving our agents, and we turn screen updating back on after we are done moving our agents.This was requested by the specification, and it substantially speeds the simulation.We arbitrarily stop after 250 iterations.(The specification does not include a stopping criterion.)

Object-Oriented Implementation
For illustrative contrast, we reimplement the first template model with more object-oriented code.We can again use Python, since it combines simplicity and power by supporting both procedural and object-oriented programming paradigms.
This time we use the GridWorldGUI and Agent classes of the gridworld module as base classes for two new classes, World01 and Agent01.Instead of defining four global functions to manipulate the objects in our model, we provide our objects with behavior by defining four corresponding methods.We initialize the shape, size, and color of our agents with an initialize method.We add a move method to our agents, which will be supported by a choose location method.These are analogues for three of the four functions we defined in the procedural version.The fourth function was our schedule, which we now implement as method of our world class.
Before proceeding, we should note two features of the gridworld module.Agent defines an initialize method, intended to be overridden, which is automatically called as part of object initialization.Also, GridWorldGUI defines a schedule method, intended to be overridden, which is called repeatedly by its run method.So we propose the following design.Here we use the term 'extends' to indicate inheritance: Agent01 is a subclass of Agent.To say that Agent01 extends Agent is to say that Agent01 inherits data and methods from Agent.Specifically, we will use the position and the world data attributes that Agent01 inherits from Agent.Similarly, we will use the is empty method that World01 inherits from GridWorldGUI, which reports whether a given location is empty or occupied by another agent.
Explicit class definition has costs and benefits relative to other possible designs.The costs accrue primarily to programming novices, which make them largely of pedagogical relevance.(This matters, since pedagogy is a common use of the template models.)Object-oriented design requires an understanding of class definition.In Python, this is a minimal barrier: understanding how NetLogo handles instance variables (as required by the second template model) is a comparable cost. 7As a somewhat more substantial cost, object-oriented design immediately requires a minimal understanding of inheritance: that a derived class behaves like its base class, in the sense the it can receive the same method calls.As we develop our objectoriented approach to the first template model, we will not find large advantages off-setting this initial cost.However, as we work through additional template models, substantial advantages of a more object-oriented approach become evident.
For most researchers choosing an ABM platform, the issue is not whether but rather when to use inheritance.For example, NetLogo is strongly procedurally oriented and is designed for simple use, so the NetLogo reference implementations initially can dodge the issue by relying on a kind of dynamic attribute creation for the base agent class (using the turtles-own and patches-own keywords).But once a model requires different types of agents, a discussion of the NetLogo concept of breed becomes unavoidable.Any reasonable introduction to breeds will strongly overlap elementary discussions of class definition and inheritance. 8he NetLogo reference models do not introduce breeds until template model 16.We could similarly postpone the introduction of inheritance, as illustrated by our procedural version of the first template model.Postponement slightly decreases the background required to implement the first template model, but it does not change the requirements for the set of template models.Additionally, an object-oriented approach substantially simplifies the set of models.A comparison of our procedural implementation with the following permits an assessment of the barrier to entry is raised by early use of a more object-oriented approach.
""" Template Model 1: Random Movement on a Toroidal Grid """ import random from gridworld import Agent, GridWorldGUI from gridworld import moore_neighborhood, Torus A reasonable first reaction is that this more object-oriented implementation appears nearly identical to our procedural implementation.The four functions defined in the procedural version are clearly evident as the three methods defined in the Agent01 class and the one method defined in the World01 class.(A method definition is just a normal function definition that is part of a class definition.)A closer look reveals some small differences, and we focus on those.
Again the module begins with a short docstring.The three import statements are unchanged.We then define a new class, Agent01, which inherits from Agent and defines three methods.The initialize method has one difference from our earlier function of the same name: the parameter name is self rather than agent.This is is inessential: the choice of the name self is a standard Python convention to emphasize that when we call this method on an instance, it will act on that instance itself.(We will return to this.) The move method also mirrors our previous move function.There is one notable difference: instead of the function call choose location(agent), we have the method call self.chooselocation(). 9Similarly, the choose location method is also essentially identical to our previous choose location function.
So far we have introduced only very minor changes in program logic, but they all reflect a more fundamental change in perspective: behavior is now an attribute of an agent.To give this a slightly misleading but nevertheless suggestive phrasing, in the procedural design we do things to agents, whereas in the objectoriented design our agents do things.
Our remaining changes are just as minor.Instead of defining a global schedule function, we subclass GridWorldGUI and override its schedule method.The schedule method has three notable changes from our earlier function of the same name.First, we do not have to turn screen updating on and off.(We will use the run method that our World01 inherits from GridWorldGUI, which handles this for us.)Second, we will not access myagents as a global variable: instead we use the agents attribute of our World01, which it inherits from GridWorldGUI.Finally, we replace the function call move(agent) with the method call agent.move().
As before, we must take four steps to run our first simulation: create a grid of locations for our agents, create a world based on that grid, populate the world with initialized agents, and run the scheduled actions repeatedly.Each of these steps is familiar, and only the last changes substantively from our procedural implementation.A World01 has a run method (inherited from GridWorldGUI) that repeatedly calls its own schedule method, so myworld.run(maxiter=250)will run our simulation for 250 iterations.Our more object-oriented implementation of the first template model is complete.
We add one modification that is not needed to implement the model: we run the simulation only if name =='main'.This is a purely forward looking change: we want to import Agent01 and World01 into other modules without running our first template model.However, a module's code is executed when the module is imported.We could put the code to set up and run the model in a separate file, but for the purposes of this paper, we wish to group our class definitions beside the code that creates and runs our simulations.Our solution is to use the special module attribute, name , which is just the filename (as a string) for an imported module.In contrast, the module executed as the main program is always assigned the string ' main ' as its name.We can therefore condition on the value of name in order to prevent some code from being executed when a module is imported.The code in the body of this if statement will not be executed if the module is imported, but it will be executed if the module is executed as a script. 10This ensures that we can freely import our module into other scripts.

Template Model 2: Agent Growth
The second template model assumes completion of the first template model.(The template models are generally sequential.)The new requirement is the addition of agent state in the form of data attributes.An associated visual-display goal is the provision of visual clues to the state of each agent. 11Once again, the emphasized text in our specification constitutes additions or changes to the original.

World and Setup
• unchanged from model 1 Iteration (sequential) • each agent moves • each agent grows Supplementary Detail • movement: agents move as in model 1 • growth: each agent "grows" at a fixed rate each agent has an data attribute named size growth is a change in the "size" attribute size is initialized to 1.0; the growth increment is 0.1 Display Suggestions • position, shape, and update: as in model 1 • color: each agent's fill color should represent its "size".(Specifically, use white if size=0.0,red if size>=10.0,and increasingly chromatic tints of red as "size" increases from 0 to 10.) • delay: ensure that the agents' color changes during the model's first ninety iterations are not too rapid for viewing We clear up one ambiguity in the original specification, which says that the growth action "is scheduled after the move action".In accord with the NetLogo reference implementation, we interpret this to mean that all agents move, and after that all agents grow.We also cut the growth increment from 1.0 to 0.1.The growth increment is inessential to the model, aside from visual display considerations.Even after our change, on many platforms the color transition will take place too quickly to be easily seen, unless the model iterations are radically delayed.We therefore add a new display suggestion: schedule a delay if needed for comfortable viewing of the color transitions.
Note that the notion of size here is very abstract, and correspondingly so is the notion of growth.A biologist might conceive of size as the physical size of the agent, while a social scientist might conceive of size as the monetary value of the agent's wealth.
With this background, we propose a basic design.As we take up the second template model, we would like to take advantage of our work on the first template model.One approach to this is to simply copy our Agent01 code into the file that implements the second template model, modifying it where appropriate.Indeed, examination of the NetLogo reference implementations reveals the use of this copy-and-paste approach.For languages that support inheritance, a much better approach is to import into our second template model any useful objects from the first template model. 12We therefore subclass Agent01 to define a new agent class (Agent02).that has a new data attribute (size) and two new methods (grow and change color).Additionally, we create a new class, named World02, for our new schedule of actions.Since World01 does not offer much here, we again subclass GridWorldGUI in order to override its schedule method.

Agent02 extends Agent01
• New data attribute: size • New Methods: grow, change color

World02 extends GridWorldGUI
• Overridden Methods: schedule With this design in hand, we are now ready to implement the second template model.We begin with three import statements.We import the time module, which is in the Python standard library, so that we can use its sleep function to delay our model iterations.From the gridworld module we import two familiar classes, GridWorldGUI and Torus, along with an inessential but convenient function, ask.Analogously to the ask command in NetLogo, this ask function applies a specified method to each object in an iterable collection.(Thus ask(myagents, 'move') is equivalent to for agent in myagents: agent.move().)Finally, from our (obviously names) template01 module we import Agent01, which we intend to subclass.Our new agent class, Agent02, has two new methods (grow and change color) and a new data attribute (size).We initialize each agent's shape, shapesize, and size, and then we initialize its color by calling its change color method.The change color method sets the agent's fillcolor based on its size, following the display suggestions in the specification.
The grow method is almost trivial: as required by the specification, an agent adds 0.1 to its size each time its grow method is called.Since the agent's color should always reflect its size, the grow method then calls the agent's change color method.Using the default RGB color model, we specify colors as (red,green,blue) triplets of floating point numbers between 0 and 1.The intensity of red is always 1.0.The intensity of green and blue decreases from 1.0 to 0.0, as size increases from 0 to 10, and remains at 0 thereafter.
Agent02 is ready for use.We just need to create a collection of these agents and schedule their movement and growth according to the specification.As before, we approach this by defining a new class (World02), which subclasses GridWorldGUI in order to override its schedule method.We first schedule a brief sleep (i.e., a suspension of the program execution), which provides us with time to examine the current state of the visual display.The schedule method then retrieves an iterable collection of the agents, sequentially calls the move method on each of these agents, and then sequentially calls the grow method on each of these agents.
With our schedule in place, we can set up and run the simulation as in the first template model.We introduce one slight change: after we run the model, we call the mainloop method of our world.For now, this is just to keep our display visible after our simulation is done running.(We will return to this.) We emphasize that our code listing is again complete.Although the second template model is slightly more complex, its code is no lengthier than that for the first template model.(Of course this is due to our import of Agent01.)This is a stark contrast to the NetLogo reference implementation of the second template model, where we find that code size increases rapidly with the complexity of the model.While brevity is no virtue if it sacrifices clarity, our Python code remains clear and readable.As early as the second template model, we discover an evident strength of Python as an ABM platform. 13

Template Model 3: Spatially Distributed Resources
In comparison to the modest goals of the first two template models, the third template model is somewhat ambitious.The core programming goal is to introduce spatial resources in the form of spatially distributed "cells" with which agents interact.This interaction changes the state of the cell and the state of the agent.To make this concrete, we say that cells produce a resource, and agent growth is determined by the resource it extracts from its cell.A secondary goal is to introduce a random change in state: cells produce randomly.
We remove two requirements from the original specification: we do not require that a "grid space object" hold the cells, and we do not require that each cell store its occupant in an instance variable.We consider these to be implementation details that users would have trouble confirming on many platforms. 14Even when a model is implemented from the ground up, these are not sensible requirements: there are many competitive designs.(For example, a cell might delegate the determination of its occupants to an intermediary, which might maintain a mapping from cells to occupants.)Furthermore, the rest of the specification (and its interpretive framework) make it more natural that an agent "know" its cell than that a cell "know" its agent.For example, in the NetLogo reference implementation a grow procedure is applied to each agent, which consumes from its cell and grows. 15We can conceive a more patch-centered approach-say, applying a supply-agent procedure to each patch-but this is not natural, necessary, or efficient.

Setup
• same as model 2, plus • create a "cell" for each grid location Iteration (sequential) • each cell produces, which adds to its available supply • each agent moves • each agent grows Supplementary Detail • production: random, uniform between 0 and the cell's maximum production rate a cell has an available supply of the produced resource (data attribute, initialized to 0.0) and a maximum production rate (data attribute, initialized to 0.01) -a cell's production is added to its supply • movement: agents move as in model 1 • growth: an agent grows by extracting from its cell an agent can interact with the cell at its position (specifically, it can extract the cell's supply) -an agent has a maximum extraction rate (a data attribute, initialized to 1.0) -an agent extracts whichever is smaller: its maximum extraction rate, or its cell's supply agent growth equals the quantity it extracts a cell's supply is reduced by the amount extracted Display Suggestions • unchanged from model 2 As a minor matter, we have adopted a somewhat more general description of the agent and cell activities.The original specification suggested the following interpretation: cells grow food, which bugs eat to grow.However many other interpretations are possible.(For example, itinerant laborers solicit paid jobs, which add to their wealth.)Again, the interpretive framework of the template models is secondary: any serious application to interactions between an agent and its spatial environment will require many more details.
With this background, we are ready to propose a design.We need to describe a cell that produces something that can be taken by our agents.We also need to make some changes to our agent description, so that it can appropriately consume and grow.

World03 extends gridworld.GridWorldGUI
• Overridden Methods: schedule At this point, our basic strategy should be growing familiar.We inherit as much as we can from past work, and we add any new behavior we need.For example, Agent03 will inherit the patch here method from Agent02, who inherited it from Agent01, who inherited in from gridworld.Agent.However, it must override the grow method rather than inherit it from Agent02.We now move to discussion of the code.For now, the only important thing we get by having Cell03 inherit from gridworld.Patch is that a GridWorldGUI knows how to create instances of Patch.(We will use this when we set up the model.)All the important cell behavior is new.We begin by overriding the initialize method, which is automatically called during instance creation.This initializes the supply and max produce attributes of each cell.We define a produce method to augment supply by a random amount, which is uniform between 0 and max produce.And the give method will give from the cell's current supply the amount requested (up to the entire supply), while reducing the cell's supply by the amount given.
An Agent03 has all the initializations of an Agent02, and we invoke by calling Agent02.initialize.(This is for illustrative purposes: the gain from reusing the Agent02 initializations is tiny in this simple class.)An Agent03 is an Agent02 that knows how to extract resources from its cell and to grows based on this extraction.The grow method calls the agent's extract method, and growth equals the amount extracted.Given a call to its extract method, an Agent03 will try to extract its max take (e.g., its maximum capacity).(Of course it can only extract up to its cell's current supply.)The max take of an Agent03 is set at initialization to 1.0.
As usual, we create a schedule this by overriding the schedule method of GridWorldGUI.First we ask each patch to produce, then we ask each agent to move, and finally we ask each agent to grow (by extracting from its cell).With our schedule in place, we can set up and run our simulation as usual, with one small change.Before we create our agents, we must create their environment (i.e., the cells).(This step has no corollary in NetLogo, which always conveniently creates a patch environment for its agents, but it is required by most ABM platforms.)Note that the specification still does not include a stopping condition, so our decision to run the simulation for 100 iterations is in this sense arbitrary.
Template Models 4, 5, 6, 7: Probes, Parameters, Histograms, and Stopping The next three template models emphasize the GUI.In principle the GUI is a mere adjunct to ABM platforms.In practice it has proved an important tool for model exploration and understanding.It therefore receives a strong emphasis in the template models.

Template Model 4: Click Monitors
The core task of the fourth template model is to implement click monitors, or "probes", fore both agents and cells.A click monitor displays the state of an object type when the object receives a mouse click.The specification is correspondingly simple.

Specification: Template Model 4 World, Setup, and Iteration
• unchanged from model 3 (with new supplementary detail) User Interaction • report agent size and cell supply in response to mouse clicks in the visual display Display Suggestions • as in model 3, plus • display click monitor reports in the GUI The ease of producing such probes varies substantially by platform.On some platforms it is a substantial effort to probe both agents and cells (Railsback et al., 2006).NetLogo once again makes things easy: probes for agents and cells are provided automatically and displayed in the GUI. 16We add probes explicitly using our world's add clickmonitor method, which takes as arguments a label for the display, an object type to monitor, and an attribute (or attributes) whose values are to be monitored. 17The resulting code is very simple.We simply reuse Agent03 and Cell03 (renamed as Agent04 and Cell04).We subclass World03 in order to override its initialize method.(Recall that the initialize method is special: it is called when our world instance is initialized.)This is where one adds probes, using the add clickmonitor method.We add two click monitors: one to report the size of a clicked agent, and another to report the supply of a clicked cell.
The code for creating our world, adding cells and agents, and running the simulation is by now familiar.When we create our world, the two click monitors appear in the GUI (see Figure 1), and they display the current state of the objects we click.This highlights a new reason for calling the mainloop method of our world: the "main loop" is an event loop, which waits for and handles GUI events.In this case, it handles our mouse click events.

Template Model 5: Model Parameters
The fifth template model introduces user settable model parameters.While the concept is not precisely defined, the idea is that certain variables that govern the simulation should be easily settable by users of the model.We make two changes in the original specification.First, we do not require GUI parameter setting.While this can be quite useful for experimentation with the model, use of the GUI for parameter setting interferes with replicability, is an inefficient approach to testing model robustness, and is not a good ultimate practice in a research setting.We therefore demote this to a display suggestion.Second, we add to the display suggestions that provision of SetUp and Run buttons.This suggestion is a natural implication of allowing parameter setting in the GUI: the parameters values must be determined before the model can be set up and run.(Thus, for example, we find setup and go buttons in the NetLogo reference implementation.) As Railsback et al. (2006) note, model parameters are often implemented as attributes of a model class.For the three specified model parameters, we introduce three class variables to our World05 class.Since patches and agents created by a GridWorldGUI know their world, they have access to these parameters as attributes of their world.
With this background, we expect that the primary change from the third template model is a change in the initialize methods of our cell, agent, and world classes.We add button and slider creation to the initialization of our world.During their initializations, cells and agents need to access the parameter values stored by their world.Correspondingly, we now move patch and agent creation into a setup method of our world.
""" Template Model 5: Parameters """ from gridworld import Patch, Torus from template04 import Cell04, Agent04, World04 Let us focus on the initialize method of World05.We begin by invoking all the World04 initializations.Then we add three sliders, one for each of the model parameters that we introduced as class variables.The sliders allow users to set new values for these parameters.(This approach matches the NetLogo reference implementation.)A slider is created with the add slider method, which needs a label, an attribute (of our world) to be set, minimum and maximum possible values for the attribute, and a resolution (i.e., minimum increment) for the slider.The values for these are not part of the specification, but clearly they should encompass the default parameter values.
We then add the two specified buttons.As a convenience, we also add a Stop button, although this is not required by the specification.Each button is created with the add button method, which requires as arguments a label and a function.This function is called a "callback" (or "command"): it is called when the button is clicked.Our buttons call the setup, run, and stop methods of our world.
Our World04 inherited run and stop methods from GridWorldGUI.We do not override these.It also inherited a setup dummy method, intended to be overridden.We override setup to create our patches and agents.
Recall that in template model 4 we saw that the mainloop method prepared our world to receive mouse clicks.Here too it sets up event handling, and now these events include button clicks and slider adjustments.We now use button clicks to set up and run the model.

Template Model 6: Dynamic Histogram
Agent-based models can generate a lot of data.Graphical summaries of the data can be helpful in understanding the model evolution and outcomes.The sixth template model addresses this need by requiring the production of a histogram to summarize the distribution of size among the agents.
We make a minor change in the original specification: we do not require that the histogram be displayed in the GUI, and we thereby remove the implicit requirement that histogram generation be synchronous with the simulation run.This reflects our view that the ability to synchronously view the histogram during a simulation run is a convenience rather than a fundamental feature of an ABM platform.(For example, MASON has no integrated graphing facilities, and lack of graphics documentation in Java Swarm suggests this is not yet a priority.)Indeed, saving data from simulation runs and analyzing it with separate tools is an reasonable and flexible approach to ABM assessment.We therefore demote GUI presentation of the histogram to a display suggestion.

Setup, Iteration, and Model Parameters
• as in model 5 Data Display • produce a series of histograms that represents the evolution of the distribution of an agent attribute Supplementary Detail • the histogram should be of the size attribute of agents • the sampling frequency for the histogram is not specified, but should be high enough to be informative about the evolution of this distribution Display Suggestions • use 10 bins for the histogram, with a minimum size of 0 and a maximum size of 10 • display a histogram chart in the GUI, and update the histogram as the simulation runs Fine graphics control will always be complex, but even the ease of basic graph creation varies substantially among platforms (Railsback et al., 2006).Once again NetLogo sets the standard for ease of basic use: to add a continually updated histogram of turtle size to the NetLogo GUI, just place histogram [size] of turtles in a procedure that will be called each iteration.The approach used by gridworld.py is only slightly more complex and very flexible.We add a dynamic histogram to the GUI with the add histogram method of our world.This method needs as arguments a title for the graph and a function that will be recomputed each iteration.When called, this function must provide the data for the histogram.We therefore define a get sizes function, which returns a list of agent sizes. 18In doing so, we add one forward looking refinement: we illustrate the get agents method our world inherited from GridWorldGUI.This returns a list of the agents of the specified type.(Of course currently all of our agents are of type Agent06, so we get a list of all agents.)From this, we produce a list of the agent sizes.This is the data needed for our histogram.We create our world, set up the model, and run the simulation as before.Our histogram appears in the GUI, where it is updated each iteration.We scarcely change the original specification.As usual, we demote the GUI aspects to display suggestions.We also remove a reference to "clean up steps" to be done upon termination, because these steps were not specified (Railsback et al., 2006). 20here are many ways to approach this problem, but the most straightforward is to add a conditional check to the schedule.(This is essentially the approach taken by the NetLogo reference implementation.)We test for the stopping criterion, and once it is satisfied, we stop the simulation and exit the program.Note that this approach is an implementation detail, and is not required by the specification.To stop the iterative process we use the stop method that our world inherited from GridWorldGUI; to exit the mainloop (and thus completely terminate the program) we use its exit method. 21""" Template Model 7: Stopping Condition """ from gridworld import Torus from template06 import Agent06 as Agent07, World06 Template Model 8: Output Files Railsback et al. (2006) point out that producing data for subsequent analysis is a core facility for ABM platforms.For the eighth template model, we can break this into two parts: the production of summary statistics, and file input-output operations.In template model 8, each iteration, a summary of the agent states is computed and written to an output file.

Template Model 7: Stopping Condition
We make a single substantive change in the original requirements: we drop the (implicit) requirement that output be written as plain text. 22Plain text output has the great advantage of being human readable, but when we generate a large amount of data this advantage is rapidly outweighted by speed (of reading and writing) and eventually even file-size considerations.(Vaingast (2009) offers a good introductory discussion.)Even if we settle on a plain text file format, many issues are unaddressed by the specification.Will the data be written in a well-known format, such as the CSV format?(CSV is the most obvious format to use for plain text data storage, since it is a standard spreadsheet format, but it is not the choice of the reference implementations.)Will the data be documented in any way, at least with a file header (as is a common first row in CSV files)?These are general concerns for data generation and maintenance.While we do not attempt to force decisions into the specification, as the needs and resources of users vary widely, we do introduce some output suggestions into the specification.Implementations of input-output facilities vary substantially: some platforms provide special classes to facilitate file output, but Java-based platforms usually expect users to use the basic Java file-handling facilities (e.g., the FileWriter class).As one expects, NetLogo provides fairly easy access to very basic facilities. 23In contrast, Python's input-output facilities are not only easy to use but also very powerful.Additionally, they can be coupled with Python's powerful string manipulation facilities to produce nicely formatted plain text output.
We will use Python's basic file handling abilities, as implemented in the built-in open command. 24We provide two arguments to open: a filename (as a string) and a mode (as a string).The basic text modes are 'r' (read), 'w' (write), or 'a' (append).For example, we can open the file sizes.csvfor writing with the statement fh=open ('sizes.csv','w').(The open command returns a file object, which we bind to the name fh.)We can then write a string mystring to the file as fh.write(mystring).
We can implement the eighth template model simply by extending World07.We add two new class variables (logfile and logformat), add two new methods (header2logfile and log2logfile), and override two methods (setup and schedule).
Our setup keeps the World07 set up but appends logging of a header and an initial data summary to our log file.Data logging is handled by a new log2logfile method, which retrieves a list of agent sizes, gets the summary statistics, and appends them to our output file.We handle data description with describe, which is a gridworld convenience function. 25This has functionally similar to Swarm's Averager class.It takes a list of numbers as its argument and returns a Python dictionary of descriptive statistics, with keys including the self-explanatory min, max, and mean.The expression self.logformat.format(**stats)uses our logformat string to format the corresponding values in the stats dictionary.(This offers a nice illustration of the power and flexibility of using a Python format string).This is all it takes to log our data in CSV format.We have one last change to make, and that is to the schedule.We begin with the schedule of World07, but we append to it the data logging we want to do for each iteration.With that adjustment, we are done with the eighth template model.We set up and run the simulation as before.
Template Models 9, 10, and 11: Randomization, Hierarchy, and Optimization In the template models, each agent moves once each iteration.However, we have not specified the order in which agents they move.Neglecting this has different implications on different platforms.For example, the most commonly used iterable collection in NetLogo is the "agent set".Iteration over a NetLogo agent set retrieves agents in random order.(For example, when we ask a NetLogo agent set to take an action, the individual agents are asked in random order to take this action.)In contrast, the basic iterable collection of gridworld is a Python list, which is not randomized.However, gridworld provides separate askrandomly and ask functions, allowing us to explicitly state whether or not we want to shuffle our agents before making our method calls.This has some advantages: shuffling the agents is a computational expense, which we should incur on an as needed basis.
In the first eight template models, the one place order might matter is when we ask agents to move.(Since occupation is unique, when one agent moves to a cell, the next agent cannot move to that cell.)Randomizing the order in which agents move can help us avoid artifacts, such as unintended first mover advantages.The ninth template model specifies that agents move in random order.We make no changes to the original specification.work on the previous template models.)Python's built-in sorted function handles the sorting for us, once we specify our sort key.(Note that by default sorting is lowest to highest, so we set the reverse keyword argument to True.)With out World10 definition in place, we set up and run the simulation as usual.
if __name__ == __main__ : myworld = World11(grid=Torus(shape=(100,100))) myworld.mainloop() We focus on this choose location method.An Agent11 must choose the unoccupied neighboring cell with the greatest supply.So first we retrieve a list of all the cells in a Moore neighborhood of radius four.Then we filter out the occupied patches.(The expression cell.getagents(AgentType) returns a list of the agents of type AgentType on cell, which has a boolean value of False if the list is empty.)We want the agent to consider its own cell as well, so we retrieve it with the agent's patch here method (inherited from gridworld.Agent and append it to the list.Then we shuffle the list as a way to ensure that any "ties" will be resolved randomly.The best cell is the one with the greatest supply.We can use Python's built-in max function to do the maximization, as long as we supply an appropriate key (sortkey11) on which to base the comparison.Having discovered the best patch, choose location returns its position.This is our agent's choice of the best location for its move.

Template Models 12 and 13: Entry, Exit, and Time-Series Plots
In some agent-based models, agents remain in the model during the entire simulation.Other models require that agents exit or enter the simulation as it runs.For example, "bugs" in a biological model may exit through death and enter via birth, or "firms" in an economic model may exit through bankruptcy and enter as new start ups.The twelfth template model illustrates this common need of agent-based simulations: existing agents have a fixed probability of exit, and new agents enter when existing agents "split".
We make two changes to the original specification.We addresses a potential first mover advantage to the split action by specifying that agents split in random order.We also remove some ambiguities by clarifying that new agents will not immediately exit and by specifying that an agent makes its attempts to split and then dies (implying that its position remains occupied during the split action).

Setup and Data Display
• unchanged from model 11 (with new supplementary detail)

Model Parameters
• as in model 11, plus • probability of agent exit (suggested default: 0.05) Iteration • as in model 11, then • each "big" agent splits • each "smaller" agent exits with a fixed probability Supplementary Detail • split: each agent of size > 10.0 makes five attempts to produce a new agent, and then exits agents take the split action in random order to produce a new agent requires finding an unoccupied location in a randomly searched Moore neighborhood of radius 3, where no more than 5 cells may be searched for each attempt to produce a new agent * when an unoccupied cell is found, it becomes the position of a new agent, and search terminates * if all five cells are occupied, search terminates, and the attempt to bring a new agent into the world fails each new agent has initial size of 0.0 • exit: each "smaller" agent (except the new entrants) exits the simulation with fixed probability the probability of agent exit is a model parameter Stopping Condition: • the number of agents reaches 0, or the number of iterations exceeds 1000 We approach the twelfth template model by very slightly extending World11 to implement our new schedule and by extending Agent11 to handle the split action and to accommodate a chance of exit.This leads to the following design.

World12 extends World11
• New Data: agent_exit_probability • Overridden Methods: schedule, setup World12 is a very small extension of World11.As usual, we modify the setup method so that it creates agents and cells of from most recent classes.We also add a new class variable, agent exit probability, for our new model parameter. 26Finally, we must append two agent actions (split and chance) to the World11 schedule, along with our new stopping condition.Turning to Agent12, consider the new chance method.Each agent has an is alive attribute which is set to False if the agent's dies method is called.("Dying" is a model specific concept, which might represent physical death, failure of a firm, or even retirement of a worker.)The chance method draws from a standard uniform distribution and compares the draw to the agent exit probability model parameter.A small draw removes a "living" agent from the simulation; by default this happens five per cent of the time.
The real work of the twelfth template model is in the split action, where "bigger" agents propagate themselves and then die.Our very simple split method handles this by delegating propagation to a propagate method, which is where the real work takes place.Here we begin by specifying that successors (or "splits") will share the agent's type.Following the specification, we consider a Moore neighborhood of radius 3 as possible locations for these successors.We create an empty list to hold the cells that can accept successors -i.e., unoccupied neighboring cells.An agent gets five attempts to split (i.e., produce a successor), but for each potential successor the agent must find an empty cell within five tries.Each try is a random choice from the neighborhood.To implement this, we use the sample function of the random module to retrieve five random cells, which we check sequentially until we either find an empty cell or run out of options.This approach yields a list of empty cells, one for each successful split.We determine the position of each of these cells, and create the new agents at those locations.All that is left to do is to set the size of each new agent to zero, according to the specification.Railsback et al. (2006) note that the twelfth template model is substantially more complex than the preceding models.They found themselves forced to resort to "clumsy and complex methods" on most platforms.The exception, once again, was NetLogo, and even so their NetLogo reference implementation is nearly 300 lines of code.Additionally, the closed-source nature of NetLogo proved problematic.While adding and removing agents during a simulation is very simple in NetLogo, they found the documentation inadequate to determine whether an agent will execute its actions in the same iteration that it was created. 28Our Python implementation of the twelfth template model relies completely on open source code, is not "clumsy", and avoids disheartening complexity (despite a nested loop that in turn nests a conditional branch).
Note that we need not change the move method of our agent.One reason is that our implementation of template model 11 already correctly handles tie resolution.The other reason is a convenience of the gridworld module: an Agent has a neighbors method that queries its world, correctly handling the topology of that world.(E.g., for a Torus, it returns a list of patches that includes locations that "wrap" on the torus, while for a RectangularGrid patches beyond the boundary are not returned.)As a result, our agent description does not change at all.changes the cell's color to match its new supply.(Note that max produce now denotes this deterministic production level.)The new change color method is used to set the cell's color to a shade of green, as specified.Once again we set the colors via the default RGB color model, which we discussed during the specification of the second template model.
World15 is identical to World14 except for the new setup method.As part of setup, we read the cell data from file using the helper function read celldata. 32This reads each line of the cell data file, discarding the first three and collecting the data from the others.It returns a Python dictionary mapping locations to production rates.It also computes the implicit shape of the grid but keeping track of the maximum values for each coordinate.We set our world's grid to a RectangularGrid (no longer a Torus), with dimensions based on the discovered shape.We then create our patches and set max produce for each patch based on the data.As the final step in our setup, we create our agents.At this point we are read to create our world and enter its main loop, as usual.is shuffled.The hunter begins searching with the variable change position set to True: we will negate this upon encountering another hunter or upon moving to the position of a discovered prey.The hunter sequentially considers each patch in the shuffled neighborhood, retrieving a list of hunters and a list of prey from that patch.Each list might be empty.If the hunters list contains another hunter, search terminates and the hunter does not change position.Otherwise, if the prey list contains a prey, search terminates and the hunter moves to that position and "kills" the prey.If no hunters are encountered and no prey found in the entire neighborhood, the hunter moves to a random cell in the neighborhood.Our new World16 class retains all the initializations and parameters of World15.It also reuses the setup method, but appends the creation of 200 hunters at random locations.The real change is in the schedule, although that too is largely familiar.We still have patches produce and agents (prey) move, grow, split, and (possibly) exit.Only the next two statements are truly new: we need to retrieve a list of hunters and ask them to hunt.Since there can be a first mover advantage in hunting, the hunters hunt in random order.We create our world and run the simulation as in model 15. Figure 1 captures the state of the GUI during a model run that keeps the default parameter values.

Conclusion
The template models discussed by Railsback et al. (2006) have proven useful to instructors and researchers for ABM platform introduction and comparison.So have the reference implementations of (Railsback et al.,  2005).However they contain some ambiguities, weaknesses, and errors.Rather than propose a new set of template models, we attempt to refine the existing set, and we provide a new, supporting reference implementation.
Reference implementations are important for removing remaining ambiguities in the specification and for providing concrete illustrations of implementation strategies.We present readable reference implementations that can serve these purposes.Our reference implementations retain the original emphasis on being "simple and intuitive" rather than clever or fast.However we also address issues of design, flexibility, and ease of use that are relevant to instructors and researchers choosing an agent-based modeling platform.Specifically, we explore some of the costs and advantages of taking an object-oriented approach to the template models.We provisionally conclude that the primary cost is a slight front-loading of the skill set needed to begin modeling and that the (somewhat language specific) benefits can include reusability, maintainability, compactness, clarity, and readability.Railsback et al. (2005) conveniently provide reference implementations for a variety of platforms.In comparison, the Python implementations introduced by this paper are more compact, readable, and correct.They therefore provide a useful code resource for those who wish to utilize the template model specifications.Additionally, they add to the literature on the choice of ABM platforms.Our reference implementations show how a general purpose programming language such as Python can be readily exploited as a very powerful and yet easy to use ABM platform.

Figure 1 :
Figure 1: Figure 1: Template Model 16, GUI Display Template model 7 simply adds a stopping condition to template model 6.The condition is that the model iterations should stop when any agent reaches a size of 100 or larger.19

Specification: Template Model 8 Setup, Model Parameters, Data Display, and Stopping Condition
are for the size of agents • summary statistics should include the minimum, mean, and maximum size Output Suggestions • open, append to, and close the output file each iteration • write output as plain text output from a single iteration is a single line in the text file use CSV format for the output file write a header as the first line in the log file