Deleting the opposite of a link in a list in netlogo - 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

Related

Netlogo - Iterating through patch list and writing each output to a row in a list

I have a list of cells destination_cells, and am trying to loop through each cell and count the number of turtles and the average weight of the turtles in each. For each cell, I want to write the cell's ID (which I am assuming is just destination_cells as coordinates) and the two variables to a list cell_list. I think my confusion stems from not understanding how to use anonymous reporters in foreach. If I replace 'next cell' with destination_cells in the foreach block, I get, for example, the same total_turtle_in_destination_cells value for every single cell in destination_cells. The same occurs with using next_cells in the block. Where am I making a mistake?
set destination_cells [self] of patches with [ any? turtles-here]
foreach destination_cells [next_cell -> ask next_cell
[
; Counts number of turtles in each cell
set total_turtle_in_destination count turtles-on destination_cells
; Finds average weight of turtles in each cell
set avg_weight_turtle_in_destination mean [mass] of turtles-on destination_cells
]
set cell_list lput (csv:to-row (list
destination_cells
total_turtle_in_destination
avg_weight_turtle_in_destination
)) cell_events_list
]
Here is an alternative that:
Makes a reporter to get the info desired (the patch info as patch x and y, the total turtles on a patch, the mean weight of present turtles) from whatever patch that calls the reporter
Updates the info list directly by querying the destination_cells
turtles-own [ weight ]
globals [ destination_cells cell_info_list]
to setup
ca
resize-world 0 5 0 5
set-patch-size 30
reset-ticks
crt 20 [
set weight random 10 + 1
move-to one-of patches
]
end
to-report report-self-info
let n_turtles_here count turtles-here
let mean_weight mean [weight] of turtles-here
report (list self n_turtles_here mean_weight)
end
to create-info-list
set destination_cells patches with [ any? turtles-here]
set cell_info_list [report-self-info] of destination_cells
print cell_info_list
end
In response to your question "how can the patch call the reporter? I tried ask destination_cell [report-self-info], but a command is expected":
When you make a to-report procedure with the structure like the above that uses self, it's somewhat like a turtles-own or patches-own variable. In this case, you can call it just as you would have a turtle variable like color or xcor or a patch variable like pcolor or pxcor- if you run something like:
ask one-of patches [ print report-self-info ]
You should get something like
[(patch 5 2) 2 7.5]
This is why the set cell_info_list [report-self-info] of destination_cells above works- because you could do something like set cell_info_list [pcolor] of destination_cells in a similar way.

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

adding agentset from different agents togother into a let

my model is a network of agents connected to each other with links.
I try to create a agentset from the neighbors of an agents and their neigbors and so on (I need this to assign different values to it).
However when I create a let with the agentset in it. the agents asked to make this agentset all have their own, this is so far so good. But when I want the original agent to ask him his second line neighbors he just returns an agentset from one of this neighbors instead of the combined agentsets of all his second line neighbors
I want the neighbors to store their own neighbors into a agentset with all the neighbors from the different agents in that set.
I cant ask the let agentset to simple do turtleset current-agentset new-agentset since in a let you cant ask to let variable. So a code which would normally be set second-neighbors (turtle-set second-neighbors other-nieghbors doesnt work since I cant ask second-neighbors already in a let
I also cant make this a global or somethins since it is agent specific.
the code I have so far looks like this
ask companies [
let this-company self
let b link-neighbors
ask b [ let c link-neighbors with [self != this-company]
ask c [ let d link-neighbors with [not member? self b]
ask this-company [
set iburen b
set iiburen c
set iiiburen d
]
]
]
]
so what I want is that all the agents in the agentset c report their link-neighbors like they do now. But also store these link-neighbors into a new agentset which has all the link-neighbors of all the agents in c. like a simple i i + 1. but than with turtle-set (what I have) (what is new from the next agent asked)
the same goes for d
If I run the model now agents report different agentset almost every tick. They just pick one agentset from any of these agents instead of combining them all togother.
Here is what I think you need:
extensions [ nw ]
breed [ companies company ]
companies-own [
buren ; a list of agentsets, with one item for each "level" of neighbors
]
to setup
clear-all
; create a random network and lay it out:
create-companies 20 [ create-links-with n-of 3 other companies ]
repeat 30 [ layout-spring turtles links 0.2 5 1 ]
let num-levels 3
ask companies [
let all-neighbors other nw:turtles-in-radius num-levels
set buren (list) ; initialize to empty list
foreach range num-levels [ i ->
let neighbors-at-this-level all-neighbors with [
nw:distance-to myself = i + 1
]
set buren lput neighbors-at-this-level buren
]
]
; demonstrate how to access the levels (sorted only for display purposes)
ask one-of companies [
show sort item 0 buren ; first level neighbors
show sort item 1 buren ; second level neighbors
show sort item 2 buren ; third level neighbors
]
end
This might not be the most efficient code possible, because it goes through the list of all neighbors once for each level, but unless you have a humongous network, you should not notice.
If you really wanted to use variables like iburen, iiburen and iiiburen, you could always alias the items of the list:
set iburen item 0 buren
set iiburen item 1 buren
set iiiburen item 2 buren
...but I don't recommend it. Having your agentsets in a list should encourage you to think of your levels in a more general way.

How to get the top 10 turtles sorted by reverse in-degree centrality?

I want to get a list of top ten turtles in terms of their degree centrality. I have tried but I am not getting the required result.
In the code below, I am storing centrality in a list and then reverse sorting it. However, it is storing centralities only. I want turtles ordered in terms of their centrality. I also have tried saving turtles on the list and have used sort-by but got an error.
I also have tried to get agents using turtles with max degree centrality, but the problem arises when several nodes have the same centrality. I want to do this in an efficient manner.
globals [indeg]
turtles-own [centrality]
to setup
ca
crt 160
ask turtles [
set indeg []
fd random 15
]
ask turtles with [color = red] [create-links-to other turtles with [color = blue]]
ask turtles with [color = green] [create-links-from other turtles with [color = yellow]]
inf
end
to inf
ask turtles [
set centrality count my-in-links
set indeg lput centrality indeg
]
set indeg sort(indeg)
print "indeg"
print reverse(indeg)
print max(indeg)
end
Here are three different ways to get that information, with potentially slightly different performance and results:
to setup
clear-all
create-turtles 160 [ forward random 15 ]
ask turtles with [color = red] [create-links-to other turtles with [color = blue]]
ask turtles with [color = green] [create-links-from other turtles with [color = yellow]]
let top-10-a reverse sort-on [ count my-in-links ] max-n-of 10 turtles [ count my-in-links ]
show-results top-10-a "Top ten turtles using max-n-of:"
let sorted-turtles reverse sort-on [ count my-in-links ] turtles
let top-10-b sublist sorted-turtles 0 9
show-results top-10-b "Top ten turtles from sorted list:"
let top-10-c filter [ t ->
[ count my-in-links ] of t >= [ count my-in-links ] of item 9 sorted-turtles
] sorted-turtles
show-results top-10-c "Turtles with top ten centrality:"
end
to show-results [ turtle-list title ]
print title
foreach turtle-list [ t -> ask t [ show count my-in-links ] ]
end
The first (method "a") and most obvious is to use NetLogo's max-n-of primitive. That primitive gives back an agentset (not a list), so if you want an agentset, that's the way to go.
Your question seem to indicate that you ultimately want a list of turtles sorted by decreasing centrality, so you have to use reverse sort-on [ count my-in-links ] on the result of max-n-of, which is what I'm doing above.
Another approach (method "b") would be to sort all turtles by their centrality, store the resulting list in sorted-turtles variables and then take the first 10 of that. That method is a bit more intuitive but could be slower than the max-n-of method since it has to sort the whole list. Depending on how many turtles you have, however,the difference could be negligible.
One thing the first two methods have in common is that the ties are broken randomly. This means that if you have, let's say, three turtles that have a centrality worthy of position number ten in your top ten, you'll only get one of those. (Given the way you construct your network in the example from your question, this is very likely to happen.) If you want your top ten to potentially include more than 10 turtles in case of equality, you need to use method "c".
The last method sorts the whole, look at the centrality of the tenth turtle in that list, and filters the list to keep only the turtles with centrality greater or equal to that one.

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

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