NetLogo nw extension: how to save the links reported by `nw:weighted-path-to`? - netlogo

I want to save the links of the shortest path between the source and destination , so thagt i can change their color to red ie the links' color. But theres is no primitive to save the links
the code is:
ask nodes with [label = "Source" ]
[
show nw:weighted-path-to turtle nodenumberdestination "bandwidth"
]
can somebody tell me how to save the links reported by the nw primitive used above, so as to change their color to red in the graph?

I'm not entirely sure what you mean by saving the links, but you can store the list of links in a variable. So, if you have a turtles-own variable path-to-destination, you can just do
ask nodes with [label = "Source" ] [
set path-to-destination nw:weighted-path-to turtle nodenumberdestination "bandwidth"
]
Alternatively, you can just store the list of links in a local variable if you don't need to do anything with them later:
ask nodes with [label = "Source" ] [
let path-to-destination nw:weighted-path-to turtle nodenumberdestination "bandwidth"
]
As for turning them red, nw:weighted-path-to returns a list of links, so we can just loop through that list ask each to become red. Extending the previous code, that looks like:
ask nodes with [label = "Source" ] [
let path-to-destination nw:weighted-path-to turtle nodenumberdestination "bandwidth"
foreach path-to-destination [ ask ? [ set color red ] ]
]

Related

Get color of global variables with netlogo

I am trying to get the real color of my global variable.
Here my code:
breed [players player]
globals [
INITIAL-POSSESSION ;
]
to setup
clear-all
reset-ticks
set-initial-possession
end
to go
ticks
ask players [
decision
]
end
to-report initial-possession
report random 2
end
to set-initial-possession
ifelse initial-possession = 1
[
set INITIAL-POSSESSION black]
[
set INITIAL-POSSESSION white]
end
to decision
if ([color] of INITIAL-POSSESSION) = black
[] ;;do something
if ([color] of INITIAL-POSSESSION) = white
[];;do something
end
But I get this error:
OF expected input to be a turtle agentset or link agentset or turtle
or link but got the number 0 instead.
So I change it with (and it works):
to decision
if INITIAL-POSSESSION = 0
[]
if INITIAL-POSSESSION = 9.9
[]
end
But there is any other way to do that? (I am using netlogo 6.0)
I think there may be some code missing so I can't confirm, but it looks like you may not have set BALL-OWNER up as a turtle or patch, and instead assigned a value directly to that variable. of queries a variable from an agent (or a list of variables from an agentset), so if BALL-OWNER is set to a value, NetLogo gets confused. If you do assign an agent to BALL-OWNER, however, your approach should work fine. For example, try running the code below:
to setup
ca
crt 10 [
setxy random-xcor random-ycor
set color one-of [ red blue ]
]
reset-ticks
end
to go
let ball-owner one-of turtles
ifelse [color] of ball-owner = red [
print "red team has possession"
] [
print "blue team has possession"
]
end
Edit: You can definitely use a global to pick a color just as you did in your second code block- I just wanted to point out that of is specifically tied to agents. If you want to store a color in a global variable for comparison, that's possible, it's just that your comparison is simpler than using of:
globals [ initial-possession ]
to setup
ca
crt 3
set-initial-possession
reset-ticks
end
to go
ask turtles [
decision
]
end
to set-initial-possession
set initial-possession ifelse-value ( random 2 = 1 ) [black] [white]
end
to decision
ifelse initial-possession = black [
print "I see that black has possession"
] [
print "I see that white has possession"
]
end
I'm not sure if that helps, it may depend on your purpose of storing a color in the global in the first place!

Copy the link breed variable in the patch below

I have a network of nodes and links. This figure
is a capture of the world. The graph represents streets of a city. I have imported a shapefile with the gis extension. The gray lines are links, black dots are nodes and red dots represent people. The people move heading to the next node. In a street corner, the red dot chooses next street by examining the variable popularity owned by the link.
The links breed has a variable, popularity, whose value I would like to copy in the patches that are below.
If I try, for example, something like this to access patches under links will produce an error
ask links [show [(list pxcor pycor)] of patch-here]
Another approach can be to access links variable popularity from patches, but I do not know how to do it.
The reason why I want this is because I want to write in a file a matrix of popularity values and its position in the matrix should correspond with the position of the link in the world. Thus, the patches below the links would give me the matrix form. I have a procedure that for each patch writes the value of the patch in a file. However, I do not know how to pass the popularityvalue from the link to the patch below it.
Is there any way to copy a link owned variable to its patch?
Regards
If someone has a better way of doing this (or can simplify my code), feel free. Here is a complete working example. Copy it into an empty NetLogo model and run it to see it work.
The setup procedure just creates some nodes and links with appropriate test values and then calls the transfer-link-values procedure, which does what I think you want. The setup procedure then puts the values into the patch labels to display them and see the results.
The way the transfer-link-values procedure works is to create a turtle at one end of the link, and that turtle moves toward the other end of the link transferring the value as it goes. When it gets to the other end, the turtle dies.
patches-own [patch-popularity]
links-own [link-popularity]
to setup
clear-all
create-turtles 10 [ setxy random-xcor random-ycor]
while [ any? turtles with [not any? my-links] ]
[ let to-pair turtles with [not any? my-links]
let thisNode one-of to-pair
ask thisNode
[ create-link-with one-of other to-pair
[ set link-popularity 5 + random 5 ]
]
]
transfer-link-values
ask patches [ if patch-popularity != 0 [set plabel patch-popularity ] ]
end
to transfer-link-values
ask links
[ let start-node one-of both-ends
let this-link self
let end-node nobody
ask start-node [ set end-node [other-end] of this-link ]
let transfer-value link-popularity
ask start-node
[ hatch 1
[ face end-node
if transfer-value > patch-popularity
[ ask patch-here [ set patch-popularity transfer-value ] ]
while [ not member? end-node turtles-here ]
[ forward 1
if transfer-value > patch-popularity
[ ask patch-here [ set patch-popularity transfer-value ] ]
]
if transfer-value > patch-popularity
[ ask patch-here [ set patch-popularity transfer-value ] ]
die
]
]
]
end

is it possible variable inhrit the my turtles label

i want my variable to inherit the label of my turtles.
im making routes for them and want them to remember the last place they visited.
so theyll continue to the next place in the chain.
ifelse last_place = home
[set place min-one-of (turtles with [label = "mall"])[distancemyself]]
[set place min-one-of (turtles with [label = "home"])[distancemyself]]
i cant use my actual code in here but hopefully, you get the gist
if
place = one-of turtles with [label = "mallI]
I want to add
set last_place label of place
i want last_place to get the label of place.
i know it can create loops if i have the same place twice in the same route but i want to create a list to prevent them but right now i need a sort of where flag that will make my turtles keep going to the end.
Hard to say without seeing more of your code- it's hard to know what turtle is doing what. If your code is sensitive, I'd recommend following the tips in the MCVE guidelines to make a reproducible example- it might be easier to address your exact problem that way!
As an alternative, instead of using a label it's probably better to just have the turtles store the "location" turtle or patch in a turtle-variable. Using this simple example setup:
breed [ walkers walker ]
breed [ locations location ]
walkers-own [ location-list ]
to setup
ca
create-walkers 10 [
setxy random-pxcor random-pycor
set location-list []
pd
]
create-locations 20 [
set size 1.5
set shape "house"
setxy random-pxcor random-pycor
]
reset-ticks
end
You can have turtles store the places they visit in a list and reference them that way.
to go
ask walkers [
; Build an agrentset of locations that do not belong
; to each turtle's 'location-list'
let unvisited-locations locations with [
not member? self [location-list] of myself
]
; Target the nearest unvisited location
let target min-one-of unvisited-locations [ distance myself ]
; if the target exists, move towards it
if target != nobody [
face target
ifelse distance target > 1 [
fd 1
] [
move-to target
set location-list lput target location-list
]
]
; if a turtle visits all locations, remove the
; first location visited from the 'location-list'
; so that it will follow the same pattern continuously
if length location-list = count locations [
set location-list but-first location-list
]
]
tick
end

Turtle cannot select path to destination in GIS generated network unless duplicate and unconnected nodes are removed

I have been trying to work out how to make a turtle move from one node to another in a network based on a GIS road map. The issue is that the turtle cannot set a path using nw:turtles-on-path-to unless I remove node duplicates and nodes that are not connected (the relevant block of code I used is from someone else's model). Below is the code that works when I remove duplicates and unconnected nodes:
foreach gis:feature-list-of roads-dataset [ vector-feature ->
foreach gis:vertex-lists-of vector-feature [ vertex ->
let previous-turtle nobody
let first-turtle nobody
foreach vertex [point ->
let location gis:location-of point
if not empty? location
[
create-nodes 1
[ set myneighbours n-of 0 turtles
set xcor item 0 location
set ycor item 1 location
set road-type gis:property-value vector-feature "Classification"
;set shape "circle"
;set size 0.5
ifelse previous-turtle = nobody
[ set first-turtle self ]
[ create-link-with previous-turtle ]
set hidden? true
set previous-turtle self ]
]
]
] ]
delete-duplicates
ask nodes [ set myneighbours link-neighbors ]
delete-not-connected
ask nodes [ set myneighbours link-neighbors ]
to delete-duplicates
ask nodes [
if count nodes-here with [ description = "road" ] > 1[
ask other nodes-here with [ description = "road" ][
ask myself [create-links-with other [link-neighbors] of myself]
die]
]
]
end
to delete-not-connected
ask nodes [set test 0]
ask one-of nodes [set test 1]
repeat 500 [
ask nodes with [test = 1]
[ask myneighbours [set test 1]]]
ask nodes with [test = 0][die]
end
to go
ask person [
if destination = 0 [ create-link select-destination ]
if mypath = 0 [ select-path ]
if mypath != 0 [ move ]
]
tick
end
to create-link
create-link-with min-one-of nodes [ distance myself ]
ask links [ set hidden? true ]
end
to select-destination
set destination one-of nodes with [ road-type = "main road" ]
end
to select-path
set mypath nw:turtles-on-path-to destination
end
to move
ifelse length mypath > 0
[ move-to item 0 mypath set mypath remove-item 0 mypath ]
[ stop ]
end
This code works perfectly fine. However, the road network gets distorted after deleting duplicate and unconnected nodes - the road networks does not have the same appearance as the original one. The only way the turtle can move along the network is by keeping the code in the format above. If I exclude delete-duplicatesand delete-not-connected then mypath returns false.
I there a way I can keep the appearance of the original network and at the same allow the turtle to set a path and move along it to reach the destination? What would be the issue that does not allow the turtle to set a path unless delete-duplicatesand delete-not-connected are used?
Your support is much appreciated. Thank you.
Are you sure delete-duplicates is necessary? My guess is that the reason delete-not-connected is necessary is because, without it, select-destination can select a node that is not reachable by the turtle. I'll get to how to fix this in a moment. First, there are a few problems with your code that we should discuss.
First, you have turtles create a link between them and their current location. This is a little weird, because it's essentially saying that this turtle is a road on the road network, which doesn't make sense. Practically, this gets weird if and when you want the turtles to select new destinations. They'll still be linked with the node they started on! This would allow them "teleport" around the network. Not good! Instead, I suggest creating a turtle variable called current-location, which tracks the node that the turtle is on.
So, create-link should be turned into
to set-location
set current-location min-one-of nodes [ distance myself ]
end
move then becomes (I deleted the stop from your code because it's unnecessary):
to move
if not empty? mypath [
set current-location first mypath
move-to current-location
set mypath but-first mypath
]
end
and select-path becomes:
to select-path
set mypath [ nw:turtles-on-path-to destination ] of current-location
end
Actually, we can simplify this further. Because the turtle is keeping track of its current location, you don't need to keep track of the path yourself anymore. Instead, delete mypath and select-path and change move to:
to move
if current-location != destination [
let next-node first [ nw:turtles-on-path-to destination ] of current-location
set current-location next-node
move-to current-location
]
end
and change go to:
to go
ask person [
if destination = 0 [
set-location
select-destination
]
move
]
tick
end
Much simpler! Note that this should still be fast as nw remembers the shortest path between nodes. If you have a really big network or something, you can still keep track of the path yourself if you want, but I'd try this first.
Okay, now we're ready to fix the disconnected nodes problem without deleting anything in the network. Basically, select-destination should only choose a destination that the turtle can get to. That looks like this:
(Edit: This code is incorrect. See below)
to select-destination
set destination one-of nodes with [
road-type = "main road" and
is-number? [ nw:distance-to [current-location] of myself ] of myself
]
end
The [ nw:distance-to myself ] of myself in there will get the distance from the current-location (which is what the first myself refers to) to the potential destination (which is what the second myself refers to). nw:distance-to will return a number (the distance) if the target node is reachable from the source node; otherwise it returns false. So is-number? checks to make sure it actually gave us a number back.
Hopefully this helps solve your problem while also simplifying your code. The duplicates thing really shouldn't matter. If it does, either reply with a comment or edit your question, and I'll take a look.
Edit:
Thanks for uploading your model and data! I realized I actually messed up the select-destination procedure. It should be:
to select-destination
set destination one-of [ nodes with [
road-type = "road" and
is-number? [ nw:distance-to myself ] of myself
] ] of current-location
end
That is, the person was supposed to be querying the current-location for a reachable road. Obviously, since the person is not connected to the network, they can't get a reachable road directly.
Next, it looks like a significant problem is actually the data is extremely disconnected. The network that you're creating contains 5619 disconnected components which each only contain 3-5 nodes. So it's no wonder that the turtle can't find a destination it can reach!
I think you may be interpreting the data incorrectly. I would expect that the various the nodes created from different feature lists should be connected somehow, but you're not doing that (which is why you end up with so many disconnected components). Unfortunately, this is where we hit the limit of my knowledge; I don't know much about GIS. I remember one of my colleagues that was working on a similar project had to do something like merging vertices that were on top of each other. This would turns the network generation code into the following:
foreach gis:feature-list-of roads-dataset [ vector-feature ->
foreach gis:vertex-lists-of vector-feature [ vertex ->
let previous-turtle nobody
foreach vertex [point ->
let location gis:location-of point
if not empty? location
[
let x item 0 location
let y item 1 location
let current-node one-of (turtles-on patch x y) with [ xcor = x and ycor = y ]
if current-node = nobody [
create-nodes 1 [
setxy x y
set shape "circle"
set size 0.5
set road-type "road"
set hidden? true
set current-node self
]
]
ask current-node [
if is-turtle? previous-turtle [
create-link-with previous-turtle
]
set previous-turtle self
]
]
]
]
]
This appears to behave correctly. (I also cleaned up a few things that we're doing anything) That is, it looks to see if there's already a node at that exact location, and connects to that one if so, otherwise it creates a new node.
Here's the full updated code: https://gist.github.com/qiemem/b59f3657bea34b9aa67648760b9c7471
I also tweaked a few other things: The person now sets their location in setup, which makes sense: their location should update correctly after that. I added tick to the end of go, which all models should have. You might want to change view updates to "on ticks". Finally, I made the person choose a new location upon getting to their destination for testing. You might want to make go a forever button now; you'll the person going from place to place.
Hope that helps!

How to create links between all turtles except itself?

I want to create links between all turtles who are green. But I dont know how to include that know link shall be created with the turtle itself.
What I got:
ask turtles with [ green? = true ] [ create-links-with turtles with [ green? = true ] ]
Error I get:
A turtle cannot link to itself. error while household 178 running
CREATE-LINKS-WITH called by procedure GREEN called by procedure GO
called by Button 'go'
Just ask to create link with other turtles:
ask turtles with [ green? ]
[
create-links-with other turtles with [ green? ]
]