NetLogo and Agent-Based Modeling

NetLogo

NetLogo is a multi-agent programmable modeling environment. It is based on the Logo programming language.

The environment, its documentation, and many interesting models can be downloaded from:

http://ccl.northwestern.edu/netlogo/

NetLogo Models 1.0

NetLogo programs, which are also called models, are based on a simple metaphor: turtles swim around a pond observing and interacting with each other. Of course NetLogo turtles don't have to represent real turtles; they can represent cows, people, robots, and so forth. And the pond doesn't have to represent a real pond. Instead it can represent a pasture, city, market, etc.

Examples of ways turtles can interact include fighting, mating, and bargaining.

Turtles can die of starvation, disease, wounds, or old age:

if energy <= 0 [die] ; this turtle is now dead

Not to worry, new turtles can always be hatched:

hatch 3 [set energy 100] ; 3 healthy turtles born

The pond is divided into a grid of patches. Like turtles, patches are also "alive". Unlike turtles, patches can't move, die, or be born. But they can interact with turtles and other patches.  We can think of patches as lily pads floating on the pond, but of course patches don't have to represent real lily pads. They can represent trees in a forest, hills and valleys in a terrain, shops in a market, neighborhoods in a city, etc. For example, a patch might represent a vendor in a market and turtles customers. Customers interact with vendors by bargaining.

Agent-Based Models

Turtles and patches are collectively called agents. More broadly, an agent is any sort of autonomous, goal-oriented object capable of observing and interacting with its environment and other agents. Agents may be mobile, like turtles, or stationary, like patches. Agents may be intelligent and worldly, or simple and provincial. Curiously, even in the latter case the collective behavior of the agents may be interesting and complex. This is called emergent behavior, when the behavior of the whole is more complex than the behavior of the parts. The goal of agent-based modeling is to study and even harness emergent behavior. Agent-based modeling is an important technique in Complexity Science.

NetLogo Models 2.0

More practically, a NetLogo model has three parts: interface, information, and code.

Interface

The interface provides the user with a view of the turtles swimming in their pond as well as controls for starting and stopping the turtles, adjusting model parameters, and monitoring important quantities. It's easy to add, edit, and remove controls.

Here's a screenshot of a typical model interface:

Information

Each model includes documentation that follows a standard format: what the model tries to show, how to use the model, how the model works, things to try, etc.

Code

The code or implementation is a list of definitions of attributes, breeds, procedures, and reporters (i.e., functions). These definitions are created, edited, and checked using the NetLogo editor (which is under the "Code" tab.)

Attributes and Breeds

The code usually begins by defining attributes and breeds.

Each patch has five pre-defined attributes (color, position, label, etc.)

Each turtle has 13 pre-defined attributes (color, position, label, heading, shape, size, etc.).

Programmers can define additional attributes:

turtles-own [age energy metabolism]
patches-own [depth temperature] 

Global variables are roughly analogous to pond attributes:

globals [pond-temperature pond-pollution-level]

Programmers can also define sub-types of turtles called breeds along with breed-specific attributes:

breed [buyers buyer]
breed [sellers seller]
sellers-own [demand cash]
buyers-own [supply price]

Procedures

Procedures are executed by turtles, patches, or a special god-like agent called the observer.

Here is an example of a turtle procedure:

to update-turtle
   if energy <= 0 [die]
   graze      ; eat any food at this patch
   move       ; move to some other patch
   fight      ; fight with some other near here
   reproduce  ; mate with some other near here
end

In this example a turtle might represent some type of herbivore possessing a programmer-defined attribute called energy. Graze, move, fight, and reproduce are programmer-defined procedures that the herbivore will execute in the course of executing the update-turtle procedure. We might guess that moving, fighting, and reproducing lower the herbivore's energy, while grazing increases its energy. If the herbivore doesn't get enough to eat, it dies.

Here is an example of a patch procedure:

to update-patch
   let num-republicans count neighbors with [party = "Republican"]
   ifelse majority <= num-republicans
   [
      set party "Republican"
      set pcolor red
   ]
   [
      set party "Democrat"
      set pcolor blue
   ]
end

In this example patches might represent voting precincts or states, each possessing a programmer-defined attribute called party that represents the political party the majority of precinct residents vote for. Executing this procedure, a precinct calculates the number of neighboring precincts that vote republican. This number is stored in num-republicans, a local variable created using let. (Think of local variables as procedure attributes.) Patches are organized into a wrap-around grid so that each patch has eight neighbors. If this number is greater than or equal to some global variable called majority, then the precinct votes Republican and turns red, otherwise it votes Democrat and turns blue. (After all, we are more influenced by neighbors than reason.)

Here's how the observer might ask each agent in the pond to execute its update procedure:

to update-model
   ask turtles [update-turtle]
   ask patches [update-patch]
end

Reporters

Implementations can also include definitions of reporters (i.e., functions). While procedures update attributes, reporters calculate and report (i.e., return) a value.

For example, assume there are two breeds of turtles: ABMs representing anti-ballistic missiles, and ICBMs representing intercontinental ballistic missiles that the ABMs try to destroy. An ABM periodically needs to compute the distance from itself to its ICBM target using the distance formula from analytic geometry. The ABM simply calls the distance-to reporter, passing the target as a parameter:

to-report distance-to [target]
   let diff1 xcor - [xcor] of target
   let diff2 ycor – [ycor] of target
   let square1 diff1 * diff1
   let square2 diff2 * diff2
   let sum square1 + square2
   report sqrt sum
end

This reporter calculates the intermediate values needed by the distance formula, along with the intermediate values they require, and stores them in local variables. Finally, it uses the report operation to output the final answer.

Here's how a turtle might call the distance-to reporter in order to calculate the impact time:

to-report impact-time
   let dist distance-to my-target
   report dist / my-speed
end

Executioners

NetLogo isn't a concurrent language. Commands are executed sequentially, one at a time. But commands are executed by agents, and there are many agents. The same command may be executed at different times by different agents producing different results. Let's call the agent executing the current command the executioner.

For example, assume turtles have an attribute called strength which is decremented by a fight procedure:

to fight
   set strength strength – 5
   ; etc.
end

Assume Leo and Ralph are turtles. When Leo executes the fight procedure, Leo's energy is decremented. But when Ralph executes the same procedure, Ralph's energy is decremented. In other words, "strength" always refers to the executioner's strength.

Suppose the executioner wants to access or modify the attribute of some other agent. This can get complicated.

For example, assume turtles have an attribute called "friend". When one turtle decides to befriend another, it executes the befriend procedure:

to befriend [candidate]
  if (candidate != self and
      friend = nobody and
      [friend] of candidate = nobody)
  [
    set friend candidate
    ask candidate [set friend myself]
  ]
end

Assume this procedure is executed by Yurtle the Turtle. Therefore, Yurtle is the executioner. Yurtle begins by checking that:

1. He isn't trying to befriend himself
2. He doesn't already have a friend
3. The candidate doesn't already have a friend

In NetLogo "self" always refers to the executioner. This provides a convenient way for Yurtle to make sure he isn't the candidate. Also, "nobody" is a special NetLogo value used to indicate the absence of an agent.

Finally, Yurtle can't reference the candidate's friend attribute simply as "friend" since this would be construed as Yurtle's friend. Instead, he must use the expression:

[friend] of candidate

Assuming all three conditions are true, Yurtle sets his friend attribute to the candidate, then asks the candidate to set his friend attribute to Yurtle:

ask candidate [set friend myself]

Here's where things get weird. Inside the ask command block the executioner switches from Yurtle to the candidate. So now "friend" refers to the candidate's friend attribute and "self" refers to the candidate. However, the candidate can use the NetLogo expression "myself" to refer to the agent that asked him to execute a command block. In this example "myself" refers back to Yurtle. Perhaps "asker" might have been a better name choice for this important mechanism.

Simulations

NetLogo models are simulations driven by a model update loop that can be paused and resumed. On each cycle through the loop the observer updates the globals and the interface, halts the simulation if necessary, and asks the turtles and patches to update themselves otherwise:

to update-model
   update-globals
   update-interface
   if halt? [stop]   ; end simulation
   ask turtles [update-turtle]
   ask patches [update-patch]
end

In the view window we see turtles moving around the pond, while monitors display the values of critical quantities and plotters graph them.

We can run the simulation numerous times. (This can be automated.) Randomness, complexity, and varying initial conditions mean that each simulation may produce different results. But the results need not be random. We study them looking for large-scale patterns and formulating theories that might explain these patterns.

More commonly, we use sliders, switches, and other controls to adjust model parameters during the simulation. We observe the effects these changes have on the model and formulate theories to explain any correlations.