Shortest path between nodes in netlogo using nw extension - netlogo

I want to find the shortest path between two nodes - slocation and new-location - in a network of links
I have several slocation and new-location. One slocation for each citizen with some age, sex, and other characteristics, and one new-location for each node close to a work building.
I could identify these nodes with colors - see image.
However, I could not identify the shortest path between each slocation (for each citizen) and newlocation.
I got the following error: BUT-FIRST expected input to be a string or list but got the TRUE/FALSE false instead.
when I run these lines of code:
ask slocation
[set path but-first nw:turtles-on-weighted-path-to new-location weight]
Is this because I have several slocation and new-location?
should I introduce and foreach variable to calculate the shortest path for each citizen? I tried already only with one citizen and still this part of the code is not capable to find the path
I think the error is that the nodes slocation and new-location are not connected with a single link. The citizens have to select the shortest path created by links connecting these nodes to reach the new-location. Someone knows how to do this?
Here, it is my other part of the code:
breed [citizens citizen]
breed [nodes node]
links-own [weight]
to go
set-timekeeper
ask citizens
[find-day-activities]
end
to set-timekeeper
tick
if (counter = 2) [set timekeeper 2] ;From 7:00 AM to 9:00 AM
end
to find-day-activities
if (timekeeper = 2) [Do_7AM_9AM]
end
to Do_7AM_9AM
if (sex = 0 and age = 1 and employment = 0 and household-size = 0)
[shortest-distance]
end
to shortest-distance
let slocation min-one-of nodes [distance myself]
ask slocation [set color yellow]
let new-location one-of nodes with-min [distance one-of workbuildings]
ask new-location [set color blue]
ask links [set weight link-length]
let path nobody
ask slocation
[set path but-first nw:turtles-on-weighted-path-to new-location weight]
ask turtle-set path [ set color yellow ]
end
If there is any question about how I create the road network from a shapefile, this is the code:
to make-road-network
clear-links
let first-node nobody
let previous-node nobody
foreach gis:feature-list-of roads [ polyline ->
foreach gis:vertex-lists-of polyline [ segment ->
foreach segment [ coordinate ->
let location gis:location-of coordinate
if not empty? location [
create-nodes 1 [
set color green
set size 1
set xcor item 0 location
set ycor item 1 location
if first-node = nobody [
set first-node self
]
if previous-node != nobody [
create-link-with previous-node
]
set previous-node self
]
]
]
set previous-node nobody
]
]
ask links [set color red
set thickness 1]
end

Related

Netlogo Dijkstra algorithm

to-report find-path [ init final ]
ask init [set dist_d 0]
let current init
let p_dij []
set p_dij insert-item 0 p_dij current
show "dij"
while [not (current = final)]
[
ask [neighbors with [pcolor = yellow and not (dist_d = -1)]] of current [set dist_d min (list dist_d (1 + [dist_d] of current))]
ask current [set dist_d -1]
let min_d min [dist_d] of neighbors
set current one-of neighbors with [dist_d = min_d and pcolor = yellow]
set p_dij insert-item (length p_dij - 1) p_dij current
]
ask patches with [pcolor = yellow] [set plabel dist_d set plabel-color red]
report p_dij
end
I'm trying to find the shortest path using Dijkstra's algorithm. There is a problem with the neighbors, every time the program tries to find the next current node, it comes back to init.
This is not a direct answer to your question, and won't help you if you're trying to figure out how to code Dijkstra's algorithm as an exercise for yourself, but if you're just looking for a shortest path, you can always use the nw:path-to from the network extension.
That primitive is actually using Dijkstra's algorithm under the hood.
In order to use it, however, you need an actual network, so you would have to use turtles instead of patches. That's easy to do, however. Supposing you have a turtle breed called nodes, you can put a node on each patch by saying:
ask patches [
sprout-nodes 1 [
set color pcolor ; give the node the same color as the patch
set hidden? true ; hide the node if you prefer not seeing it
]
]
Then you can create links between, say, yellow nodes:
ask nodes with [ color = yellow ] [
create-links-with (nodes-on neighbors) with [ color = yellow ]
]
The path from one yellow node another is then just:
let yellow-nodes nodes with [ color = yellow ]
show [ nw:path-to one-of other yellow-nodes ] of one-of yellow-nodes
If all you want is the distance, you can use nw-distance-to instead.

How to assign the shortest-distance to all agents in NetLogo?

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

Netlogo, Moving Turtle along links

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

How to avoid turtles revisiting the patch on which they were last time?

Turtles stay on patches for 60 ticks, and then move to another target patch. How to avoid turtles revisiting the patch on which they were last time? Thanks
Hi Seth and Frank,
Thank you very much for your reply. I am sorry I did not describe the questions in detail.
Turtles will not visit the patch that they were on the last tick, and will move to another nearest patch instead in next tick. The following codes mean they find the nearest patch, and move on to it.
What I would want to do is the turtle will find the nearest patch again in the next tick. They will move to other alternative that is nearest to themselves, if the nearest patch is still the same one that they were on the last tick. Thanks
let closest-leaf min-one-of (patches in-radius 1 with [pcolor = lime]) [distance myself]
face closest-leaf
fd distance closest-leaf
A good way is to have a turtles-own variable of patches visited that can be maintained (remember to initialize it to the empty list when you create the turtle).
turtles-own [ patches-visited ]
to setup
...
ask turtles [ set patches-visited [] ]
...
end
to move
let potential-targets filter [ not member? ? patches-visited ] target-patches
let target-patch one-of potential-targets
if target-patch != NOBODY [
set patches-visited fput target-patch patches-visited
; move to target patch
]
end
Add a get-target reporter.
to-report get-target ;;turtle proc
let %close patches in-radius 1 with [pcolor = lime and self != [patch-here] of myself]
ifelse (any? %close) [
report min-one-of %close [distance myself]
] [
report nobody
]
end
Now you can easily change your mind about how to pick a target. You can then move to the target (if one exists).
to move ;; turtle proc
let %target get-target
ifelse (%target = nobody) [
;handle this case
] [
face %target move-to %target
]
end

On netlogo, what command do I use to make a turtle stop if the patch it wants to move to is a certain color

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.