Netlogo: average cluster size - netlogo

I have an urban growth model that outputs clusters of urban areas and want to measure them. Progress has been made to the point of plotting the frequency distribution of patch size following the code stated in this post.
Now all that is needed is to plot the average cluster size but I'm stuck in the coding. I have the idea of using the mean primitive but don't know how to make the model estimate this mean cluster size using the data that the model already outputs. Here is the current code:
to find-clusters
loop [
;; pick a random patch that isn't in a cluster yet
let seed one-of patches with [cluster = nobody
and pcolor = 8
]
;; if we can't find one, then we're done!
if seed = nobody
[
stop ]
;; otherwise, make the patch the "leader" of a new cluster
;; by assigning itself to its own cluster, then call
;; grow-cluster to find the rest of the cluster
ask seed
[ set cluster self
grow-cluster ]]
display
end
to grow-cluster ;; patch procedure
ask neighbors4 with [(cluster = nobody
and pcolor = 8
) and
(pcolor = [pcolor] of myself)]
[ set cluster [cluster] of myself
grow-cluster ]
end
and the code for estimating frequency:
to calc-frequency
let freq map [[i] -> count patches with [cluster = i]] remove-
duplicates [cluster] of patches
set-current-plot "Frequency distribution of urban patch size"
histogram freq
end
Any help will be appreciated. Thanks.

I think the object named 'freq' in your final block of code is a list of cluster sizes. If it is, then you can simply take mean freq to get the average cluster size. However, you then get into a tangle with accessing the result. If you have a global variable to store that average (called aveCluster in my code), then you can simply include a line set aveCluster mean freq.
However, a cleaner way to do it, would be to change your code block into a reporter. Something like (note that I have assumed the code for calculating sizes is correct):
to-report cluster-frequencies
report map [[i] -> count patches with [cluster = i]] remove-duplicates [cluster] of patches
end
Then you can do your histogram with histogram cluster-frequencies and the average with set aveCluster mean cluster-frequencies. Note that this will be less efficient because the list of sizes is calculated twice - once for the histogram and once for the average. If you have the two requirements close together then you can instead:
...
let freqs cluster-frequencies
histogram freq
set aveCluster mean freq
...
and it will only have to calculate once.

Related

Is Netlogo implementation of rngs:rnd-negbinomial getting the wrong results?

I'd like to use the negative binomial distribution to assign values to turtles, but the outcome seems not to be correct.
In my model I'd like to assign values with the negative binomial distribution to the breeds-own variable time-treatment of the breed children.
I used the following code for this:
extensions [ rngs ]
breed [children child]
children-own [
time-treatment
]
to setup
clear-all
rngs:init
rngs:set-seed 1 500
reset-ticks
end
to go
create-children 100 [
setxy random-xcor random-ycor
set time-treatment rngs:rnd-negbinomial 1 20 0.78
]
tick
end
When showing results and calculating the mean of time-treatment the value will be around 70.
However, according the mathematical formula for the mean, it should be r(1-p)/p = 20(1-0.78)/0.78 = 5.641... How is this possible?
The reverse formula rp/(1-p) gives 70.91 which is very close to the result you got here. I assume that is where the problem lies.
According to wikipedia there are a few alternative formulations of the negative binomial distribution.
The link you provided counts the number of failures before 20 successes happen, whereas it looks like the formula here counts the number of successes before 20 failures happen.

Adding multiple turtle values in a list on NETLOGO to then calculate the variance

I am calculating the consumption rate of each turtle in the model. I then want to create a list of each turtle's consumption rate value so I can then calculate the variance of it. I can not figure out how to add those values into my list so that I can calculate the variance, any help? Here is my code so far:
ask turtles
[ set consumption-rate ( [ quality ] of patch-here ) / ( strength-of-competition * count turtles-here )]
show variance [ ]
NetLogo makes this kind of thing very easy. It's just:
show variance [ consumption-rate ] of turtles
The of primitive isn't just for accessing the variables of individual agents: it also works with agentsets, in which case it constructs a list of the results, which is exactly what you need here.

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.

Two Turtles Breeds _ one breed is the variable of the other?

I've got a doozy of a Netlogo question. If I have two different breeds of turtles, can the sum of a specified number of one breed's variables BE THE VARIABLE of the other breed?
Here is my train of thought. I’d like to model water usage of multiple households, but that water usage of a household needs to be dependent on a) the fixed values of the house (like water used by a faucet) * b) frequency of use of faucet by a person. With each household containing either 1 or more person (people) and that frequency of use can vary person to person.
The idea of using two turtle breeds would allow me to see how the decisions made by one breed affects the other.
Here is my pseudo code to help illustrate what I was thinking (not intended to be a working code)
globals []
breed [People person]
breed [Community household]
People-own [frequency]
Community-own [waterusefacuet HouseholdWaterUse]
;; =================================================================================================================
;; =================================================================================================================
to setup
clear-all
HouseholdCreation
PersonCreation
reset-ticks
end
to go
ask Community [WaterConsumption]
tick
end
;; =================================================================================================================
;; =================================================================================================================
to HouseholdCreation
ask patches [ sprout-Community n of 1 [
set size 1.0 set shape "square" set color blue
set waterusefacuet (1)
] ]
end
to PersonCreation
ask Community [ hatch-People 1 [
set size 0.5 set shape "circle" set color red
set frequency (1 + random 4)
]]
end
to WaterConsumption
Set HouseholdWaterUse (waterusefacuet * (frequency * # of people) )
end
Why not simply make each patch a household, have each patch have one or more turtles (persons), and then calculate household factors as patch factors? To define communities one could place patches into zones (e.g., if pxcor >= 5 and pxcor <=8 and pycor >=3 and pycor <= 6 set zone 1) <== not meant to be code, just the idea.
You could set patch size to make each patch small and specify a large zone of patches.
can the sum of a specified number of one breed's variables BE THE VARIABLE of the other breed?
Absolutely.
snipsnip for clarification : In my code here, I do not let the water use of people who live in a household BE the water use variable of that household. And generally I would recommend against a solution that lets the state of one (or more) agents be the state of another variable - unless there is a very good reason for it. Having states depend on each other is dangerous because you always have to make sure that you sync the values between agents. More importantly, it's often unnecessary. In my solution here, each person belongs to a household, and when that households calculates its total water use, it asks all its inhabitants to send them their use on that day, and then returns the sum of all those numbers. I hope that makes sense. If not, please do ask.
*< /snipsnip>
You need to use the of keyword though. of allows you direct access to variables from the context/perspective of one or more individual agent. So, let's say we have households and people, and people (because we all have different water use habits) have some frequency of water tap uses. In fact, we could have people draw the amount of water they use every day from a a normal distribution that is unique to them. Let's do that:
breed [people person]
breed [households household]
people-own [
mean-use-per-day ;; mean use per day
sd-use-per-day ;; standard dev per day
my-household ;; the household to which a person belongs
]
to setup
create-households 10 [
hatch-people random 4 + 1 [ ;; between 1 and 4 people in a household
set mean-use-per-day random 5 + 5 ;; mean 5-9
set sd-use-per-day random-float 3 ;; sd 0.00-2.99
set my-household myself ;; we set the person's household to the household that hatched them
]
]
to-report household-water-use ;; household reporter
report sum [random-normal mean-use-per-day sd-use-per-day] of people with [my-household = myself] ;; this creates a list of water uses based on the random use of each person in the household.
end
in order to run this code, you can simply call
show [household-water-use] of households
from the command center. This will give you a list of the water use of each household. Or if you want to just see the water use of one household on one random day, you can try
show [household-water-use] of one-of households

How to avoid individual patch updates

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.