9  NetLogo language basics

In this session, we will learn more about NetLogo’s programming language. We will start with the very basics to ease you into it, in case you are not familiar with any type of programming.

Caution

NOTE

In the explanation below I’m using <UPPERCASE_TEXT> to express the positions in the code to be filled by the name of entities, variables, and other elements, depending on the context. For instance, <COLOR> <FRUIT> would represent many possible phrases, such as “red apple”, “brown kiwi”, etc. Beware that these fragments are only place holders and are not NetLogo code.

For now, we will interact freely with the program, without a particular file or model. The code snippets shown here can sometimes be executed directly, but will often not run without a proper context in code.

9.1 Console interaction

As a preamble, important to anyone without previous experiences with programming languages, the very first thing one can do in NetLogo is give oneself a bit of encouragement. In the NetLogo interface, go to the bottom area named ‘Command Center’ and type the following in the empty field on the right of ‘observer>’ and press Enter:

The console prints:

ERROR: Nothing named YOU has been defined. 

Oops! NetLogo still doesn’t know “you”. Or is it that it cannot understand you? Well let us get you two properly introduced…

9.2 Entities

The (real) first thing one should learn about NetLogo, and most agent-based modeling systems, is that it handles mainly two types of entities/agents: patches, cells of a square grid, and turtles, which are proper “agents” (i.e., mobile, autonomous entities). Both entities have primitives (built-in, default properties), some of which can be modified by processes in your model. For example, you can’t modify the position of a patch, but you can change its filling color.

NetLogo entities
NetLogo world and entities (Figure 2 in Izquierdo et al. 2019)

As seen in the figure above, NetLogo also includes a third type of entity, links, which has the particularity of describing a connection between two turtles and thus not having specific spatial coordinates of their own. We will deal with links later on, but for now we focus on the other entities, which are more commonly used in models.

All patches and turtles can be identified individually through primitives. Turtles have a unique numerical identifier (who) that is assigned automatically upon the creation of the turtle. Patches, in turn, have an unique combination of x and y integer coordinates in 2D space (pxcor and pycor), as they occupy each a single position in a grid (see Grid). To reference a specific turtle or patch:

NetLogo allows you to define types of turtles as if it where a primitive, declarings its name as a breed:

We can then use the plural or singular form of the breed name directly, instead of referring to the generic turtles.

This is useful, of course, when there are more the one breedto be defined, so that they are easily distinguished and inteligible in the code.

Agents can be specifically selected also without considering their specific IDs. The one-of primitive offers a easy way to randomly select one agent (turtles and patches) from all (or a subset of all) agents of a given type.

Last, we should keep in mind that turtles can be created and destroyed on-the-fly during simulations, while patches are created in the background upon initialisation, according to the model settings (e.g. grid dimensions), but never destroyed during simulation runs.

See NetLogo’s documentation on agents for further details (https://ccl.northwestern.edu/netlogo/docs/programming.html#agents).

9.3 Variables

The most fundamental elements of NetLogo, as in any programming language, is variables. To assign a value to a variable we use the general syntax or code structure:

While variable names are fragments of contiguous text following a naming convention (e.g. my-variable, myVariable, my_variable, etc.), values can be of the following data types:

  • Number (e.g., 1, 4.5, 1E-6)
  • Boolean (i.e., true, false)
  • String (effectively text, but enclosed by quote marks: e.g., "1", "my value")
  • turtles, patches (i.e., NetLogo’s computation entities; see Entities)
  • AgentSet (a set of either turtles or patches; see Entities)
  • List (a list enclosed in squared brakets with values of any kind separated by spaces: e.g., [ "1" 1 false my-agents-bunch ["my value" true 4.5] ])

Before we assign a value to a variable, we must declare its scope and name, though not its data type, which is only defined when assigning an specific value. Variable declaration is typically done at the first section of a model script and its exact position will depend on if it is stored globally or inside entities. These types of declarations follow their own structures:

As an exception to this general rule, variables can also be declared “locally” using the following syntaxes:

As in other programming languages, having a variable declared locally means it is inside a temporary computation environment, such as a procedure (see below). Once the environment is closed, the variable is automatically discarded in the background.

9.4 Expressing equations

As we will see examples further on, the values of variables can be transformed in different ways, using different syntaxes, depending on their type. Possibly the most straightforward case is to perform basic arithmetic operations over numerical variables, expressing equations. These can be writen using the special characters normally used in most programming languages (+, -, *, /, (, etc.):

Notice that arithmetic symbols and numbers must be separated by spaces and that the order of operations can be structured using parentheses.

NetLogo allow line breaks, which can help you read expressions that are too long because they hold several operations. However, too many operation at a time can become hard to read and verify, even with line breaks. The best and safer practice to overcome this is to use parentheses abundantly to ensure the right sequence of operations is performed:

Valid

Additionally, as proper equations, such expressions in NetLogo will also accept variables names representing their current value. Equations can then serve to create far reaching dependencies between different parts of the model code:

It will normally be better to keep operations in separate lines. However, be aware that NetLogo accepts sequential commands in the same line, as long as their syntax is correct:

Knowing this, is particularly useful whenever you want to test the outcome of a longer command sequence in NetLogo’s console (“Command Center”).

9.5 Logic operators

As most programming languages, NetLogo can evaluate equalities and inequalities and return a Boolean value (true or false). The related logical operators are:

  • =: “equals”.
  • !=: “not equal to”.
  • >: “greater than”.
  • >=: “greater than or equal to”.
  • <: “less than”.
  • <=: “less than or equalt to”.

For example, try:

Equality and inequality operators can also be used with other data types, though beware of the different implications. Some operations will return an error.

For example, you can compare Boolean values with = or !=:

but not with quantitative comparisons:

The same applies to lists and agent sets, but not to strings or entities (turtles, patches, links):

Valid: check if the two lists are exactly the same.

Invalid: a quantitative comparison between lists is not interpreted from this.

Valid: check if strings are exactly the same.

Valid: compares the length of the strings.

Valid: checks if entities are the same (useful when entities are referenced indirectly by variables)

Valid, but not recommended: compares the internal ID of entities, which express the creation order, which is often arbitrary.

Note that in other programming languages the equal sign might be reserved to setting the value of a variable. For example, "a" = "b" will return false in NetLogo, while in R it will assign a value “b” to an variable named “a”. By the way, to acheive the same in R, we should write "a" == "b".

9.6 Procedures

In NetLogo, any action we want to perform, that is not manually typed in the console, must be enclosed within a procedure that is declared in the model script (the text in ‘Code’ tab in the user interface). Similarly to ‘functions’ or ‘methods’ in other programming languages, a procedure is the code scripted inside the following structure:

Any procedure can be executed by typing <PROCEDURE_NAME> + Enter in the NetLogo’s console at the bottom of the ‘Interface’ tab. The “Hello World” program, a typical minimum exercise when learning a programming language, correspond to the following procedure hello-world:

which generates the following “prints” in the console:

observer> hello-world
Hello World!

Procedures are particularly useful to group and enclose a sequence of commands that are semantically connected for the programmer. For example, the following procedure declares a temporary (local) variable, assigns to it a number as value, and prints it in the console:

Procedures can then be used elsewhere by writing its name (more complications to come). A procedure can be included as a step in another procedure:

NetLogo’s interface editor allows us to create buttons that can execute one or multiple procedures (or even a snippet of ad hoc code). The interface system is quite straightforward. First, at the top of the interface tab, click “Add” and select a type of element in the drop-down list. Click anywhere in the window below to place it. Select it with click-dragging or using the “Select” option in the right-click pop-up menu. You can edit the element by selecting “Edit”, also in the right-click pop-up menu. For any doubts on how to edit the interface tab, please refer to NetLogo’s documentation (https://ccl.northwestern.edu/netlogo/docs/interfacetab.html).

9.7 Logic bifurcations: if and ifelse

The code exemplifies how to create conditional rules according to predefined general conditions using if/else statements, which in NetLogo can be written as if or ifelse:

9.8 Iterators (loops)

Using while, we can use a structure similar to bifurcations, to reiterate over the same code a number of times as long as a logical condition is true:

Notice the use of square brackets to surround the condition ([<CONDITION_1_IS_TRUE>]).

A variant of this is the primitive loop, where there is no condition, meaning that the action within will be repeated forever until the code inside stop the flow explicitly (stop or report), or the user interrupts NetLogo.

Caution

ALERT

Avoid using while or loop until you are confident with you code. A loop hidden inside you code, that might go forever in a few cases, can become a headache when performing simulation experiments in batches.

A more useful iterator is repeat, which will reiterate code a certain number of times:

You may quickly test it in the console with:

A especial type of iterator abundantly used in NetLogo is ask. You can ask all or any subset of entities to perform specific commands by following the structure:

9.9 Entities with variables, logic operations, and procedures

Commands inside the ask structure can be both direct variable operations and procedures. For instance:

However, all variables referenced inside these structures must be properly related to their scope, following NetLogo’s syntax. For example, an agent is only able to access the variable in another agent if it we use the following kind of structure:

It is possible to select a subset of any set of entities through logic clauses to be checked separately for each individual entity. For example, to get all agents with a certain numeric property greater than a given threshold:

When operating from the inside an ask command, we can also make sure to filter-out the agent currently performing the call, by using the primitive other:

All this can be combined to form quite complex rules of behaviour, yet keeping itself generally readable:

9.10 Grid

One should spend some time understanding the grid structure and associated syntax. It is recommendable to consult the “settings” pop-up window in the “interface tab”:

The settings pop-up window in NetLogo
The settings pop-up window in NetLogo

The default configuration is a 33x33 grid with the position (0,0) at the centre. Both dimensions and centre can be easily edited for each particular model. Moreover, we can specify agents behaviour at the borders by ticking the “wrap” options. Wrapping the world limits means that, for instance, under the default setting mentioned above, the position (-16,0) is adjacent to (16,0). In the console, we can “ask” the patch at (-16,0) to print its distance to the patch at (16,0), using the primitive function distance (https://ccl.northwestern.edu/netlogo/docs/dictionary.html#distance):

observer> ask patch -16 0 [ print distance patch 16 0 ]
1

Wrapping one dimension represents a cylindrical surface while wrapping two depicts a strange toroidal object (Doughnut!). Although this aspect is relatively hidden among the options, it can have great importance if spatial relations play any part in a model. So if you want your grid to represent a geographical map, make sure to unpick the wrapping features.

9.11 Commenting code

Annotations or comments (i.e., text that should be ignored when executing the code) can be added to the code by using the structure:

or

9.12 Dictionary

One of the most useful resources of NetLogo’s documentation is the dictionary that can be accessed in the “Help” menu. This is true at any moment throughout your learning curve; even when you know all primitives and built-in functions by heart. Moreover, all documentation is present with any copy of NetLogo, so it is fully available offline.

The dictionary is particularly useful whenever you are learning by example, as in our case. For instance, regarding the earlier mention of distance, you could have searched it in the dictionary directly. Whenever you find yourself reading NetLogo code with violet or blue words that you do not understand, take the habit of searching them in NetLogo’s dictionary.

For more information consult NetLogo Programming Guide.

9.13 Other platforms and languages

Consider yourself introduced to NetLogo! However, please remember that ABM is not limited to this language and platform. It is highly recommended that you learn and practice with other programming languages to experience ABM models beyond NetLogo implementations.

Potentially, any programming language can be used to implement an ABM model. However, it is useful to count on specific support software in most cases. A few of the most relevant platforms and libraries to know about are: RePast, AnyLogic, Mesa, Agents.jl, and Pandora. See many others in this list by SWARM.org.