How to assign the shortest-distance to all agents
Current status: My codes only finds the shortest-path for 1 person but cannot when there are more than 1 person.
Question: How can I assign the shortest-path for each person?
Background
I manipulated the traffic grid model inside the NetLogo model library to create a shortest-path algorithm for pedestrians (somewhat close to A*). The interface below shows that an agent is standing on its origin which is coloured in pale yellow, and has the same colour as a destination. It also works fine for 3 people.
1 person
3 people
Setup
Here is a code chunck that I wrote as a setup. It doesn't seem to have any problem in this section.
globals
[
grid-x-inc ;; the amount of patches in between two roads in the x direction
grid-y-inc ;; the amount of patches in between two roads in the y direction
intersections ;; agentset containing the patches that are intersections
roads ;; agentset containing the patches that are roads
population
]
breed[people person]
patches-own
[
father
navigated?
active?
Heuristic
step
total-cost
is-intersection?
start
finish
]
people-own
[
origin
destination
h-distance ;; short for heuristic distance. Euclidean distance to goal
path
]
to setup
clear-all
setup-globals
setup-patches
setup-people
setup-destination
reset-ticks
end
to setup-globals
set grid-x-inc world-width / grid-size-x
set grid-y-inc world-height / grid-size-y
ask patches
[
set father nobody
set navigated? false
set active? false
set total-cost 0
]
end
to setup-patches
;; initialize the patch-owned variables and color the patches to a base-color
ask patches [ set pcolor brown + 3 ]
;; initialize the global variables that hold patch agentsets
set roads patches with
[(floor((pxcor + max-pxcor - floor(grid-x-inc - 1)) mod grid-x-inc) = 0) or
(floor((pycor + max-pycor) mod grid-y-inc) = 0)]
set intersections roads with
[(floor((pxcor + max-pxcor - floor(grid-x-inc - 1)) mod grid-x-inc) = 0) and
(floor((pycor + max-pycor) mod grid-y-inc) = 0)]
ask roads [ set pcolor white ]
ask intersections [ set is-intersection? true
ask neighbors [ set is-intersection? true ]]
end
to setup-people
create-people no-of-people
[
set shape "person"
set size 1
set color black
move-to one-of patches with [pcolor != brown + 3]
set origin patch-here
set destination one-of patches with [pcolor != brown + 3 and is-intersection? != true]
set h-distance distance destination
]
set population [] ;; create list of individuals
let sort-turtles sort people set population sort-turtles
end
to setup-destination
foreach population [ individual ->
ask individual [
let roads_ roads with [pcolor = white]
ask roads_ [
set navigated? false
set active? false
set Heuristic 0
set step 0
set total-cost 0
set start false
set finish false
]]
let current [origin] of individual
let target [destination] of individual
ask individual [
if target != nobody [
ask current [
set pcolor (10 + random 130)
set step 0
set start true
set finish false
set navigated? false
]
ask target [
set pcolor [pcolor] of current
set navigated? true
set start false
set finish true
]]
]]
end
Problem 1: Set all paths
set-path traces all the steps from the origin patch to everywhere inside the virtual world. The code will colour the road to yellow and add a label on the path. This procedure will repeat 50 times to find all the possible steps.
The problem occurs from this section where this code only works for one agent not for the entire agents.
to set-path
repeat 50 [
ask patches with [pcolor = white and pcolor != yellow] [
if any? neighbors4 with [ start = true ] or
any? neighbors4 with [ pcolor = yellow ]
[ set pcolor yellow
let laststep [step] of one-of neighbors4 with [pcolor = yellow or
start = true]
ifelse [plabel] of patches != nobody [
set step laststep + 1
set plabel step
set father step
set total-cost father + heuristic
set plabel-color red][set plabel ""]
]]]
let allroads [self] of patches with [pcolor != brown]
let final_location one-of patches with [finish = true]
foreach allroads [ road_patch ->
ask road_patch [set Heuristic distance final_location]
]
end
Problem 2: Set shortest path
This procedure finds the shortest path by finding the patches and adding them to a list named path. Because the previous procedure only worked for one agent this procedure will also assign the patches to one agent, which is not what I want.
to shortest-path
ask patches with [start = true] [
let maxsteps 0
ask patches with [navigated? = true]
[ let check-steps min-one-of neighbors4 with
[pcolor != brown + 3 and pcolor != white][step]
set maxsteps [step] of check-steps
]
let num (range maxsteps 0 -1)
let paths []
foreach num [ navigation ->
ask patches with [navigated? = true] [
let nav-patch min-one-of neighbors4 with
[step = navigation and pcolor != brown + 3][step]
if nav-patch != nobody [ask nav-patch [set navigated? true set paths fput self paths]]
]]
ask people [set path paths]
]
ask patches with [pcolor = yellow][set pcolor white set plabel ""]
end
Summary: What I want the model to look like
How can I assign the shortest-path for each person if there are more than 2 people inside NetLogo?
What I want the model to look like
File: https://drive.google.com/file/d/1gxhkcnlBniB5M4aSYmt65PE6LBekgVp6/view?usp=sharing
Related
I am working on an infectious disease model, I've created a world with two regions. The specified number of people get initialized in their specific region.
Now, I need to initially infect the same number of people in each region with the disease using the initially_infected global variable. e.g 10 people infected in one region and 10 in the other region.
The infection should be indicated by changing color of turtles to red.
I've tried using "n-of" but it is not working correctly as want to restrict the initially infected people in their respective regions.
to setup_agents
create-humans green_population [
move-to one-of patches with [pcolor = green and not any? humans-here]
set shape "green person"
set color yellow
set size 1
set green_antibodies 0
]
ask n-of initially_infected humans [set color red]
create-humans blue_population [
move-to one-of patches with [pcolor = blue and not any? humans-here]
set shape "blue person"
set color yellow
set size 1
set blue_antibodies 0
]
ask n-of initially_infected humans [set color red]
end
Your code is not working because you are asking humans in general (by using ask n-of initially_infected humans [set color red]), and not based on where they are.
You can tackle this in a variety of pretty much equivalent ways. To do it in the tidies way, you should ask yourself what is the main programming feature that univocally differentiates these two groups: their shape? the color of the patche they are on? should they hold a turtles-own variable differentiating them? should they be separate breeds?
Whatever you choose this feature to be, use that feature in the ask n-of ... statement.
In the fully-reproducible example below, I just use the turtles' color as the distinguishing element:
breed [humans human]
globals [
green_population
blue_population
initially_infected
]
humans-own [
green_antibodies
starting_region
]
to setup
clear-all
ask patches [
ifelse (pxcor > 0)
[set pcolor green]
[set pcolor blue]
]
set green_population 300
set blue_population 270
set initially_infected 10
setup_agents
end
to setup_agents
create-humans green_population [
move-to one-of patches with [(pcolor = green) AND (not any? humans-here)]
set color green + 1
]
create-humans blue_population [
move-to one-of patches with [(pcolor = blue) AND (not any? humans-here)]
set color blue + 1
]
ask n-of initially_infected humans with [color = green + 1] [
set color red
]
ask n-of initially_infected humans with [color = blue + 1] [
set color red
]
end
Perhaps a more elegant option would be to create a little procedure that takes the populations' color and the quantity to infect as inputs. Modifying only the relevant part of the code, it would be:
to setup_agents
create-humans green_population [
move-to one-of patches with [(pcolor = green) AND (not any? humans-here)]
set color green + 1
]
create-humans blue_population [
move-to one-of patches with [(pcolor = blue) AND (not any? humans-here)]
set color blue + 1
]
infect-humans (green + 1) initially_infected
infect-humans (blue + 1) initially_infected
end
to infect-humans [hue quantity]
ask n-of quantity humans with [color = hue] [
set color red
]
end
In my example I used the humans' colors as distinguishing factor, but you can easily adapt this to any other thing you might want to use.
I am doing model where I want my agents to move along links between nodes. The idea is that all turtles move a constant distance after each tick. (Note I dont want them jump from one node to the another, also lets assume that its not possible to make the nodes at a constant distances, because I am trying to implement it on a gis model where of course the vertices are not at constant distances)
For this model there are two type of agents butterflies and collectors. Each of the agents placed on nodes which are linked to each other. The collectors find the closest butterfly to them using in-radius and then finds the path using nw: turtles-on-weight-path function. So for example lets suppose collector-02 has located butterfly-19. The path is [node-2 node-5 node-1 node-9]. I want the collector to travel to these nodes to get to the butterfly but instead of jumping to each node. He has to travel a distance of 0.01 netlogo units on the link from node-2 to node-5 and eventually node-9 where the butterfly is located.
The function follow-path is incomplete and it where i getting into trouble.
ANy ideas how to solve this problem. Thanks
extensions [nw]
globals [current-loc-global butterfly-location link-distance]
breed [nodes node]
breed [collectors collector]
breed [butterflys butterfly]
links-own [dist]
nodes-own [consist-butterfly linked-to]
collectors-own [ distance-from-location current-loc new-location targeted-
butterfly initial-node next-node current-node previous-node
node-butterfly-at commute-path route-length next-pos]
butterflys-own [ initial-node-collectors targeted? node-butterfly-on]
to setup
clear-all
;creating nodes
create-nodes 60[
set color blue
set shape "circle"
set consist-butterfly nobody
]
ask nodes [create-link-with one-of other nodes]
repeat 500[layout]
ask nodes [setxy 0.95 * xcor * 0.95 ycor]
create-butterflys number-of-butterflys[
set node-butterfly-on one-of nodes
set shape "butterfly"
move-to node-butterfly-on
set initial-node-collectors current-loc-global
set targeted? false
]
ask nodes [
set consist-butterfly min-one-of butterflys in-radius 0.0001 [distance
myself]
]
create-collectors number-of-collectors[
set current-loc one-of nodes with [consist-butterfly = nobody]
set color red
set targeted-butterfly nobody
move-to current-loc
]
ask collectors[
set current-loc-global current-loc
]
ask links [
let end-point-1 end1
let end-point-2 end2
set link-distance 0
ask end1[set linked-to end-point-2
set link-distance distance end-point-2
]
set dist link-distance
ask end2[
set linked-to end-point-1
]
]
reset-ticks
end
to layout
layout-spring nodes links 0.5 1 1
end
to go
find-agents
find-path
follow-path
end
to find-agents
ask collectors [
if targeted-butterfly = nobody[set targeted-butterfly min-one-of
butterflys in-radius 10 with [not targeted?] [distance myself]]
if targeted-butterfly != nobody [ask targeted-butterfly [set targeted?
true]]
]
ask collectors with [targeted-butterfly != nobody][
ask targeted-butterfly [set butterfly-location node-butterfly-on]
set node-butterfly-at butterfly-location
]
end
to find-path
ask collectors with [targeted-butterfly != nobody ][
set initial-node min-one-of nodes in-radius 0.0001 [distance myself]
let end-location node-butterfly-at
let path []
ask initial-node [set path nw:turtles-on-weighted-path-to end-location
dist]
set commute-path path
set route-length length commute-path
set current-node initial-node
set previous-node current-node
set next-node current-node
]
end
to follow-path
ask collectors with [targeted-butterfly != nobody][
set distance-from-location distance current-node
ifelse 0.09 < distance-from-location
[jump 0.09]
[move-to current-node
set current-node next-node
face next-node]
]
end
Managed to sort it out. Need to change the follow-path function as follows:
to follow-path
ask collectors with [targeted-butterfly != nobody][
set distance-from-location distance current-node
set next-pos ((position(current-node) commute-path) + 1)
if next-pos < route-length [set next-node item(next-pos) commute-path]
ifelse 0.09 < distance-from-location
[jump 0.09]
[move-to current-node
set current-node next-node
face next-node]
]
end
I'm modeling territory selection in NetLogo, where turtles pick a territory center ("start-patch") and then build a territory out from there based on value of patches. Turtles always return to the start-patch after claiming a new patch, then choose, move to, and claim the next most valuable patch. After choosing a territory, the turtle knows which patches it owns, and patches know their owner.
Ultimately, the start-patch of a territory may not actually end up being the true geographic center. After a turtle has selected its territory, how might I ask it to evaluate the territory, identify the geographic center, and calculate proximity of the start-patch to the true center of the territory? (Note: I don't want to force turtles to keep the start-patch in the geographic center--they are free to choose any patches they want. But I may force turtles to re-select a territory if there isn't a close match--these territories are not very efficient otherwise.)
Here's an example of how territory start-patches (black stars) do not equal geographic centers. Some example code is below. Any suggestions? Thanks in advance!
patches-own [
benefit ;; ranges 0.1-1 and represents food available in the patch
owner ] ;; patches are owned once selected for a territory
turtles-own [
start-patch ;; the selected center of the territory
sum-value ;; sum of values of patches in my territory
territory-list ;; list of patches I've selected
territory ;; agentset of patches I've selected
established ] ;; true/false, true when has settled in a final territory after assessing geographic center
globals [threshold = 25]
to setup
ask patches [ set owner nobody ]
end
to go
ask turtles [
pick-center
build-territory]
tick
end
to pick-center
if start-patch = 0
[move-to best-center ;; (calculated by a reporter elsewhere as moving windows for a cluster of high-benefit patches)
set start-patch patch-here
set owner self
set territory-list (list patch-here)
set territory (patches with [owner = myself])
]
to build-territory
ifelse sum-value < threshold
[ pick-patch ] ;; keeps picking patches for territory until I've met my threshold
[ assess-geographic-center] ;; once met threshold, assess real center of patch-set
end
to pick-patch
let _destination highest-value ;; (this is calculated by reporters elsewhere based on benefit / travel costs to a patch)
face _destination forward 1
if patch-here = _destination
[ claim-patch _destination ]
end
to claim-patch [_patch]
ask _patch [set owner myself]
set sum-value sum-value + (benefit / (distance start-patch))
set territory-list lput patch-here territory-list
set territory (patch-set territory _patch)
move-to start-patch
end
to assess-geographic-center
;; Once the territory is built, the turtle should identify the actual
;; geographic center of the patch-set it has selected...how to do this?
;; Once it knows the center, the turtle should compare the distance to the original start-patch.
;; If >10 patches away, it will move to that start-patch and start over with selecting a territory....
end
Could you get away with just the mean pxcor and pycor of all patches? Something like:
to setup
ca
reset-ticks
let n 70
ask one-of patches [
set pcolor red
]
while [ ( count patches with [pcolor = red ] ) < n ] [
ask one-of patches with [ pcolor = red ] [
ask one-of neighbors4 [set pcolor red ]
]
]
let xmean mean [pxcor] of patches with [ pcolor = red ]
print xmean
let ymean mean [pycor] of patches with [ pcolor = red ]
print ymean
ask patch xmean ymean [ set pcolor blue
]
end
Following the previous answer, here is what I came up with. This goes in the last procedure in my original code:
to assess-geographic-center
let xmean mean [pxcor] of patches with [ owner = myself ]
let ymean mean [pycor] of patches with [ owner = myself ]
ask patch xmean ymean [ set pcolor black ] ;; make the geographic center visible
let geographic-center patch xmean ymean
let distance-away distance geographic-center ;; the turtle is on its start-patch when assessing this distance
ifelse distance-away <= 5
[ set established true ] ;; turtle is happy if start-patch and geographic-center are approximately equal, territory "established"
[ move-to geographic-center ;; otherwise, turtle moves to geographic-center,
reposition ] ;; and follows a procedure "reposition" to makes this the new start-patch and repick the territory
end
I am working on a project in netLogo in which i have a random network in which each and every link is assigned a bandwidth. The algorithm chooses a random Source and Destination by itself and after which it has to choose an optimal path between these two.
My question is how to choose the optimal path by exploring all the possible paths.
hereby attaching the sourcecode of my model:
breed[nodes node]
breed[ants ant ]
globals [nodename nodenumbersource nodenumberdestination relaynode dead-network num ]
nodes-own[visited ]
links-own[visit bandwidth]
ants-own
[
distance-gone
distance-to-go
target-node
current-node
]
to cr11
ask nodes with [label = "Source"]
[
set num count (link-neighbors)
]
create-ants num ;num-ants
[
let n one-of nodes with [label = "Source"]
setxy ([xcor] of n) ([ycor]of n)
set current-node n
set color white set size 0.95
set distance-gone 0
set distance-to-go 0
set target-node one-of nodes with [ label = "Relay Node" ] ;nobody
]
end
to face-targets
ask ants ;with [ target-node]; = node 4 ] ;nobody ]
[
let d 0
face (one-of nodes with [ label = "Relay Node" ]);target-node
ask current-node [
set d distance (one-of nodes with [ label = "Relay Node" ]);target-node)
]
set distance-to-go d
]
end
to move-forward
face-targets
ask ants [
while [ distance-gone < (distance-to-go )]
[
fd 1
set distance-gone (distance-gone + 1)
]
]
ask ants [
if distance-gone < distance-to-go
[
set current-node target-node
setxy ([xcor] of current-node) ([ycor] of current-node)
set distance-gone 0
set distance-to-go 0
]
]
end
;This is used to design the Network
to setup
setup1
setup-spatially-clustered-network
ask links [set color white
set visit false
set bandwidth (5 + random 10) ;min bw 5 max 15
]
end
to setup1
__clear-all-and-reset-ticks
set dead-network 0
create-nodes number-of-nodes
[
setxy (random-xcor * 0.95) (random-ycor * 0.95)
set shape "circle"
set color green
set visited false
set label who
]
end
;Links are created for the nodes
to setup-spatially-clustered-network
let num-links (6 * number-of-nodes) / 2
while [count links < num-links ]
[
ask one-of turtles
[
let choice (min-one-of (other turtles with [not link-neighbor? myself])
[distance myself])
if choice != nobody [ create-link-with choice
]
]
]
repeat 10
[
layout-spring turtles links 0.3 (world-width / (sqrt number-of-nodes)) 1
]
end
;This is to Generate Message for nodes
to test1
ask one-of nodes
[
set color red
set label "Source"
set nodenumbersource who
]
ask one-of nodes with [color = green]
[
set color red
set label "Destination"
set nodenumberdestination who
]
cr11
end
to test3
ask turtles with [label = "Source"]
[
set label "ants moving"
ask my-links
[
set color green
]
ask link-neighbors
[
set color blue
]
ask min-one-of turtles with [color = blue and my-links] [distance turtle nodenumberdestination ]
[
ask max-one-of my-links [bandwidth ]
[
set color red
]
set color white
set relaynode who
set label "Relay Node"
]
; face-targets
move-forward
end
to test4
ask turtle nodenumberdestination
[
while [color != white]
[
ask turtle relaynode
[
set label ""
ask my-links
[
set color green
]
ask link-neighbors
[
set color yellow
]
]
ask turtles with [color = yellow]
[
set color violet
]
ask turtles with [color = violet] with [visited = false]
[
set color magenta
]
ask min-one-of turtles with [color = magenta] [distance turtle nodenumberdestination]
[
set color white
set relaynode who
set label "Relay Node"
set visited true
]
move-forward
]
]
end
to test6
ask nodes ; turtles
[
set color green
set visited false
set label ""
]
ask links
[
set color white
set visit false
]
end
to test5
test1
test3
test4
end
You can use the NW-Extension for that! Just download it and stick it in NetLogo's extensions folder. Then, in your model, you can start using by adding
extensions [ nw ]
to the top of your code. Then you can use one of the weighted-path-to primitives to get the turtles or links along the shortest path between two nodes.
Note that the nw extension is under active development, though it is well tested. You also must be using the latest version of NetLogo.
If you want to implement it yourself, Dijkstra's algorithm is the classic solution if you have nonnegative weights in your graph.
I'm making a maze on netlogo and I want to do it so that once it tries to walk into the violet lines, it'll stay on its own patch instead of moving forward. What command would that be? I tried bk 1 to reverse the fd 1 but it doesn't work all the time
You can undo your step like this:
ask turtles [
fd 1
if pcolor = violet [fd -1]
]
Or you can check ahead of time as Marzy answered. Basically it's the difference of asking for forgiveness vs permission :-)
I hope this example answer your questions:
turtles-own [target]
to setup
clear-all
reset-ticks
ask n-of 100 patches [
set pcolor red
]
create-turtles 1
[ move-to one-of patches with [pcolor != red]
set heading 90
set target one-of patches with [pcolor != red]
ask target
[
set pcolor green
]
]
end
to go
ask turtles
[ifelse pcolor != green
[
ifelse [pcolor] of patch-ahead 1 != red
[
Your-Move-Function
]
[
Your-Bounce-Function
]
leave-a-trail
]
[stop
print ticks
]
]
tick
end
to Your-Move-Function
let t target
face min-one-of all-possible-moves [distance t]
fd 1
end
to Your-Bounce-Function
let t target
face min-one-of all-possible-moves [distance t]
end
to-report all-possible-moves
report patches in-radius 1 with [pcolor != red and distance myself <= 1 and distance myself > 0 and plabel = "" ]
end
to leave-a-trail
ask patch-here [set plabel ticks]
end
This is how it works:
Random patches are colored Red to show walls or obstacles, one turtle is created in a random location with a random target which is colored green:
I have used a variable to store all available patches which turtle can step on , but since I have considered a target for the turtle, turtle chooses the one patch which is closest to the target, and since I have noticed in some cases it might go in circle I have asked the turtle to leave tick number which is its move number as a plabel, you can use a variable for that for specifying if that path was already selected or not.