What is the most appropriate way to include randomness in the movement - NetLogo - netlogo

First, let me describe what I am doing and why I am asking this question.
I have 74 cities included in the model and I want to simulate movement between them. I have an OD probability matrix where rows are origins and columns are destinations. Matrix looks like this:
0 1 ..... 73
----------------------
0 |0.5 0.1 .... 0.0
...| . . .. . .
73 | 0.1 0.2 .. 0.3
Please note: if we look at the first row, that means that an agent from the city with index 0 has the probability to stay in it 0.5, to move to the city with idx=1 0.1 and so on.. What I want to do is to on the best statistically speaking way distribute agents' destination. For the agents which origin is city 0 I want to stay approximately 50% of agents (not exact 50%), but also I want to give some chance to the cities that have 0% probability, like pair 0-73.
I already coded the randomness according to the answer to this question: Netlogo: How can send agents from "area x" to "area y" using an O/D matrix?
But the answer for me in this question is not logical, concretely this part:
ask turtles with [residency = "nw"]
[ let myrandom random-float 1
ifelse myrandom <= 0.5 [ set destination "nw" ] [
ifelse myrandom <= 0.8 [ set destination "ne" ] [
ifelse myrandom <= 0.0 [ set destination "sw" ] [
set destination "se" ]]]
If I understood well, myrandom would take a value in the range 0-1 and then it would go to check one by one condition whether its' value is smaller or equal than this constant values.
In that sense, myrandom wound never get to the "sw" part (0 would always be smaller than 0.5) and there is more chance to get the "nw" part where probability is 0.5 than the "ne" part where the probability is higher-0.8. And only because it's not listed first. I am no sure that this is the right way to go, and also I am not sure which is (I can't sort my probabilities because their position represents city-id(see below)). Or I understood wrong?
Here is presented the part of my code. I imported the matrix without the headings/cities ID because they are equivalent to NetLogo indexing. The cities with ID are already imported into the model. Also, in each point/city I created the corresponding number of agents that I read for each city from the CSV file. During the creation of the agents, I use the row from the matrix that corresponds to the current city/origin and go through the probabilities as JenB did in his answer above.
breed [city cities]
breed [inhabitant inhabitants]
;; part of the setup
;; open the csv file that contains population per city
file-open path
while [ not file-at-end? ] [
let data csv:from-row file-read-line
let city-id item 0 data
let population item 1 data
to add-inhabitants
create-inhabitants population [
set city-home one-of cities with [id = city-id] ;; set the origin
move-to city-home
set-destination(city-id) ;; for this origin chose the destination
]
]
to set-destination [row] ;; row from the matrix which represent the movement from the current city/origin to other cities
let row-probabilities matrix:get-row od-matrix row ;; use the row that correspondents to the city
let random-value random-float 1
let i 0 ;; index counter
foreach row-probabilities [ ;; for each probability in row
p ->
if random-value <= p ;; this part is coded as in the JenB's answer
[
set destination one-of cities with [id = i] ;; i is column index which is actually index of destination city
stop ;; if you set city -> stop
]
if i = 73 [set destination one-of cities with [id = i]
stop] ;; the last city -> there is no more option/reason to check
set i i + 1
]
end
I know it's a little bit longer, but I wanted to explain clearly. Some guidelines and explanations would be much appreciated!

Your question suggests that you don't understand what the code in that section is doing. This is the corrected code for that bit:
ask turtles with [residency = "nw"]
[ let myrandom random-float 1
ifelse myrandom <= 0.5 [ set destination "nw" ] [
ifelse myrandom <= 0.8 [ set destination "ne" ] [
ifelse myrandom <= 0.9 [ set destination "sw" ] [
set destination "se" ]]]
Yes, the first line in the block draws a random number in the range 0 to 1. Imagine that the draw gave 0.4. Then the first ifelse would be true and the destination would be set to "nw". Now imagine the draw was 0.6, then the first ifelse would be false and the code would go on to test the else part, which is true because 0.6 <= 0.8.
The code works because the initial draw is uniform. That is, 10% of the time (on average) it returns a number in the range 0 to 0.1, and 10% in the range 0.1 to 0.2 and so on. So 50% of the time it returns a number in the range 0 to 0.5, which returns true for the first line. 30% of the time it returns a number in the range 0.5 to 0.8, which is false for the first test and true for the second test. 10% of the time it returns a number in the range 0.8 to 0.9 and 10% of the time it returns a number in the range 0.9 to 1.
So breaking the interval with check points at 0.5, 0.8, 0.9 (and 1 for the remainder) gives you sections that are 0.5, 0.3 (=0.8-0.5), 0.1 (=0.9-0.8) and 0.1 (=1=0.9) in length. And a uniform random number will fall into those sections with probability distribution 50%, 30%, 10% and 10% of the draws.

Related

calculate the total move distance of one turtle

I am new to Netlogo and learning a model is about animals moving around to eat grass based on the grazing model from NetLogo. The moving behavior is based on the biomass's richness, so it is not just impacting at right angles.
Given the conditions, I don't know how to add a monitor in my model that calculates the total distance a turtle moved by traveling each pixel.
Move specifically, I wonder if there is a way to calculate the total length of the pen-marked lines. (Show in the picture)
enter image description here
The basic setting of move is
to move-turtles
uphill-biomass
forward 1
set distance-traveled (distance-traveled + 1)
if not can-move? 1 [ rt random 150 ]
end
to uphill-biomass
let biomass-ahead biomass-scent-at-angle 0
let biomass-right biomass-scent-at-angle 35
let biomass-left biomass-scent-at-angle -35
if (biomass-right = biomass-ahead) and (biomass-left = biomass-ahead) [ wiggle ]
if (biomass-right > biomass-ahead) or (biomass-left > biomass-ahead)
[ ifelse biomass-right > biomass-left
[ rt 35 ]
[ lt 35 ] ]
end
Thank you very much for any helps!
You need to use some turtle variables with the turtles-own primitive and do the distance calculation by hand.
The easiest way to do such a calculation is to save the coordinates between a turtle's previous coordinates with turtle variables and then use the distancexy primitive (link for dictionary entry: https://ccl.northwestern.edu/netlogo/docs/dictionary.html#distancexy)
Here's a simple implementation:
turtles-own [last-x last-y distance-traveled]
move-turtle
uphill-biomass
set last-x xcor
set last-y ycor
forward 1
set distance-traveled (distance-traveled + (distancexy last-x last-y))
if not can-move? 1 [ rt random 150 ]
end
I hope this answers your question.

Create 1000 turtles near each others

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.

Multiple statements in ask

Is is allowed to use multiple statements in an ask command. I ask this because my agents do not count their lost variable in a correct way. Slider-s is zero and slider is 10.
[ ask smaller [ set heading [ heading ] of larger forward 0.05 set lost lost + 1 set lostcount lostcount + 1 set color [color] of larger
if random 100 < slider-s [ if lost > random 100 [ set heading random 360 set lost 0 set color random-float 100]]]]
[ if random 100 < slider
[ ask larger [ set heading [ heading ] of smaller forward 0.05 set lost lost + 1 set lostcount lostcount + 1 set color [color] of smaller
if random 100 < slider-s [ if lost > random 100 [ set heading random 360 set lost 0 set color random-float 100]]]]]
yes, it is valid to have multiple commands within an ask block. It is also valid to have multiple statements on a single row (though somewhat unreadable). If it wasn't valid, the green tick syntax checker would throw a yellow highlighted error message.
<whatever is the line before - presumably ask some agentset>
[ ask smaller
[ set heading [ heading ] of larger
forward 0.05
set lost lost + 1
set lostcount lostcount + 1
set color [color] of larger
if random 100 < slider-s
[ if lost > random 100
[ set heading random 360
set lost 0
set color random-float 100
]
]
]
]
[ if random 100 < slider
...
]
]
If you use indenting as above, your code takes more lines but it is easier to pick up some types of errors. In particular, is it possible that your code is miscounting the lost variable because the bracketing is incorrect and some agents are passing through these nested loops an incorrect number of times?

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

How do I properly use the 'random' function for multiple agents?

In my model I have some agents collecting from another agent who they bump into at random after which they move back to their base. As they move back they drop off some material as defined by the random function. Here's some sample code
to go
ask searchers
[ set energy energy - 1
fd 0.0125
if random-float 1 < (1 / 50)
[ ifelse random 2 = 0
[ rt 45 ]
[ lt 45 ]
]
search
]
end
to search
if any? depots in-radius vision with [color = yellow]
[spread
set energy 0] ;; makes them to back to base
end
to spread
if random 10000 = 1 [hatch-rubbish 1 [ set color white
set shape "circle"
set size 0.5]]
end
If I set the visual radius to something enormous so they can always see the depot the number of bits of rubbish works out.
However if I allow them to move around with a radius of 1, the count of rubbish is much higher than 1 in 10,000.
Why would that make a difference?
Thanks