0. Introduction

0.4. The fundamentals of NetLogo

This section provides a succinct overview of the fundamentals of NetLogo. It is strongly based on the excellent NetLogo user manual, version 6.0.2 (Wilensky, 2017). By no means do we claim originality on the content of this section; all credit should go to Uri Wilensky and his team. The following table provides links to the different aspects of NetLogo programming that we cover here.

Very basics More advanced Final polishing
The three tabs Ask Consistency within procedures
Types of agents Lists Breeds
Instructions Agentsets Ticks and Plotting
Variables Synchronization Skeleton of many NetLogo models
The code for Schelling-Sakoda model

Feel free to skip this section if you are already familiar with NetLogo. For future reference, you may wish to download our NetLogo quick guide, which is a 6-page pdf file containing the main concepts outlined here.

1. The three tabs

The main window of NetLogo contains three tabs, i.e. the interface tab, the info tab and the code tab (see figure 1).

Figure 1. Top bar of the NetLogo Interface tab, where you can select the tab you want to see.

The interface tab is used to run the model. It often contains buttons, sliders, switches, plots… Most models include a button labeled setup, which is used to initialize the model, and another button labeled go, which is used to run the model.

The Info tab can be used to include the documentation of the model.

Finally, the code tab contains most of the code of the model. We say most because in some models part of the code is included within the plots in the interface tab.

2. Types of agents

Figure 2. The NetLogo world is made up of turtles, patches, links and the observer.

The NetLogo world is made up by four types of agents (see figure 2), i.e.:

  • Turtles. Turtles are agents that can move.
  • Patches: The NetLogo world is two-dimensional and is divided up into a grid of patches. Each patch is a square piece of “ground” over which turtles can move.
  • Links: Links are agents that connect two turtles. Links can be directed (from one turtle to another turtle) or undirected (one turtle with another turtle).
  • The observer: There is only one observer and it does not have a location. You can think of the observer as the conductor of the whole NetLogo orchestra.

Note that in many descriptions of agent-based models, the word agent is used only to refer to the turtles (i.e. the mobile agents in NetLogo), while patches are links are not considered agents (and the observer is not even mentioned). However, when reading NetLogo documentation, it is important to remember that these four types of entities are all agents in NetLogo.

3. Instructions

Instructions tell agents what to do. Three characteristics are useful to remember about instructions:

  • Whether the instruction is implemented by the user (procedures), or whether it is built into NetLogo (primitives). Once you define a procedure, you can use it elsewhere in your program. The NetLogo Dictionary has a complete list of built-in instructions (i.e. primitives). The following code is an example of the implementation of procedure to setup:
    to setup             ;; comments are written after semicolon(s)
      clear-all          ;; clear everything 
      create-turtles 10  ;; make 10 new turtles
    end                  ; (one semicolon is enough, but I like two)
    

    The instruction to setup is a procedure (since it is implemented by us), whereas clear-all and create-turtles are both primitives (they are built into NetLogo).

    Note that primitives are nicely colored, and you can click on them and press F1 to see their syntax, functionality, and examples. You may want to copy and paste the code above to see all this for yourself.

  • Whether the instruction produces an output (reporters) or not (commands).
    • A reporter computes a result and reports it. Most reporters are nouns or noun phrases (e.g. “average-wealth”, “most-popular-girl”). These names are preceded by the keyword to-report. The keyword end marks the end of the instructions in the procedure.
      to-report average-wealth          ;; this reporter returns the 
        report mean [wealth] of turtles ;; average wealth in the 
      end                               ;; population of turtles
      
    • A command is an action for an agent to carry out. Most commands begin with verbs (e.g. “create”, “die”, “jump”, “inspect”, “clear”). These verbs are preceded by the keyword to (instead of to-report). The keyword end marks the end of the procedure.
      to go
        ask turtles [ 
          forward 1        ;; all turtles move forward one step
          right random 360 ;; and turn a random amount
        ] 	
      end
      

    Note that primitive commands are colored in blue while primitive reporters are colored in purple. Keywords are colored in green.

  • Whether the instruction takes an input (or several inputs) or not. Inputs are values that the instruction uses in carrying out its actions.
    to-report absolute-value [number]     ;; number is the input
      ifelse number >= 0         ;; if number is already non-negative    
        [ report number ]        ;; return number (a non-negative value).
        [ report (- number) ]    ;; Otherwise, return the opposite, which
    end                          ;; is then necessarily positive.

4. Variables

Variables are places to store values (such as numbers). A variable can be a global variable, a turtle variable, a patch variable, a link variable, or a local variable (local to a procedure). To change the value of a variable you can use the set command. If you don’t set the variable to any value, it starts out storing a value of zero.

  • Global variables: If a variable is a global variable, there is only one value for the variable, and every agent can access it. You can declare a new global variable either in the Interface tab –by adding a switch, a slider, a chooser or an input box– or in the Code tab –by using the globals keyword at the beginning of your code, like this:
    globals [ n-of-strategies ]
    
  • Turtle, patch, and link variables: Each turtle has its own value for every turtle variable, each patch has its own value for every patch variable, and each link has its own value for every link variable. Turtle, patch, and link variables can be built-in or defined by the user.
    • Built-in variables: For example, all turtles and all links have a color variable, and all patches have a pcolor variable. If you set this variable, the corresponding turtle, link or patch changes color. Other built-in turtle variables are xcor, ycor, and heading. Other built-in patch variables include pxcor and pycor. Other built-in link variables are end1, end2, and thickness. You can find the complete list in the NetLogo Dictionary.
    • User-defined turtle, patch and link variables: You can also define new turtle, patch or link variables using the turtles-own, patches-own, and links-own keywords respectively, like this:
      turtles-own [ energy ]    ;; each turtle has its own energy
      patches-own [ roughness ] ;; each patch has its own roughness
      links-own   [ weight ]    ;; each link has its own weight
      
  • Local variables: A local variable is defined and used only in the context of a particular procedure or part of a procedure. To create a local variable, use the let command. You can use this command anywhere. If you use it at the top of a procedure, the variable will exist throughout the procedure. If you use it inside a set of square brackets, for example inside an ask, then it will exist only inside those brackets.
    to swap-colors [turtle1 turtle2]  ;; turtle1 and turtle2 are inputs
      let temp ([color] of turtle1)   ;; store the color of turtle1 in temp
      ask turtle1 [ set color ([color] of turtle2) ]
    	;; set turtle1’s color to turtle2’s color
      ask turtle2 [ set color temp ]
    	;; now set turtle2’s color to turtle1’s (original) color
    end     ;; (which was conveniently stored in local variable “temp”).
    

Setting and reading the value of variables

Global variables can be read and set at any time by any agent. Every agent has direct access to her own variables, both for reading and setting. Sometimes you will want an agent to read or set a different agent’s variable; to do that, you can use ask (which is explained in further detail later):

ask turtle 5 [ show color ]      ;; turtle 5 shows its color
ask turtle 5 [ set color blue ]  ;; turtle 5 becomes blue 

You can also use of to make one agent read another agent’s variable. of is written in between the variable name and the relevant agent (i.e. [reporter] of agent). Example:

show [color] of turtle 5 ;; observer shows turtle 5's color

Finally, a turtle can read and set the variables of the patch it is standing on directly, e.g.

ask turtles [ set pcolor red ]

The code above causes every turtle to make the patch it is standing on red. (Because patch variables are shared by turtles in this way, you cannot have a turtle variable and a patch variable with the same name –e.g. that is why we have color for turtles and pcolor for patches).

5. Ask

NetLogo uses the ask command to specify instructions that are to be run by turtles, patches or links. Usually, the observer uses ask to ask all turtles or all patches to run commands. Here’s an example of the use of ask syntax in a NetLogo procedure:

to setup
  clear-all            ;; clear everything
  create-turtles 100   ;; create 100 new turtles with random heading
  ask turtles [        ;; ask them
    set color red      ;; to turn red and
    forward 50         ;; to move 50 steps forward
  ]       
  ask patches [        ;; ask patches
    if (pxcor > 0) [   ;; with pxcor greater than 0
      set pcolor green ;; to turn green
    ]
  ] 
end

You can also use ask to have an individual turtle, patch or link run commands. The reporters turtle, patch, link, and patch-at are useful for this technique. For example:

to setup
  clear-all               ;; clear the world
  create-turtles 3        ;; make 3 turtles
  ask turtle 0 [ fd 10 ]  ;; tell the first one to go forward 10 steps
  ask turtle 1 [	  ;; ask the second turtle (with who number 1)
    set color green       ;; ... to become green
  ]
  ask patch 2 -2 [        ;; ask the patch at (2,-2)...
    set pcolor blue       ;; ... to become blue
  ]
  ask turtle 0 [	    ;; ask the first turtle (with who number 0)
    create-link-to turtle 2 ;; to link to turtle with who number 2
  ]
  ask link 0 2 [          ;; ask the link between turtle 0 and 2...
    set color blue        ;; ... to become blue
  ]
  ask turtle 0 [          ;; ask the turtle with who number 0
    ask patch-at 1 0 [    ;; ... to ask the patch to her east
      set pcolor red      ;; ... to become red
    ]
  ]
end

6. Lists

In the simplest models, each variable holds only one piece of information, usually a number or a string. Lists let you store multiple pieces of information in a single variable by collecting those pieces of information in a list. Each value in the list can be any type of value: a number, a string, an agent, an agentset, or even another list.

Constant lists

You can make a list by simply putting the values you want in the list between brackets, e.g.:

set my-list [2 4 6 8]

Building lists on the fly

If you want to make a list in which the values are determined by reporters, as opposed to being a series of constants, use the list reporter. The list reporter accepts two other reporters, runs them, and reports the results as a list.

set my-random-list list (random 10) (random 20)

To make shorter or longer lists, you can use the list reporter with fewer or more than two inputs, but in order to do so, you must enclose the entire call in parentheses, e.g.:

show (list random 10)
show (list (random 10) (turtle 3) "a" 30)  ;; inner () are not necessary

The of primitive lets you construct a list from an agentset (i.e. a set of agents). It reports a list containing each agent’s value for the given reporter (syntax: [reporter] of agentset).

set fitness-list ([fitness] of turtles)	
	;; list containing the fitness of each turtle (in random order)
show [pxcor * pycor] of patches

See also: n-values, range, sentence and sublist.

Reading and changing list items

List items can be accessed using first, last and item. The first element of a list is item 0. Technically, lists cannot be modified, but you can construct new lists based on old lists. If you want the new list to replace the old list, use set. For example:

set my-list [2 7 5 "Bob" [3 0 -2]]     ;; my-list is now [2 7 5 "Bob" [3 0 -2]]
set my-list replace-item 2 my-list 10  ;; my-list is now [2 7 10 "Bob" [3 0 -2]]

See also: but-first, but-last, fput, lput, length, shuffle, position and remove-item.

Iterating over lists

To apply a function (procedure) on each item in a list, you can use foreach or map. The function to be applied is usually defined using anonymous procedures, with the following syntax:

[ [input-1 input-2 ...] -> code of the procedure ]
  ;; this syntax was different in versions before NetLogo 6.0

The names assigned to the inputs of the procedure (i.e. input-1 and input-2 above) may be used within the code of the procedure just like you would use any other variable within scope. You can use any name you like for these local variables (complying with the usual restrictions). An example of an anonymous procedure that implements the absolute value is:

[ [x] -> abs x ]  ;; you can use any symbol instead of x
[  x  -> abs x ]  ;; if there is just one input 
                  ;; you do not need the square brackets

foreach is used to run a command on each item in a list. It takes as inputs the list and the command to be run on each element of the list, e.g.:

foreach [1.2 4.6 6.1] [ n -> show (word n " rounded is " round n) ]
  ;; output: "1.2 rounded is 1" "4.6 rounded is 5" "6.1 rounded is 6"

map is similar to foreach, but it is a reporter (it returns a list). It takes as inputs a list and a reporter; and returns an output list containing the results of applying the reporter to each item in the input list. As in foreach, procedures can be anonymous.

map [ element -> round element ] [1.2 2.2 2.7]	 ;; returns [1 2 3]

Simple uses of foreach, map, n-values, and related primitives can be written more concise.

map round [1.2 2.2 2.7]	   
  ;; (see Anonymous procedures in Programming Guide)

Both foreach and map can take multiple lists as input; in that case, the procedure is run once for the first items of all input lists, once for the second items, and so on.

(map [[el1 el2] -> el1 + el2] [1 2 3] [10 20 30])  ;; returns [11 22 33]
(map + [1 2 3] [10 20 30])  	;; a shorter way of writing the same

See also: reduce, filter, sort-by, sort-on, and -> (anonymous procedure).

7. Agentsets

An agentset is a set of agents; all agents in an agentset must be of the same type (i.e. turtles, patches, or links). An agentset is not in any particular order. In fact, it’s always in a random order.[1] What’s powerful about the agentset concept is that you can construct agentsets that contain only some agents. For example, all the red turtles, or the patches with positive pxcor, or all the links departing from a certain agent. These agentsets can then be used by ask or by various reporters that take agentsets as inputs, such as one-of, n-of, with, with-min, max-one-of, etc. The primitive with and its siblings are very useful to build agentsets. Here are some examples:

turtles with [color = red]         ;; all red turtles
patches with [pxcor > 0]           ;; patches with positive pxcor
[my-out-links] of turtle 0         ;; all links outgoing from turtle 0
turtles in-radius 3                ;; all turtles three or fewer patches away
other turtles-here with-min [size] ;; other turtles with min size on my patch 
(patch-set self neighbors4)        ;; von Neumann neighborhood of a patch

Once you have created an agentset, here are some simple things you can do:

  • Use ask to make the agents in the agentset do something.
  • Use any? to see if the agentset is empty.
  • Use all? to see if every agent in an agentset satisfies a condition.
  • Use count to find out exactly how many agents are in the set.

Here are some more complex things you can do:

ask one-of turtles [ set color green ]
	;; one-of reports a random agent from an agentset 
ask (max-one-of turtles [wealth]) [ donate ]
	;; max-one-of agentset [reporter] reports an agent in the
	;; agentset that has the highest value for the given reporter
show mean ([wealth] of turtles with [gender = male])
	;; Use of to make a list of values, one for each agent in the agentset. 
show (turtle-set turtle 0 turtle 2 turtle 9 turtles-here)
	;; Use turtle-set, patch-set and link-set reporters to make new 
	;; agentsets by gathering together agents from a variety of sources
show (turtles with [gender = male]) = (turtles with [wealth > 10])
	;; Check whether two agentsets are equal using = or !=
show member? (turtle 0) turtles with-min [wealth]
	;; Use member? to see if an agent is a member of an agentset.
if all? turtles [color = red]     ;; use all? to see if every agent in the
  [ show "every turtle is red!" ] ;; agentset satisfies a certain condition
ask turtles [
  create-links-to other turtles-here ;; on same patch as me, not me,
    with [color = [color] of myself] ;; and with same color as me.
]	
show [([color] of end1) - ([color] of end2)] of links   ;; check everything’s OK

8. Synchronization

When you ask a set of agents to run more than one command, each agent must finish all the commands in the block before the next agent starts. One agent runs all the commands, then the next agent runs all of them, and so on. As mentioned before, the order in which agents are chosen to run the commands is random. To be clear, consider the following code:

ask turtles [
  forward random 10 ;; move forward a random number of steps (0–9)
  wait 0.5          ;; wait half a second
  set color blue    ;; set your color to blue
]

The first (randomly chosen) turtle will move forward some steps, she will then wait half a second, and she will finally set her color to blue. Then, and only then, another turtle will start doing the same; and so on until all turtles have run the commands inside ask without being interrupted by any other turtle. The order in which turtles are selected to run the commands is random. If you want all turtles to move, and then all wait, and then all become blue, you can write it this way:

ask turtles [ forward random 10 ]
ask turtles [ wait 0.5 ]        ;; note that you will have to wait 
ask turtles [ set color blue ]  ;; (0.5 * number-of-turtles) seconds

Finally, you can make agents execute a set of commands in a certain order by converting the agentset into a list. There are three primitives that help you do this: sort, sort-by and sort-on.

set my-list-of-agents sort-by [[t1 t2] -> [size] of t1 < [size] of t2] turtles
 ;; This sets my-list-of-agents to a list of turtles sorted in
 ;; ascending order by their turtle variable size. For simple orderings
 ;; like this, you can use sort-on, e.g.: sort-on [size] turtles
foreach my-list-of-agents [ ag ->
    ask ag [            ;; each agent undertakes the list of commands
    forward random 10   ;; (forward, wait, and set) without being 
    wait 0.5            ;; interrupted, i.e. the next agent does not 
    set color blue      ;; start until the previous one has finished.
  ]
]

9. Consistency within procedures

Some primitives in NetLogo can only be run by a certain type of agent. For instance, forward can only be run by turtles, since turtles are the only type of agent that can move. An easy way of knowing which type of agent can run a certain primitive is to find the primitive in the NetLogo Dictionary and look at the icon beneath the name of the primitive. If you click on forward, you will see the icon Turtle icon, which denotes turtles. The icons for the other types of agent are: Observer icon for the observer, Patch icon for patches, and Link icon for links. There are primitives that can be run by more than one type of agent. For instance, reporter turtles-here can be run by turtles and by patches.

The question that naturally comes to mind now is: How do we tell NetLogo what type of agent should run a certain procedure (which we implement)? The answer is simple: we don’t. NetLogo infers that from the code of the procedure; we just have to be consistent. An example of inconsistency would be to code a procedure containing two primitives that can be run only by two different types of agents, as in the following example:

to setup
  create-turtles 10
  forward 1
end

If we implement this code, we obtain the following error message: “You can’t use FORWARD in an observer context, because FORWARD is turtle-only” (see figure 3).

Figure 3. Inconsistency error.

The reason is that NetLogo reads the primitive create-turtles and, since it can only be run by the observer, NetLogo infers that the procedure to setup will be run only by the observer, i.e. everything inside is in an observer context. Then, NetLogo reads the primitive forward, which can only be run by turtles, and throws the error.

We would obtain similar inconsistency errors if we tried to access individually-owned variables within procedures that can only be run by a type of agent that cannot access those variables, as in the following examples.

to setup
  create-turtles 10
  show xcor
end
;; Here we would obtain the error:
;; "You can't use XCOR in an observer context, because XCOR is turtle-only"
to setup
  create-turtles 10
  show pxcor
end
;; Here we would obtain the error:
;; "You can't use PXCOR in an observer context, because PXCOR is turtle/patch-only"

Note that in the example above, NetLogo says that pxcor is “turtle/patch-only”. This is because all patch variables can be directly accessed by any turtle standing on the patch (see section Variables above).

to setup
  create-turtles 10
  show end1
end
;; Here we would obtain the error:
;; "You can't use END1 in an observer context, because END1 is link-only"

10. Breeds

NetLogo allows you to have different types of turtles and different types of links. There are called breeds. Here we discuss breeds of turtles only, since breeds of links follow the same logic. Breeds are defined with the syntax:

breed [plural-name singular-name]

For instance, to define a breed of sellers and a breed of buyers, we would type the following at the top of our code:

breed [sellers seller]
breed [buyers buyer]

From then onwards, we could assign different individually-owned variables to each of the breeds, using the keywords sellers-own and buyers-own. Also, there are a number of primitives that are automatically added to the NetLogo language once you have defined a breed, such as create-sellers, hatch-sellers, sprout-sellers, sellers-here, sellers-at, sellers-on, and is-seller?.

11. Ticks and Plotting

In most NetLogo models, time passes in discrete steps called “ticks”. NetLogo includes a built-in tick counter so you can keep track of how many ticks have passed. The current value of the tick counter is shown above the view. Note that –since NetLogo 5.0– ticks and plots are closely related.

You can write code inside the plots. Every plot and each of its pens have setup and update code fields where you can write commands. All these fields must be edited directly in each plot –i.e. in the interface, not in the code tab. To execute the commands written inside the plots, you can use setup-plots and update-plots, which run the corresponding fields in every plot and in every pen. However, in models that use the tick counter, these two primitives are not normally used because they are automatically triggered by tick-related commands, as explained below.

To use the tick counter, first you must reset-ticks; this command resets the tick counter to zero, sets up all plots (i.e. triggers setup-plots), and then updates all plots (i.e. triggers update-plots); thus, the initial state of the world is plotted. Then, you can use the tick command, which advances the tick counter by one and updates all plots.

See also: plot, plotxy, and ticks.

12. Skeleton of many NetLogo models

In most NetLogo models there are two basic procedures that are run by the observer: to setup and to go.

Procedure to setup is run just once at the beginning of the simulation, most often by clicking a button in the interface tab. In this procedure:

  • we initialize the model from scratch using the primitive clear-all,
  • we set up all initial conditions (this often implies creating several agents), and
  • we finish with the primitive reset-ticks.

Procedure to go contains all the actions that will be executed repeatedly in the model. Some of these actions will be executed directly by the observer, while others will be run by the turtles, the patches or the links. In any case, procedure to go is run by the observer, so it is the observer who must ask the other agents to run the appropriate instructions, using the primitive ask. Most often, procedure to go contains the primitive tick, which advances the (discrete) NetLogo clock in one unit.

globals  [ … ]     ;; global variables (also defined with sliders, …)
turtles-own [ … ]  ;; user-defined turtle variables (also <breeds>-own)
patches-own [ … ]  ;; user-defined patch variables
links-own [ … ]    ;; user-defined link variables (also <link-breeds>-own)

to setup 
  clear-all 
  …
  setup-patches  ;; procedure where patches are initialized
  …
  setup-turtles  ;; procedure where turtles are createdreset-ticks
end

to go
  conduct-observer-procedure 
  …
  ask turtles [conduct-turtle-procedure] 
  …
  ask patches [conduct-patch-procedure] 
  …
  tick ;; this will update every plot and every pen in every plot
end

to-report a-particular-statistic 
  …
  report the-result-of-some-formula  	
end

13. The code for Schelling-Sakoda model

To conclude this section, we present some simple code that implements the Schelling-Sakoda model described in section 0.2 “Introduction to agent-based modeling”. The code we show here is simpler than the one used for the videos in section 0.2, which is more efficient but less readable.[2] In the interface, we have used two sliders to define parameters number-of-agents and %-similar-wanted (see figure 4).

Figure 4. Interface of a simple version of Schelling-Sakoda model.

Figure 5. Window that pops up when you inspect a turtle. You can ask the turtle to execute instructions by typing them on the bottom line.

The code that goes in the code tab is shown below. You can download the whole model here and take this code as a test to check whether you are ready to proceed to the next chapter. If you can understand most of it, you are definitely prepared!

To work your way through the code, you will most likely have to use the NetLogo Dictionary intensively, and run small pieces of code in the Command Center (especially because the model includes several NetLogo primitives that we have not seen yet). You can also inspect individual turtles and make them run (turtle) instructions such as:

ask turtles-on neighbors [set label "Hi!"]

You will have to type these instructions on the bottom line of the window that pops up when you inspect a turtle (see figure 5). To inspect a turtle, right-click on it, select the name of the turtle (e.g. turtle 21), and click on “inspect”. Alternatively, you can just type the following instruction in the command center:

inspect turtle 21

Developing these skills will be useful, since programming in NetLogo most often involves looking up the dictionary very often and testing short snippets of code. Once you have understood most of the code below we can start building our first agent-based evolutionary model in the next chapter!

;;;;;;;;;;;;;;;;;
;;; VARIABLES ;;;
;;;;;;;;;;;;;;;;;

turtles-own [
  happy?
]

;;;;;;;;;;;;;;;;;;;;;;;;
;;; SETUP PROCEDURES ;;;
;;;;;;;;;;;;;;;;;;;;;;;;

to setup
  clear-all
  setup-agents
  reset-ticks
end
to setup-agents
  set-default-shape turtles "person"
  ask n-of number-of-agents patches
    [ sprout 1 [set color cyan] ]
  ask n-of (number-of-agents / 2) turtles
    [ set color orange ]
  ask turtles [update-happiness]
end

;;;;;;;;;;;;;;;;;;;;;;
;;; MAIN PROCEDURE ;;;
;;;;;;;;;;;;;;;;;;;;;;

to go
  if all? turtles [happy?] [stop]
  ask one-of turtles with [not happy?] [move]
  ask turtles [update-happiness]
  tick
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; TURTLES' PROCEDURES ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;

to move
  move-to one-of patches with [not any? turtles-here]
end
to update-happiness
  let my-nbrs (turtles-on neighbors)
  let n-of-my-nbrs (count my-nbrs)
  let similar-nbrs (count my-nbrs with [color = [color] of myself])
  set happy? similar-nbrs >= (%-similar-wanted * n-of-my-nbrs / 100)
end

  1. If you want agents to do something in a fixed order, you can make a list of the agents instead.
  2. Both implementations lead to exactly the same dynamics.

License

Icon for the Creative Commons Attribution 4.0 International License

0.4. The fundamentals of NetLogo by Luis R. Izquierdo, Segismundo S. Izquierdo & William H. Sandholm is licensed under a Creative Commons Attribution 4.0 International License, except where otherwise noted.

Share This Book