NetLogo Project Prototype: Exit I
From Backspaces Wiki
NetLogo Tutorial
|
This module is a bit different. It is an "investigation" used on a real project by Redfish LLC. The project was a crowd management study for the City of Santa Fe's Zozobra event. We worked with the police, fire department, parks and recreation department and many others to produce a geographically accurate crowd model.
All "real world" (i.e. for pay!) projects begin with a few throw-away models to investigate various aspects. In this case, our Exit model looks at the "flow" of people/agents within a geometrically bounded, limited access space .. in this case a city park.
The modeling project was very broad, including professional ethnographic studies, viewing of the last decade's events on video, and discovering several unusual features:
- Police not allowed on field when lights go out, too dangerous.
- The event has been dangerous in the past including a murder on the Santa Fe plaza.
- The park management's major fear: the automatic sprinklers would go on, causing panic.
- The event is one of Homeland Security "high risk" events, and includes snipers on surrounding buildings.
Who said modeling is boring?!
Contents |
Getting Started
We decided on a really simple investigation: agents leaving a rectangular area with a limited number of exits. There are optional "obstacles" which represent buildings, garbage cans, vendor carts and the like. The behavior is kept to simply seeking a path to their desired exit. (The final model included anxiety, injuries, and even a bomb, but that a tale for a beer or two)
So the first problem is building a landscape consisting of a field with an "inside", a boundary of the inside, and exits in the boundary, the image below, left. This requires modifications to the default View Settings, middle image:
- max-pxcor & max-pycor: 35x35 (its fine to use non-square)
- Patch size: 7 (fine to play with this too, but visibility counts)
- World wrap: turned off for both horizontal and vertical.
We will color the exits random bright colors, and populate the inside with agents of the same color as their desired exit, right image below.
| | | |
So first, create a new NetLogo model.
- Open the View Settings installing the values above.
- Create a setup button, with the procedure setup as its command.
- Open the Procedures pane, creating a setup procedure which calls clear-all and setup-patches.
- Create an empty setup-patches procedure.
- Use patches-own to define two patch variables, exit? and inside?, for the inside and exits patches. (See variables in Programming Manual.) Note ?-mark is allowed.
- Save your file!
patches-own [exit? inside?] to setup ca setup-patches end to setup-patches end
Setup Patches: Inside
Our first task is to set our two patch variables:
to setup-patches
ask patches
[ set exit? false
set inside? (abs pycor < (.7 * max-pycor)) and (abs pxcor < (.7 * max-pxcor)) ]
end
Lookup: abs, pxcor/pycor, max-pxcor/max-pycor. Notice a trick: the absolute value of the pxcor/pycor works because in the View Settings, we kept the Center geometry.
We'll add two simple utility reporters following setup-patches to return the patches that are inside? or exit?
;; Simple utilities to-report inside report patches with [inside?] end to-report exits report patches with [exit?] end
Now test our results. Click the setup button, then from the Command Center enter these two lines:
observer> ask patches [set pcolor black + random-float 3] observer> ask inside [set pcolor red]
Setup Patches: Wall & Exits
Next, we'll draw a boundary around the inside .. a wall. Put this inside the setup-patches, after the exiting code:
ask inside [ ask neighbors4 with [not inside?] [set pcolor grey] ]
Lookup: neighbors/neighbors4. Also look up Code Example: Neighbors Example in the Models library.
Note that we use neighbors4, not neighbors, because we want the wall corners not to be painted grey .. so no exits will be in the corner position. Enter the above code in the Command Center, replacing neighbors4 with neighbors to see the wall with the corners painted.
This is a bit clever, and very common in NetLogo .. one-liners that do a lot. We're asking the inside patches (the ones you colored red above), to ask their neighbors4 who are not inside to color themselves grey.
We now have a "wall" to build our exits in. First, add a slider to the UI with:
- Global variable: num-exits
- Min, Increment, Max: 1, 1, 20
- Value: 10
Add this to the end of setup-patches:
ask n-of num-exits patches with [pcolor = grey] [ set exit? true set pcolor (grey + 10 * count exits)]
Click setup a few times to see the exits randomly chosen on the "wall". Your UI will look like:
You can explore the patches by right clicking on them, which pops up a menu. Chose the "inspect patch" item, which pops up a small panel which will show the patch variable values, which will be different between the outside, inside and exits. Note the wall itself will be just like the outside, but with a different color.
Your program will now look like this:
patches-own [exit? inside?]
to setup
ca
setup-patches
end
to setup-patches
ask patches
[ set exit? false
set inside? (abs pycor < (.7 * max-pycor)) and (abs pxcor < (.7 * max-pxcor)) ]
ask inside [ ask neighbors4 with [not inside?] [set pcolor grey] ]
ask n-of num-exits patches with [pcolor = grey]
[ set exit? true set pcolor (grey + 10 * count exits)]
end
;; Simple utilities
to-report inside report patches with [inside?] end
to-report exits report patches with [exit?] end
Setup Turtles: Structure
Now we'll fill the inside of our world with agents that will eventually move towards and through the exits.
First, we'll add a global variable for our population, and a slider to initialize. Create a Slider:
- Global variable: %-population
- Min, Increment, Max: 5, 5, 95
- Value: 75
Next add a global variable, population, to the Procedures pane, just under the patches-own declaration:
patches-own [exit? inside?] globals [population]
Now initialize the global variable at the end of the setup procedure using:
set population int (( %-population * count inside ) / 100)
Note that this has to be called after setup-patches because it needs the patch inside? variable to have been initialized.
Generally the number of turtles used is directly setup with a slider for population. But we want to use a percentage of the available space, thus the percentage slider.
Now we'll add a setup-turtles procedure and call it after the "set population" command in setup. It will need a turtle variable for the exit the turtle is assigned.
- Add a turtle variable, exit, just below the patch and global variables:
turtles-own [exit]
- Add a call to setup-turtles at the end of the setup procedure.
- Create this setup-turtles procedure:
to setup-turtles set-default-shape turtles "circle" end
Lookup: set-default-shape
This is the start of setting up the turtles. It now just sets the default shape for all turtles to be a circle.
Setup Turtles: Command Center
We're going to use the Command Center to help us puzzle our way through completing setup-turtles. Our strategy is:
- Build an expression for randomly choosing a "population" sized subset of our "inside" patches.
- Create a turtle on each of these patches. This is a common NetLogo "cliché": creating N random turtles placed in their own unique patch.
- Set the "exit" turtle variable for each turtle to be the closest exit patch to that turtle.
- Finally we'll set each turtle's color to be the same as their exit.
To choose the "population" random patches, we'll use n-of, which returns a specified number of patches. First click setup to initialize. The first Command Center entry tries "n-of population inside" (to see if it works!), using the show command to see the result .. it reports the agentset, of size 1800 (note: the observer: line is a result, not a command to be executed!). OK, that's what we hoped for. The second goes a step further: it uses the n-of expression to color the patches so that we can see what they look like, see image below, left:
click setup observer> show n-of population inside observer: (agentset, 1800 patches) observer> ask n-of population inside [set pcolor red]
Lookup: n-of, show, color, pcolor
Now we'll repeat this, but creating turtles rather than coloring patches. The sprout patch command takes a number of turtles to create on this patch. So our first command creates the turtles, and the second colors them white so that we can see them (they are random colors by default) See image below, right.
click setup observer> ask n-of population inside [sprout 1] observer> ask turtles [set color white]
Lookup: sprout.
|
|
The next set of explorations find the closest exit for each turtle, and colors that turtle the exit's color:
- Initialize again, via setup.
- Extend the "ask n-of" command to create the turtles, and use the sprout command's optional command block to color them white. Note: this is another common NetLogo approach: use simple commands to get started, then combine them into a single compound command.
- Use an arbitrary turtle to test finding the closest exit to it. We'll use "turtle 0".
- First color it red so we see where it is. Its in the top-right quadrant, see image on left below.
- Ask it to show the distance to the yellow exit. Even there is only one, we still use the one-of command which choses one item from a set of items. Check that the result seems reasonable. Try different colors too, to get a feeling for the different values you'll get. How many exits do you think we would need to have before getting duplications of exits with that color? Remember that we use a multiple of 10 in coloring the exits wihin the NetLogo color space.
- Next we'll find the closest exit by using yet another NetLogo command: min-one-of. Be sure to look up the command using the link below. Does it look like a it is the closest exit?
- Now we'll ask all the turtles we've created to combine our tests above to set there "exit" variable to be the closest one.
- Test our results by asking all the turtles to print their exits. Make sure you see redundancies, there are a limited number of exits.
- Finally ask the turtles to set their color to be the color of their exit.
click setup observer> ask n-of population inside [sprout 1 [set color white]] observer> ask turtle 0 [set color red] observer> ask turtle 0 [show distance one-of exits with [pcolor = yellow] ] (turtle 0): 28.653097563788805 observer> ask turtle 0 [show min-one-of exits [distance turtle 0]] (turtle 0): (patch 25 4) observer> ask turtles [set exit min-one-of exits [distance myself]] observer> show [exit] of turtles observer: [(patch -25 -10) (patch 25 -13) (patch -25 -10) (patch -1 -25) (patch 25 1) ...] observer> ask turtles [set color [pcolor] of exit]
Lookup: sprout, min-one-of, distance, myself (as opposed to self).
|
|
Setup Turtles: Finishing
Using the Command Center explorations above, we can complete the setup-turtles procedure:
to setup-turtles
set-default-shape turtles "circle"
ask n-of population inside [ sprout 1 ]
ask turtles
[ set exit min-one-of exits [distance myself]
set color [pcolor] of exit ]
end
Install this in the Procedures pane and click the setup button several times. You'll see an interesting dynamic sequence:
- All the turtles are put in place, but with random colors.
- Then they start to change to the color of their exit, as desired.
- It's a bit slow.
This is a good time to introduce another NetLogo feature. Just above the View area, to the left of the Settings button, you'll see a drop down menu (it should show "continuous" .. if not, set it to continuous and click setup a few more times).
Now read about the NetLogo View update style. Change it from "continuous" to "ticks" and click setup a few more times. You'll see the turtles appear with their exit color right away, with no intermediate colors or flickering.
Now a final refinement of setup-turtles. You remember above that "sprout" can take a command block that is applied to each turtle as it is created. We'll combine the two "ask" commands in setup-turtles to one compound command:
to setup-turtles
set-default-shape turtles "circle"
ask n-of population inside [ sprout 1
[ set exit min-one-of exits [distance myself]
set color [pcolor] of exit ]]
end
Summary
Here's our entire program at this state. We've done the basics of setting up the patches and turtles, with the associated UI. We'll take a break here, with our next module adding interactivity to the model.
patches-own [exit? inside?]
globals [population]
turtles-own [exit]
to setup
ca
setup-patches
set population int (( %-population * count inside ) / 100)
setup-turtles
end
to setup-patches
ask patches
[ set exit? false
set inside? (abs pycor < (.7 * max-pycor)) and (abs pxcor < (.7 * max-pxcor)) ]
ask inside [ ask neighbors4 with [not inside?] [set pcolor grey] ]
ask n-of num-exits patches with [pcolor = grey]
[ set exit? true set pcolor (grey + 10 * count exits)]
end
to setup-turtles
set-default-shape turtles "circle"
ask n-of population inside [ sprout 1
[ set exit min-one-of exits [distance myself]
set color [pcolor] of exit ]]
end
;; Simple utilities
to-report inside report patches with [inside?] end
to-report exits report patches with [exit?] end
Notes
- Small: Note how small our model is thus far. This is partly due to the Lisp-like history of the Logo programming language, partly due to NetLogo being a "Domain Specific Language" .. i.e. designed around the domain of ABM.
- Command Center: The Command Center is often overlooked as we become more familiar with NetLogo. Yet in this prototype of a much more sophisticated model, we found the Command Center necessary as a way to understand new primitives, and the distinction between "self" and "myself". You'll never outgrow it.
- See ExitTutSetup.nlogo in the NetLogoTut download folder.




