I am struggling with trying to write this command.
Basically, what I want to do is this:
I have a collectors [own carryingcapacity], bins [own waste in bins] and warehouses [own waste_in_warehouse] as turtles.
The collectors have a maximum carrying capacity value.
I want to make the collectors check if they have carrying capacity when they find a bin, if trash in bin <= collectors max capacity, the collectors will collect, if not they'll ignore the bin.
I came up with something like this:
ask collectors
[
if any? bins with [distance myself <= 1]
[set carryingcapacity (carryingcapacity + (bins_holding_capacity of myself))]
]
Second command:
I want to make the collectors take the trash they collected to the warehouse. But this variable's value might change from one collector to another, and might vary with the quantity of bins they checked.
I want the warehouse to sum the value that it already had it on the previous days with the new daily values.
I came up with something like this as a line of command:
ask warehouses
[
if any? collectors with [distance myself <= 1]
[set waste_in_warehouse ( waste_in_warehouse + (carryingcapacity of myself))]
Thank you in advance.
Best wishes.
If I'm understanding correctly, your code for command #1 is doing the following:
ask collector agents
See if there are any bins close to a collector (but you didn't ask for this group)
increment the collector's carryingcapacity by (bins_holding_capacity) of myself (you can't use myself like this, because you aren't in a nested ask)
Step 3's logic also seems wrong, since this would be changing the collector's capacity each time, as opposed to checking if it is full.
It should be noted that by using any?, you are not also commanding that group of agents. any? only returns true or false, corresponding to whether there were agents that met the criteria or not. You need to use a second ask to command these agents.
Based on what you said, you'll need to do something like this:
ask collectors
[
ask bins with [distance myself <= 1] ;;myself refers to the collector asking
[
ifelse (waste_in_bin + [waste_in_collector] of myself) > [carryingcapacity] of myself
[;;add the waste to the collector]
[;;stop asking bins, collector is full]
]
]
These same steps should help with your second question, too.
Related
Looking for a way to store a turtle length of stay in the model after they have left the model. My model runs for several months and a few thousand turtles enter, undergo process then leave the area. It's complicate model (it's a hybrid DES and ABM) so I've tried to reproduce the simple bit below.
Turtles will be created at every tick and given a random length of stay but will only be able to begin process when they move to the right area (area-name) and when their time is up they leave the area. Their time-in-system reflects the wait for the area and the length-of-stay which I want to save once they're complete. If I leave them in the model it starts to break down after a couple of months and I suspect this is because the model has too many turtles still in the system for calculation and is inefficient.
go
create turtles 2
[
set time-in-system 0
set length-of-stay ceiling ((random-normal 48 4) + ticks)]
set shape "person"
if any? area-name with [not any? turtles-here]
[move-to one-of area-name]
]
undergo-process
end
to-undergo-process
ask turtles with [shape = "person"]
[
set time-in-system time-in-system + 1
]
ask turtles-on area-name
[if ticks = length-of-stay
[set shape "dot"
move-to exit-door]
end
I can then plot and see in realtime to make sure it is working
histogram time-in-system of turtles with [shape = "dot"]
but can't seem to figure out how to store them as unique values for plotting after the model has run and I have a dataset of outcomes without keeping them alive in the model. The real-time plot isn't necessary as long as I can store the unique values after they have left
If I ask them to die then I lose the unique values in the histogram. I don't want a tally of all values but each turtle's unique value at the end of the process after they left - at the moment the only solution I have to storing them is as an agent-set that stays alive in the exit-door patch but this takes up a lot of calculation power as the model progresses for months...
There may be a really simple command for this but I've been going round in circles through the programming manual trying to find it. Any tips appreciated
You should create a list storing the values of turtles that left.
Isolating only the code that is relevant for this purpose, it would be something like:
globals [
times
]
to setup
set times (list)
end
to leave-simulation ; This being executed by turtles.
set times lput (time-in-system times)
die
end
If your program is going to run for actual months, I recommend you use the file-write command to store your data. This way the data is preserved if the program halts for any reason; it gives you much more freedom to do the analysis you want without running the full simulation again.
If you write to a .csv (comma separated value) file, you can use almost any program (excel, R, matlab, python, C# or back to netlogo) to plot a histogram.
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] [...]
I'm working with a NetLogo model on EV charging behaviour. All (500) agents monitor their my-charging-demand per tick and I want to find out what happens to this emergent behaviour when I change the policy intervention that is active (costs of electricity in this case). I am trying to show changes in charging characteristics such as charging-duration, charging power etc.
What is the best way to create data on the agents' my-charging-demand in time?
Right now I am plotting all their data in one graph using the following code:
ask adopters
[ create-temporary-plot-pen (word-who)
set-plot-pen-color color
plotxy ticks my-charging-demand
]
It works, but unfortunately it also made the model incredibly slow, as 500 pens are to be updated every tick. The model needs 105120 ticks before a whole year/run is completed, as each tick in the model represents 5 minutes. Therefore, speed does matter :-)
Is there a more efficient way to keep track / create data of one variable all agents have?
If I have understood this correctly, you want each agent to remember the value of its variable my-charging-demand across all time. If so, the easiest way (but I don't know if it's more efficient) is to have the list as a turtle variable. So, modify your turtles-own to add another variable:
adopters-own
[ ....
my-charging-demand
my-charging-demand-series
]
And wherever you have the code for calculating demand, add the result to the list
ask adopters
[ ...
set my-charging-demand ...
set my-charging-demand lput my-charging-demand my-charging-demand-series
...
]
I can't imagine a plot with 500 lines is readable. The plot should do something like the average of my-charging-demand or the proportion of turtles with my-charging-demand greater than some threshold.
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, 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.