netlogo: send message to all but one agent - netlogo

I'm new at NetLogo. I'm not new at agent-based modeling. Now and then I see people saying NetLogo is so fun and easy that I'm giving it a try.
I'm stuck at square 1, can't figure out code for messaging between agents, scheduling actions for subsets of agents, other basic ABM things.
I'm working on a majority rule election model in which the turtles are voters with randomly placed x,y coordinates. Candidates (a new breed) make promises in x,y plane, the winning candidate is the one preferred by (closer to) more agents.
The patches play no role at all, except the spatial graph seems to require use of a grid
I'm having trouble in the updating of candidate positions. I conceived this as follows: Remove a 'winner' agent from the candidate agentset, tell the other candidates to adjust, then put the winner back in the agent list and see who wins in the next time.
I believe the following is close to minimum reproducible example. Please look at adjustOfferings. (Sorry, I left in a lot of show statements, otherwise can't tell what's going on.)
; Paul Johnson
; 20160801
breed [candidates candidate]
globals[
N
D
]
; turtles are voters, Euclidean-based preferences. Use
; built-in 2d coordinates for ideal points for now,
; need to learn how to create weighted multi-dimensional
; preferences later
turtles-own
[
name
]
to setup
ca ; clear all
reset-ticks ; time start 0
set N 100
; N voters with random x,y ideal points
create-turtles N
[
setxy random-xcor random-ycor
]
set D 2
create-candidates D
[
setxy random-xcor random-ycor
set shape "square"
set size 2
]
end
; collect up the votes. Don't worry about invading agent
; privacy, just measure for them
to-report election2 [choices]
let fave [min-one-of choices [distance myself]] of turtles
report fave
end
; Ask all non winners to adjust their offering
to adjustOfferings [winner]
show (word "in adjustOfferings, winner was: " winner)
let losers candidates with [self != winner]
show (word "adjustOfferings losers are: " losers)
ask losers
[
setxy random-xcor random-ycor
]
end
; ask each voter for its favorite,
; use modes to calculate the winner
to electionCycle
let theVotes election2 candidates
show (word "electionCycle: " theVotes)
let winner modes theVotes
show (word "electionCycle Winner: " winner)
adjustOfferings winner
end
to go
tick
if ticks > 1000
[
stop
]
electionCycle
end
The setup works fine, I see agents and candidates. When I hit the "Step button", I can see the election works, a winner is selected, but all candidates adjust (not just losers). Here's the console:
observer: "electionCycle: [(candidate 100) (candidate 101)
(candidate 101) (candidate 101) (candidate 100) (candidate 101)
[snip]
(candidate 100) (candidate 101)]"
observer: "electionCycle Winner: [(candidate 100)]"
observer: "in adjustOfferings, winner was: [(candidate 100)]"
observer: "adjustOfferings losers are: (agentset, 2 turtles)"
Appears to me this is the source of error:
let losers candidates with [self != winner]
The winner is still in losers after that.
I realize now you can't actually run this without the rest of the NetLogo file. What is your custom here for providing the fully runable example? Can I point you at a file on a website? http://pj.freefaculty.org/scraps/majority.nlogo. I could put this in GitHub or someplace else if you prefer.
I appreciate your advice.

The problem is indeed with the line you suggested. Both agents report true for the condition [self != winner], but why is it the case. Look at how you create and pass the winner variable to the function. You create it by using the modes primitive, which is a good idea. But modes will report you a list with one element. The problem is that you pass this list directly to your adjustofferings function. This means, the agents than compare [self != [(candidatexy)]]instead of [self != (candidatexy)] (mind the additional brackets in the first example, indicating the list).
To solve the problem, you have to extract the winner agent from the list by using the first primitive, which reports you the first item of a list. You only have to add this to the line, where you define the winnervariable: let winner first modes theVotes

Related

Unable to generate multiple 'species' per breed in NetLogo

I'm new to NetLogo and I'm trying to create 2 sub-breeds (denoted by different shapes) within each breed for 2 breeds total (i.e. sharks and fishes). The chunks of code work as expected when ran individually, however, when running both chunks the first sub-breed of the fishes does not seem to initialise in the interface tab. For some reason the initialisation of the shark breed seems to interfere with the initiation of the fishes breed.
Any idea what i'm doing wrong? Code below.
; Create the agents
breed [sharks shark]
breed [fishes fish]
; Create the agents' variables
fishes-own
[
x0
y0
]
globals
[
species
species-f
]
to setup
; Always start with this
clear-all
reset-ticks
; Create sharks and species
create-sharks N-sharks ; N-sharks is a slider
[
set color blue
setxy random-xcor random-ycor
set species N-sharks
ask sharks
[
set shape "default"
set size 2.5
]
ask sharks with [who >= (species * (1 / 2))]
[
set shape "square"
set size 2
]
ask sharks with [who < (species * (1 / 6))]
[
set shape "star"
set size 3
]
] ; End create sharks and species
; Create fishes
create-fishes N-fishes
[
setxy random-xcor random-ycor
set x0 xcor
set y0 ycor
set species-f (N-fishes * species-ratio)
ifelse who <= species-f
[
set shape "sheep"
set size 5
]
[
set shape "cow"
set size 3
]
set color white
] ; End create fishes
end
There seem to be a number of misunderstandings about what code is run when by NetLogo, and what some pieces of code do: when you use create-turtles *number* [*commands*] (or with breeds, as in your case), commands is run once by every turtle being created (first the new turtles are created, then they run the commands in turn).
That means that every time you use ask sharks within the create-sharks' command block, every new shark will ask all other sharks to set shape and size. For example, if you create 100 sharks, instead of setting the shape and size only once you are doing it 10,000 times (100 * 100).
So you need to put all those commands out of their respective create-<breed>'s command blocks; for example:
create-sharks N-sharks [
set color blue
setxy random-xcor random-ycor
]
ask sharks [
set size 2.5
]
ask sharks with [who >= (species * (1 / 2))] [
set shape "square"
set size 2
]
ask sharks with [who < (species * (1 / 6))] [
set shape "star"
set size 3
]
This is still improvable code, but it shows how to achieve exactly the same thing by doing it once and not doing it N-sharks ^ 2 times.
A better way to do it is to bring those commands back inside the create-<breed>'s command block, but letting each agent carry out the task for itself only. That is, without using ask sharks but using ifelse, so that each shark will check its own condition:
create-sharks N-sharks [
set color blue
setxy random-xcor random-ycor
(ifelse
who >= (species * (1 / 2)) ; the first condition
[set shape "square" set size 2]
who < (species * (1 / 6)) ; the second condition
[set shape "star" set size 3]
; else
[set size 2.5])
]
All of this applies to the other breed too.
It is generally said that using who is a sign that the code should be improved, but let's not focus on this now.
You will have noticed that I omitted the part where you set species N-sharks. This is because I think there is another misunderstanding here and it is not clear to me what you wanted to do: species (such as species-f for the other breed) is a global variable. You are basically asking each of the 100 sharks (again, 100 for example) to do the same thing: set the value of a global variable to equal the value of another global variable. In this case, you are asking each shark to set species 100. This seems very unnecessary, especially considering that N-sharks is a slider used for setup and thus probably won't be changed during the simulation (which means that there is probably no need to store the current value of N-sharks as a separate global variable).
Why are you basing the repartition of your sub-breeds on the value of species? What do you want species to represent? Is it correct for it to be a separate variable from N-sharks? If yes, then it is not clear what is its point; if no, then it can be eliminated.
You need to make sure that whatever you wanted to do with N-sharks & species, and with N-fishes and species-f, is better reflected in your code.
Also because I think this is the reason why your first fish sub-breed isn't showing. First of all, what is species-ratio? It is not present in your example, but it seems to be relevant for your question. In any case, if your first fish sub-breed isn't showing, it means that there is no fish who satisfies the condition who <= species-f.
This doesn't surprise me. who numbers are progressive for turtles: if you create 15 sharks and later you create 10 fish...
... the oldest shark will have who = 0
... the youngest shark will have who = 14
... the oldest fish will have who = 15
... the youngest fish will have who = 24
As you can see in this example, there is no fish for which who <= N-fishes (where N-fishes = 10). Let alone that in your case you set species-f (N-fishes * species-ratio) and, although you didn't tell what species-ratio is, I imagine it is a value between 0 and 1 - thus making the value of species-f even smaller.
The problem is that you are using who to determine your fishes. To quote the Netlogo programming guide: "Who numbers are assigned irrespective of breeds. If you already have a frog 0, then the first mouse will be mouse 1, not mouse 0, since the who number 0 is already taken."
As such, you need to take the number of sharks into account for determining the cutoff point for your fish species
set species-f (N-fishes * species-ratio) + N-sharks - 1
One other comment I have on your code is that you use the following structure:
create-sharks N-shark [
ask sharks [...]
]
Every shark executes the entire command block of create-sharks. That means that every shark asks every shark to do something. Thus follows that every shark sets their shape to default N-shark times.
It is much more efficient to use one of the following constructions
create-sharks N-shark [...]
ask sharks [...]
or
create-sharks N-shark [
if <condition> [<reshape-self>]
]

NetLogo chain of turtles breaks up when linking

I'm doing a model of some chains of cells (as part of a larger DNA string model). They wiggle around on screen, and when they wiggle so much, that they come close to a cell of the same type in the same string, they must create a link with that cell.
Code below.
It kinda works.... But after I introduced the linking behavior described above, the string breaks into pieces after a short while. I can't figure out why :-) Any ideas?
Thanks,
Palle
breed [cells cell]
cells-own [paired?]
globals [chains]
to setup
clear-all
set chains []
addchain
reset-ticks
end
to go
foreach chains [c -> movechain c]
ask cells [if any? other cells-here with [label = [label] of myself and paired? = false] [
let makker one-of other cells-here with [label = [label] of myself and paired? = false]
create-link-with makker [tie]
set color red
set paired? true
ask makker [set color red set paired? true]
print word label " was found!"
]]
tick
end
to addchain
set chains lput makechain chains
end
to movechain [mylist]
let antalfollowers length mylist - 1
let i antalfollowers
repeat antalfollowers [
ask item i mylist [
move-to (item (i - 1) mylist)
]
set i i - 1
]
ask first mylist [
right random-float wigglefactor
left random-float wigglefactor
fd 1
]
end
to-report makechain
let mylist []
let text "MGIVEQCCTSICSRYQ"
let startx random-xcor / -3
let starty random-ycor / -3
let i 0
repeat length text [
create-cells 1 [
set color green
set shape "circle"
set label item i text
set paired? false
set mylist lput self mylist
setxy startx + i * .75 starty + i * .75
]
set i i + 1
]
report mylist
end
OK - I finally figured out what's going on. This was hard to see. The tricks I used
in order to see it are listed at the bottom of this post.
In the case of a single strand of synthetic DNA floating around,
when two cells of the same type hit and stick, at that point there will
be a loop of all the cells that were between the moving cell and the
cell that got run into in the list of the sequence of cells.
What you need to do is to:
(a) take the cell that just got run into and link it and tie it to the moving
cell, making the moving cell the MASTER of the link [tie]. You do that
already.
(b) remove the cell you just made a SLAVE from the list of cells your code
has to move, because it will now be moved automatically when the master cell
moves.
AND ... importantly ...
(c) repeat steps (a) and (b) for EVERY cell on the list in positions between
the two cells that just collided and stuck.**
That will effectively freeze the configuration of the entire loop and make it
into a single large unit that will move as one unit when the master cell is
moved by your code.
The User Manual states in the subsection on TIE in the section on LINKS:
When the root turtle turns right or left, the leaf turtle rotates
around the root turtle the same amount as if a stiff were attaching
the turtles. When tie-mode is set to “fixed” the heading of the leaf
turtle changes by the same amount.
I think that you do want to set tie-mode to FIXED so the whole cluster will rotate when the master cell rotates.
I think, but have not looked at it, that this algorithm will work even if the linked cell is the very first or very last one on the chain. Better check it though. Maybe the cell that should be the MASTER is the one that got hit, not the one doing the moving.
In the case of two different strands of DNA intersecting,
basically forming an X, or more complicated cases ... I leave it up to you to figure out what you want the larger connected structure to do, and how hit should move. Do BOTH of the leading cells of each strand tug on it at once? Do you need to shut off one of them so there is only one cell moving the crowd? Will you need to change your code that moves the chain to insert one of the chains entirely into the middle of the other chain on the list that moves them in sequence? I don't know!
By the way, to figure this out, I had to:
slow down the motion and
set the color of the cells to [0 255 0 125] which is a half-transparent green
so I could see through them and see through them overlap, and
use the "watch" feature of the Inspector to follow one of the cells I knew
was going to get linked up, and
use the slider in the inspector to zoom up as far as it would go, and
put a 500 millisecond "wait" in side the innermost loop of the motion.
I'm working on your question and have made some progress -- at least I have a revision of your code with some troubleshooting additions to it, and a revision of the Interface. I can't figure out how to attach a model here, or an image of the view you will see when you run it, so I posted the full model and a PNG file in the netlogo-users Google Group.
The revisions do not fully answer your question about how to solve the breaking up of the chain, but they provide a reproducible version of the model that you can be sure will break at step 746 and that you can turn on dense printing and slow action and watch what is going on with attempted moves after that.
Maybe if we both look at that it will be obvious why this is breaking.
One thing I think may be happening is that, once two cells link and tie, your move algorithm no longer is the correct logic for how the knotted chain should move.
Here's the changes that I made:
I added a random-seed command in setup so that the model can be repeatedly run with exactly the same choices in random variables, so we can both look at the results.
I added a "verbose?" switch on the Interface to turn on or off detailed printing of what's going on.
I added a "clear-stop" button that will allow the "stop" commands I put in the model to stop the running using a stop-requested? flag, which the code sets and this button resets so that "go" and "one step" work again after a stop and the ticks counter keeps on incrementing.
I added a msec-per-tick slider to put a fixed number of milliseconds at the end of the go step so the model will run at a speed that is usable for debugging. I don't know how other people can do it -- when I try to use the built-in slider at the top of the interface to control speed, either it's way too slow, or it's way too fast, and I can't seem to be able to tweak it to just right. So I added this kludge.
I guessed what limits you had on your wigglefactor slider on your interface and made one that goes from 0 to 90 (degrees). It works ok and reproduces your bug.
I added some additional tests to prevent the two C-cells that are adjacent in your choice of cells from linking to each other when they discover, as they do sometimes, that they are on the same patch. With a random seed of 23456 your original code ties its own CC adjacent pair together in tick 2 for instance.
(
Here's the revised code, and comments as to how to use it are in the posted model (in netlogo-users) and below after the code as well.
breed [cells cell]
cells-own [paired?]
globals [
chains
stop-requested? ;;//////////////////////////////////////////////////
]
to setup
clear-all
;; random-seed 12345 ;; /////////////// breaks at either step 35 or 45 ////
;; random-seed 23456 ;; ////////////////// ties its own CC in tick 2 ///
random-seed 34567 ;; /////////////////// ties own cc in tick 84 , ties C at 746 and breaks in 6 steps
;;// wow -- it SNIPS TSIC out of the middle of the chain!! snips out CTIS, turtles 7 8 9 and 10
;; cell 6 C is directly followed by cell 11 -- also C
set chains []
addchain
set stop-requested? FALSE ;; ////////////////////////////////////////
reset-ticks
end
to go
if stop-requested? [ stop ] ;;////////////////////////////////////////////
foreach chains [c -> movechain c]
ask cells [if any? other cells-here with [label = [label] of myself and paired? = false
and who != [who] of myself + 1
and who != [who] of myself - 1
] [
let makker one-of other cells-here with [label = [label] of myself and paired? = false]
create-link-with makker [tie]
set color red
set paired? true
ask makker [set color red set paired? true]
print ( word label " was found at tick " ticks)
set stop-requested? TRUE ;;/////////////////////////////////////////////
]]
wait ( msec-per-tick / 1000 ) ;;////////////////////////////////////////
tick
end
to addchain
set chains lput makechain chains
end
to movechain [mylist]
if verbose? [print ( word "\n\nin code at tick " ticks " starting movechain") ];;//////////////
;;if verbose? [ show mylist ]
let antalfollowers length mylist - 1
let i antalfollowers
repeat antalfollowers [
ask item i mylist [
if verbose? [
;;print (word " asking item " i " on mylist to move to item " (i - 1) )
let mover [label] of item i mylist
let moveto [label] of item (i - 1) mylist
let mover-color [color] of item i mylist
let moveto-color [color] of item (i - 1) mylist
;; BLUE one moves TO the YELLOW ONE at the end of this second
print (word " move " mover " to " moveto )
ask item i mylist [set color blue set shape "square" set size 2]
ask item (i - 1) mylist [set color yellow set shape "square" set size 2]
display
wait 4
ask item i mylist [set color mover-color set shape "circle" set size 1]
ask item (i - 1) mylist [set color moveto-color set shape "circle" set size 1]
display
]
move-to (item (i - 1) mylist)
;;print word "just moved follower " i ;;//////////////////////////
;; wait 0.1 ;;////////////////////////////////////////////////////
]
set i i - 1
]
ask first mylist [
right random-float wigglefactor
left random-float wigglefactor
fd 1
]
end
to-report makechain
let mylist []
let text "MGIVEQCCTSICSRYQ" ;; NOTE - this has a repeat of CC in it which SOMETIMES gets tied (23456 tick 2)
let startx random-xcor / -3
let starty random-ycor / -3
let i 0
repeat length text [
create-cells 1 [
set color green
set shape "circle"
set label item i text
set paired? false
set mylist lput self mylist
setxy startx + i * .75 starty + i * .75
]
set i i + 1
]
report mylist
end
to clear-stop ;;////////////////////////////////
set stop-requested? FALSE ;;////////////////////////////////
end ;;////////////////////////////////
Anyway, here's how to run it to reproduce the problem and examine it
in fine detail very closely.
WHAT IS IT?
model of DNA in motion modified for troubleshooting. When a "C" cell
touches another "C" cell in step 746, and sets a link between the two
C cells and ties them to move as one, the algorithm for motion
breaks somehow. This may help figure out why,
HOW IT WORKS
This has added to it a msec-per-tick slider, default 50, to set the
display speed about right if you leave the usual speed slider at the
very top in the middle (normal).
I also added a button ("clear stop") and a switch ( verbose?)
normally off. With verbose? ON, the model runs very very slowly and
color codes which cell is about to move to which cell ( blue is moving
to yellow ) and they both temporarily change to squares.
HOW TO USE IT
1) set msecs-per-tick to 50 2) shut off verbose?, click SETUP, click
GO. The model will run 746 ticks. ( thats with the random-seed set to
a value of 34567 in globals. )
3) After it stops at tick 746. click clear-stop.
NOTICE the CTI group at the upper right. This is logically BETWEEN the
two C-cells which have linked up. This group will be snipped-out of
the moving DNA It has who numbers 7, 8, 9 and 10 as you can see by
inspecting it.
4) click one-step 6 times to advance to where you can see more clearly
that the two groups have become separate. Then turn on verbose? and
click one-step once to watch the gory details with a 4 second pause
between cell-moves and the running commentary in the Command Center
telling which cells are about to move.

Netlogo: How to compute sum of items of lists within a list?

I would like to make the sum = the total of pollen recieved by a plant from other plants (Donnors) which is stored in a list of a list (own by each turtle = plant).
The following code make an error (when computing the sum):
OF expected input to be an agent or agentset but got the list
[[119.05593 50 50] [301.25853 50 50] [30.23906 50 50] [460.525845 50
50] [55.16717 50 50] [301.25853 50 50]] instead.
Does any one could help me about the mistake in the line "set Tot_pol sum ..." ?
Many thanks for your help.
to check-pol [m] ;; we check the pollen recieved by the two morphs
set Donnors [] ;; empty list of pollen donnors
ask zsps with [morph = m] ;; morph of the pollen reciever
[
set totpol 0
;; check for pollen donnors and morph for compatiblity within a radius :
ask zsps with[distance myself <= 20 and morph != m]
[
set totpol (NMaleFlowers * 100 * item round (distance myself) pollination-list) ;; the farther the less pollen
set Donnors lput [ (list totpol NMaleFlowers NFemFlowers)] of myself Donnors
]
set Tot_pol sum [ item (position 0 Donnors) Donnors ] of Donnors ;; total of pollen recieved
]
end
Luke's answer is good and should fix your problem. I suspect, however, that you are going to be doing lots of these types of sums. You may wish to set up a to-report that you can use for whichever item you want to sum over, just by passing the item number and the name of the list of lists. It would look like this:
to-report sum-item [#pos #listoflists ]
let items map [ x -> item #pos x ] #listoflists
report reduce [ [a b] -> a + b] items
end
The first line extracts the relevant item (remember index from 0) into a new list which the second line sums.
You would then use it with set Tot_pol sum-item 0 Donnors
Here's an answer that is not actually responding to your question. Instead, it is a more NetLogo-ish way of doing what I think you are trying to do with your code.
to check-pol [m]
ask zsps with [morph = m]
[ let senders zsps with [distance myself <= 20 and morph != m]
set totpol sum [NMaleFlowers * 100 * round (distance myself)] of senders
]
end
Your code gets into levels of ask that I think are unnecessary. What I think you are doing with your list is keeping track of the pollen donors. But an agentset is a cleaner approach and then you can simply pull out the information you want from the agentset using of.
Further, when you ask zsps with[distance myself <= 20 and morph != m] to set variable values in your code, then THOSE agents (not the receiving agent) are the ones having their variables changed. I think you are trying to take the perspective of the receiver of pollen, who looks around and received pollen from the other agents that are close enough. So the receiving agent should have the value changed.
This is not tested.
I'm not 100% sure what you're after here (you may want to look at the Minimum, Complete, and Verifiable Example guidelines), but if I'm reading you right you want the sum of the first item for each entry in the Donners list.
As to why your approach didn't work- NetLogo is telling you with that error that you've used of with a list, but of only works with agents or agentsets. Instead, you have to use a list processing approach. The simplest way might be to use sum in conjunction with map first in order to get what you need:
to sum-first-item
let example-list [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]
let sum-of-firsts sum map first example-list
print sum-of-firsts
end
To translate to Donnors, try:
set Tot_pol sum map first Donnors
That should work, but without reproducible a code example I can't check.

Netlogo error when using procedure from code example Many Regions Example procedure

I'm new in Netlogo . I'm trying to use the code included in the Many Regions Example of the library. But I get one error in this procedure
to keep-in-region [ which-region ]
if region != which-region [
let region-min-pxcor first item (which-region - 1) region-boundaries
let region-max-pxcor last item (which-region - 1) region-boundaries
let region-width (region-max-pxcor - region-min-pxcor) + 1
ifelse xcor < region-min-pxcor [
set xcor xcor + region-width ]
[if xcor > region-max-pxcor [
set xcor xcor - region-width
]
]
]
The error I get is .... any advices? Thanks in advance
-1 no esta mas que o iqual a cero.
error while a-seller 31 running ITEM
called by procedure KEEP-IN-REGION
called by procedure ADJUST
called by procedure GO
called by Botón 'go'
The error you are getting ("-1 isn't greater than or equal to zero.", once translated to English) is caused by passing -1 as an index for the item primitive.
There are two lines in the code that make use of item:
let region-min-pxcor first item (which-region - 1) region-boundaries
let region-max-pxcor last item (which-region - 1) region-boundaries
As you can see (which-region - 1) is the expression passed to item as index. If you are getting -1, it must be because which-region = 0.
In the "Many Regions Example" model, region 0 is reserved for the patches that are not part of any regions, namely, the patches that act as region boundaries. The regions themselves are numbered from 1.
Look in your code for the place where keep-in-region is called and make sure that you are using a region number that is between 1 and the number of regions you have (inclusively).
Disclaimer: I originally wrote the "Many Regions" code example. Maybe I could have used a value like nobody for the patches outside of any region and number the actual regions starting from 0 instead of one, but I don't remember if I actively decided against it or just didn't think of it.

subsetting agentsets transforming a list of agents into an agentset

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