nw:weighted-path-to, nw:turtles-on-weighted-path-to and multiple equally weighted paths - netlogo

I apologise upfront if this is a stupid question.
When one calls nw:weighted-path-to a list of links is returned describing the shortest path between origin and destination turtles.
Similarly, calling nw:turtles-on-weighted-path-to returns a list of the turtles on the shortest path between origin and destination.
It is my understanding that if there are 2 equally weighted paths between origin and destination both functions returns one of these paths at random. This happens independently and as such one set of links can be produced for the shortest path, but another set of turtles. This can be replicated using the following code:
extensions [nw]
links-own [ weight ]
to go
clear-all
create-turtles 4
ask turtle 0 [ create-link-with turtle 1 [ set weight 2 ] ]
ask turtle 0 [ create-link-with turtle 2 [ set weight 2 ] ]
ask turtle 1 [ create-link-with turtle 3 [ set weight 2] ]
ask turtle 2 [ create-link-with turtle 3 [ set weight 2] ]
ask turtle 0
[
let pathLinks nw:weighted-path-to turtle 3 "weight"
let pathNodes nw:turtles-on-weighted-path-to turtle 3 "weight"
let pathUtility nw:weighted-distance-to turtle 3 "weight"
show pathLinks
show pathNodes
show pathUtility
]
end
Which will happily produce:
(turtle 0): [(link 0 2) (link 2 3)]
(turtle 0): [(turtle 0) (turtle 1) (turtle 3)]
(turtle 0): 4
Obviously, this is not an error but it has unfortunately tripped me up.
My question is - what is the most sensible way to link these two procedures to produce lists of links and turtles that make up a single randomly selected shortest path?
I am assuming it would be best to return the links with nw:weighted-path-to, then ask the links to return both-ends and do some sort of unique operation to produce a set of turtles on that path, if that is the case I'm not sure how to preserve the order of turtles. Does this make sense? Is that how you would do it?
As ever, thanks for reading.
Edit: this also applies to path-to and turtles-on-path-to in a topological network with multiple equal length paths.

Good question! You can generate either list from the other, but I think turtle-path to link-path is easier:
;; Construct the turtle path, putting the current turtle on the front:
let turtle-path fput self nw:turtles-on-weight-path-to turtle 3 "weight"
;; Iterate through pairs of turtles, getting the link connecting them
let link-path (map [[link-with ?2] of ?1] but-last turtle-path but-first turtle-path)
Edit:
Nicolas is absolutely right about "link-path to turtle-path". However, his comment made me realize you could use the almighty reduce and the ever-useful other-end to do it!
reduce [ lput [[other-end] of ?2] of (last ?1) ?1 ] fput (list self) nw:weighted-path-to turtle 3 "weight"
Edit2: The "link-path to turtle-path" code is pretty opaque. Here's an attempt to clarify it:
to-report add-link-to-turtle-path [ turtle-path next-link ]
let last-turtle last turtle-path
report lput [[other-end] of next-link] of last-turtle
end
;; turtle-procedure - Assumes the current turtle is the starting point of the path
to-report link-path-to-turtle-path [ link-path ]
let start-of-path (list self)
report reduce add-link-to-turtle-path fput start-of-path link-path
end

Related

Different results of reporters turtles/turtle x

I have created an opinion dynamics model, that works just fine. But now I wanted to see, how the opinion of all of my turtles changes. So I created the reporter "report [opinion] of turtles". When I put this in behaviorspace I get wildly jumping results that do not correspond with what I observe. If I test this with individual turtles like "report [opinion] of turtle 0", I get the smooth curve progression that I expected to see.
Does anyone know why this is happening? I would find it rather unwieldy, if I had to put every turtle individually in my behaviorspace, because I have sliding Agentsnumbers.
You can let each turtle have a list variable, at the beginning of which each turtle will record its ID. At every step, each turtle will append its opinion value.
Then you can have a global variable, which you will use as a list of lists, to which at the end of the simulation each turtle will append its own list.
In BheaviorSpace, you will only need to use one reporter (the list of lists) at the end of each experiment's run.
See below for a working example:
globals [
results
]
turtles-own [
opinion
my-list
]
to setup
clear-all
reset-ticks
set results (list)
create-turtles 3 [
set opinion random 10
set my-list list self opinion
]
end
to go
if (ticks = 5) [
ask turtles [
set results lput my-list results
]
stop
]
ask turtles [
set opinion opinion + 1
set my-list lput opinion my-list
]
tick
end
At the end of each run, the results reporter will look like:
[[(turtle 2) 3 4 5 6 7 8] [(turtle 0) 0 1 2 3 4 5] [(turtle 1) 5 6 7 8 9 10]]
Note that, this way, the lists in results will always be in random order.
If you're interested in having them ordered according to some criterion, you can do it.
The example below changes the if (ticks = 5) statement to order results according to turtles' ID, but you can just use sort on whatever characteristic you're interested in.
if (ticks = 5) [
let sorted-turtles sort turtles
foreach sorted-turtles [this-turtle -> ask this-turtle [set results lput my-list results]]
stop
]

Is there a way to create a modification of Breed-On that includes specific characteristics?

I want my forager turtles to follow a path laid down by leader turtles, and this path consists of a turtle breed called trail-markers. The forager turtles also lay down trail-markers (to reinforce the trail), so I would like them to check for leader trail-markers on some patch/patches. I know Netlogo includes breeds-on to check for the presence of members of a breed, but I need the foragers to check for blue leader trail-markers. Is there a way to do this?
Here is what I had in mind:
if count (trail-markers with [color = blue]) on patch-ahead 1 > 0 [fd 1]
But I got, error:nothing named on has been defined, which makes sense, since the Netlogo primitive is breeds-on, so I modified it to:
if any? (trail-markers with [color = blue])-on patch-ahead 1 [fd 1]
However, I simply received: error:nothing named -on has been defined instead.
See the code below. I think you just want to use trail-markers-on, but you can simplify by using any? a bit. And you might want to have the custom reporter so you can just check for blue-markers-on if you find that simpler.
breed [ trail-markers trail-marker ]
to example
; I think this is what you want
if count ((trail-markers-on patch-ahead 1) with [color = blue]) > 0 [ forward 1 ]
; this is slightly simpler, using `any?` instead of `count ... > 0`
if any? (trail-markers-on patch-ahead 1) with [color = blue] [ forward 1 ]
; you could also write a custom reporter if you'll need to get this info a lot
if any? blue-markers-on patch-ahead 1 [ forward 1 ]
end
to-report blue-markers-on [p]
report (trail-markers-on p) with [ color = blue ]
end

Deleting the opposite of a link in a list in netlogo

i have a list of links but sometimes within the list two links that are opposite of each other appear in the list. All links have values and the list is organized from highest value to lowest. what i want to do is to make the opposite link with the lower value die.
does any one have any ideas?
not that it would help a great deal but i got my list from this line of code:
set max-links sort-on [(- label)] link-set [max-one-of my-in-links [label]] of turtles
I'm assuming that these are directed links as there can not be two undirected links between any two turtles. The following code is not elegant, but I think it will do what you want. I've embedded it within a working model.
to test
clear-all
create-turtles 10 [fd random 10]
ask turtles [ create-links-to n-of 8 other turtles ]
ask links [set label random 100 ]
let link-list sort links
let to-die []
let remaining link-set link-list
foreach link-list [[m] ->
let opposite (link [who] of [end2] of m [who] of [end1] of m)
if opposite != nobody and member? opposite remaining [
ifelse ([label] of opposite < [label] of m) [
set to-die lput opposite to-die
]
[
set to-die lput m to-die
]
set remaining remaining with [self != m]
]
]
foreach to-die [m ->
set link-list remove m link-list
]
ask link-set to-die [die]
end
For each link in the list, it looks to see if there is an opposite link in the linkset remaining, originally made up of the links in the list. If so, it marks the proper link for deletion and then takes itself out of remaining so that when the opposite link is tested it won't be found. Once all links to be deleted are found, they are removed from the list and asked to die.
Hope this helps,
Charles

Netlogo: Making a turtle interact with anotherone after evaluating similarity in a given variable

I have several turtles each with three variables opinion1, opinion2 and opinion3. I need them to:
identify which of these three variables has the highest value
find another turtle in their network with a value at least as high
as the one found in 1.
update its own value found in 1. with
respect to that of the turtle found in 2.
What I have done doesn't really work because it only updates looking at o1 without really having a look at which of the tree (opinion1, opinion2 or opinion3) is the highest and THEN looking for a neighbour.
to update-opinion
ask turtles [
let my-nearby-turtles nw:turtles-in-radius 1
let my-opinion1 opinion1
set neighbour one-of my-nearby-turtles with [ opinion1 > my-opinion1 ]
if neighbour != nobody [
let opinion_n [opinion1] of neighbour
set opinion1 ((opinion1 + opinion_n) / (2))
]
]
end
I don't know a simple way to do this with unique variables like opinion1 etc, but maybe having a list of opinions instead of individual variables for each opinion will work. For example, with this setup:
extensions [ nw ]
turtles-own [
opinions
]
to setup
ca
resize-world -5 5 -5 5
set-patch-size 30
crt 30 [
set shape "dot"
set opinions n-values 3 [ precision random-float 10 2]
set color scale-color blue sum opinions -5 35
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
]
ask turtles [
create-links-with turtles-on neighbors4
]
reset-ticks
end
You get something like this:
Where each turtle has an opinions list variable that is three items long. Now, you can have each turtle determine its highest opinion value using max, get that maximum values index position in the list using position, and then query that turtle's neighbors to see if any of them have a higher value in the same index position. If they do, modify your asking turtles opinions list using replace-item to be the average of the two values:
to go
ask turtles [
; Get adjacent turtles
let my-nearby-turtles nw:turtles-in-radius 1
; Identify the highest highest value variable of
; the current turtle, and get its list position
let my-opinion max opinions
let my-op-ind position my-opinion opinions
; Pick one of the turtles whose value in the same indexed
; position is higher than my-opinion
let influence one-of my-nearby-turtles with [
item my-op-ind opinions > my-opinion
]
; If that turtle exists, update my own opinions list as appropriate
if influence != nobody [
let new-opinion precision (
( [ item my-op-ind opinions ] of influence + my-opinion ) / 2
) 2
set opinions replace-item my-op-ind opinions new-opinion
]
set color scale-color blue sum opinions -5 35
]
tick
end
Hopefully that is sort of on the right track, not sure if a list will work for what you need. If you must have the variables as standalone values at each tick, I suppose you could convert them to a list then follow the procedure above. If you only need them for output, you could just update your unique variables as needed based on the values in the list (as long as you are consistent with the order).

Netlogo: How to select a turtle with the lowest ID for each stagnant turtle in each specified patch in the world?

I have a model that keeps turtles in several patches each. I would like to select a turtle with the lowest ID for each stagnant turtle in each specified patch in the world.
For example, the answer is as follows. At patch coordinates (1, 0), five turtles stayed. And the ID of the turtle with the smallest ID was ID = 5 within the patch coordinates (1, 0).
The following is a sample program. But this program is not intended. Is there something good syntax instead of the syntax "min-one-of turtles [who]"? I want your advice. Thank you.
ask (turtles-on patch 1 0) [
ask min-one-of turtles [who] [
set flag-1 TRUE
]
I'm not sure what you mean by 'program is not intended'. Your problem is that you ask each of the turtles on patch 1 0 to identify the minimum who over all turtles. What you want is:
let targets (turtles-on patch 1 0)
[ ask min-one-of targets [who]
[ set flag-1 TRUE
]
]
If the only thing you are going to do with the turtles on that patch is to select the lowest who, you don't need to set up the agentset explicitly. Instead:
ask min-one-of (turtles-on patch 1 0) [who]
[ set flag-1 TRUE
]