Normal distribution for turtle at start - netlogo

I want to randomly place turtles within some x and y coordinates confines according to a Gaussian Distribution with no two turtles at the same patch.
Things I have tried:
1. There exists http://ccl.northwestern.edu/netlogo/docs/dictionary.html#random-normal
but there how do I avoid turtles getting located same patch.
Previous code I used(only randomly distributed):
ask n-of population patches-in-box
[
sprout-inboxturtles 1
]
;population- number of turtles
;patches-in-box -where i want to place turtles

I just realized that you can get around the speed problem completely by using the rnd:weighted-n-of primitive of the NetLogo Rnd Extension! Here is some revised code:
extensions [ rnd ]
to distribute-turtles [ pop box ]
if pop > count box [ error "Box can't hold all turtles!" ]
let ys [ pycor ] of box
let xs [ pxcor ] of box
let min-x min xs
let min-y min ys
let max-x max xs
let max-y max ys
let mid-x mean list min-x max-x
let mid-y mean list min-y max-y
let w max-x - min-x
let h max-y - min-y
ask rnd:weighted-n-of pop box [
[ (p (pxcor - mid-x) (w / 6)) * (p (pycor - mid-y) (h / 6)) ] of ?
] [ sprout 1 ]
end
to-report p [ x std-dev ]
report (1 / (std-dev * sqrt (2 * pi))) * e ^ (0 - ((x ^ 2) / (2 * (std-dev ^ 2))))
end
What rnd:weighted-n-of does is that it takes an agentset (or a list) and a reporter task that should return a "weight" for each element. Elements with greater weights have better chances of being picked. In our case, we assign these weights to patches in the box using the probability density function of a normal distribution (that's the p reporter in the code).
You can use distribute-turtles in the same way as in my other answer:
to setup
ca
let patches-in-box patches with [ abs pxcor < 10 and abs pycor < 10 ]
let population (count patches-in-box - 10)
ask patches-in-box [ set pcolor black + 2 ]
distribute-turtles population patches-in-box
end
...but in this case, the code runs very fast even if population is almost as big as count patches-in-box. Why? Because rnd:weighted-n-of is "smart" enough to sometimes discard the elements that have already been picked and keep picking amongst only the ones that haven't been picked yet. (You can look at the underlying Scala code if you are interested in the details.) In our case, it means that patches near the center of the box won't get unsuccessfully picked over and over again: only the free spots will remain in play towards the end.

There is no built-in equivalent of n-of for normal distributions (and it's not clear to me what it should be if there was one). So you'll have to use random-normal and adapt it to your special case:
to distribute-turtles [ pop box ]
if pop > count box [ error "Box can't hold all turtles!" ]
let ys [ pycor ] of box
let xs [ pxcor ] of box
let min-x min xs
let min-y min ys
let max-x max xs
let max-y max ys
let mid-x mean list min-x max-x
let mid-y mean list min-y max-y
let w max-x - min-x
let h max-y - min-y
crt pop [
loop [
let x random-normal mid-x (w / 6)
if x > max-x [ set x max-x ]
if x < min-x [ set x min-x ]
set xcor x
let y random-normal mid-y (h / 6)
if y > max-y [ set y max-y ]
if y < min-y [ set y min-y ]
set ycor y
if not any? other turtles-here [ stop ]
]
move-to patch-here ; to center in patch
]
end
And this is an example of how you would call it:
to setup
ca
let population 100
let patches-in-box patches with [ abs pxcor < 10 and abs pycor < 10 ]
ask patches-in-box [ set pcolor black + 2 ]
distribute-turtles population patches-in-box
end
A few notes:
The code would be more efficient if you passed it min-x, max-x, min-y and max-y directly instead of figuring out these values from the box agentset, but it should not make a huge difference unless your box is really big.
We need to make sure that pop is less than the number of the patches, or it would loop forever because there would not be any free patch where to put the turtles: this is why we throw an error when it happens. And the closer pop is to count box, even if it gives no error, the longer it will take to complete because the last few turtles will have a hard time finding a spot.
You can play with the standard deviations (w / 6 and h / 6) to get the distribution shape you want (that's basically the "steepness" of the bell curve).
random-normal is theoretically unbounded, so it could give you coordinates that are outside the box. This is why we "clip" the results to the min and max possible coordinates. If your standard deviations are too high, you may find that a lot of turtles end up "stuck" on the borders of the box.

Related

Divide regions accordingly to physical features

I'm working on a smaller project and got stuck on an issue, I'm not really sure if it's possible to solve it in NetLogo but I want to give StackOverflow a go!
I got a model that divides the world into different parts and randomly add physical features (such as rivers). If a feature goes through the whole region, I want it to separate the region and make into two regions. As an example, in the picture below, I want to separate the purple region into two unique regions accordingly to the physical feature (black).
The code I used to generate the picture above, can be found below.
to setup
ca
;Setting world.
resize-world 0 19 0 19
;Creating regions.
let x 5
let y 5
let col 45
while [y <= max-pycor + 1][
while [x <= max-pxcor + 1 ][
ask patches with [pxcor < x and pxcor >= x - 5 and pycor < y and pycor >= y - 5][
set pcolor col
]
set x x + 5
set col col + 10
]
set x 5
set y y + 5
]
;Generating physical features.
ask n-of 5 patches[ sprout 1[
set pcolor black]
]
let i 0
while [ i < (max-pycor * 2 )][
ask turtles [
fd 1
set pcolor black
ifelse (random 20 <= 1)
[
rt one-of [-90 0 90]
forward 1
]
[
fd 1
set pcolor black
fd 1
set pcolor black
]
set pcolor black
set i i + 1]
]
ask turtles [die]
end
My strategy for handling this is to realize that all we really need to do is "flood" a patch out by color and tag all the found adjacent patches, then repeat for any un-tagged, non-black patches until they are all done.
NetLogo does not have a "flood" command to get all patches adjacent to a patch meeting a criteria, so we make a special reporter of our own to handle it, patches-adjacent. Then it's just easy to ask those patches-adjacent to set their region to the currently chosen region.
I don't love this code, it's a little finicky and would be prone to infinite loops if tweaked incorrectly, but it should work. I bet there is a cleaner way to do this that I'm not thinking of at the moment.
; add a variable to track the different regions
; the default value will be `0` for each patch when `clear-all` is called
patches-own [ region ]
to set-regions
let current-region 1
; only act on non-black patches that haven't yet been assigned a region
let untagged patches with [ region = 0 and pcolor != black ]
while [any? untagged] [
ask one-of untagged [
ask patches-adjacent [
set region current-region
]
]
; update the region and the untagged patches we have left to process
set current-region current-region + 1
set untagged patches with [ region = 0 and pcolor != black ]
]
; this is just to get a view of the regions to quickly see if our code worked, it can be removed
ask patches [ set plabel region ]
end
to-report patches-adjacent
report patches-adjacent-ex (patch-set self) pcolor
end
to-report patches-adjacent-ex [found pc]
let newly-found neighbors4 with [ (not member? self found) and pcolor = pc and region = 0 and pcolor != black ]
set found (patch-set found newly-found)
ask newly-found [
; use recursion to find the patches adjacent to each newly-found one
; relying on updating the `found` agentset as we go to avoid duplicates
; or looping forwarder
set found (patches-adjacent-ex found pc)
]
report found
end
I solved this by using the Patch Clusters model that can be found in the NetLogo model library.

Can I modify NetLogo commands with variables?

To start with example:
to make-new-car [freq x y head ]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-cars 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
yet I want to have more breeds for cars - not just one car breed. I also want to keep it simple and insted of doing this(first function is the same as one above):
to make-new-car [freq x y head ]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-cars 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
to make-new-carSE [freq x y head ]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-carsSE 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
and being redundant by repeating the same procedure just with different breed name I wan to do something like this(put breed-name as an argument and use it with create- command):
to make-new-car [freq x y head breed-name]
if (random-float 100 < freq) and not any? turtles-on patch x y [
create-breed-name 1 [
setxy x y
set heading head
set color one-of base-colors
]
]
end
However Netlogo is complaining that create-breed-name is not defined. Any ideas ?
Easiest way to do this is to do create-turtles then set breed breed-name. Here's an example.
breed [ testers tester ]
to make-turtles [ breed-name ]
create-turtles 1 [ set breed breed-name ]
end
to setup
make-turtles testers
end
You can also do probably do something with run after constructing an appropriate string, but I think the above is more straightforward.
Go with Jen's answer. It is, by far, the most straightforward way to accomplish what you need.
Just for the sake of it, however, here is one way to do it with run:
to make-new-car [freq x y head breed-name]
let commands [ ->
setxy x y
set heading head
set color one-of base-colors
]
if (random-float 100 < freq) and not any? turtles-on patch x y [
run (word "create-" breed-name " 1 [ run commands ]")
]
end
Notice that I put the commands that should be executed by the newly created turtle inside an anonymous procedure (using NetLogo 6.0.1 syntax) and then run that inside the string passed to run. You could also put everything in one big string, but then you would loose compiler checking, syntax highlighting, speed, etc.
But, anyway, don't do any of this. Use Jen's method.

NetLogo - Distributing grains of sand in sandpile model to random neighbours

This code relates to an adaption of the NetLogo sandpile model. When the count go grains in each patch exceeds the threshold which in this case is 3, the grains are re-distributed to the surrounding neighbors. I am trying to re-distribute one grain to 4 random neighbour patches.
The code returns a run time error because patches at the edge will not have all the 8 neighbors, so when asking for 4 random neighbours it returns an errors stating can't request 4 ransom agents from 3 etc.
I am trying to find a piece of code that will resolve this problem.
****Code Below*****
to-report stabilize [animate?]
let active-patches patches with [ n > threshold ]
;; The number iterations the avalanche has gone for. Use to calculate lifetimes.
let iters 0
;; we want to count how many patches became overloaded at some point
;; during the avalanche, and also flash those patches. so as we go, we'll
;; keep adding more patches to to this initially empty set.
let avalanche-patches no-patches
while [ any? active-patches ] [
let overloaded-patches active-patches with [ n > threshold ]
if any? overloaded-patches [
set iters iters + 1
]
ask overloaded-patches [
set base-color fired-color
;; subtract 'threshold' amount from this patch
update-n -4
if animate? [ recolor ]
;; edge patches have less than four neighbors, so some sand may fall off the edge
ask n-of 4 neighbors [
update-n 1
if animate? [ recolor ]
]
]
if animate? [ display ]
;; add the current round of overloaded patches to our record of the avalanche
;; the patch-set primitive combines agentsets, removing duplicates
set avalanche-patches (patch-set avalanche-patches overloaded-patches)
;; find the set of patches which *might* be overloaded, so we will check
;; them the next time through the loop
set active-patches patch-set [ neighbors ] of overloaded-patches
]
report (list avalanche-patches iters)
end
Instead of asking 4 neighbors, ask min list 4 count neighbors:
ask n-of (min list 4 count neighbors) neighbors [
...
]
But from the model point of view, there will be different redistribution on the edge of the table, so this is not a good idea. Maybe it is better to have a wrapped world and then manually "push" the grains off the table: select 4 neighbours and call just the ones with close pxcor and pycor. The rest is off the table.
If the world is wrapped (horizontally and vertically), we can always select 4 neighbors:
let selected-neighbors n-of 4 neighbors
Among these 4 neighbors only real neighbors are on the table
set selected-neighbors selected-neighbors with [
(abs (pxcor - [ pxcor ] of myself) < 2)
and
(abs (pycor - [ pycor ] of myself) < 2)
]
ask selected-neighbors [
....
]

Find the presence of other turtles in a given direction upto a distance

I wish to find out whether in a given turtle's heading there is another agent present upto a given distance.
Here the Distance is "D".
Note:
Any agent present before D in the given direction should be also considered.
Even the direction doesn't coincide with the other's agent centre but just touches it ,even then that agent should be considered.
Problem:
No turtle-ahead procedure available. Combination of patch-ahead and turtles-on not applicable due to patch-size>> turtle-size.
Possible approach:
1.Represent the turtle's heading by the equation of a line.
to-report calculate-line[x y angle]
let m tan angle
let A m
let B -1
let C (- m * x + y)
report (list A B C)
end
to-report heading-to-angle [ h ]
report (90 - h) mod 360
end
let line-equ calculate-line (xcor) (ycor) (heading-to-angle heading)
2.Calculate the perpendicular distance from other turtles here, Check if there are within a range that the size of other turtles.
to-report value[A X1 Y1];;A is list of coefficents of line, x1 and y1 are coordinates of red turtle
if-else(abs((item 0 A * X1 + item 1 A * Y1 + item 2 A) / (sqrt((item 0 A ^ 2) + (item 1 A ^ 2) ))) < [size] of wall )
[ report "true"][report "false"]
end
3.To check if the red turtle is within D. One could obtain a line perpendicular to black one and compute the red turtle distance from it to check if it is less than or equal to D. But then that adds more complication.(Though one can simplify rotate the turtle by 90 left or right and get the line equation.)
This is what I meant by my comment. Run this code (as its own model). What it does is turn all the turtles on a few 'ahead' patches a different colour. I know this is not what you are trying to do, but the agentset candidates is a relatively small number of turtles. These are the only ones that you have to check whether they are on the correct path. So instead of turning them a different colour you could check the direction that they are from your initial turtle.
to setup
clear-all
set-patch-size 25
resize-world -10 10 -10 10
create-turtles 1000
[ setxy random-xcor random-ycor
set color yellow
set size 0.4
]
ask one-of turtles
[ set color red
set size 1
check-from-me 5
]
end
to check-from-me [howfar]
let counter 0
let candidates turtles-here
while [counter < howfar]
[ set counter counter + 1
set candidates (turtle-set candidates turtles-on patch-ahead counter)
]
ask candidates [set color red]
end
to-report check-wall
let return false
hatch 1[
set color black
set size ([size] of one-of walls) / 2
show (2.5 * ([size] of myself))
while [distance myself < (2.5 * ([size] of myself))]
[
fd ([size] of one-of walls) / 64
if any? walls in-radius size
[
set return true
]
show distance myself
]
]
report return
end
The above works. But still is approx. I am looking for better solution with probably less maths as one elucidated in the question.

Making box in the middle of the world by exact percentage from the overall space

I want to make box in the middle of the Netlogo world
I managed to make a box but in the corner of my space the location of the origin is corner and the max pxcor = 9 and the maxpycor = 9
The code for 25%
to setup-area-25%
ask patches with [pxcor >= 5 and pycor >= 5] [ set pcolor blue ]
end
and the other code for 50 %
to setup-area-50%
ask patches with [pxcor >= -5 and pycor >= 5] [ set pcolor blue ]
end
I want to make blue area represent 25 and 50 % of the world but in the middle of the world I tried to use in radius but it did not give me a right area.
Thanks in advance
Here is a quick and dirty way that won't necessarily give you the exact percentage that your looking for, but could be good enough, depending on what you are trying to do:
to make-box [ pct box-color ]
let side round sqrt (count patches * (pct / 100))
let x min-pxcor + ceiling ((world-width - side) / 2)
let y min-pycor + ceiling ((world-height - side) / 2)
ask patches with [
pxcor >= x and pxcor < x + side and
pycor >= y and pycor < y + side
] [
set pcolor box-color
]
end
Calling make-box 25 red should give you a red square that is about 25% of the overall area, calling make-box 50 blue should give a blue square that is about 50%, etc.
The code uses the square root of the desired box area as the side of the box to draw. Not all numbers are perfect squares, however, and this is why you don't always get the exact percentage that you are looking for. You could try to look for the closest factor pair instead, but in some cases, they're just not very square. For example, 50% of the default NetLogo world size is 544.5 patches. If we round this up, we get 545 patches: not a perfect square. The closest factor pair that will give you exactly 545 is 109 * 5, which is probably not what you want.
Edit:
Here is a version that uses the closest factor pair, thereby always giving an area equal to the desired percentage of the world (rounded to an integer number of patches, but that can't be avoided). Just be warned that the box may end up being much more rectangular than square; so much that it very well may wrap around the world. You'll have to vary world-size or requested percentage if you want to avoid that.
to make-box [ pct box-color ]
let n round (count patches * (pct / 100))
let h height (floor sqrt n) n
let w (n / h)
let x min-pxcor + ceiling ((world-width - w) / 2)
let y min-pycor + ceiling ((world-height - h) / 2)
ask patches with [
pxcor >= x and pxcor < x + w and
pycor >= y and pycor < y + h
] [
set pcolor box-color
]
end
to-report height [ h n ]
report ifelse-value (n mod h = 0) [ h ] [ height (h - 1) n ]
end
The algorithm for finding the closest factor pair loosely follows this answer.