subsetting agentsets transforming a list of agents into an agentset - netlogo

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

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
]

Netlogo, how to capture values of variables of turtles and add each turtles value, map them, and reduce them to a single #

I am trying to write a procedure where a turtle of a certain breed asks turtles of the same breed, within a certain distance, the value of a certain variable. The asking turtle will then capture the values add them to it's own, map + them and then reduce + to a single number. Here's the code
ask Teams
[ if AsgnE = "E 1"
[
ask Teams with [ distance myself < 25]
[
; assuming that there are no more then 2 teams within distance
let Val1 []
let Val2 []
let Val3 []
set Val1 Value
set Val2 Value
set Val3 [Value] of self
let Val4 (map + Val1 Val2 Val3)
set Val4 (reduce + Val4)
set Storys1 [Stories] of Epic 0
if Storys1 > 0 [ set TotValue1 Val4 ]
]
]
]
The values of each Team continuously update as long as the go button is pressed. The issue is that the resulting number never matches the aggregate of all the values. As the number updates they never match the totals of the separate Teams. Sometimes the number drops to a lower number (I'm assuming it's representing a single teams value) before jumping back to a higher number.
Any idea on how to fix this?
Thanks
Rudy
My guess is that it's a synchronicity problem. The ask will iterate (in random order) through all the turtles. Let's say it starts with turtle 1 - so turtle 1 updates its value to be the sum of its old value and all the values of the nearby turtles. Then the ask moves on to turtle 2, and turtle 2 happens to be nearby to turtle 1. That means turtle 2 adds all the numbers again, with turtle 1 having its adjusted value. With just these two turtles, the value for turtle 2 gets added in twice because turtle 1 also has it hidden in its new value.
If this is not the behaviour you want, the easiest thing to do is to have an extra variable called something like next-value. Calculate next-value for each turtle as the appropriate sum. Then, in a new ask, get each turtle to set value next-value to update them all at the same time.
Also, your map and reduce seems unnecessarily complicated. If what you are trying to achieve is to add the value of a variable over a bunch of turtles, then you can simply do a sum of the variable after constructing the relevant turtle agentset. But it may be that you simplified for the purposes of the question, in which case just ignore this!
UPDATE ---- added complete model example
turtles-own
[ team
myval
nextval
]
to setup
clear-all
create-turtles 20
[ setxy random-xcor random-ycor
set team one-of ["A" "B"]
set myval 1
]
reset-ticks
end
to go
ask turtles
[ let myteam turtles with [team = [team] of myself]
set nextval sum [myval] of myteam
]
type "total before: " print sum [myval] of turtles
ask turtles
[ set myval nextval
]
type "total after: " print sum [myval] of turtles
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

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.

Logical Statement Determining if the intersection between two agentsets is empty

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 ]).