Get the mean age of all turtles on the time of death - netlogo

I want to get the mean age of all dying turtles. I try to achieve that with the following code snipped:
globals [mean-death-age]
turtles-own [age prob-die?]
to-report mean-age
if (prob-die? = true) [
set mean-death-age mean [age] of turtles
]
report mean-death-age
end
Every turtle has the probability of dying (prob-die?) which should be calculated new with every time step (tick). If prob-die? is set to true mean-death-age should be updated. At the moment I have the problem that
I don't know how to initiate the variable mean-death-age. Maybe, working with an if loop would help
if (ticks >= 1) [
if (prob-die? = true) [
set mean-death-age mean [age] of turtles
]
]
I don't get an update of the already calculated mean-death-age but the variable is overwritten and the mean death age of the turtles of this tick is returned
I have problems accesing the value. When I try to call it with e.g.
print mean-age
I get the error message that mean-age is turtle-only even though I tried to save is as a global variable.
The entire code is available here.

I think you're making this more complicated than it needs to be. The easiest approach would be to just keep a list of ages at which turtles die, and then take the mean of that list:
globals [death-ages]
turtles-own [age]
to setup
clear-all
create-turtles 100 [
setxy random-xcor random-ycor
set age random 100
]
set death-ages [] ; start with an empty list
reset-ticks
end
to go
if not any? turtles [ stop ]
ask turtles [
if random 100 < age [
set death-ages lput age death-ages ; add age to our list of ages of death
die
]
]
print mean death-ages
tick
end
The only downside is that your list of death-ages is going to keep growing as your model runs. If that turns out the be a problem (though it probably won't), you will need to keep track of the current average and the current count of observations and update your average with something like set avg ((n * avg) + age) / (n + 1) set n n + 1.
As for why your current code doesn't work, there would be a lot of unpacking to do to explain it all (I'm sorry I can't now). As a general comment, I would suggest trying to take a step back when you run into difficulties like this and think about the minimum amount of information that you need to solve the problem. In this case, you need to mean age of death. What the simplest way to get that? Keep a list of ages of death and take the mean of that list when needed­.

Related

How to optimize assignation process in Netlogo

I want place 1 million fish in a lake at random to do so i have this.
ask patches[ if sum [peces] of patches < 1000000 [ask one-of patches with [mallor = 1][set peces peces + 1]]]
This is taking too long, how would you suggest to make it quicker? I know it´s the sum part as it has to always check, but i dont know how else to do it
A first thing I noticed is that you have the construction:
ask patches [ if ... [ ask one-of patches [...]]]
That first ask patches is completely redundant here. It lets each patch direct another random patch to make a fish. Since you use one-of the second time around I don't expect that the speed impact is too big but it should still help
Next, I suggest counting the fish you have already placed with a single local variable, instead of using sum [peces] of patches 1000000 times. Getting variables from an agent (with of or with) takes a lot of time if you have a lot of agents, and I remember from your previous questions that your number of patches is pretty huge.
Then thirdly, you also check for which patches the mallor = 1 condition is true 1000000 times. That one can also be grouped into a local agentset
let fish-placed 0
let mallor_patches patches with [mallor = 1 ]
while [fish-placed < 1000000] [
ask one-of mallor_patches [
set peces peces + 1
set fish-placed fish-placed + 1
]
]
Disclaimer, I haven't tested any of this code in Netlogo since I don't have the bigger model to test the code in. However I expect it will run a many times faster than what you originally wrote.

ask turtles - ordering of agentset

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

Netlogo: How do I make turtles of a specific breed make a decision based on previous ticks?

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

Is there a way in NetLogo to give turtles (of different generations) different ages?

I want to modell the interactions of different tree species in a forest. To do so, I also have to simulate the growth/spread of the forest.
There I face the two following problems:
I want the trees to reach a minimum age from which on they can hatch a new tree each year. But I only know how to make them reproduce every (e.g.) 20 years.
There is also a set age at which the trees are chopped town. The problem is, that when this age is reached, all trees of one breed are chopped down, even if their age should actually be less than their harvest-age.
Here are the relevant parts of my code:
to go
ask oaks [set age ticks]
end
to set-harvest-age
ask oaks [set harvest-age 240]
end
to spread
ask oaks [
if (age mod 30 = 0) and (count oaks > 1) [hatch-oaks 1 [setxy random-xcor random-ycor set age 1]]]
end
to chop-down
ask oaks [if (age >= harvest-age) [die]]
end
The "set age 1" in "spread" does not seem to work. Maybe someone of you has an idea.
Thank you!
I think your main problem is the process order here. Every time go is called, all oaks will set their age to the current ticks. That includes any new saplings that you've hatched, so even if their age was 1 when they hatched, those saplings would instantly be set to the same age as all other oaks (which is just the number of ticks. Instead, you should use your oaks-own (or whatever species you want) variable to track the age of each individual turtle by incrementing it every tick rather than setting it to the ticks.
Additionally, it's probably better to use go or a similarly named procedure to act as the scheduler to call all the other relevant procedures. For example, check out these setup chunks:
breed [ oaks oak ]
oaks-own [ age harvest-age ]
to setup
ca
spawn-oaks
reset-ticks
end
to spawn-oaks ; setup procedure
create-oaks 10 [
set shape "tree"
set color green
setxy random-xcor random-ycor
; Set the harvest age
set harvest-age 100
; Randomly choose the age of the first generation
; to be somewhere between 50 and 75
set age 50 + random 25
]
end
This creates 10 oaks with a an age randomly between 50 and 75. It also sets their harvest age. Now, use a procedure to increase every oak's individual age by one each tick:
to get-older ; Oak procedure
set age age + 1
end
Then, something to have them start creating saplings when they reach maturity. I've included an if any? other oaks-here qualifier so that the population size doesn't immediately explode (as saplings can only survive on a patch without an established oak), but you would limit that growth in whatever way makes sense for your model.
to spread ; Oak procedure
; Get living, mature oaks to spead saplings nearby
; only some years (to avoid population explosion)
if age > 30 and random 50 < 5 [
hatch 1 [
; set sapling age to zero, and have it
; move away from its parent randomly
set age 0
rt random 360
fd random 5
if any? other oaks-here [
die
]
]
]
end
Finally, your chop-down procedure should actually work without changing now that the age issue is sorted out:
to chop-down ; Oak procedure
if age >= harvest-age [
die
]
end
Now all that's needed is to use go to call those procedures in the correct order:
to go
; Use the go procedure to schedule subprocedures
ask oaks [
get-older
spread
chop-down
]
tick
end
Bit of a silly example but hopefully will get you pointed in the right direction!

Update a monitor once per tick instead of continuously. Slow model

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.