The following material explains some important features of programming in NetLogo.
(Note: If you are already familiar with StarLogo or StarLogoT, then the material in the first four sections may already be familiar to you.)
The Code Example models mentioned throughout can be found in the Code Examples section of the Models Library.
The NetLogo world is made up of agents. Agents are beings that can follow instructions. Each agent can carry out its own activity, all simultaneously.
In NetLogo, there are three types of agents: turtles, patches, and the observer. Turtles are agents that move around in the world. The 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. The observer doesn't have a location -- you can imagine it as looking out over the world of turtles and patches.
When NetLogo starts up, there are no turtles yet. The observer can make new turtles. Patches can make new turtles too. (Patches can't move, but otherwise they're just as "alive" as turtles and the observer are.)
Patches have coordinates. The patch in the center of the world has coordinates (0, 0). We call the patch's coordinates pxcor and pycor. Just like in the standard mathematical coordinate plane, pxcor increases as you move to the right and pycor increases as you move up.
The total number of patches is determined by the settings screen-edge-x and screen-edge-y. When NetLogo starts up, both screen-edge-x and screen-edge-y are 17. This means that pxcor and pycor both range from -17 to 17, so there are 35 times 35, or 1225 patches total. (You can change the number of patches by editing NetLogo's Graphics window.)
Turtles have coordinates too: xcor and ycor. A patch's coordinates are always integers, but a turtle's coordinates can have decimals. This means that a turtle can be positioned at any point within its patch; it doesn't have to be in the center of the patch.
The world of patches isn't bounded, but "wraps" -- so when a turtle moves past the edge of the world, it disappears and reappears on the opposite edge. Every patch has the same number of "neighbor" patches -- if you're a patch on the edge of the world, some of your "neighbors" are on the opposite edge.
In NetLogo, commands and reporters tell agents what to do. Commands are actions for the agents to carry out. Reporters carry out some operation and report a result either to a command or another reporter.
Commands and reporters built into NetLogo are called primitives. The Primitives Dictionary has a complete list of built-in commands and reporters.
Commands and reporters you define yourself are called procedures. Each procedure has a name, preceded by the keyword to. The keyword end marks the end of the commands in the procedure. Once you define a procedure, you can use it elsewhere in your program.
Many commands and reporters take inputs -- values that the command or reporter uses in carrying out its actions.
Examples: Here are two command procedures:
to setup ca ;; clear the screen crt 10 ;; make 10 new turtles end to go ask turtles [ fd 1 ;; all turtles move forward one step rt random 10 ;; ...and turn a random amount lt random 10 ] endNote the use of semicolons to add "comments" to the program. Comments make your program easier to read and understand.
In this program,
setup and go can be called by other procedures or by buttons. Many NetLogo models have a once-button that calls a procedure called setup, and a forever-button that calls a procedure called go.
In NetLogo, you must specify which agents -- turtles, patches, or the observer -- are to run each command. (If you don't specify, the code is run by the observer.) In the code above, the observer uses ask to make the set of all turtles run the commands between the square brackets.
ca and crt can only be run by the observer. fd, on the other hand, can only be run by turtles. Some other commands and reporters, such as set, can be run by different agent types.
Variables are places to store values (such as numbers). A variable can be a global variable, a turtle variable, or a patch variable.
If a variable is a global variable, there is only one value for the variable, and every agent can access it. But each turtle has its own value for every turtle variable, and each patch has its own value for every patch variable.
Some variables are built into NetLogo. For example, all turtles have a color variable, and all patches have a pcolor variable. (The patch variable begins with "p" so it doesn't get confused with the turtle variable.) If you set the variable, the turtle or patch changes color. (See next section for details.)
Other built-in turtle variables including xcor, ycor, and heading. Other built-in patch variables include pxcor and pycor. (There is a complete list here.)
You can also define your own variables. You can make a global variable by adding a switch or a slider to your model, or by using the globals keyword at the beginning of your code, like this:
globals [ clock ]
You can also define new turtle and patch variables using the turtles-own and patches-own keywords, like this:
turtles-own [ energy speed ] patches-own [ friction ]
These variables can then be used freely in your model. Use the set command to set them. (If you don't set them, they'll start out storing a value of zero.)
Global variables can by read and set at any time by any agent. As well, a turtle can read and set patch variables of the patch it is standing on. For example, this code:
ask turtles [ set pcolor red ]
causes every turtle to make the patch it is standing on red. (Because patch variables are shared by turtles in this way, you can't have a turtle variable and a patch variable with the same name.)
In other situations where you want an agent to read or set a different agent's variable, you put -of after the variable name and then specify which agent you mean. Examples:
set color-of turtle 5 red ;; turtle with ID number 5 turns red set pcolor-of patch 2 3 green ;; patch with pxcor of 2 and pycor of 3 turns green ask turtles [ set pcolor-of patch-at 1 0 blue ] ;; every turtle turns the patch to its east blue ask patches with [any? turtles-here] [ set color-of random-one-of turtles-here yellow ] ;; on every patch, a random turtle turns yellow
NetLogo represents colors as numbers in the range 0 to 140, with the exception of 140 itself. Below is a chart showing the range of colors you can use in NetLogo.
The chart shows that:
Code Example: The color chart was made in NetLogo with the Color Chart Example model.
Note: If you use a number outside the 0 to 140 range, NetLogo will repeatedly add or subtract 140 from the number until it is in the 0 to 140 range. For example, 25 is orange, so 165, 305, 445, and so on are orange too, and so are -115, -255, -395, etc. This calculation is done automatically whenever you set the turtle variable color or the patch variable pcolor. Should you need to perform this calculation in some other context, use the wrap-color primitive.
If you want a color that's not on the chart, more can be found between the integers. For example, 26.5 is a shade of orange halfway between 26 and 27. This doesn't mean you can make any color in NetLogo; the NetLogo color space is only a subset of all possible colors. A fixed set of discrete hues is available, and you can either decrease the brightness (darken) or decrease the saturation (lighten) of those hues to get your desired color, but you may not decrease both the brightness and saturation.
There are a few primitives that are helpful for working with color shades. The scale-color primitive is useful for converting numeric data into colors. And shade-of? will tell you if two colors are "shades" of the same basic hue. For example, shade-of? orange 27 is true, because 27 is a lighter shade of orange.
Code Example: Scale-color Example shows you how to use the scale-color reporter.
For many models, the NetLogo color system is a convenient way of expressing colors. But sometimes you'd like to be able to specify colors the conventional way, by specifying HSB (hue/saturation/brightness) or RGB (red/green/blue) values. The hsb and rgb primitives let you do this. extract-hsb and extract-hsb let you convert colors in the other direction.
Since the NetLogo color space doesn't include all hues, hsb and rgb can't always give you the exact color you ask for, but they try to come as close as possible.
Code Example: You can use the HSB and RGB Example model to experiment with the HSB and RGB color systems.
NetLogo uses the ask command to specify commands that are to be run by turtles or patches. All code to be run by turtles must be located in a turtle "context". You can establish a turtle context in any of three ways:
The same goes for patches and the observer, except that code to be run by the observer must not be inside any ask.
Here's an example of the use of ask syntax in a NetLogo procedure:
to setup ca crt 100 ;; create 100 turtles ask turtles [ set color red ;; turn them red rt random-float 360 ;; give them random headings fd 50 ] ;; spread them around ask patches [ if (pxcor > 0) ;; patches on the right side [ set pcolor green ] ] ;; of the screen turn green end
The models in the Models Library are full of other examples. A good place to start looking is in the Code Examples section.
Usually, the observer uses ask to ask all turtles or all patches to run commands. You can also use ask to have make an individual turtle or patch run commands. The reporters turtle, patch, and patch-at are useful for this technique. For example:
to setup ca crt 3 ;; make 3 turtles ask turtle 0 ;; tell the first one... [ fd 1 ] ;; ...to go forward ask turtle 1 ;; tell the second one... [ set color green ] ;; ...to become green ask turtle 2 ;; tell the third one... [ rt 90 ] ;; ...to turn right ask patch 2 -2 ;; ask the patch at (2,-2) [ set pcolor blue ] ;; ...to become blue ask turtle 0 ;; ask the first turtle [ ask patch-at 1 0 ;; ...to ask patch to the east [ set pcolor red ] ;; ...to become red end
Every turtle created has an ID number. The first turtle created has ID 0, the second turtle ID 1, and so forth. The turtle primitive reporter takes an ID number as an input, and reports the turtle with that ID number. The patch primitive reporter takes values for pxcor and pycor and reports the patch with those coordinates. And the patch-at primitive reporter takes offsets: distances, in the x and y directions, from the first agent. In the example above, the turtle with ID number 0 is asked to get the patch east (and no patches north) of itself.
You can also select a subset of turtles, or a subset of patches, and ask them to do something. This involves a concept called "agentsets". The next section explains this concept in detail.
An agentset is exactly what its name implies, a set of agents. An agentset can contain either turtles or patches, but not both at once.
You've seen the turtles primitive, which reports the agentset of all turtles, and the patches primitive, which reports the agentset of all patches.
But what's powerful about the agentset concept is that you can construct agentsets that contain only some turtles or some patches. For example, all the red turtles, or the patches with pxcor evenly divisible by five, or the turtles in the first quadrant that are on a green patch. These agentsets can then be used by ask or by various reporters that take agentsets as inputs.
One way is to use turtles-here or
turtles-at, to make
an agentset containing only the turtles on my patch, or only the
turtles on some other particular patch. There's also
turtles-on so you can
get the set of turtles standing on a given patch or set of patches,
or the set of turtles standing on the same patch as a given turtle
or set of turtles.
Here are some more examples of how to make agentsets:
Once you have created an agentset, here are some simple things you
can do:
And here are some more complex things you can do:
More examples of using agentsets are provided in the individual
entries for these primitives in the NetLogo Dictionary. In developing
familiarity with programming in NetLogo, it is important to begin to
think of compound commands in terms of how each element passes
information to the next one. Agentsets are an important part of this
conceptual scheme and provide the NetLogo developer with a lot of
power and flexibility, as well as being more similar to natural
language.
NetLogo allows you to define different "breeds" of
turtles. Once you have defined breeds, you can go on and make the
different breeds behave differently. For example, you could have
breeds called
sheep and wolves, and have the wolves try to eat the
sheep.
You define breeds using the breeds keyword, at the top
of your model, before any procedures:
When you define a breed such as sheep, an agentset for
that breed is automatically created, so that all of the agentset
capabilities described above are immediately available with
the sheep agentset.
The following new primitives are also automatically available once
you define a breed:
create-sheep,
create-custom-sheep (cct-sheep for short),
sheep-here, and
sheep-at.
Also, you can use sheep-own to define new
turtle variables that only turtles of the given breed have.
A turtle's breed agentset is stored in the breed turtle
variable. So you can test a turtle's breed, like this:
Note also that turtles can change breeds. A wolf doesn't have to
remain a wolf its whole life. Let's change a random wolf into
a sheep:
The set-default-shape
primitive is useful for associating certain turtle shapes with certain
breeds. See the section on shapes below.
Here is a quick example of using breeds:
Buttons in the interface tab provide an easy way to control the
model. Typically a model will have at least a "setup" button, to set
up the initial state of the world, and a "go" button to make the model
run continuously. Some models will have additional buttons that
perform other actions.
A button contains some NetLogo code. That code is run when the
user presses the button.
A button may be either a "once-button", or a "forever-button". You
can control this by editing the button and checking or unchecking the
"Forever" checkbox. Once-buttons run their code once, then stop and
pop back up. Forever-buttons keep running their code over and over
again, until either the code hits the stop command, or the
user presses the button again to stop it. If the user stops the
button, the code doesn't get interrupted. The button waits until the
code has finished, then pops up.
Normally, a button is labeled with the code that it runs. For
example, a button that says "go" on it usually contains the code "go",
which means "run the go procedure". (Procedures are defined in the
Procedures tab; see below.) But you can also edit a button and enter
a "display name" for the button, which is a text that appears on the
button instead of the code. You might use this feature if you think
the actual code would be confusing to your users.
When you put code in a button, you must also specify which agents
you want to run that code. You may choose to have the observer run
the code, or all turtles, or all patches. (If you want the code to be
run by only some turtles or some patches, you could make an observer
button, and then have the observer use the ask command to ask
only some of the turtles or patches to do something.)
Buttons and display updates
When you edit a button, there is a checkbox called "Force display
update after each run". Below the checkbox is a note that reads
"Checking this box produces smoother animation, but may make the
button run more slowly."
Most of the time, it's enough to know that if you care more about
smooth animation than raw speed, you should uncheck the box, but if
you care more about smooth animation, you should leave it checked. In
some models, the difference is dramatic; in others, it's hardly
noticeable. It depends on the model.
What follows is a more detailed explanation of what's really going
on with this checkbox.
To understand why this option is offered, you need to understand a
little about how NetLogo updates the graphics window. When something
changes in the world, for example if a turtle moves or a patch changes
color, the change does not always immediately become visible. NetLogo
would run too slowly if changes always immediately became visible. So
NetLogo waits until a certain amount of time has passed, usually about
1/20 of a second, and then redraws the world, so that all the changes
that have happened so far become visible. This is sometimes called
"skipping frames", by analogy with movies.
Skipping frames is good because each frame takes NetLogo time to
draw, so your model runs faster if NetLogo can skip some of them. But
skipping frames may be bad if the frames skipped contained information
that you wanted the user to see. Sometimes the way a model looks when
frames are being skipped can be misleading.
Even when the checkbox is on for a button, NetLogo will still skip
frames while the code in the button is running. Checking the box only
ensures that NetLogo will draw a frame when the code is done.
In some contexts, you may want to force NetLogo to draw a frame
even in the middle of button code. To do that, use the display command; that
forces NetLogo to refresh the screen immediately.
In other contexts, you may want to force NetLogo never
to draw a frame in the middle of button code, only at the end. To
ensure that, put no-display at the beginning of the code
and display at the end. Note also that NetLogo will never
draw on-screen when inside a without-interruption block.
Turtle and patch forever-buttons
There is a subtle difference between putting commands in a turtle
or patch forever-button, and putting the same commands in an observer
button that does ask turtles or ask patches. An
"ask" doesn't complete until all of the agents have finished running
all of the commands in the "ask". So the agents, as they all run the
commands in parallel, can be out of sync with each other, but they all
sync up again at the end of the ask. The same isn't true of turtle
and patch forever-buttons. Since ask was not used, each
turtle or patch runs the given code over and over again, so they can
become (and remain) out of sync with each other.
At present, this capability is very rarely used in the models in
our Models Library. A model that does use the capability is the
Termites model, in the Biology section of Sample Models. The "go"
button is a turtle forever-button, so each termite proceeds
independently of every other termite, and the observer is not involved
at all. This means that if, for example, you wanted to add a plot to
the model, you would need to add a second forever-button (an observer
forever-button), and run both forever-buttons at the same time.
At present, NetLogo has no way for one forever-button to start
another. Buttons are only started when the user presses them.
In both StarLogoT and NetLogo, commands are executed
asynchronously; each turtle or patch does its list of commands as fast
as it can. In StarLogoT, one could make the turtles "line
up" by putting in a comma (,). At that point, the turtles would
wait until all were finished before any went on.
The equivalent in NetLogo is to come to the end of an ask block.
If you write it this way, the two steps are not synced:
Since the turtles will take varying amounts of time to move,
they'll begin "do-calculation" at different times.
But if you write it this way, they are:
Here, some of the turtles will have to wait after moving until all
the other turtles are done moving. Then the turtles all begin
"do-calculation" at the same time.
This latter form is equivalent to this use of the comma in StarLogoT:
Here are some more advanced features you can take advantage of when
defining your own procedures.
Your own procedures can take inputs, just like primitives do.
To create a procedure that accepts inputs, include a list of
input names in square brackets after the procedure name. For example:
Elsewhere in the program, you could ask turtles to each draw an
octagon with a side length equal to its ID-number:
Just like you can define your own commands, you can define your own
reporters. You must do two special things. First, use to-report instead of
to to begin your procedure. Then, in the body of the
procedure, use report to
report the value you want to report.
Procedures with local variables
A local variables is defined and used only in the context of a
particular procedure. To add a local variable to your procedure, use
the locals keyword. It must
come at the beginning of your procedure. For example:
In the simplest models, each variable holds only one piece of
information, usually a number or a string. The list feature lets
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, or a string, an agent
or agentset, or even another list.
Lists allow for the convenient packaging of information in
NetLogo. If your agents carry out a repetitive calculation on
multiple variables, it might be easier to have a list variable,
instead of multiple number variables. Several primitives simplify
the process of performing the same computation on each value in
a list.
The Primitives Dictionary has a
section that lists of all the list-related primitives.
Constant Lists
You can make a list by simply putting the values you want in the
list between brackets, like this: set mylist [2 4 6 8].
Note that the individual values are separated by spaces. You can
make lists that contains numbers and strings this way, as well
as lists within lists, for example [[2 4] [3 5]].
The empty list is written by putting nothing between the brackets,
like this: [].
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.
If I wanted a list to contain two random values, I might use the
following code:
To make longer lists, you can use the list reporter with
more than two inputs, but in order to do so, you must enclose the entire
call in parentheses, like this:
;; all red turtles:
turtles with [color = red]
;; all red turtles on my patch
turtles-here with [color = red]
;; patches on right side of screen
patches with [pxcor > 0]
;; all turtles less than 3 patches away
turtles in-radius 3
;; the four patches to the east, north, west, and south
patches at-points [[1 0] [0 1] [-1 0] [0 -1]]
;; shorthand for those four patches
neighbors4
;; turtles in the first quadrant that are on a green patch
turtles with [(xcor > 0) and (ycor > 0)
and (pcolor = green)]
;; turtles standing on my neighboring four patches
turtles-on neighbors4
This only scratches the surface -- see the Models Library for many
more examples, and consult the Primitives Guide and Primitives
Dictionary for more information about all of the agentset primitives.
set color-of random-one-of turtles green
Or tell a
randomly chosen patch to sprout a new turtle:
ask random-one-of patches [ sprout 1 [ ] ]
ask max-one-of turtles [sum assets] [ die ]
show max values-from turtles [sum assets]
Code Example: Ask Agentset Example
Breeds
breeds [wolves sheep]
if breed = wolves [ ... ]
ask random-one-of wolves [ set breed sheep ]
breeds [mice frogs]
mice-own [cheese]
to setup
ca
create-custom-mice 50
[ set color white
set cheese random 10 ]
create-custom-frogs 50
[ set color green ]
end
Code Example: Breeds and Shapes Example
Buttons
Synchronization
ask turtles
[ fd random 10
do-calculation ]
ask turtles [ fd random 10 ]
ask turtles [ do-calculation ]
fd random 10 ,
do-calculation ,
Procedures (advanced)
to draw-polygon [num-sides size]
pd
repeat num-sides
[ fd size
rt (360 / num-sides) ]
end
ask turtles [ draw-polygon 8 who ]
to-report absolute-value [number]
ifelse number >= 0
[ report number ]
[ report 0 - number ]
end
to swap-colors [turtle1 turtle2]
locals [temp]
set temp color-of turtle1
set (color-of turtle1) (color-of turtle2)
set (color-of turtle2) temp
end
Lists
set random-list list (random 10) (random 20)
This will set random-list to a new list of two random integers
each time it runs.
(list 1 2 3 4 5)
For more information, see Varying Numbers of Inputs.
Some kinds of lists are most easily built using the n-values reporter, which allows you to construct a list of a specific length by repeatedly running a given reporter. You can make a list of the same value repeated, or all the numbers in a range, or a lot of random numbers, or many other possibilities. See dictionary entry for details and examples.
The values-from primitive lets you construct a list from an agentset. It reports a list containing the each agent's value for the given reporter. (The reporter could be a simple variable name, or a more complex expression -- even a call to a procedure defined using to-report.) A common idiom is
max values-from turtles [...] sum values-from turtles [...]and so on.
You can combine two or more lists using the sentence reporter, which concatenates lists by combining their contents into a single, larger list. Like list, sentence normally takes two inputs, but can accept any number of inputs if the call is surrounded by parentheses.
Changing List Items
Technically, only one command changes a list -- set. This is used in conjunction with reporters. For example, to change the third item of a list to 10, you could use the following code:
set mylist [2 7 5 Bob [3 0 -2]] ; mylist is now [2 7 5 Bob [3 0 -2]] set mylist replace-item 2 mylist 10 ; mylist is now [2 7 10 Bob [3 0 -2]]
The replace-item reporter takes three inputs. The first input specifies which item in the list is to be changed. 0 means the first item, 1 means the second item, and so forth.
To add an item, say 42, to the end of a list, use the lput reporter. (fput adds an item to the beginning of a list.)
set mylist lput 42 mylist ; mylist is now [2 7 10 Bob [3 0 -2] 42]
But what if you changed your mind? The but-last (bl for short) reporter reports all the list items but the last.
set mylist but-last mylist ; mylist is now [2 7 10 Bob [3 0 -2]]
Suppose you want to get rid of item 0, the 2 at the beginning of the list.
set mylist but-first mylist ; mylist is now [7 10 Bob [3 0 -2]]
Suppose you wanted to change the third item that's nested inside item 3 from -2 to 9? The key is to realize that the name that can be used to call the nested list [3 0 -2] is item 3 mylist. Then the replace-item reporter can be nested to change the list-within-a-list. The parentheses are added for clarity.
set mylist (replace-item 3 mylist (replace-item 2 (item 3 mylist) 9)) ; mylist is now [7 10 Bob [3 0 9]]
Iterating Over Lists
If you want to do some operation on each item in a list in turn, the foreach command and the map reporter may be helpful.
foreach is used to run a command or commands on each item in a list. It takes an input list and a block of commands, like this:
foreach [2 4 6] [ crt ? show "created " + ? + " turtles" ] => created 2 turtles => created 4 turtles => created 6 turtlesIn the block, the variable ? holds the current value from the input list.
Here are some more examples of foreach:
foreach [1 2 3] [ ask turtles [ fd ? ] ] ;; turtles move forward 6 patches foreach [true false true true] [ ask turtles [ if ? [ fd 1 ] ] ] ;; turtles move forward 3 patches
map is similar to foreach, but it is a reporter. It takes an input list and another reporter. Note that unlike foreach, the reporter comes first, like this:
show map [round ?] [1.2 2.2 2.7] ;; prints [1 2 3]map reports a list containing the results of applying the reporter to each item in the input list. Again, use ? to refer to the current item in the list.
Here is another example of map:
show map [? < 0] [1 -1 3 4 -2 -10] ;; prints [false true false false true true]
foreach and map won't necessarily be useful in every situation in which you want to operate on an entire list. In some situations, you may need to use some other technique such as a loop using repeat or while, or a recursive procedure.
The sort-by primitive uses a similar syntax to map and foreach, except that since the reporter needs to compare two objects, the two special variables ?1 and ?2 are used in place of ?.
Here is an example of sort-by:
show sort-by [?1 < ?2] [4 1 3 2] ;; prints [1 2 3 4]
Some commands and reporters involving lists and strings may take a varying number of inputs. In these cases, in order to pass them a number of inputs other than their default, the primitive and its inputs must be surrounded by parentheses. Here are some examples:
show list 1 2 => [1 2] show (list 1 2 3 4) => [1 2 3 4] show (list) => []Note that each of these special commands has a default number of inputs for which no parentheses are required. The primitives which have this capability are list, word, sentence, map, and foreach.
NetLogo supports two different kinds of math, integer and floating point.
Integers have no fractional part and may range from -2147483648 to 2147483647 (-2^31 to 2^31-1). Integer operations that exceed this range will not cause runtime errors, but will produce incorrect answers.
Floating point numbers are numbers containing a decimal point. In NetLogo, they operate according to the IEEE 754 standard for double precision floating point numbers. These are 64 bit numbers consisting of one sign bit, an 11-bit exponent, and a 52-bit mantissa. See the IEEE 754 standard for details. Any operation which produces the special quantities "infinity" or "not a number" will cause a runtime error.
In NetLogo, integers and floating point numbers are interchangeable, in the sense that as long as you stay within legal ranges, it is never an error to supply 3 when 3.0 is expected, or 3.0 when 3 is expected. In fact, 3 and 3.0 are considered equal, according to the = (equals) operator. If a floating point number is supplied in a context where an integer is expected, the fractional part is simply discarded. So for example, crt 3.5 creates three turtles; the extra 0.5 is ignored.
Floating point accuracy
When using floating point numbers, you should be aware that due to the limitations of the binary representation for floating point numbers, you may get answers that are slightly inaccurate. For example:
O> show 0.1 + 0.1 + 0.1 observer: 0.30000000000000004 O> show cos 90 observer: 6.123233995736766E-17
This is an inherent issue with floating point arithmetic; it occurs in all programming languages that support floating point.
If you are dealing with fixed precision quantities, for example dollars and cents, a common technique is to use only integers (cents) internally, then divide by 100 to get a result in dollars for display to the user.
If you must use floating point numbers, then in some situations you may need to replace a straightforward equality test such as if x = 1 [ ... ] with a test that tolerates slight imprecision, for example if abs (x - 1) < 0.0001 [ ... ].
Also, the precision primitive is handy for rounding off numbers for display purposes. NetLogo monitors round the numbers they display to a configurable number of decimal places, too.
The random numbers used by NetLogo are what is called "pseudorandom". (This is typical in computer programming.) That means they appear random, but are in fact generated by a deterministic process. "Deterministic" means that you get the same results every time, if you start with the same random "seed". We'll explain in a minute what we mean by "seed".
In the context of scientific modeling, pseudorandom numbers are actually desirable. That's because it's important that a scientific experiment be reproducible -- so anyone can try it themselves and get the same result that you got. Since NetLogo uses pseudorandom numbers, the "experiments" that you do with it can be reproduced by others.
Here's how it works. NetLogo's random number generator can be started with a certain seed value, which can be any integer. Once the generator has been "seeded" with the random-seed command, it always generates the same sequence of random numbers from then on. For example, if you run these commands:
random-seed 137 show random 100 show random 100 show random 100
You will always get the numbers 95, 7, and 54.
Code Example: Random Seed Example
Note however that you're only guaranteed to get those same numbers if you're using the same version of NetLogo. Sometimes when we make a new version of NetLogo we change the random number generator. For example, NetLogo 2.0 has a different generator than NetLogo 1.3 did. 2.0's generator (which is known as the "Mersenne Twister") is faster and generates numbers that are statistically more "random" than 1.3's (Java's built-in "linear congruential" generator).
If you don't set the random seed yourself, NetLogo sets it to a value based on the current date and time. There is no way to find out what random seed it chose, so if you want your model run to be reproducible, you must set the random seed yourself ahead of time.
The NetLogo primitives with "random" in their names (random, random-float, random-one-of, and so on) aren't the only ones that use pseudorandom numbers. Some other primitives also make random choices. For example, the sprout command creates turtles with random colors and headings, and the downhill reporter chooses a random patch when there's a tie. These random choices are governed by the random seed as well, so models runs can be reproducible.
To input a constant string in NetLogo, surround it with double quotes.
The empty string is written by putting nothing between the quotes, like this: "".
Most of the list primitives work on strings as well:
butfirst "string" => "tring" butlast "string" => "strin" empty? "" => true empty? "string" => false first "string" => "s" item 2 "string" => "r" last "string" => "g" length "string" => 6 member? "s" "string" => true member? "rin" "string" => true member? "ron" "string" => false position "s" "string" => 0 position "rin" "string" => 2 position "ron" "string" => false remove "r" "string" => "sting" remove "s" "strings" => "tring" replace-item 3 "string" "o" => "strong" reverse "string" => "gnirts"A few primitives are specific to strings, such as is-string?, substring, and word:
is-string? "string" => true is-string? 37 => false substring "string" 2 5 => "rin" word "tur" "tle" => "turtle"
Strings can be compared using the =, !=, <, >, <=, and >= operators.
To concatenate strings, that is, combine them into a single string, you may also use the + (plus) operator, like this:
"tur" + "tle" => "turtle"
If you need to embed a special character in a string, use the following escape sequences:
In StarLogoT, turtle shapes were bitmaps. They all had a single fixed size and could only rotate in 45 degree increments.
In NetLogo, turtle shapes are vector shapes. They are built up from basic geometric shapes; squares, circles, and lines, rather than a grid of pixels. Vector shapes are fully scalable and rotatable.
A turtle's shape is stored in its shape variable and can be set using the set command.
New turtles have a shape of "default". The set-default-shape primitive is useful for changing the default turtle shape to a different shape, or having a different default turtle shape for each breed of turtle.
Use the Shapes Editor to create your own turtle shapes. For more information, see the Shapes Editor section of this manual.
Code Examples: Breeds and Shapes Example, Shape Animation Example
In NetLogo, there are a set of primitives that give the user the power to interact with outside files. They all begin with the prefix file-.
There are two main modes when dealing with files: reading and writing. The difference is the direction of the flow of data. When you are reading in information from a file, data that is stored in the file can be read into NetLogo. On the other hand, writing allows data to flow out of NetLogo and into a file.
When working with files, always begin by using the primitive file-open. This specifies which file you will be interacting with. None of the other primitives work unless you open a file first.
The next file- primitive you use dictates which mode the file will be in until the file is closed, reading or writing. To switch modes, close and then reopen the file.
The reading primitives include file-read, file-read-line, file-read-characters, and file-at-end? Note that the file must exist already before you can open it for reading.
Code Examples: File In Example
The primitives for writing are similar to the primitives that print things in the Command Center, except that the output gets saved to a file. They include file-print, file-show, file-type, and file-write. Note that you can never "overwrite" data. In other words, if you attempt to write to a file with existing data, all new data will be appended to the end of the file. (If you want to overwrite a file, use file-delete to delete it, then open it for writing.)
Code Examples: File Out Example
When you are finished using a file, you can use the command file-close to end your session with the file. If you wish to remove the file afterwards, use the primitive file-delete to delete it. To close multiple opened files, one needs to first select the file by using file-open before closing it.
;; Open 3 files file-open "myfile1.txt" file-open "myfile2.txt" file-open "myfile3.txt" ;; Now close the 3 files file-close file-open "myfile2.txt" file-close file-open "myfile1.txt" file-close
Or, if you know you just want to close every file, you can use file-close-all.
Two primitives worth noting are file-write and file-read . These primitives are designed to easily save and retrieve NetLogo constants such as numbers, lists, booleans, and strings. file-write will always output the variable in such a manner that file-read will be able to interpret it correctly.
file-open "myfile.txt" ;; Opening file for writing ask turtles [ file-write xcor file-write ycor ] file-close file-open "myfile.txt" ;; Opening file for reading ask turtles [ setxy file-read file-read ] file-close
Code Examples: File In and Out Example