This question is related to a question I asked some time ago.
I am trying to create a population in NetLogo. Therefore, I am trying to start with the mortality rate. However, I am not sure how to test if my code works. The age of the oldest dying turtles seems to be fine, however when I print the mean death-ages it is way too high and I don't know how to solve that.
The model is available here.
The problem might be the calculation of the probability of dying which I did as follows:
if (gender = "female") [
let die-val mortality-female age ; mortality prob included for the age of the turtle
if (die-val >= random-float 1)[
set prob-die? true
]
]
It looks like your code is working fine, but your implementation may be unrealistic.Your turtles all eventually die, and because your mortality likelihoods increase as age increases, your older turtles contribute far more to the death-ages list than the younger turtles. For example, after running go until all turtles were 90, there were still 52 turtles alive- so all of those (over half) would contribute their old age to the death-ages list. So, your death-ages list is strongly left-skewed, something like:
Where your average death-age over 100 replicates is around 90.5 years. I think this is due to your aging process- try only having your turtle age increase by 1 instead of 5- see if that gives output more like you're expecting. It immediately changes the distribution to look more normal, where your mean death-age for 100 reps is around 81.2 years:
Edit:
You can quickly set up a histogram using a plot widget with settings like this:
Note that the code
if length death-ages > 0 [
set-plot-x-range ( min death-ages - 5 ) ( max death-ages + 5)
]
is included because auto-scaling does not work for the x-scale of histograms. You can exclude that code in the "Plot update commands" field and manually set your x min and max if you'd like, but you'll miss any turtles that die after whatever x max value that you choose.
You also need to change your pen settings from line to bar- click the pencil icon at the right of the pen field to open the menu below and select "Bar" from the "Mode" drop-down menu. Note as well that I've set my "Interval" to 5 to get the plots as shown above.
Related
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.
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.
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!
In NetLogo: suppose the model has
a turtle (0) of breed A with undirected links with 3 turtles (1, 2 and 3) of breed B;
the turtle 0 has an attribute named "number-of-links" that equals 3.
Now, let one of the 3 neighbors of 0 dies..
How can I program turtle 0 to change its number-of-links automatically to 2?
If all you want is a way of keeping track of the number links, use count my-links instead of a custom variable.
In general, the least bug prone way of having a value update when the number of links changes is to compute that value when you need it. For number of links, this is simply count my-links. For more complicated things, wrap them in a reporter:
to-report energy-of-neighbors
report sum [ energy ] of link-neighbors
end
If this doesn't work for whatever reason (agents need to react to a link disappearing or you're seeing a serious, measurable performance hit from calculating on the fly), you'll have to make the updates yourself when the number of links change. The best way to do this is to encapsulate the behavior in a command:
to update-on-link-change [ link-being-removed ] ;; turtle procedure
; update stuff
end
and then encapsulate the things that can cause the number of links to change (such as turtle death) in commands as well:
to linked-agent-death ;; turtle procedure
ask links [
ask other-end [ update-on-link-change myself ]
]
die
end
I am modeling diffusion in my model, but I think I am getting a calculation artifact due to NetLogo sequentially updating individual patches. I will not be using the diffuse command (due to inaccurate diffusion). However, much like how this command works, I would like to update all the calculations of the patches simultaneously, rather than sequentially. I have a slight recollection of seeing some sample code that used values at the beginning of the tick, however I can´t seem to find it now.
Specifically, I need help programming a way to store patch values at the turn of each tick, and then carry out a simultaneous calculation based on these stored values.
Great question. As you indicate, basically you want to calculate the new value of the variable in one ask block, but store it in a separate variable, and then update the actual value of the variable in a second ask block, like so:
turtles-own [
value
new-value
]
...
to go
ask patches [
;; Change this line to however you want the diffusion to work
set new-value 0.5 * value + sum [ 0.5 * value / 4 ] of neighbors4
]
ask patches [
set value new-value
]
end
This way all patches calculate their updated values from the same information, and then actually update the values themselves simultaneously.