Programming Guide NetLogoR

Sarah Bauduin, Eliot McIntire

June, 20th 2016

This document is based on the NetLogo Programming Guide. It describes how the NetLogo’s programming language is translated in the R language.

1 NetLogoR features

1.1 World and agents

In NetLogoR, the world is either a worldMatrix object (similar to a matrix) or a worldArray object (similar to an array which is a collection of matrices). It represents a two dimensional landscape, divided into a grid of square patches (i.e., the matrix cells) of resolution 1.

There are two types of agents in NetLogoR: the patches and the turtles. Patches cannot move whereas turtles can move. Patches are represented as matrix objects with two columns pxcor and pycor, representing the spatial location (i.e., coordinates) of the center of the patches. See help("worldMatrix-class") for more details on the patch coordinates system. Turtles are defined by their coordinates xcor and ycor and data associated in agentMatrix objects. Patches coordinates are always integers but turtles coordinates can have decimals (i.e., a turtle can be positioned anywhere on a patch).

worldMatrix and worldArray are similar to RasterLayer and RasterStack in the raster package. However, there are several differences. Two important differences are the mapping of X and Y coordinates and whether integer locations are in the center or at the corners of integer coordinate systems. In worldMatrix and worldArray, (0, 0) is at the bottom left, like a mathematical graph, whereas it is in the top left in Raster* objects, as in geographic coordinates. In worldMatrix and worldArray, integer coordinates are in the middle of the patch or cell, i.e., (0, 0) is in the middle of the patch in a worldMatrix that has 1m resolution and integer coordinates, whereas, (0, 0) would be at the edge of a cell in a Raster* that has 1 m resolution and integer coordinates. agentMatrix is similar to SpatialPointsDataFrame from sp package, with a few differences. The key difference in this case is for speed. agentMatrix is based on matrices and has no coordinate reference system, both of which make operations dramatically faster than with SpatialPointsDataFrame objects. In all cases of similar object types, we have implemented functions to convert between the types.

Links are not implemented in NetLogoR.

1.2 Procedures

In NetLogoR, functions act on the worlds and on the agents. Functions can modify or used them to compute some values. Functions available from the R software and from different packages can be used, as well as the functions from NetLogoR. Most of the NetLogoR functions are a translation into the R language of the NetLogo primitives (i.e., “built-in commands and reporters”). You can create new functions or wrap several existing functions into one. The rules to do so are imposed by the R language.

R functions take arguments which are R objects or values. Arguments are used to carry out actions and compute results.

# Create a world according to a given extent
w1 <- createWorld(minPxcor = 0, maxPxcor = 10, minPycor = 0, maxPycor = 10)

# Report the distance between the patch [pxcor = 0, pycor = 0] and the patch [pxcor = 1, pycor = 1]
pDist <- NLdist(
  agents = cbind(pxcor = 0, pycor = 0),
  agents2 = cbind(pxcor = 1, pycor = 1), world = w1, torus = TRUE
)

In NetLogoR, the function arguments indicate which world and/or agents (i.e., patches and/or turtles) are involved in the function. For example, in the NLdist function, the argument agents takes one patch coordinates, the argument agents2 takes another patch coordinates, the argument world takes a worldMatrix or a worldArray object to indicate in which world agents and agents2 are located and the argument torus indicate that the world is wrapped.

The result/output of a function needs to be assigned to an object to be kept and re-used later in the model. Functions in R create new objects, they do not directly modify the ones given as arguments. For example, when moving turtles around using the fd function, the output of the function (i.e., the turtles with new coordinates) needs to be re-assigned to the turtles object.

# Create 10 turtles in the world w1
t1 <- createTurtles(n = 10, world = w1)

# Move all the turtles by a distance of 1
t1 <- fd(world = w1, turtles = t1, dist = 1)

In NetLogo, pressing a button runs some code. To perform the button action in NetLogoR, the code must be sent to the R console to be executed. The code can be sent directly by the observer or by a scheduler function (e.g., see SpaDES package) which executes the code according to the schedule.

The R language uses # to add comments to the script. Comments make your code easier to read and understand, but they don’t affect its behaviour.

1.3 Variables

R objects that are neither worlds, patches or turtles can be seen as global variables.

To create a global variable, you create an R object. e.g., score <- 15.

Agent variables are places to store different values for an agent. An agent variable can be a patch or a turtle variable. A worldMatrix object holds only one variable (i.e., value) per patch. A worldArray object holds several variables per patch (i.e., from the different worldMatrix stacked). Turtles variables are stored as columns in the data of the agentMatrix object that represent them. You can have patch and turtle variables defined by the same name as they are not stored in the same object.

To create a new patch variable, you create a worldMatrix and assign values. The name of the object to which the world is assigned is treated as the name of the patch variable.

# For all patches, assign a random value between 0 and 1
pQuality <- createWorld(minPxcor = 0, maxPxcor = 9, minPycor = 0, maxPycor = 9,
                        data = runif(n = 100, min = 0, max = 1))

Several turtle variables built-in in NetLogo are created at the same time when creating a turtle object in NetLogoR: xcor, ycor, who, heading, prevX, prevY, breed, and color. New turtle variables can be created:

# Now each turtle in t1 has a "sex" variable
t1 <- turtlesOwn(
  turtles = t1, tVar = "sex",
  tVal = c("M", "M", "M", "M", "M", "F", "F", "F", "F", "F")
)

Turtle’s breed is a turtle variable and you can have different breeds behaving differently. For example, you could have breeds called sheep and wolf, and have the wolves trying to eat the sheep. You can either specify different breeds in the same turtle object or create two objects, one sheep and one wolf.

You define turtles’ breed by filling the breed column when creating the turtles.

# 5 sheep and 5 wolves
t2 <- createTurtles(world = w1, n = 10, breed = c(rep("sheep", 5), rep("wolf", 5)))

# Or
sheep <- createTurtles(world = w1, n = 5, breed = "sheep") # 5 sheep
wolves <- createTurtles(world = w1, n = 5, breed = "wolf") # 5 wolves

Or you can modify the turtles’ breed after creation.

# Turtle 0 which was "sheep" becomes "wolf"
t2 <- NLset(turtles = t2, agents = turtle(t2, who = 0), var = "breed", val = "wolf")

Global variables are available for all agents. Patch and turtle variables are available to other agents if they can be identified by their coordinates or some other variables.

# Reports the pQuality value of the patches:
# [pxcor = 0, pycor = 0], [pxcor = 0, pycor = 1], and [pxcor = 0, pycor = 2]
of(world = pQuality, agents = patch(pQuality, c(0, 0, 0), c(0, 1, 2)))

Local variables may occur in NetLogoR as inherent to the R software. For example, variables only defined inside functions are local variables and therefore cannot be accessed outside of the functions.

1.4 Agentsets

An agentset is a set of agents and you can construct agentsets that contain only some patches or some turtles. An agentset cannot contain the two agent types (patches and turtles) at once. A patch agentset is a matrix that contains patches coordinates; a turtle agentset is an agentMatrix object containing turtles. Agentsets can then be passed on as arguments in functions. Agentsets can be redefined at any time.

1.5 World topology

By default, NetLogoR functions act as if the world is bounded and does not “wrap”. Patches on the sides of the world will have fewer than 8 neighbors and turtles will not move beyond the edges of the world. What happen to the turtles when they reach the edge of the world must be defined.

However you can make the world a torus (“wrap”), so that each patch has the same number of neighbor patches (some located on the other side of the world) and when a turtle moves past the edge of the world, it disappears and reappears on the opposite edge. The option for a torus world is an argument in some of the NetLogoR functions and can be set TRUE or FALSE.

1.6 Tick counter

It is common that time passes in discrete steps. Time can be defined as a global variable in the model setup (e.g., time <- 0) and then can be incremented in the model when needed (e.g., time <- time + 1 at the end of the procedure affecting all the agents).

If a for-loop or a scheduler function (e.g., see SpaDES package) is used in the model, time does not have to be explicitely defined with a global variable and is handled internally.

1.7 Lists and strings

Lists may be seen as global variables holding one or more values and strings may be seen as global variables holding characters. Lists and strings are inherent to the R language. Please see R manuals for any related questions.

NetLogo uses lists to store elements. In R, it is faster to use vectors when possible.

1.8 Math and random numbers

R is a software dedicated for data management and statistical analyses. The notation and basic rules of math, as well as the random number generation, are inherent to the R software. Please see R manuals for any related questions.

1.9 Input/output

Reading and writing files is inherent to the R language. Please see R manuals for any related questions on basic functions, as well as the different packages, for more complex functions to manage files.

In R, a file is loaded/opened by assigning its content to an R object. The R object can be read, used and modified but this does not affect the original file. The modified R object can later be written out as a file, either by overwriting the original file or by creating a new file.

1.10 View, plot, screen output

There is no interface built-in as part of NetLogoR.

However, you can use different plot functions for visualizations similar to the “View” of NetLogo. plot(nameWorld) works with both worldMatrix and worldArray. To visualize only one layer of a worldArray, use plot(nameWorldArray[[layerNumber]]) or plot(nameWorldArray[["layerName"]]). Turtles can be plotted alone with plot(nameTurtles) or on a world already plotted with points(nameTurtles). Plot() functions (with a capital “P”) from quickPlot give a better rendering when plotting multiple time steps. These functions work the same way as the plot() ones, except when adding turtles on a world, use Plot(nameTurtles, addTo = "nameWorld") instead of points(nameTurtles).

Users can also create any other figures (e.g., the number of turtles through time) on the R plot interface or generate outputs directly on the screen (e.g., show the current time step).

All these procedures need to be coded in the model, either using the plot() or Plot() functions adapted to the NetLogoR classes for the world visualization, or using R functions and of different packages for any other figures. Please refer to their manuals for any related questions.

2 How to build a model using NetLogoR

The following steps describe how to build a basic NetLogo-type model in R using NetLogoR. Examples of R scripts are available in the “examples” folder, which can be found using:

system.file("examples", package = "NetLogoR")