I'm trying to have NetLogo draw values from a bounded random normal distribution following the recommendation in a previous question in stackoverflow
NetLogo : How to make sure a variable stays in a defined range?
Specifically I'm asking the model to create a circular home range that varies in size according to empirical data
set homerange patches in-radius ((sqrt (( random-normal-in-bounds [ 54.4 35.8 19 151 ] * 1000000)/ pi))/ 100)
to-report random-normal-in-bounds [mid dev mmin mmax]
let result random-normal mid dev
if result < mmin or result > mmax
[ report random-normal-in-bounds mid dev mmin mmax ]
report result
end
However I keep getting the error that random-normal-in-bounds expected 4 inputs. I'm sure it's something silly I'm doing but it looks like 4 inputs (54.4, 35.8, 19, 151) to me. Any suggestions on what I'm doing wrong? Thanks in advance!
I think your error is caused by [] you don't need these brackets.
Update:
to test
clear-all
let homerange nobody
let radius sqrt (( random-normal-in-bounds 54.4 35.8 19 151 * 1000000)/ pi) / 100
crt 1 [
set homerange patches in-radius radius
]
ask homerange [set pcolor violet]
end
to-report random-normal-in-bounds [mid dev mmin mmax]
let result random-normal mid dev
if result < mmin or result > mmax
[ report random-normal-in-bounds mid dev mmin mmax ]
report result
end
Related
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.
I want to select all the patches at a randomly-generated distance eps from all turtles in a simulation and reset their color to yellow. This essentially draws a circle of patches around each turtle in the simulation. I have tried a few different options without success. Through perusing this forum I found some code that looks promising but still has some issues (posted here). I appreciate any suggestions for tweaking this code or using something else to solve this problem.
let eps2 eps
foreach [ eps2 ]
[
ask patches with
[
distance myself > eps2 - 0.5 and
distance myself < eps2 + 0.5
]
[
set pcolor yellow
]
]
eps is a turtle variable so using the let command allows me to circumvent using a turtle variable in patch context.
The foreach command does not recognize eps because it is not a constant, is there another command I could use here?
You can use list (see below), but ... why do you want a list? As it stands, there is no need to use a list.
to setup
ca
crt 1
ask turtle 0 [test]
end
to test
let eps2 10
foreach (list eps2 ) ;you can use `list`
[
ask patches with
[
distance myself > eps2 - 0.5 and
distance myself < eps2 + 0.5
]
[
set pcolor yellow
]
]
end
Addendum:
Since you indicate that you do not in fact need that list, you might try something along the lines of the following:
to test2
ca
crt 1
ask encirclingPatches turtle 0 10 1 [set pcolor yellow]
end
to-report encirclingPatches [#t #dist #width]
let _w2 (#width / 2)
report patches with [
distance #t > #dist - _w2
and
distance #t < #dist + _w2
]
end
I have limited programming experience (mechanical engineering student, so a bit of matlab and labview experience) and am very new to NetLogo, so I apologize in advance if this question is pretty basic or my code is of poor quality.
I need to have my turtles move to 1 of 2 possible neighboring patches based on a given probability function. The two patches that I need to input to the probability function are the two neighboring patches with the lowest nest-scent value. I have been able to pull the two lowest nest-scent values, but I cannot figure out how to actually figure out which patches those are, and how to put those coordinates into an ifelse statement to move the turtle to one of them based on the aformentioned probability function. I have the following code that is obviously not working:
to move
set farthest-patch sort-by < [nest-scent] of neighbors
let a1x pxcor of item 0 farthest-patch
let a1y pycor of item 0 farthest-patch
let a2x pxcor of item 1 farthest-patch
let a2y pycor of item 1 farthest-patch
let a1 item 0 farthest-patch
let a2 item 1 farthest-patch
let x (((a1 + a2) / 100 ) - 1)
let probability-move 0.5 * (1 + ((exp(x) - exp( - x)) / (exp(x) + exp( - x))))
ifelse random-float 1 < probability-move
[set to-move 1]
[set to-move 0]
let a1-probability (a1 / (a1 + a2))
ifelse random-float 1 < a1-probability
[set destination [a1x a1y]]
[set destination [a2x a2y]]
ifelse count turtles-here >= 20
[set full 1]
[set full 0]
if [a1x a21] = full
[set destination [a2x a2y]]
if [a2x a2y] = full
[set destination [a1x a1y]]
if [a2x a2y] and [a1x a1y] = full
[set to-move 0]
ifelse to-move = 1
[move-to destination]
[stop]
end
Basically what I have (tried) to do here is sort a farthest-patches list by increasing nest-scent, and I have pulled the two lowest nest-scent values in order to input those values into my probability functions (both for whether or not to move, and if they are to move which of the two patches to select). I am not sure how to properly pull the patch coordinates of the patches that the a1 and a2 values were taken from.
Thanks for any help,
Brad
okay, you are making life way more complicated than it needs to be. You can select the two patches (or turtles) with the smallest values of a variable with min-n-of. Look it up in the dictionary to get the details.
Having found the two candidates, the best option is to use the rnd extension for choosing the destination because it has a primitive for random selection by weight. Finally, since you are using a function of your variable as the weight (rather than the variable value itself), you need a way to construct that weight. The best option is to separate it out - you could also have a second variable with the weight value, but that just proliferates variables.
Here is a complete working model. Please copy the whole thing into a new instance of NetLogo and try and understand how it works, rather than just copy the relevant bits into your code because min-n-of, using agentsets and passing variables to procedures are important aspects of NetLogo that you need to know about. I have also set up colouring etc so you can see the choices it makes.
extensions [rnd]
patches-own [ nest-scent ]
to setup
clear-all
create-turtles 1 [ set color red ]
ask patches
[ set nest-scent random 100
set plabel nest-scent
]
reset-ticks
end
to go
ask one-of turtles [ move ]
tick
end
to move
set pcolor blue
let targets min-n-of 2 neighbors [ nest-scent ]
let destination rnd:weighted-one-of targets [ calc-weight nest-scent ]
move-to destination
end
to-report calc-weight [ XX ]
let weight 0.5 * (1 + ((exp(XX) - exp( - XX)) / (exp(XX) + exp( - XX))))
report weight
end
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.
In NetLogo I setup a model such that male predators create a home range that varies within some bounds. I previously asked for help on stackoverflow on how to do that.
Selecting values from bounded normal distribution in NetLogo
This worked great. When the predator moves around the landscape I ask the predator to check whether it is outside its specific home range (these are different sizes because of the random process), and if so to face the center of the home range my-base. I can ask the predator to check whether it is outside of a circle with a specific radius, however, I'm having trouble asking the predator to detect its specific home range created at setup. I figure I could have "home range" be a predator characteristic and then ask them to look at their own home range, but again I'm having trouble with that. Any suggestions? A snippet of my code with the setup and "random-movement" procedure is below.
to setup
ca
clear-all-plots
clear-output
clear-turtles
create-males 20
[
move-to one-of patches with [is-park?] ;inside a National Park
if any? males in-radius (((sqrt ((54.4 * 1000000)/ pi))/ 100) * 0.4) ;avoid other males
[move-to one-of patches with [is-park?] ]
set size 4
set shape "harimau"
set my-base patch-here
set homerange patches in-radius (((sqrt ((random-normal-in-bounds 54.4 35.8 19 151 * 1000000)/ pi))/ 100) * 0.4)
set numberofAdultMale ( numberofAdultMale + 1)
]
reset-ticks
end
to-report random-normal-in-bounds [mid dev mmin mmax]
let result random-normal mid dev
if result < mmin or result > mmax
[report random-normal-in-bounds mid dev mmin mmax]
report result
end
to random-movement
if-else my-base != no-patches[if distance my-base > (((sqrt ((54.4 * 1000000)/ pi))/ 100) * 0.4) ;this checks within a certain radius but not within the specific home range of the male
[ face my-base]
]
[ ]
rt random 180
lt random 180
fd time-step * random-gamma((meansRandomMove * meansRandomMove)/((deltaRandomMove)^ 2)) (1 / (((deltaRandomMove)^ 2) / meansRandomMove))
end
In above code I have the predators distribute themselves based on a predefined home range size (((sqrt ((54.4 * 1000000)/ pi))/ 100) * 0.4). A related question is how to have predators distribute themselves based on the actual home ranges homerange patches in-radius (((sqrt ((random-normal-in-bounds 54.4 35.8 19 151 * 1000000)/ pi))/ 100) * 0.4) created from the random distribution?
I think I figured it out. First I set homerange as an attribute of males. Then, at setup, set homerange patches in-radius (((sqrt ((random-normal-in-bounds HomerangeSizeMales 35.8 19 151 * 1000000)/ pi))/ 100) * 0.4). Then, in the movement procedure, used sqrt (count homerange / pi)