NetLogo - Finding Turtles Within 2 Squares - netlogo

I am trying to find out how to check if there are any turtles near another (which we will call the base turtle, or base). I need this to include diagonals, as I am spawning people around these bases and so need 1 full square around the base empty. Thus. when spawning bases I need to make sure there are no others within 2 squares, including diagonal.
I tried using "turtles in-radius (2,3,4,...)" and it doesn't work, since it seems that the radius command is circular. How would I go about this?

NetLogo's neighbors gives you the 8 patches surrounding the patch the turtle is on. Do you need the 16 surrounding patches, or will 8 do?
A simple procedure for neighbors16 in a non-wrapping world might be
to-report neighbors16
; can be called by a patch or a turtle
; assumes there is no wrapping of the world
let xm max (list (pxcor - 2) min-pxcor)
let xh min (list (pxcor + 2) max-pxcor)
let ym max (list (pycor - 2) min-pycor)
let yh min (list (pycor + 2) max-pycor)
let ptchs no-patches
foreach (range xm (xh + 1) 1) [x ->
foreach (range ym (yh + 1) 1) [y ->
set ptchs (patch-set patch x y ptchs)
]
]
report ptchs with [self != patch [pxcor] of myself [pycor] of myself]
end
Hope this helps,
Charles

Related

NetLogo: How to pull coordinates from neighboring patches based on patch-variable

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

Creating overlapping agents in a line

Using the below code I get agents are like this:
to setup
ask breadth-patches [sprout-walls wall-agents[set color 2]]
ask length-patches [sprout-walls wall-agents[set color 2]]
ask gap-patches [sprout-walls wall-agents[set color 2]]
ask length-patches[align-inside-at-top]
ask breadth-patches [align-inside-at-right-left]
ask gap-patches[align-inside-at-top]
end
to align-inside-at-top ;; patch procedure
let counter count walls-here ;; we will use this as a count-down, after using it in some calculations
if counter > 0 ;; could assume there are turtles, but we are not.
[ let gap1 1 / counter ;; size of turtles, gap between turtles
let half-gap gap1 / 2 ;; half-size of turtles
let ytop 0
if-else(pycor < 0)[set ytop pycor - .5 - half-gap]
[set ytop pycor + .5 - half-gap]
let xleft pxcor - .5 - half-gap
ask walls-here
[ set size gap1
set ycor ytop
set xcor xleft + gap1 * counter
set counter counter - 1 ;; so we're placing them from right to left
; set ycor ycor + 0.125
]
]
end
to align-inside-at-right-left ;; patch procedure
let counter count turtles-here ;; we will use this as a count-down, after using it in some calculations
if counter > 0 ;; could assume there are turtles, but we are not.
[ let gap1 1 / counter ;; size of turtles, gap between turtles
let half-gap gap1 / 2 ;; half-size of turtles
let ytop pycor + .5 + half-gap
let xleft 0
if-else (pxcor < 0)[
set xleft pxcor + .5 - half-gap]
[ set xleft pxcor - .5 + half-gap
]
ask turtles-here
[ set size gap1
set ycor ytop - gap1 * counter
set xcor xleft ;+ gap * counter
set counter counter - 1 ;; so we're placing them from right to left
]
]
end
Note: The gap in the rectangle is due to the following code
ask patches with [pxcor > (gap * (-1)) and pxcor < gap and pycor =(breadthrec - 1)][ask walls-here[die]]
Here, gap = 1 ,i.e, a width of 1 patch.
So the input parameter is the wall-agents which specifies the number of agents to created per patch along the length and breadth patches.
I wish to change to create overlapping agents as in the figure below(Sorry the figure is not so perfect, but I hope it explains it). Please help on how to achieve this.
This is a lot of code to ask anybody to debug for you.
I would suggest solving a simpler version of the problem first. Do you have code that can create wall-agents turtles in a single patch, evenly spaced along a line? Once you had a working code that did that, then you could attempt to generalize it to your more complex problem.
If you run into trouble writing that simpler version, you'll have a smaller question to ask here on Stack Overflow that will be much easier for someone to answer than your current, very large question.
If you are able to write the simpler version, don't throw it away — keep it, so you can go back to it if you need to. Then tackle the bigger problem.
You might even be able to take the simpler version, put it into a procedure, and then call that procedure from your larger solution. Making small procedures that work, and then calling those smaller procedures from other ones, is often a good way to break a problem down into manageable parts.

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.

Normal distribution for turtle at start

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.

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.