i wonder if any netlogo expert can help me with the following: supposed my patches have 2 attributes (attr1 and attr2, say) and i need to compute a function of both attributes, as in this silly example
patches-own [ attr1 attr2]
to setup
clear-all
ask patches [set attr1 random 10]
ask patches [set attr2 random 20]
let mean-1 mean [attr1] of patches
let mean-2 mean [attr2] of patches
show mean-1
show mean-2
end
i would like to write a procedure which computes the mean (say) of any attribute i pass to it. something like:
ask patches [set attr1 random 10]
ask patches [set attr2 random 20]
compute-mean attr1
compute-mean attr2
end
to compute-mean #attr
let mean-1 mean [#attr] of patches
show mean-1
end
would anyone be able to help? thank you in advance
It would be a lot easier to compute-mean [attr1] of patches and not have to bother with extracting the values within your procedure. It also makes your procedure more flexible, allowing you to use it for subsets of patches.
If you want a procedure to be a calculation, it is better to write it down as a reporter procedure using to-report. This way you can use the output it generates in other parts of your code as well instead of just showing it.
to go-1
show compute-mean-1 [attr1] of patches
show compute-mean-1 [attr2] of patches
end
to-report compute-mean-1 [#attr-list]
let mean-1 mean #attr-list
report mean-1
end
Now if you really just want to pass your procedure the name of the attribute and not the list of values, you will need to pass it the name of the attribute as a string and then use run-result to interpret that string ("attr1") as if it is a reporter (attr1)
to go-2
show compute-mean-2 "attr1"
show compute-mean-2 "attr2"
end
to-report compute-mean-2 [#attr-name]
let mean-2 mean [run-result #attr-name] of patches
report mean-2
end
Related
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:
I have one doubt:
Context: I have a code in which, briefly, turtles have an integer variable (energy-collected) and from that, patches update their own variable (energy-of-my-agent), as described in the code snippet below.
Problem: The turtle variable is of type int (-1, for example), but the patch variable is a one-element list ( [-1] ).
Question: Should this happen? Otherwise, how can I make the patch variable just an integer value?
ask turtles
[
set energy-collected (energy - euse)
]
ask patches
[
set energy-of-my-agent [energy-collected] of turtles-here
]
Thanks in advance
The main thing you have to consider is what of reports.
In your case turtles-here is an agentset, not a specific agent.
This is because, although you might have a single turtle on a patch, you may also have multiple turtles on a patch. Therefore turtles-here reports an agentset, even if that agentset may be made of a single turtle.
It follows that a collection of values from an agentset, obtained with of (and [energy-collected] of turtles-here is exactly that), will be a list of values - even if that list contains only one element.
Therefore I would say:
Is your model made in such a way that each patch cannot have more than one turtle at a time? Then you could do:
ask patches [
if any? turtles-here [
set energy-of-my-agent [energy-collected] of one-of turtles-here
]
]
In the code above, one-of turtles-here reports a specific agent - not an agentset anymore.
So its variable's value, obtained with of, will be stored as a single value (provided that the agent's variable is not a list itself, but that's not your case).
Can it happen that your patches have more than one turtle at a time? Then, if you're interested in the single patch holding "its" turtles' values, dealing with lists is probably necessary.
Update
I made a connection between this question and your other one suggesting that you want to use patches as elements of matrices.
Maybe this is useful to your case: if your model allows for the possibility of having more than one turtle on the same patch, you might be interested in doing something like:
ask patches [
set energy-of-my-agent sum [energy-collected] of turtles-here
]
As you can see, sum takes a list as input and reports a number. Each patch will take the sum of all the values of energy-collected by turtles standing there, or you can change the calculation using whatever you want (e.g. mean, max etc).
Actually, you can use this approach regardless: this way, even when you have a single turtle on a patch, sum (or any other function taking a lost and returning a value) will give you a single value where before you had a list of one value.
The proejct I'm building is a little too big to post here; I think this snippet should suffice.
breed [CMs CM]
CMs-own [flag?]
to go
set flag? random 2
check-von-neumann-neighborhood
end
to check-von-neumann-neighborhood
create-links-with CMs-on neighbors4
ifelse mean flag? of CMs-on neighbors4 >= 0.5
[set flag? 1]
[set flag? 0]
end
What I'm trying (and failing) to do here is to ask each CM to average the values of "flag?" of its Von Neumann neighbors and then take on that value as its own flag?.
I slapped the create-link-with code on there because I thought it would allow CMs to sense its neighbor's flag?, but that doesn't appear to me the problem.
The error message highlights "flag?" in "ifelse mean flag? of CMs-on neighbors4 >= 0.5" and says "OF expected this input to be a reporter block, but got anything instead."
I would really appreciate any help! Thanks in advance.
You don't need the links, NetLogo can detect the turtles on the neighbouring patches and then access the variables of those turtles. Your problem is that you have flag? of but need [flag?] of.
The error message means that you have used of without telling NetLogo what to report. You need the [ ] to mark the boundary of the reporter block, even if it's simply a variable. Reporter blocks could be complicated calculations so NetLogo needs to know where to start and end the calculations for each entity that is reporting (in this case, all the CMs on the neighbors4).
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.
In NetLogo: suppose the model has
a turtle (0) of breed A with undirected links with 3 turtles (1, 2 and 3) of breed B;
the turtle 0 has an attribute named "number-of-links" that equals 3.
Now, let one of the 3 neighbors of 0 dies..
How can I program turtle 0 to change its number-of-links automatically to 2?
If all you want is a way of keeping track of the number links, use count my-links instead of a custom variable.
In general, the least bug prone way of having a value update when the number of links changes is to compute that value when you need it. For number of links, this is simply count my-links. For more complicated things, wrap them in a reporter:
to-report energy-of-neighbors
report sum [ energy ] of link-neighbors
end
If this doesn't work for whatever reason (agents need to react to a link disappearing or you're seeing a serious, measurable performance hit from calculating on the fly), you'll have to make the updates yourself when the number of links change. The best way to do this is to encapsulate the behavior in a command:
to update-on-link-change [ link-being-removed ] ;; turtle procedure
; update stuff
end
and then encapsulate the things that can cause the number of links to change (such as turtle death) in commands as well:
to linked-agent-death ;; turtle procedure
ask links [
ask other-end [ update-on-link-change myself ]
]
die
end