I am working with NetLogo code written with somebody else (freely available to public). I try to understand how the procedure of turtle moving is elaborated and, most important - how make it computationally faster without loosing sensitivity of turtle movement in relation to worlds' patches?
I suppose that the most of the calculation time is used to calculate the distance of each step of turtle movement - I would like to measure only one variable from patch of turtle's origins to last patch where it will stay.
I have decoded some of features but I am still not able to reproduce them. I'll really appreciate any help !
My understanding what the procedure could accomplish:
to move-turtles
ifelse perceptdist = 0
[ifelse patch-ahead 1 != nobody
[rt random moveangle lt random moveangle
let xcorhere [pxcor] of patch-here
let ycorhere [pycor] of patch-here
fd 1
let xcornext [pxcor] of patch-here
let ycornext [pycor] of patch-here
set dist sqrt (xcor * xcor + ycor * ycor)
set t_dispers (t_dispers + 1)
set energy (energy - (1 / efficiency))
let flightdistnow sqrt ((xcornext - xcorhere) * (xcornext - xcorhere) + (ycornext - ycorhere) * (ycornext - ycorhere))
set flightdist (flightdist + flightdistnow)
][]]
[let np patches in-radius perceptdist ; find the patch with the highest totalattract value within perception range
let bnp max-one-of np [totalattract]
let ah [totalattract] of patch-here
let xcorhere [pxcor] of patch-here
let ycorhere [pycor] of patch-here
let abnp [totalattract] of bnp
; -- why this ifelse condition is here ansd why they use these numbers?? ---
ifelse abnp - ah > 2 and random-float 1 < 0.1
[move-to bnp ; move to the patch with the highest attractivity value
let xbnp [pxcor] of bnp
let ybnp [pycor] of bnp
let flightdistnow sqrt ((xbnp - xcorhere) * (xbnp - xcorhere) + (ybnp - ycorhere) * (ybnp - ycorhere))
set t_dispers (t_dispers + flightdistnow)
set energy (energy - (flightdistnow / efficiency)) ; how the turtle decision to stay/move further is made - ratio of turtle energy/efficiency
set flightdist (flightdist + flightdistnow)
set dist sqrt (xcor * xcor + ycor * ycor)
[rt random moveangle lt random moveangle
set dist sqrt (xcor * xcor + ycor * ycor)
set t_dispers (t_dispers + 1)
set energy (energy - (1 / efficiency))
let xcorhere2 [pxcor] of patch-here
let ycorhere2 [pycor] of patch-here
fd 1
let xcornext2 [pxcor] of patch-here
let ycornext2[pycor] of patch-here
set dist sqrt (xcor * xcor + ycor * ycor)
let flightdistnow sqrt ((xcornext2 - xcorhere2) * (xcornext2 - xcorhere2) + (ycornext2 - ycorhere2) * (ycornext2 - ycorhere2))
set flightdist (flightdist + flightdistnow)
end
Related
I am trying to simulate an F1 race where the cars go around different tracks and need to pit when their tyres have degraded enough. They stick to the patches that are the track color (black). I have the code where I get the cars to follow the track shown below:
breed[cars car]
cars-own[tyre-level
tyre-type
tyre-total
speed
maxSpeed
draftSpeed
speed
]
;part of the setup
create-cars num-cars [
setxy xcord ycord
set shape "car top"
set size 5
set heading head
set tyre-level one-of (list soft_tyre_durability medium_tyre_durability hard_tyre_durability)
if tyre-level = soft_tyre_durability [set tyre-type "Soft"]
if tyre-level = medium_tyre_durability [set tyre-type "Medium"]
if tyre-level = hard_tyre_durability [set tyre-type "Hard"]
if tyre-level = soft_tyre_durability [set tyre-total soft_tyre_durability]
if tyre-level = medium_tyre_durability [set tyre-total medium_tyre_durability]
if tyre-level = hard_tyre_durability [set tyre-total hard_tyre_durability]
set maxSpeed 30
set draftSpeed 50
]
end
to move ;; turtle procedure
ask cars [face-chosen-neighbor
fd 0.5
set tyre-level tyre-level - 0.01]
end
to face-chosen-neighbor ;; turtle procedure
;; turtle faces the patch that requires the least change in
;; heading to face
let closest-border-patch min-one-of different-colored-neighbors [abs turn-amount]
rt [turn-amount * track-help] of closest-border-patch
end
;; computes the turn the calling turtle would have to make to face this patch
to-report turn-amount ;; patch procedure
let this-patch self
report [subtract-headings (towards this-patch) heading] of myself
end
to-report different-colored-neighbors ;; patch procedure
;; report neighbors that are a different color than me
report neighbors in-cone 2 180 with [pcolor = [pcolor] of myself] ;; report patches or neighbors in cone
end
This runs okay. However I now change the move procedure and add a speed procedure for the accelerating and decelerating - they slow down on turns and speed up if they aren't. They also have an increased max speed if drafting another car.
to move ;; turtle procedure
ask cars [face-chosen-neighbor
control-speed
fd speed / 200
set tyre-level tyre-level - 0.01]
end
to control-speed
let drafting any? other cars in-cone 4 130
ifelse drafting = nobody [set maxSpeed maxSpeed * ( (tyre-level + 50 ) / tyre-total)] [set maxSpeed draftSpeed * ( (tyre-level + 50 ) / tyre-total)]
if turn-amount * track-help > 60 [set speed speed - (deceleration * turn-amount * 0.5)]
let car-ahead any? other cars in-cone 1 130
ifelse car-ahead = nobody [
ifelse speed < maxSpeed [set speed speed + acceleration] [set speed speed - deceleration]
]
[
ifelse [speed] of car-ahead >= maxSpeed [
set speed maxSpeed
set speed speed - deceleration
] [
;try to overtake
ifelse [pcolor] of patch-left-and-ahead 90 1 = [pcolor] of myself and not any? turtles-on patch-left-and-ahead 90 1
[move-to patch-left-and-ahead 90 1] [
ifelse [pcolor] of patch-right-and-ahead 90 1 = [pcolor] of myself and not any? turtles-on patch-right-and-ahead 90 1
[move-to patch-right-and-ahead 90 1] [
set speed [speed] of car-ahead
set speed speed - deceleration]
]
]
]
end
Now if I run this, I get the error "There is no agent for MYSELF to refer to". I assume its got to do with the different definitions of self and myself. I have tried my best to understand it all and have scoured the forums. I'm not sure if I still understand it correctly.
Any help will be greatly appreciated!
I suspect that the error occurs in the lines where you look at the [pcolor] of myself. self and myself can be confusing. Here you have asked cars to look at the color of the patches that they are on, so it is self that you want. Agents can directly determine the color of the patch they are on, in a sense, the patch's pcolor is one of the agent's built-in variables, like its own color, so in fact, you could just ask the car to look at pcolor. Since an agent, in this case a car, can be on only one patch at a time, there is no confusion as to which patch is being referred to. Equivalently, you could use [pcolor] of patch-here.
myself would be used if the car asked the patch to then look at one of the car's variables. E.g., if the car asked the patch to do something with the tyre-type of the car who asked, it would be [tyre-type] of myself.
Currently, I have a model with many parameters in it, and one of them is having male yearling deer disperse according to certain criteria. The distance each male yearling disperses is pulled from a log-normal distribution. Here is what I have so far:
to move-dispersing-maleyearlings
ask maleyearlings [
let chance-disperse random-float 1.001
if chance-disperse < .62 [ ;;average dispersal rates in Long et. al paper
let mu 7.5
let sigma 6.1
let beta ln (1 + (sigma * sigma) / (mu * mu))
let S (sqrt beta)
let M (ln mu) - (beta / 2)
let new-distance exp (random-normal M S)
while [any? other turtles-here and dispersal-distance < new-distance]
[right random 360
fd 1
set dispersal-distance dispersal-distance + 1]]]
end
So this code should have 62% of the male yearling deer disperse, and they'll disperse a distance of "new-distance". If I am understanding my while loop correctly, they will move until they reach their "new-distance" and until they land on an unoccupied patch.
But now instead what I want to do is have each male yearling deer disperse their respective "new-distance", but if they land on a patch that is occupied, I want them to then move to the nearest unoccupied patch. If the patch they land on after moving "new-distance" is unoccupied, then they would stay on that patch.
Any ideas of how to do this? Thanks for your help!
If I am understanding your request correctly, you want to replace:
while [any? other turtles-here and dispersal-distance < new-distance]
[right random 360
fd 1
set dispersal-distance dispersal-distance + 1]]]
with code that moves to the closest empty patch. Try something like this (not tested):
if any? other turtles-here
[ move-to min-one-of (patches with [not any? turtles-here]) [distance myself]
I have a model in which a population is normally distributed across the patches. I used the following code to do that:
ask patches [
let x1 (pxcor - mean1) / sd-pop1
let y1 (pycor - mean2) / sd-pop1
set popualation ( (pop1) * exp (-0.5 * ( x1 ^ 2 + y1 ^ 2)) / (2 * pi * sd-pop1 ^ 2))
]
I want to distribute 10 turtles in a similar manner. In the attached image just as how the major chunk of the population is distributed across the patches close to the center of the grid space. Similarly of the 10 turtles to be created, i want a major chunk to be randomly spread across the population rich patches and a few which are spread on the periphery.
to setup-parties
create-parties Num-of-parties
let sp sqrt((((sd-pop1 ^ 2) * (pop1 - 1)) + ((sd-pop2 ^ 2) * (pop2 - 1))) / (pop1 + pop2 - 2))
ask parties [
ifelse (pop2 > 0) [ set heading random-float 360 jump random-float sp ] [ set heading random-float 360 jump random-float sd-pop1 ]
set size 3
set color random 130
set label who + 1
set label-color red
set my-old-size 1
set shape "default"
set old-x xcor
set old-y ycor
update-rule
]
end
I would use the rnd extension for this and select 10 patches (weighted by population) to sprout a turtle. Something like ask rnd:weighted-n-of 10 patches [ population ] [ sprout 1 ]. You will also need extensions [rnd] at the top of your code if you use this method.
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.
How do I implement a line of sight in NetLogo whereby
A turtle calculates/counts all turtles between it and the a given patch on the line of sight.
Thanks.
Let's say that each turtle has a turtles-own called target, which is the given patch, you can ask each turtle to face the target patch and count all the turtles between it and the given patch:
ask turtles [
face target
let n 1
let c 0
while [patch-ahead (n - 1) != target][
ask patch-ahead n [
if any? turtles-here [set c (c + 1)]
]
set n (n + 1)
]
print (word who " has " c " turtles on the line of sight")
]
A while loop doesn't look very clean in NetLogo but it works.
See Line of Sight Example, in the Code Examples section of NetLogo's Models Library.
Very similar to Dr_stein
To-report count-turtles-on-line-to[target]
Let c 0
Let d distance target
Face target
While d > 0
[
Let c c + count turtles-on patch-ahead d
Let d d - 1
]
Report c
End
I would suggest using the patches-ahead reporter from this answer:
to-report patches-ahead [ dist step ]
report patch-set map patch-ahead n-values (dist / step) [ step + ? * step ]
end
You can use it like this:
to setup
clear-all
create-turtles 100 [ setxy random-xcor random-ycor ]
ask turtles [
let target one-of patches
face target
show (word
count other turtles-on patches-ahead distance target 0.1
" turtles between me and " target)
]
end