I want to assign a generated autocorrelated variable (0 to 1) to turtles spread over a grid. I can create autocorrelated data in R and then import them into Netlogo, but for sure, there is a more efficient way to do it in Netlogo.
Here a simple example:
turtles-own [
variable
]
to setup
clear-all
create-turtles 30
[
move-to one-of patches with [ not any? turtles-here ]
; I would like to assign a spatially autocorrelated variable
; for now, I am using a uniform variable
set variable random-float 1.0
]
end
Here an example using R:
N <- 16 * 16
p <- 0.07
# generate some points
set.seed(1234)
x.coord <- rep(1:16, 16)
y.coord <- rep(1:16, each = 16)
points <- cbind(x.coord,y.coord)
# distance matrix between points
Dd <- as.matrix(dist(points))
# weights matrix
w <- exp(-p * Dd)
Ww <- chol(w)
# variable
z <- t(Ww) %*% rnorm(N,0,1)
z <- scale(z, center = min(z), scale = max(z) - min(z)) # rescale to 0-1 variable
# plot
require(ggplot2)
df <- data.frame(x = x.coord, y = y.coord, z = z)
ggplot(df, aes(x = x, y = y, col = z)) +
geom_point() +
scale_colour_gradient(low="red", high="white")
Because I get data for each patch, I can create variable from the patch in which turtles are. Anyway, this looks unnecessarily complicated.
Any ideas?
Probably not the best solution, but at least it is close. I use the k-means extension to generate clusters based on distances between turtles. Then, I assign a random number between 0 to 1 + some noise to the turtles of each cluster.
let clusters k-means:cluster-by-xy targets 10 100 0.1
(foreach clusters (n-values 10 [random-float 1.0])
[ ask ?1 [ set variable random-between ?2 0.15 ]] ) ]
random-between is a report:
to-report random-between [number width-interval]
let half-interval width-interval / 2
let random-number (number - half-interval) + random-float width-interval
if random-number < 0 [set random-number 0]
if random-number > 1 [set random-number 1]
report random-number
end
This is not really clear - I don't believe you mean autocorrelated because you haven't mentioned time at all. Based on your R-code, you want to have turtles at regular points (in which case you want to ask patches [ sprout 1 ] rather than create turtles) and for them to have a variable with a value based on its position, in which case you can write a function with xcor and ycor as inputs.
Related
I'm trying to help a student with a NetLogo homework. The gist of the homework is to load images, save the patch values to properties c1 c2 for each patch, set an alpha value 0.0 <= alpha <=1.0 and then set the patches to a linear combination of c1 and c2 under alpha.
This ought to be simple: all I want to do is code (this is pseudocode, I know this doesn't actually work) like:
to combine
ask patches [ set pcolor (c1 * alpha) + (c2 * alpha) ]
end
the problem being that c1,c2 are vectors, alpha is a scalar, and I can't figure out how to do vector multiply and vector addition in NetLogo.
Here's the code to set up a test case:
patches-own [ c1 c2]
to setup
ask patches [ set pcolor one-of [ red green blue] ]
end
to load-image
import-pcolors image
end
to set-one
ask patches [ set c1 pcolor ]
end
to set-two
ask patches [ set c2 pcolor ]
end
to return-c1
ask patches [ set pcolor c1 ]
end
I don't know what your various vectors (or lists really in NetLogo) and other numbers look like. But if the heart of the problem is that you want to multiply a 'vector' and scalar, here is a function that does so:
to-report mult-vec-num [ #vec #num ]
report map [ ii -> ii * #num] #vec
end
The map primitive is essentially an implicit foreach, with the arbitrarily named ii being used as an iterator through the provided list (named #vec) and multiplied by the provided scalar (named #num). Example use case:
show mult-vec-num [ 1 2 3 ] 5
UPDATE:
To add two lists together, again use the map primitive:
let l1 [1 2 3]
let l2 [4 5 6]
show (map + l1 l2)
I have to create a lot of turtles forming a compact group of any shape, a simple 10x100 rectangle is enough. The important thing is that they must be near each others.
In c i would do something like this:
for(x = 1; x <= rows; x++)
{
for(y = 1; y <= columns; y++)
{
create_turtle(x,y);
}
}
And the equivalent in netlogo would be:
crt 1000
let n 0
let x 1
let y 1
while[y <= 10]
[
set x 1
while[x <= 100]
[
ask turtle n
[move-to patch x y]
set x x + 1
set n n + 1
]
set y y + 1
]
But it's not an elegant solution. Any suggestion?
Edit: More precisely I have to reproduce what has been done in this article: http://science.sciencemag.org/content/345/6198/795.full
Every turtle is a little robot.
And here you can see one way turtles could be positioned turtles schema
I'm using circle turtles like the robots of the article.
One of the trickiest things for programmers from other languages to do when learning NetLogo is getting rid of all the loops. Iterating through the agents or patches is embedded in the ask primitive, you don't need to code the iteration. ask also iterates in a random order so that repeated processes don't lead to any advantage to whichever agent happens to be first in the loop.
Also, when you create turtles, you can immediately give them instructions. You can also place them initially in an arbitrary position rather than move them there. Here is one solution that places them all in a rectangle that is 5 patches to the left/right of centre (0,0) and occupies half the height of the world.
create-turtles 1000 [ setxy random-float 10 - 5 random-ycor * 0.5 ]
From the edit, I think you are wanting them to be created at gridpoints rather than randomly within the space. If that is true, then select the patches you want and ask them to sprout a turtle.
let in-shape patches with [ pxcor >= -10 and pxcor <= 10 and pycor >= -10 and pycor <= 10 ]
ask in-shape [ sprout 1 ]
You will need to work out your own values and make sure they are within the world dimension.
I have a very simple model of 50 turtles moving away from a central point. I would like to be able to extract the spatial coordinates (xcor, ycor) of a subset of them every nth tick in behaviour space. Hope you can help!
The modulo operator mod is probably the simplest way to do this. It outputs the remainder from a division operation, so you can just use a logical flag such that the coordinates are only extracted when ticks divided by n is equal to 0. For example:
to setup
ca
crt 10
reset-ticks
end
to go
; set up lists for example output
let tlist []
let xlist []
let ylist []
ask turtles [
rt random 60 - 30
fd 1
]
tick
; If ticks is not zero, and the remainder of
; the number of ticks / 3 is zero, extract
; some info about the turtles and print it.
if ticks > 0 and ticks mod 3 = 0 [
ask turtles with [ xcor > 0 ] [
set tlist lput self tlist
set xlist lput xcor xlist
set ylist lput ycor ylist
]
print tlist
print xlist
print ylist
]
end
Run this several times and you'll see that on tick 3 (and 6, 9, 12, etc), the lists are printed out. Note that where you have your tick increment will affect when this output is actually extracted- in the example above, tick happens at the end of the go procedure but before the if statement is evaluated.
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.
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.