Although NetLogo has a good set of primitives allowing for the handy creation of agentsets, sometimes we might want to ask agents to 'manually' add themselves to an agentset as part of a procedure they're running - for instance, by using turtle-set
.
Example:
globals [
good-folks
bad-folks
]
to setup
clear-all
set good-folks (turtle-set)
set bad-folks (turtle-set)
create-turtles 50 [
ifelse (random 2 < 1)
[set good-folks (turtle-set good-folks self)]
[set bad-folks (turtle-set bad-folks self)]
]
end
to go
ask good-folks [
do-good-things
]
ask bad-folks [
do-bad-things
]
end
to do-good-things end
to do-bad-things end
The advantage of this approach above is better readability, the possibility to avoid having to create a turtles-own variable and avoid having to resort to with
or if
statements - as shown below:
turtles-own [
group
]
to setup
clear-all
create-turtles 50 [
ifelse (random 2 < 1)
[set group "good folks"]
[set group "bad folks"]
]
end
to go1
ask turtles with [group = "good folks"] [
do-good-things
]
ask turtles with [group = "bad folks"] [
do-bad-things
]
end
; OR
to go2
ask turtles [
ifelse (group = "good folks")
[do-good-things]
[do-bad-things]
]
end
to do-good-things end
to do-bad-things end
Especially, it seems to me that the latter approach does not scale up as smoothly as the former, i.e. more groups will require more with
s or if
s, instead of just being able to refer to the needed group neatly.
However, I am not aware of a way to do the exact opposite of set good-folks (turtle-set good-folks self)
, i.e. asking the turtle to 'manually' remove itself from the agentset.
; In this case, bad-folks try to recruit some good folks
to do-bad-things
if (random 3 < 2) [
ask one-of good-folks [
set good-folks (turtle-set good-folks - self) ; Leave the good folks <- **How to do this?**
set bad-folks (turtle-set bad-folks self) ; Join the bad folks
]
]
end
I know this could be achieved by using a turtles-own variable and then updating agentsets as set <good/bad>-folks turtles with [...]
, but this is exactly the whole thing that I am trying to avoid in this question: less readable, more variables, more commands etc. And, perhaps equally important, it looks inconsistent with the use that can be done of turtle-set
to grow the agentset by using it in combination with self
. It would look easier and more consistent if existed a way to subtract self
from the agentset - does it exist?
Jasper's solution (i.e. using breeds instead of agentsets) works as long as the groups that I want to keep track of are mutually exclusive: agents switch from one single breed to another single breed only needing set breed ...
, which will both make the agent join the new breed and leave their previous breed. However, this would not work in case I want to keep track of multiple groups with overlaps: beyond good-folks
and bad-folks
, I may have tall-folks
and short-folks
. Agents will have to belong to multiple groups simultaneously - something that agentsets can handle while breeds cannot.
The answer, which I realised following some line of thought after Jasper's reply, is actually quite simple and it only requires other
:
to do-bad-things
if (random 3 < 2) [
ask one-of good-folks [
set good-folks (turtle-set other good-folks) ; Leave the good folks
set bad-folks (turtle-set bad-folks self) ; Join the bad folks
]
]
end
This makes me also think that it would be handy if NetLogo had two primitives called join
and leave
that worked like:
to join [agentset]
(ifelse
is-turtle? self [
set agentset (turtle-set agentset self)
]
is-patch? self [
set agentset (patch-set agentset self)
]
; else command:
[set agentset (link-set agentset self)])
end
to leave [agentset]
(ifelse
is-turtle? self [
set agentset (turtle-set other agentset)
]
is-patch? self [
set agentset (patch-set other agentset)
]
; else command:
[set agentset (link-set other agentset)])
end
So that one could do:
to do-bad-things
if (random 3 < 2) [
ask one-of good-folks [
leave good-folks
join bad-folks
]
]
end
Which feels almost like reading a book rather than reading code; although I recognise the need for it in the end is really minimal.