Hatching in NetLogo by fractional probabilities - simulation

I'm trying to hatch a certain amount of turtles according to some statistics I've complied about births in a particular country.
To save you the math there are 201 births everyday in the adult population of 3565765.
What I want to do is scale my numbers to correspond to a netlogo model with 73 adults, 19 children and 8 toddlers so one hundred agents in total. (I've scaled these numbers according to their population distribution)
The birth rate defined by the user at the interface and currently I have..
to births
ask n-of(count adults * birth-rate) adults[
hatch-toddlers 1
.....
The way I'm currently deciding the birth rate is 201(average births per day)/3565765(adult population) = 0.00005636939 x 73(my adult population in model) = 0.00411496551
when I get work through by code with this figure I get a birth rate of 0.30039248239. When I run my model no new toddlers are born. Can I assume that ask n-of will only hatch a new toddler if its over 1?
If so is there a way I can use these probabilities to slip a coin so to speak to see a turtle is hatched?

Right, n-of will discard the fractional part of any number you pass it.
I think you want random-poisson here. To demonstrate its usage, suppose I want an average of 0.1 births to occur every tick. Then:
to demo
clear-all
reset-ticks
while [ticks < 100] [
let births random-poisson 0.1
if births > 0 [
crt births
print (word births " born on tick " ticks)
]
tick
]
print (word "after 100 ticks, there are " count turtles " turtles")
end
Where a typical run ends up looking like:
observer> demo
1 born on tick 2
1 born on tick 7
1 born on tick 12
1 born on tick 28
1 born on tick 39
1 born on tick 48
1 born on tick 49
1 born on tick 52
2 born on tick 58
1 born on tick 66
after 100 ticks, there are 11 turtles
On the average, you'll get 10 turtles.

Related

NetLogo Burnin / Warmup issue

Using NetLogo 5.3.1, i'm trying to set up BehaviorSpace so that all its model runs start after exactly the same 500-tick warmup period. However, the results are not intuitive to me.
For illustrative purposes, I will use the 'Flocking.nlogo' model in the model library. Below is the model code, with 2 lines of code added to the end of the setup which saves the model's state after 500 ticks.
turtles-own [
flockmates ;; agentset of nearby turtles
nearest-neighbor ;; closest one of our flockmates
]
to setup
clear-all
create-turtles population
[ set color yellow - 2 + random 7 ;; random shades look nice
set size 1.5 ;; easier to see
setxy random-xcor random-ycor
set flockmates no-turtles ]
reset-ticks
; Now execute a 500-tick warm-up period and save the model's state
repeat 500 [ go ]
export-world "Flocking-after-500ticks.csv"
end
to go
ask turtles [ flock ]
;; the following line is used to make the turtles
;; animate more smoothly.
repeat 5 [ ask turtles [ fd 0.2 ] display ]
;; for greater efficiency, at the expense of smooth
;; animation, substitute the following line instead:
;; ask turtles [ fd 1 ]
tick
end
to flock ;; turtle procedure
find-flockmates
if any? flockmates
[ find-nearest-neighbor
ifelse distance nearest-neighbor < minimum-separation
[ separate ]
[ align
cohere ] ]
end
to find-flockmates ;; turtle procedure
set flockmates other turtles in-radius vision
end
to find-nearest-neighbor ;; turtle procedure
set nearest-neighbor min-one-of flockmates [distance myself]
end
;;; SEPARATE
to separate ;; turtle procedure
turn-away ([heading] of nearest-neighbor) max-separate-turn
end
;;; ALIGN
to align ;; turtle procedure
turn-towards average-flockmate-heading max-align-turn
end
to-report average-flockmate-heading ;; turtle procedure
;; We can't just average the heading variables here.
;; For example, the average of 1 and 359 should be 0,
;; not 180. So we have to use trigonometry.
let x-component sum [dx] of flockmates
let y-component sum [dy] of flockmates
ifelse x-component = 0 and y-component = 0
[ report heading ]
[ report atan x-component y-component ]
end
;;; COHERE
to cohere ;; turtle procedure
turn-towards average-heading-towards-flockmates max-cohere-turn
end
to-report average-heading-towards-flockmates ;; turtle procedure
;; "towards myself" gives us the heading from the other turtle
;; to me, but we want the heading from me to the other turtle,
;; so we add 180
let x-component mean [sin (towards myself + 180)] of flockmates
let y-component mean [cos (towards myself + 180)] of flockmates
ifelse x-component = 0 and y-component = 0
[ report heading ]
[ report atan x-component y-component ]
end
;;; HELPER PROCEDURES
to turn-towards [new-heading max-turn] ;; turtle procedure
turn-at-most (subtract-headings new-heading heading) max-turn
end
to turn-away [new-heading max-turn] ;; turtle procedure
turn-at-most (subtract-headings heading new-heading) max-turn
end
;; turn right by "turn" degrees (or left if "turn" is negative),
;; but never turn more than "max-turn" degrees
to turn-at-most [turn max-turn] ;; turtle procedure
ifelse abs turn > max-turn
[ ifelse turn > 0
[ rt max-turn ]
[ lt max-turn ] ]
[ rt turn ]
end
; Copyright 1998 Uri Wilensky.
; See Info tab for full copyright and license.
The BehaviorSpace window looks like this:
The added 2 lines of code, which saves the model's state after 500 ticks, come from the answer to question 6 in Chapter 9 in Railsback & Grimm 2012: Agent-based and individual-based modeling (1st edition). The answer continues by stating the next step: "Then, in BehaviorSpace, change the "Setup commands" to just import the saved world and run 1000 more ticks".
I did this, and then imported the file into R to summarise the data by calculating the mean and SD of number of flockmates at tick 100, 200, 300, 400, and 500. Below the R code:
df <- read.csv("ibm_table_output-test.csv", skip = 6)
df1 <- df %>%
rename(run_number = X.run.number.,
time_step = X.step.,
mean_flockmates = mean..count.flockmates..of.turtles
) %>%
select(run_number,
time_step,
mean_flockmates,
vision) %>%
arrange(run_number,
time_step) %>%
filter(time_step == 100 |
time_step == 200 |
time_step == 300 |
time_step == 400 |
time_step == 500)
df1_long <- melt(df1, # Apply melt function
id.vars = c("run_number", "time_step","vision"))
# Calculate a summary table
df1.summ <- df1_long %>%
group_by(time_step, vision) %>%
summarise(avg = mean(value),
sd = sd(value))
The output is as follows:
# A tibble: 15 × 4
# Groups: time_step [5]
time_step vision avg sd
<int> <int> <dbl> <dbl>
1 100 1 8.34 0
2 100 2 8.34 0
3 100 3 8.34 0
4 200 1 7.83 0
5 200 2 7.83 0
6 200 3 7.83 0
7 300 1 7.95 0
8 300 2 7.95 0
9 300 3 7.95 0
10 400 1 7.45 0
11 400 2 7.45 0
12 400 3 7.45 0
13 500 1 7.92 0
14 500 2 7.92 0
15 500 3 7.92 0
To me this output doesn't make sense.
My question is why is the average number of flockmates the same across different vision levels within the same time_step group? And why are the SDs all 0? In other words, why do the model runs produce identical outputs? I thought that initiating a burnin period would initiate identical starting positions for all simulations, but create different mean and SD values for each run because of different random numbers used? Or am I misunderstanding?
EDIT: The reason why the SDs are 0 is because there is no variation in mean values, but I don't understand why there is no variation. Below is the df1_long data frame:
run_number time_step vision variable value
1 1 100 1 mean_flockmates 8.340000
2 1 200 1 mean_flockmates 7.833333
3 1 300 1 mean_flockmates 7.953333
4 1 400 1 mean_flockmates 7.446667
5 1 500 1 mean_flockmates 7.920000
6 2 100 1 mean_flockmates 8.340000
7 2 200 1 mean_flockmates 7.833333
8 2 300 1 mean_flockmates 7.953333
9 2 400 1 mean_flockmates 7.446667
10 2 500 1 mean_flockmates 7.920000
11 3 100 2 mean_flockmates 8.340000
12 3 200 2 mean_flockmates 7.833333
13 3 300 2 mean_flockmates 7.953333
14 3 400 2 mean_flockmates 7.446667
15 3 500 2 mean_flockmates 7.920000
16 4 100 2 mean_flockmates 8.340000
17 4 200 2 mean_flockmates 7.833333
18 4 300 2 mean_flockmates 7.953333
19 4 400 2 mean_flockmates 7.446667
20 4 500 2 mean_flockmates 7.920000
21 5 100 3 mean_flockmates 8.340000
22 5 200 3 mean_flockmates 7.833333
23 5 300 3 mean_flockmates 7.953333
24 5 400 3 mean_flockmates 7.446667
25 5 500 3 mean_flockmates 7.920000
26 6 100 3 mean_flockmates 8.340000
27 6 200 3 mean_flockmates 7.833333
28 6 300 3 mean_flockmates 7.953333
29 6 400 3 mean_flockmates 7.446667
30 6 500 3 mean_flockmates 7.920000
My understanding is that you're running setup once, manually, and then running your BehaviorSpace experiment. The problem you will have with that is that the random number generator seed is including in the export-world data that you generate once by running the setup procedure. Then when you call import-world in the Setup commands: of each experiment run you will get that RNG seed imported as well. The export actually includes the full state of the RNG, but thinking of it as being the same seed is close enough.
LeirsW is correct that Flocking (as most NetLogo models, and probably the original one you had the problem with) is totally deterministic. So the outcome will be the same with the same RNG seed each time.
The fix is easy, add a second line to your BehaviorSpace experiment Setup commands: after the import-world that runs random-seed new-seed. This will make sure each model run has a new, unique RNG seed to use for the rest of its run.
The simple answer to the lack of variation is that the flocking model (after setup) is as good as 100% deterministic. There are some elements in the code that at first sight you might think have some stochasticity to them but that sochasticity doesn't have any effect.
The order in which turtles flock and move is stochastic, but they all choose how they want to move before any of them do so, which results in this stochasticity having no effect on the outcome.
The other part that you would expect carries some stochasticity is set nearest-neighbor min-one-of flockmates [distance myself], when two birds are at the exact same distance away from the focal bird. But all their locations have floating point numbers in both x and y, so I assume that the chance that you will have a tie in distances is also extremely low.

The in-radius works different in Netlogo 6.1.0 than in previous version

I have the following code which creates a grid of agents and place links between pairs if they are in a distance of interference.
breed [ readers reader ]
undirected-link-breed [ rris rri ]
globals [
interf-rri-radius
num-readers
distance-var-x
distance-var-y
readers-per-row
readers-per-column
num-checkouts
]
to setup
ca
setup-globals
ask patches [ set pcolor blue - 3 ]
spawn-by-row-col
reset-ticks
end
to setup-globals
set interf-rri-radius 1005
set num-readers 40
set distance-var-x 12
set distance-var-y 22
set readers-per-row 8
set readers-per-column 5
set num-checkouts 0
end
to spawn-by-row-col
let half-step 0.5 * distance-var-x
let d-vals ( range ( min-pxcor + half-step ) ( min-pxcor + (readers-per-row * distance-var-x)) distance-var-x )
let dc-vals ( range ( min-pxcor + half-step ) ( min-pycor + (readers-per-column * distance-var-y)) distance-var-y )
show dc-vals
; Create an empty list to build into
let possible-coords []
; For each possible vertical value, map all horizontal values in order and
; combine these into an ordered list starting at the lowest px and py coords
foreach dc-vals [
d ->
set possible-coords ( sentence possible-coords map [ i -> (list i d) ] d-vals )
]
show (word "possible-coords = " possible-coords)
; Use the number of readers to sublist the possible coordinates, and
; create a turtle at each of the coordinate combinations left.
let max-positions length possible-coords
if max-positions > (num-readers + num-checkouts) [ set max-positions (num-readers + num-checkouts) ]
let use-coords sublist possible-coords num-checkouts max-positions
foreach use-coords [
coords ->
create-readers 1 [
setxy item 0 coords item 1 coords
set shape "square 2"
set size 2
set color 15
]
]
ask readers [ create-rris-with other readers in-radius (interf-rri-radius / 10) ]
end
The neighbors of reader 0 are
show [sort [who] of rri-neighbors] of reader 0
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39]
However, the distance between reader 0 and reader 39 is
show [distance reader 0] of reader 39
121.6552506059644
and the connection radius is 1005/10= 100.5 so they should not be connected with an rri link.
Notice, I use a origin-centered world of -50 to 50 in X and Y dimensions.
I have tested the code in previous Netlogo version 6.0.4 and the reader 39 is not a neighbour of the reader 0.
I do not know what can be the problem. I believe is the new version but I would like to be sure.
In case anyone else runs into this, there is a confirmed bug with in-radius in the NetLogo 6.1.0 release, and the details are in the bug report on GitHub.
The issue only affects in-radius when used in a non-wrapped world, and only when used on turtles, and only when used with a radius that's a significant % of the world width. If you're using a world with wrapping, or using in-radius with patches, or using a small radius relative to the world size, your data will be correct and you don't need the below workaround.
As a workaround if your model is affected, you can use a simple user-defined NetLogo procedure in your model until the fix is published. It's not going to be super-fast if your having turtles calculate in-radius many times per tick, but if you have few turtles or are just using it during setup, it should be okay:
to-report temp-in-radius [agentset r]
report agentset with [ distance myself <= r ]
end
Then, instead of create-rris-with other readers in-radius (interf-rri-radius / 10) you would do create-rris-with (temp-in-radius other readers (interf-rri-radius / 10)).
Or more generally, instead of something like count other turtles in-radius 5 would become count temp-in-radius (other turtles) 5.

Spider Aggression: Creating A Simple Behavioral Model

UPDATE
Thanks Luke C & JenB. Here's my revised code. I just converted the females to "killer" by turning her territory to a different color (green to blue) if a male wanders into her territory. If any male happens to be on a blue colored patch, he dies. It seems that the male who initially triggers the conversion does not get eaten immediately, which is what I want. He can be eaten if he doesn't get out of her blue territory on the next tick. Then, any subsequent males are eaten immediately.
Also, I am exploring some cool things with the BehaviorSpace tool, like how many ticks it takes for all the males to be eaten in a number of runs.
The only loose ends are creating a graph window that displays the number of males over time (ticks) and a report window(s) with the number of nonkiller/killer females.
ORIGINAL POST
I would like to model a behavioral system of wolf spiders with the following rules:
Females are stationary
Males move around
If any male encroaches within a certain radius of a female, that female becomes a “killer” two ticks later
Any males within a “killer” female’s territory is eaten and taken out of the population
The simulation ends when all males are eaten
All females are “non-killers” at setup
End goals of the model:
How many ticks does it take for all of the males to be eaten?
Are there any ‘non-killer’ females in the population at the end of the simulation?
Here is what I have so far. The parts I am struggling with are setting up the female territories, converting non-killer females to killer females when a male enters her territory, accounting for/taking out eaten males, reporting the duration of the simulation in ticks and if any non-killer females remain at the end.
breed [females female]
breed [males male]
to setup
clear-all
reset-ticks
ask patches [set pcolor white]
setup-females
setup-males
end
to setup-females
create-females 15 [
set shape "spider"
set color 15
set size 25
setxy random-xcor random-ycor]
ask females [move-to one-of patches with [not any? females in-radius 40]
; prevents overlapping
ask patches in-radius 20 [set pcolor green]
]
end
to setup-males
create-males 30 [
set shape "spider"
set color black
set size 20
setxy random-xcor random-ycor]
ask males [move-to one-of patches with [not any? males in-radius 10]
; prevents overlapping
]
end
to go
move-males
tick
if count males = 0 [stop]
end
to move-males
ask males [
right random 360
if random 100 > 49 [forward 1 + random (15 - 1)]
if pcolor = blue [die]
;moves male 1 to 15 units per tick if condition satisfied
score-females
]
end
to score-females
ask females in-radius 20 [
if count males > 0 [ask patches in-radius 20 [set pcolor blue]]
]
end

Create two rows of turtles with an equal x-cor distance

first of all, sorry for my english. I hope you can understand me.
I'm trying to create an ABM of couple bargaining. In order to accomplish this, I want to set two rows of men and women, like in the "Party" Netlogo model.
As I see, I want to have one row with men disposed with equal distances between every man, like man, (5 empty patches), man (5 positions), man... starting with one on the left in a determined position. And the same goes for woman's row.
How can I do this?
With this:
setxy random-xcor 15 ; for the man's row
setxy random-xcor 15 ; for the woman's row
I can get two rows of men and women within a fixed axis, and a random-xcor on the other axis, but i don't get equal distances between turtles.
Thank you so much for your help.
ask patches with [pxcor mod 5 = 0 and abs pycor = 1] [
sprout 1 [
set shape "person"
set color ifelse-value (pycor > 0) [blue][pink]
]
]
You could do something like this:
create-turtles num-men [ setxy who * distance 15]
create-turtles num-women [setxy (who - num-men) * distance -15]
For example,
if you have 5 turtles, their whos will be [0 1 2 3 4] and a distance of 5, thus their xcors will be [0 5 10 15 20] respectively. The only reason this would work is if the men's whos start at 0. You may need to offset their whos by how many other turtles were created before...see the women.

To create fixed number turtles each with separate headings on fixed ycor and equidistant xcor

I want to create 4 turtles on fixed pycor (like pycor = 10) and even spacing xcor over that pycor; and also I want to make the headings of each turtles separate from other. The display is like
............. O ............. O .............. O ........... O ............
(heading 45) (heading 90) (heading 230) (heading 180)
O is the turtle here. My code is as below.
ask n-of 4 patches with [ pcolor = 18 and pycor = 10 ] [
sprout-turtles 1 [
set shape "default"
set color blue
set size 2
set heading one-of [90 270]
]
]
With this code turtles are created but many time with same heading, sometimes on same patch, sometimes neighboring patch as shown below
..........OOO...................O or .........OO..........O.........O...
but this i don't want. Should i have to use Create turtles four times separately specifying xcor, ycor and heading? Actually i don't want to use it four times. Please any suggestion and help? Thanks a lot.
Since the only thing you are taking from the patch to the turtle, you may as well just use create-turtles instead of sprout-turtles and then put them where you want. Typically, sprout is used when the particular patch meets relevant conditions - such as having lots of resources. Also, since you want specific values, using one-of or n-of will not work because they randomly select.
Instead you want something more like this (not tested):
let gap 15 ; spacing between turtles
let directions [45 90 230 180] ; heading values
let ii 0 ; counter / index
repeat 4
[ create-turtles 1
[ setxy (0 + ii * gap) 10
set shape "default"
set color blue
set size 2
set heading item ii directions
]
set ii ii + 1
]