I have two procedures (Levy Walk and Correlated Random Walk movement strategies, each with their own buttons for debugging purposes, as well as their own parameter sets on the netlogo interface), but I have also embedded both the aforementioned procedures in a single "Go" procedure for batch simulation processing in the following code implementation:
to setup
clear-all
create-turtles 100 [ setxy random-xcor random-ycor ]
reset-ticks
end
to Correlated-Random-Walk
rt random 360
fd 1
end
to Levy-Walk
rt random 90
fd 2
end
to go
Correlated-Random-Walk
tick
if ticks = 1000 [
setup
stop
Levy-Walk
if ticks = 1000 [
setup
stop
]
]
end
The above section of the "Go" procedure code is supposed to take the correlated random walk procedure and execute it for the entire duration (1000 ticks) of the simulation, then stop, reset (setup) the world and execute the levy walk procedure to the entire duration of the simulation (also a 100 ticks), then stop. As it is now, the code executes for the correlated random walk but does not go on to the levy walk procedure. It simply repeats the Correlated Random Walk procedure. What might the issue be?
Your stop command will stop the go procedure. (See the docs.) Does the following meet your needs?
to go1000each
repeat 1000 [Correlated-Random-Walk tick]
setup
repeat 1000 [Levy-Walk tick]
end
If you make a button for this, it should not be a forever button.
Related
I want to write in Netlogo that a certain percentage of the agent's population has this attribute. How do I do that in NetLogo?
So far, in a toy model, I do it manually. i.e: ask n-of 740 households [set composition 1] when in fact I want to say: ask 8% of the households to set composition 1.
There are two ways. I will call them ex-ante and ex-post.
Ex-ante
A frequent approach is to let each agent have a certain chance (expressed as the percentage value) of doing something. In this case you will use the random-float command in combination with your percentage value, which is the standard way to make things happen in NetLogo according to a certain probability (see here, or also see just random if you're working with integers). It can be used directly within the create-turtles block of commands:
globals [
the-percentage
]
turtles-own [
my-attribute
]
to setup
clear-all
set the-percentage 0.083 ; In this example we set the percentage to be 8.3%.
create-turtles 500 [
if (random-float 1 < the-percentage) [
set attribute 1
]
]
end
This means that you will not always have the exact number of turtles having that attribute. If you check count turtles with [attribute = 1] on multiple iterations, you will see that the number varies. This approach is good if you want to reproduce the probability of something happening (over a population of agents or over time), which is the case for many uses of NetLogo models.
Ex-post
The ex-post approach follows the logic that you more or less expressed: first you create a number of turtles, later you assign to them the attribute. In this case, you simply need to treat the percentage as in any other mathematical expression: multiply it by the total number of turtles to get the relevant turtles:
globals [
the-percentage
]
turtles-own [
my-attribute
]
to setup
clear-all
set the-percentage 0.083
create-turtles 500
ask n-of (count turtles * the-percentage) turtles [
set attribute 1
]
end
With this approach, you will always have the exact same number of turtles with that attribute. In fact, if you run count turtles with [attribute = 1] on multiple iterations you'll see that the result is always 41 (500 * 0.083 = 41.5, in fact if the number passed to n-of is fractional, it will be rounded down).
I would like to apply some process stochastically, but the order matters, or rather it should be done at random, how can I select a set of the same turtles to "treat" but to do it such that each tick, the order is random?
ask turtles [
;; apply a process to turtles, but not all turtles will get something as the pool of energy may have run out by the time they are selected.
]
Elements of agentsets (such as turtles) are always returned in a random order. Each time you use ask with an agentset, it will ask them in a new, random order. From the docs on agentsets:
An agentset is not in any particular order. In fact, it’s always in a random order. And every time you use it, the agentset is in a different random order. This helps you keep your model from treating any particular turtles, patches or links differently from any others (unless you want them to be). Since the order is random every time, no one agent always gets to go first.
And here is a quick example to demonstrate. If you run it in the Command Center you'll see the who numbers will be different each time you ask them to be shown.
to test
clear-all
create-turtles 10
show "Asking once..."
ask turtles [ show who ]
show "Asking a second time..."
ask turtles [ show who ]
end
And here is an example showing an energy pool that will be randomly used until it is gone. Note the turtles that will get to use it are whichever happen to come first out of the agentset for ask:
to test-pool
clear-all
let energy-pool 1000
create-turtles 100
ask turtles [
; can only act if some energy is left...
ifelse energy-pool > 0 [
let energy-use (min (list random 100 energy-pool))
set energy-pool (energy-pool - energy-use)
show (word "I used up " energy-use " energy points! " who " Only " energy-pool " points left")
] [
show (word "No energy left for me! " who)
]
]
end
I am not sure how netlogo processes commands. Consider the following scenario. There are 100 turtles. The "go" procedure calls the following other procedures: A, B, and C. Procedure A tells turtles to do some things, Procedure B tells turtles to do some things, and Procedure C tells turtles to do some things.
Understanding X:
It is my understanding that all turtles would complete the commands in A, then all turtles would complete the commands in B, then all turtles would complete the commands in C.
Now, inside procedure A there are commands A1, A2, and A3.
Understanding Y:
It was my understanding that, inside procedure A, one turtle would do command A1, then A2, then A3, then a second turtle would do command A1, A2, and A3, and so on.
Is my understanding Y correct?
Thanks for any insights you can provide.
It depends. The basic rules is that the user presses the go button (or types 'go' in the command center) and that tells NetLogo to run the go procedure. NetLogo runs that procedure from top to bottom. But how you include the called procedures changes the order.
Consider version 1. The first line ask turtles says to choose a random turtle, make it do everything in the code block (delimited by the [ ] symbols) and then choose the next random turtle, make it do everything and then the next turtle until all the turtles are done. In this case, both proc-A and proc-B are within the same code block, so the turtle would do both before NetLogo switches to the next turtle.
to go
ask turtles
[ proc-A
proc-B
]
end
to proc-A
forward 1
set heading heading + random 10
end
to proc-B
forward 3
set heading heading - random 20
end
How about version 2? The first line ask turtles [proc-A] says to choose a random turtle, make it do everything in the code block (delimited by the [ ] symbols) which in this case is only proc-A. And then choose the next random turtle, make it do everything and then the next turtle until all the turtles are done. Only after ALL the turtles are done with the ask turtles will the code move on to the next line. In this case therefore, all turtles do proc-A and then all turtles do proc-B.
to go
ask turtles [ proc-A ]
ask turtles [ proc-B ]
end
to proc-A
forward 1
set heading heading + random 10
end
to proc-B
forward 3
set heading heading - random 20
end
You could also do something like version 3. The first line says to run through proc-A, which gets every turtle to do something. Then, at the end of proc-A, control returns to the go procedure and moves to the next line, which is to run the procedure proc-B. This would achieve the same outcome as version 2.
to go
proc-A
proc-B
end
to proc-A
ask turtles
[ forward 1
set heading heading + random 10
]
end
to proc-B
ask turtles
[ forward 3
set heading heading - random 20
]
end
When I am teaching NetLogo, I encourage my students to construct the code along the lines of version 3. This is because the ask is within the same procedure as the actions they are being asked to do. This has several advantages. (1) Much easier to read because you don't have to try and read across procedures that could be a long way apart. (2) Avoids one of the most common beginner issues of nested ask - with an ask turtles in the go procedure and then ask turtles again as the first line of the called procedure. This is actually such a common bug that the NetLogo developers have made it impossible to have nested asks.
However, if you truly want a turtle to do more than one thing before the next turtle starts, then you have two options. You either code as in version 1. Or you put both things that you want the turtle to do in the same procedure.
I'm trying to build a simulation where commuters can choose to take the car or bike to work. I'm want the turtles to make a decision based on their wait time in traffic from the last 20 ticks e.g. if average wait time is more than 10, they will take the bike to work. I have a plot that shows average wait time of cars and managed to have them make decision on that overall average. However, I have not managed to make each car make a decision based on their own experience. I'm not getting any errors, just not any results.
So far I have turtles owning average-wait-time-list and wait-time.
Create-cars ;;(cars are one of two breeds)
set average-wait-time-list []
to-report average-wait-time-sum
;; drop the first member of the list, but not until there are at least 60 items in the list
if (length average-wait-time-list > 20) [ set average-wait-time-list but-first average-wait-time-
list ]
;; add the number of raindrops created in last tick to the end of the list
set average-wait-time-list lput wait-time average-wait-time-list
report sum average-wait-time-list
end
to record-data ;; turtle procedure
ifelse speed = 0 [
set num-cars-stopped num-cars-stopped + 1
set wait-time wait-time + 1
]
[ set wait-time 0 ]
end
I know that monitors are updated several times per second, and that can be helpful when checking the output of a model; however, that is not the case for my model, it just weighing it down.
I am trying to plot data from a monitor. I want the monitor to only update the reporter once per tick, if possible.
My model currently functions but it is bogged down updating multiple times a second. I was hoping someone could help me minimize my model's computational effort by updating once per tick.
sample of current code:
globals [initial-patch0-health patch0-health intial-patch2-health patch2-health]
patches-own [ptype penergy max-penergy alive?]
to setup
clear-all
set patch-health 0
ask-patches [
setup-patches
]
reset-ticks
end
to setup-patches
let temp random 100
if temp <= 50 [
set ptype 2
set max-penergy random-in-range 0 5
set alive? true
]
if temp > 50 and temp <= 75 [
set ptype 0
set max-penergy random 10
set alive? true
]
set penergy max-penergy
set patch2-health (ptype2-health)
set patch0-health (ptype0-health)
end
to go
ask-patches
update-patch-health
tick
end
to patch-health
if ptype = 2[
set patch2-health (ptype2-health)
]
if ptype = 0 [
set patch0-health (ptype0-health)
]
end
to-report ptype2-health
report [penergy] of patches with [ptype = 2]
end
to-report ptype0-health
report [penergy] of patches with [ptype = 0]
end
My monitors and plot read (same for patch2-health):
sum (initial-patch0-health)
and
plot sum (patch0-health)
I use sum in this situation because the reporter delivers a list.
For context, I am doing a simple "sheep-wolf predation" style model but I want to monitor the initial grass health vs grass health over time, with multiple grass types (ptype). I have turtles but did not include that code here. Let me know if you need more code from me.
This code gives me the output I desire just at the cost of speed. I figured only reporting once every tick would save some computing time. Any suggestions for cleaning and speeding it up?
Your code example is not usable to me (undefined variables, patch0-health is not output from a reporter, other errors)- check the MCVE guidelines. With that in mind, I'm having trouble replicating the issue you describe- I ran a few profiler tests with a monitor present and not present, and didn't get any difference in runtime. With this setup:
extensions [ profiler ]
globals [ patch-turtle-sum profiler-results]
to setup
ca
ask n-of ( ( count patches ) / 2 ) patches [
set pcolor red
]
crt 1000 [
setxy random-pxcor random-pycor
]
set profiler-results []
reset-ticks
end
to profile-check
repeat 20 [
profiler:start
repeat 20 [
go
]
set profiler-results lput profiler:inclusive-time "go" profiler-results
profiler:reset
]
print profiler-results
end
to go
ask turtles [
fd 1
]
tick
end
to-report patch-turtle-sum-report
report sum [count turtles-here] of patches with [ pcolor = red ]
end
I ran the profile-check procedure from the interface, once with a monitor that monitors patch-turtle-sum-report present (mean go inclusive time: 678.59 ms) and once without (mean go inclusive time: 678.56 ms)- no detectable difference. However, I'm not sure if profiler accounts for monitor, so maybe that assessment is just not useful in this case. It could also be that the number of patches you're dealing with is quite large (in my test example I was doing 100 X 100 patches) so that the calculations get bogged down.
I wonder if you could get around your issue by using a monitor that just reports a variable that you manually calculate once per tick (instead of a to-report reporter)- eg to follow my example above, monitor a variable that is updated with something like:
set patch-turtle-sum sum [count turtles-here] of patches with [ pcolor = red ]
That way you control when the calculation is done, which may speed up the model if the calculation is what's actually slowing down your model.