NetLogo foreach list - netlogo

I am trying to create a code that will allow me to get the who numbers of 10 turtles and store them in a list. However, the "who" number can only be added to the list if it has not been added to the list before.
I have to use the "foreach" command to check if the number has already been added to the list.
Any suggestions on how to do so?
My code:
turtles-own [contact-list]
to setup
clear-all
create-turtles 10 [
set contact-list []
print who
]
reset-ticks
end
to go
ask turtles [
set contact-list lput [who] of one-of other turtles-here contact-list
foreach contact-list[
; this is where the command goes
]
print contact-list
]
end

Might it be easier to add all the who numbers to the list and then use the remove-duplicates primitive to remove the duplicate numbers? I assume that you have a reason for putting who numbers into the list rather than having a list of the agents themselves, or an agentset. In general, who numbers are to be avoided.

Related

How to report agent variables in a consistent order in Netlogo's Behaviourspace

Picture of my behaviourspace menu
I'm working on an agent based model where a variable (agentvariable1) owned by all agents changes every tick. I want to report a time series for the values of this variable for every agent using Behaviourspace.
However, when I measure runs using the following reporter
[agentvariable1] of turtles
the values that are reported for agentvariable1 are randomly shuffled, because "turtles" calls all turtles in a random order, which is different every tick. Because of this the data that is exported is not usable to create a time-series.
Is it posstible to create a reporter in Behaviourspace that reports the values of the agentvariable1 in a sequence that remains the same every tick?
Using sort on an agentset creates a list of those agents sorting them by some criteria. In the case of turtles, they are sorted by their who which means that their relative order will always be the same.
However you cannot directly do [agentvariable1] of sort turtles, because of expects an agent/agentset but you are giving it a list.
What you can do is creating a global variable as a list: at each tick the list is emptied, and later all turtles (sorted as per sort) will append their value to the list.
That list is what you will report in your Behavior Space.
globals [
all-values
]
turtles-own [
my-value
]
to setup
clear-all
reset-ticks
create-turtles 5
end
to go
set all-values (list)
ask turtles [
set my-value random 10
]
foreach sort turtles [
t ->
ask t [
set all-values lput my-value all-values
]
]
show all-values
tick
end
As an alternative to Matteo's answer (which is perfectly suitable and directly addresses your intention, I just present another option depending on preference) you could also pair the variable of interest with some turtle identifier and report that as a list of lists. This adds a bit of flexibility in cases where the number of turtles increases or decreases. In this example, I use who and xcor for simplicity, but you may want to create your own unique turtle identifier for more explicit tracking. With this toy model:
to setup
ca
crt 5
reset-ticks
end
to go
ask turtles [
rt random 30 - 15
fd 1
]
tick
end
to-report report-who-x
report list who xcor
end
At any point, you can call the list with [report-who-x] of turtles to get a list of lists. With a behaviorspace setup such as:
you get an output that would look something like:

ask turtles - ordering of agentset

I would like to apply some process stochastically, but the order matters, or rather it should be done at random, how can I select a set of the same turtles to "treat" but to do it such that each tick, the order is random?
ask turtles [
;; apply a process to turtles, but not all turtles will get something as the pool of energy may have run out by the time they are selected.
]
Elements of agentsets (such as turtles) are always returned in a random order. Each time you use ask with an agentset, it will ask them in a new, random order. From the docs on agentsets:
An agentset is not in any particular order. In fact, it’s always in a random order. And every time you use it, the agentset is in a different random order. This helps you keep your model from treating any particular turtles, patches or links differently from any others (unless you want them to be). Since the order is random every time, no one agent always gets to go first.
And here is a quick example to demonstrate. If you run it in the Command Center you'll see the who numbers will be different each time you ask them to be shown.
to test
clear-all
create-turtles 10
show "Asking once..."
ask turtles [ show who ]
show "Asking a second time..."
ask turtles [ show who ]
end
And here is an example showing an energy pool that will be randomly used until it is gone. Note the turtles that will get to use it are whichever happen to come first out of the agentset for ask:
to test-pool
clear-all
let energy-pool 1000
create-turtles 100
ask turtles [
; can only act if some energy is left...
ifelse energy-pool > 0 [
let energy-use (min (list random 100 energy-pool))
set energy-pool (energy-pool - energy-use)
show (word "I used up " energy-use " energy points! " who " Only " energy-pool " points left")
] [
show (word "No energy left for me! " who)
]
]
end

NetLogo - Sum lists of all turtles

I am having trouble with summing lists of all turtles and am not sure where I am going wrong.
For instance, in the following code I would like to show the total number of apples among all the turtles. Every time I run the code I get a value of 0, when it should in theory be 100. I am not sure what the error is. Any assistance would be much appreciated!
turtles-own [ apples ]
to test
clear-all
create-turtles 5 [
set apples []
set apples lput 20 apples
]
show sum [apples] of turtles
end
The following code and test should sum all the numbers in all the turtles' lists.
turtles-own [ apples ]
to test
clear-all
create-turtles 5 [
set apples []
set apples lput 20 apples
set apples lput 10 apples
]
ask one-of turtles [set apples lput 30 apples]
show sum map sum [apples] of turtles ; here's the key command
end
map sum [apples] of turtles sums the number in each turtle's list and puts those sums in a list, and then the first sum adds them all up. I made one turtle's list longer than the others' just to be sure that all the lists do not need to be the same length.
Hope this helps,
Charles

Netlogo: asking "up to a maximum number"

Is there a way to ask up to a certain number of patches? For example, ask up to 100 patches but there are only 50 available, so the action takes on this 50 patches. Thanks.
The way to do this at the moment would be something like:
to-report at-most [n agents]
report ifelse-value (n <= count agents) [ agents ] [ n-of n agents ]
end
You can then say ask at-most 100 patches [ ... ] and you will get what you want.
Note that this doesn't work if there is a chance that your variable contains nobody instead of an agentset. In that case, you can convert nobody to an agentset using patch-set, turtle-set or link-set, depending on the type of agent you expect it to contain. For example:
ask one-of turtle-set other turtles-here [ ... ]
Note that the need to jump through all these hoops might disappear in the near future. There is currently an open proposal to add a primitive to NetLogo for handling these cases: https://github.com/NetLogo/NetLogo/issues/1594.

How to 'ask' all turtles in a list

I would like to use ask to loop over all of my turtles, but I do not want the order to be random. My solution is to add all of the turtles to a list, sorted by their ID, and then loop over this list:
let sorted-turtles sort-on [who] turtles
foreach sorted-turtles [
x -> ask x [ ; x is the turtle
; do something
]
]
That works correctly, but vastly slows down my model.
My question is: is this the best way to ask all the turtles to do something in a pre-defined order?
I have tried using ask on the list directly (e.g. ask sorted-turtles [ print who ] but NetLogo says that ask needs an agentset rather than a list.
Thanks in advance,
Nick
First, you can use sort turtles instead of sort-on [who] turtles. It does the same thing, but it's shorter and more idiomatic. Not sure if it's faster, though (it might help a little bit).
The foreach sorted-turtles [ x -> ask x [ ... ] ] pattern should be fast enough. It's the list creation that is costly.
The main thing you can do to improve the speed of your model is thus to store the sorted list of turtles in a global variable and reuse that list instead of re-sorting every time.
That would only work, however, if you're not constantly creating and/or killing turtles, it which case you would have to re-create the sorted list every time.