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.
Related
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
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).
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.
A toy example. There are two groups of people: A and B. Only A can say "hello" to people B. People walk around the world and meet each other. When people A meet people B, they say hello to them. Each person A record who was said hello to and the tick when that occurred. They cannot say hello to the same person until five new ticks happen. The procedures below only apply to people A.
Each time a person A say hello to a person B I define:
set tick-last-greeting lput ticks tick-last-greeting
set previous-person-b-greeted lput selected-person-b previous-person-b-greeted
Before the say-hello procedure happens again:
if (length tick-last-greeting != [] and previous-person-b-greeted != []) [
; wait 5 ticks
set temp (map [ticks - ? > 5] tick-last-greeting)
; filter the list, I don't know if there is a better way to do this
set previous-person-b-greeted (map last filter [first ? = false] (map list temp previous-person-b-greeted))
set tick-last-greeting (map last filter [first ? = false] (map list temp tick-last-greeting))
]
So, I get a list of people B that shouldn't be greeted by a person A but until five ticks happen. Here is my key problem: how to define an agentset that excludes the agents of the list previous-person-b-greeted.
set potential-persons-b targets-on (patch-set neighbors patch-here)
if (previous-person-b-greeted > 0) [
; Here, I get an error as expected
let who-previous-person-b [who] of previous-person-b-greeted
set potential-persons potential-persons with [who != who-previous-person-b]
]
A possible solution: transform the list previous-person-b-greeted into an agentset (I don't know if there is simple way to do this).
Any ideas?
To transform a list of agents into an agentset, use turtle-set or patch-set or link-set. So e.g.:
observer> create-turtles 5
observer> let mylist (list turtle 0 turtle 2 turtle 4) print turtle-set mylist
(agentset, 3 turtles)
I will assume that you're not using specific breeds for people A or people B.
Perhaps you could try using breeds, for example:
breed [personA peopleA]
breed [personB peopleB]
Will define 2 different agentsets and then you can use the <breeds>-own statement to define a list of recently greeted people.
peopleA-own [recently-greeted-people recently-greeted-people-time]
And then everytime that a personA has to greet someone your procedure could look like this:
to greet [personB-who]
if (not (and (member? personB-who recently-greeted-people)
(procedure-that-checks-ticks-less-than-5))
...ADD HERE OTHER LOGICAL CHECKS DEPENDING ON YOUR PROBLEM
)
[
fput personB-who recently-greeted-people
fput current-tick recently-greeted-people-time
]
end
Observe that for every personB greeted, the who and the id are added to different lists and then they must be removed at the same time to keep consistence.
You can read more about breeds in the NLogo dictionary.
Finally, following your suggestions, I ended up with this solution:
set potential-persons-b sort (targets-on (patch-set neighbors patch-here))
if (previous-person-b-greeted != [])
[
foreach previous-victimized-target
[ set potential-persons-b remove ? potential-persons-b]
set potential-persons-b turtle-set potential-persons-b
]
Here a more general solution using to-report:
to-report subsetting-agents [agent-set1 agent-set2]
set agent-set1 sort agent-set1
set agent-set2 sort agent-set2
foreach agent-set2
[ set agent-set1 remove ? agent-set1]
set agent-set1 turtle-set agent-set1
report agent-set1
end
I have seen on here how to create an intersection or union of two agentsets, but I am trying to say if any turtle in agentset a is in agentset b, return true. I was trying
ifelse (member? (one-of my-intersections) destination-intersections)
but I am pretty sure this is just testing if one element in my-intersections is in destination -intersections instead of testing every element. Is there some way to use a for each? Or is there another functionality I am unaware of?
Again, I have already referenced
NetLogo two agentsets operations
Thank you!!
The most straightforward way to write such a test is:
to-report test [ as bs ]
report any? as with [ member? self bs ]
end
To try it:
create-turtles 5
show test (turtle-set turtle 0 turtle 1 turtle 2) (turtle-set turtle 3 turtle 4)
show test (turtle-set turtle 0 turtle 1 turtle 2) (turtle-set turtle 0 turtle 3 turtle 4)
will show:
observer: false
observer: true
It's not the most efficient way, however, because the with clause builds an intermediate agentset that's not really needed.
A faster test would be:
to-report test [ as bs ]
let result false
ask as [
if member? self bs [
set result true
stop
]
]
report result
end
Edit:
I spoke too fast. As per the NetLogo wiki page on compiler architecture, the combination of any? and with does get optimized to exit early. Bottom line: you should use the first version (i.e., any? as with [ member? self bs ]).