Netlogo: is nobody still being treated as an agent? - netlogo

I have a list of parcel agents. but I will kill the parcels periodically. However, the list is still recording someting like this: [nobody nobody nobody nobody nobody nobody nobody nobody], and overtime the running of the model is getting slower and eventually pop up message "your model is too large to run with available memory"
In this case, are the dead agents (i.e. nobody) still treated as an agents that consumes much of the memory? what if it is a pure list of numbers or strings? would it cause the same OOM issue? how big the list can be in Netlogo and any uppper limit?

From, the NetLogo dictionary for die: If you have a list of agents and the agent dies, then the agent is removed from any agentset and:
The agent will disappear from any agentsets it was in, reducing the size of those agentsets by one.
Any variable that was storing the agent will now instead have nobody in it
The dead agents are not consuming resources, but the list is (as you have found by printing out the list). You can see this with the following model:
globals [mylist myagentset]
to setup
clear-all
create-turtles 1
set mylist sort-on [who] turtles
set myagentset turtles
reset-ticks
end
to go
create-turtles 1
[ set myagentset (turtle-set myagentset self)
]
set mylist lput one-of turtles mylist
ask one-of turtles [die]
type "turtles: " print count turtles
type "list: " print length mylist
type "agentset: " print count myagentset
tick
end
If you want the dead turtle to be removed from the list, you need to explicitly do so with remove-item. The same is true of lists of numbers, strings etc.
Alternatively, if the list doesn't need to be maintained over ticks, but can be reconstructed (eg if it is a sorted list of the turtles agentset), you could create it each tick and that list would only contain turtles that are alive.

Related

Problem making a calculation in a monitor on the interface in Netlogo

I have a model that tracks energy levels in sheep, which I have defined as a breed. I have set up a monitor to calculate the mean energy level for the sheep, but need to consider what happens if there are no sheep at some point. I have tried numerous variations, the simplest of which is:
ifelse (any? sheep) ["NA"] [mean [energy] of sheep]
Unfortunately, I keep getting the error
Expected reporter.
I can work around this by creating a new global variable and reporter in the code, but this seems to be a bit of a waste. Am I doing something wrong or are there limitations on what kind of calculations can be done in a monitor on the Interface? If so, where are these limitations summarized?
Answer in three steps:
Difference between ifelse and ifelse-value
You are getting a syntax error there because a monitor expects a reporter, but ifelse is made to handle commands. The reporter version of ifelse is ifelse-value. If you just change ifelse to ifelse-value in your example, you see that you don't get any syntax error anymore. However, you will also see that if you do so and start your model with sheep having their energy, the monitor will show NA - see next point.
Correct use of any?
This happens because you are using any? the other way around. As you can see, any? reports true if the agentset is not empty. This means that the following reporter:
ifelse-value (any? sheep) ["NA"] [mean [energy] of sheep]
will report "NA" when there are sheep in the model, because that is the first reporter block.
Switch to:
ifelse-value (any? sheep) [mean [energy] of sheep] ["NA"]
and you have what you want. Just as in English: "If there are any sheep, do the calculation, else, this does not apply".
In any case, this does the job but it is superflous - see next point.
What monitors can do
Monitors are able to handle some of their reporters' runtime errors. You can simply put mean [energy] of sheep in your monitor and it will automatically show N/A when there are no sheep, without the need for you to handle the case.

Speed up an age and position check for turtles in R?

I'm writing a program that is testing the ability of turtles to navigate in an environment. This line of code has two checks. I want it to kill off the oldest turtle that has made the least amount of progress. It does what it is supposed to, but the program slows down dramatically, creating little hiccups every time it makes this check. I was wondering if someone knew a better way to go about this or make this line more efficient. Thanks!
ask one-of turtles with [XCOR = min [XCOR] of turtles with [age = max [age] of turtles]] [
die]
First of all, there are primitives that are specifically finding the turtles with maximum or minimum values of some variable using min-one-of or with-min. So your code would look something like this I think:
ask min-one-of (turtles with-max [age]) [xcor] [...]
I suspect that would solve your efficiency problem, since it may well be because of implicit brackets not being where you think they are so it's trying to loop everything a couple of times. But a much cleaner to read version that would solve the efficiency problem is to specifically limit the position loop to those who are oldest and then choose the lowest position from that set.
let old-turtles turtles with-max [age]
ask min-one-of old-turtles [xcor] [...]

How do I count the number of unique interactions between turtles in my model?

I am writing a NetLogo model to describe the food exchange interactions between pairs of bees until the food is distributed evenly among all. I have two breeds of "fulls" and "hungries" in my model. Right now I am counting the number of interactions until the model stops, like this:
ask turtles [
set neighborhood other hungries-on neighbors
set target one-of neighborhood with-min [distance myself]
ifelse target != nobody
[ exchange-food
set counter counter + 1]
;if there are no hungry neighbors continue moving and searching for one
[continue ]
]
The counter here, counts all the exchange-food interactions but I am also interested in the number of unique interactions. Does it mean that I have to keep a list of tuples as a turtle-own variable for each turtle! But I don't even need the actual ids, I just want to count the number of unique interaction. How can I keep track of this? Any simpler ideas?

Turtle variable representing memory of other turtles

I have a model in which turtles navigate a graph of nodes (also stored as turtles) and links in discrete increments (using the move-to procedure). I would like to create a turtle based variable that allows turtles to remember the number of times they have visited particular nodes in the graph.
e.g.
turtle move-to a node
look up the presence of that node in the desired structure
if it exists set #visits #visits + 1 associated with that node
if not include it in the structure and set #visits 1
I imagine my options are related to lists or tables - however I am not sure which of these will be most efficient. With regards to tables I don't think the key can be a turtle - perhaps a string derived from its who - but this feels like it may be inefficient.
Two points that are likely pertinent:
some of the graphs will have a large number of nodes (~5000) , and often some of the turtles will never visit all of them, so it may be sensible to grow the structure on-the-fly to save memory.
there can also be a relatively large number of agents (~2500)
Any advice, as ever, much appreciated.
Tables are the more efficient way to go as well as easier codewise, though using agents as keys does not work (much to my surprise). That said, you can just use who numbers as keys.
It would look something like:
extensions [ table ]
turtles-own [ node-visits ]
...
to move-to-node [ node ]
move-to node
let key [ who ] of node
let visits ifelse-value (table:has-key? node-visits key) [ table:get node-visits key ] [ 0 ]
table:put node-visits key (visits + 1)
end
tables are efficient in both memory use and lookup speed. You could do this with lists and be efficient in memory use (if you use key value pairs) or lookup speed (if you use who numbers as indices or something) but not both, unless you basically write your own hash table implementation with lists.
Now, all that aside, you generally should worry about performance problems like these until you are:
having performance problems right now
know that these things are the source of your performance problems (by profiling either with the timer or with the profiler extension)
The real reason I suggest the table extension is because it's the simplest to implement.
I realize I am late to the party, and Bryan's answer is perfectly fine, but an alternative solution would be to use a separate breed of links to record the number of visits to a node:
breed [ nodes node ]
undirected-link-breed [ edges edge ] ; node <---> node
breed [ agents an-agent ]
directed-link-breed [ visits visit ] ; agent ----> node
visits-own [ num-visits ]
to setup
clear-all
create-nodes 10 [ create-edges-with n-of (1 + random 2) other nodes ]
create-agents 10 [ move-to one-of nodes ]
end
to go
ask agents [
let destination one-of [ edge-neighbors ] of one-of nodes-here
move-to destination
if out-visit-to destination = nobody [ create-visit-to destination ]
ask out-visit-to destination [ set num-visits num-visits + 1 ]
]
end
It might not be quite as fast as using the table extension, but it would have the advantage of allowing queries from both sides: you ask an agent how many times it visited which nodes, but you can also ask a node how many times it has been visited by which agents.

In NetLogo, what is the most efficient way to copy the values of variables in an agentset to another agentset with the same number of agents

In NetLogo, I have the same number of turtles on different patches. Now I want to copy the agent variable values of the agents on one patch to those agents on another patch. I know I can define a list of members for each patch, and then copy the values agent by agent according to the order of the list, but I have to define a list for each patch, which may take some memory and reduce the running speed.
In other words, I want the agents on one patch with their agent variable values the same as the agents on another patch.
Are there more efficient ways to do this?
I use something like this hatch makes exact duplicates of the original turtles same variables same color etc
targ is the patch you want them at
to dup-turtles-to [targ]
ask turtles-here
[
hatch 1 [move-to targ]
]
end
I hope that is helpful and I understood your question correctly.