How to extract the who number of agents in an agentset? (NetLogo) - netlogo

I have a patch variable set as visitantBees [].
The intention is that each patch has a record of which agents were in it.
The method for registering the "visiting agents" is as follows:
to computing Frequency
ask patches
[
if any? turtles-here
[
set visitantBees lput [who] of turtles-here visitantBees
]
]
end
However, this way a list of list is returned ([[3 1 0 2 4]], for example).
Would anyone know how I can add only the who number to the visitantBees list?
Maybe a way to extract all the items from the turtles-here.

The reason why you get a list of lists is that both visitantBees and [who] of turtles-here are lists.
While visitantBees is a list because you set it as a list, why is [who] of turtles-here a list? Because turtles-here is an agentset - and the only way to report a variable of an agentset is to create a list. For example, if you wanted to know [color] of turtles, the only way NetLogo has to give you this information is to put all the turtles' colors in a list.
So, why is turtles-here an agentset? Because, even if sometimes turtles-here can contain 0 or 1 turtle, it can also contain multiple turtles. And anything that is fit to contain multiple agents has to be an agentset.
On the other hand, when you ask a single agent to report one of its variables, you get the value as such, i.e. not a list (unless that value is a list in itself, of course). For example, [color] of turtle 0 is just its color, not a list containing a color.
Therefore, you can achieve your goal by individually asking every turtle on the patch to append their who to visitantBees:
to computingFrequency
ask patches [
ask turtles-here [
set visitantBees lput who visitantBees
]
]
end
Or, given that turtles can automatically read and change the patches-own variables of the patch they are standing on, you can make it even simpler:
to computingFrequency
ask turtles [
set visitantBees lput who visitantBees
]
end
Which is also faster because it will only engage with turtles (who, by definition, are standing on a patch) rather than engaging with every patch even if there are no turtles on it.

Related

Give agents on patch the same value that patches have NETLOGO

I have a model where there are multiple animals in a den
patches-own [den-ID]
where the dens are pink and the number of dens is controlled with a slider global var
ask patches with [pcolor = pink] [set den-ID random n-dens]
Now, I want agents that spawn on that patch to set their own parameter "family" to a value equal to the den-ID that they spawn on - therefore having a group of animals that can be traced back to a den site and all share a home range.
I have tried many solutions but cant get anything to work.
basically something like
set family (family = den-id of patch-here)
thanks
The answer: ask turtles [ set family patch-here ]
Down below is how we arrived there
You seem a bit confused in your Netlogo syntax.
= is only used for logical expressions in Netlogo, not for setting variables. For that you use set.
If you want to use of to access variables of another agent, you need to encase the variable in square brackets: [den-id] of patch-here.
The solution you are looking for looks something like the following:
ask turtles [ set family [den-id] of patch-here ]
It can be made even easier. A turtle can directly access the variables of a patch that they are on without needing to name that patch.
ask turtles [ set family den-id ]
I noticed another thing in your code. Nothing in set den-ID random n-dens prevents multiple dens of having the same number. There are numerous ways of doing it, for example with a while loop where you increment the current-ID each time.
set current-ID 1
while [any? patches with [pcolor = pink and den-ID = 0]] [
ask one-of patches with [pcolor = pink and den-ID = 0] [set den-ID current-ID]
set current-ID current-ID + 1
]
You could even opt to forget about den-id and just let the turtles remember their den itself:
ask turtles [ set family patch-here ]

Making links based on turtles-own variable

In this example I am trying to make two directed-link-breed links based on turtles-own Value. The condition is as follows ask turtles to link to other turtles who have a smaller Value than me.
directed-link-breed [active-links active-link]
turtles-own [ Value ]
to setup
crt 100 [setxy random-xcor random-ycor set value random 500]
ask turtles [ create-active-links-to min-n-of 2 other turtles [Value < myself] ][set links to have xxxxx ]
end
when I do the following:
ask turtles [ create-active-links-to min-n-of 2 other turtles with [value < [ value ] of myself ] [set links to have xxxxx ]
I am getting the following error:
Requested 3 random agents from a set of only 2 agents.
error while turtles 8 running N-OF
called by procedure GO
called by Button 'go'
That message is telling you that (for the particular lettuce), there were only two that satisfied the criteria, but you wanted to link with 3 of them. Looking at your question, you want turtles to send links to turtles with lower values of a specific variable. What do you want the turtle with the lowest value of that variable to do? Clearly it can't link to lower valued turtles because there aren't any.
I'm also not clear why you are using min-n-of. Do you want to link to the lowest valued turtles (in which case every turtle will send links to the same few turtles) or do you want to link to randomly selected turtles with lower values (in which case turtles with higher values will have more choices)?
There are a couple of ways you can handle this once you have the logic sorted out. If you definitely want the lowest value, then use min-n-of first to find the candidates, then link to any with a lower value than the asking turtle. If you want to randomly select from a potentially larger group, use up-to-n-of instead of n-of. Or you could count the number found before trying to link to make sure there's enough.

Updating a list in Netlogo

I'm trying to update the values in a list on netlogo.
The code here is my collision function: one breed collides into another, turns the circle black and then I want it to store the 'who' number of the 'found' circle in a list.
It currently just outputs the who number of each found one and prints a 'list' of one number each time.
Here's the code.
to collide2
if any? circles2-on neighbors [
set mylist [] ; not sure why I need this but
;doesn't work otherwise
set whovalue [who] of circles2-on neighbors
set mylist lput whovalue mylist
ask circles2-on neighbors [set color black]
output-print mylist
]
end
If there are multiple circles-on neighbors, then the code [who] of circles-2 on neighbors will return a list of their values of the who ID. You need the sentence command to concatenate two lists, using lput will add the list as one item in a list. For example: print lput [1 2] [3 4] will print out the list [3 4 [1 2]]. In your case, you are adding this to an empty list so the created list only has one element, and that element is itself a list.
But if your goal is to get a list of the who values, you don't need to do anything that complicated. The code let whovalues [who] of circles2-on neighbors will create a list automatically, because of creates a list.
So your code could be replaced with:
to collide2
if any? circles2-on neighbors
[ set whovalues [who] of circles2-on neighbors
ask circles2-on neighbors [set color black]
output-print whovalues
]
end
However, see how you're having to keep track of the who values but then separately re-find all the neighbouring turtles? This is because you are storing the who values instead of storing the agents themselves. It is almost always better to refer to agents directly rather than identify them via their who value, so you can avoid awkward code like: ask turtle with [who = <some value>] [do-something].
So, switching to turtles instead of who, and also switching to agentsets rather than lists (not essential but lists are only relevant if you need to track the order or have multiple instances etc):
to collide2
if any? circles2-on neighbors
[ set colliders circles2-on neighbors
ask colliders [set color black]
output-print colliders
]
end
So now it is clear that the same turtles are being found and turned black. Even better, you can do this so that the agentset is only created once (more efficient as well as easier to read):
to collide2
let colliders circles2-on neighbors
if any? colliders
[ ask colliders [set color black]
output-print colliders
]
end

NetLogo - turtles to imprint 'who' on patches and only move-to patches which match their 'who'

I'm working on a land-use model featuring a forested World where turtles (smallholders and companies) have the ability to convert forest into crop-land. I would like to introduce a feature that turtles 'own' the patches they convert and are able to revisit them later to get these patches certified. The main issue is that when turtles move-to crop-land patches to get them certified, they do not only move to those they 'own' but also jump across the world to other turtles' crop-land patches and certify those. I've tried a few different workarounds, but I seem to run into the same two issues eventually:
#1 - error: can't use who in a patch context
I wanted to use the 'who' variable to mark crop-land patches as belonging to the turtle that converted the patch, e.g., turtle 0 goes to the forest, converts it to crop-land and that patch of cropland should be 'owned' by turtle 0, i.e., the patches owned-by variable should be equivalent to the turtle's 'who'. The issue here is that 'who' is a turtles-own variable. So, when I use it in a patch-context it produces an error. For example, ask smallholders [move-to one-of patches with [[owner = who]] --> error.
#2 - can't manage to set a global variable = 'who'
Two, I tried to work around this by using a proxy variable: a globals-variable called 'owner-ID'. I would use set owner-ID who to imprint the turtles individual number to the owner-ID. This seems to work to some extent, namely that the patches' 'owner' variable corresponds to the turtle that converted the patch. It also works when counting how many patches of certified and conventional crop-land turtles own (see set-land-ownership command below). However, when the smallholders-certify-crop-land commands are triggered, turtles don't stick to the patches they own, but 'jump' across the world. When prompting turtles through the command-center ask turtles [print owner-ID] they all return the same owner-ID value. I feel there might be a mistake in my move-to command-line but I just can't find it.
Summary & Question
I want crop-land patches to be 'owned by' the turtles that converted them, and want turtles to move only to the patches they 'own' when certifying crop-land patches, not to patches they don't own. I guess my questions revolve around whether it's possible to somehow use the 'who' variable in a patch-context. And, if not, what a good workaround for the problem could look like.
Relevant code is below (I hope)!
globals [owner-ID]
turtles-own [conventional-land-ownership certified-land-ownership]
patches-own [owned-by owner certified?]
to setup [
ask patches [
set pcolor green ;; green = forest
set certified? "no"
set owner "nobody"
]
]
to go
ask turtles [set-land-ownership]
ask smallholders [check-smallholder-status]
tick
end
to set-land-ownership
ask smallholders [
set owner-ID who
set conventional-land-ownership count patches with [owner = owner-ID and certified? = "no"]
set certified-land-ownership count patches with [owner = owner-ID and certified? = "yes"]
]
end
to check-smallholder-status
if wealth >= 0 and (conventional-land-ownership + certified-land-ownership) < SH_max-land-ownership [
smallholders-choose-activity
]
if wealth < 0 [
set color red
set shape "cow skull"
]
if (conventional-land-ownership + certified-land-ownership) >= SH_max-land-ownership [
set color orange + 2
]
end
;; smallholders-choose-activities is a reporter-based command where turtles choose the most economical option available. One of the outcomes is: smallholders-certify-crop-land
to smallholders-certify-crop-land
let available-patch max-one-of patches with [owner = owner-ID and certified? = "no"] [count neighbors with [certified? = "yes"]]
ifelse not any? turtles-on available-patch [
move-to available-patch
]
[]
set wealth wealth - smallholder-certification-cost
set pcolor brown + 1
set certified? "yes"
end
Your first approach is definitely the way to go and could be fixed with one small adjustment.
ask smallholders [move-to one-of patches with [owner = who]]
should be
ask smallholders [move-to one-of patches with [owner = [who] of myself]]
Within the block after with, variables are in the context of patches, but myself refers to the agent that asked the patches to check their owner, in this case, each smallholder. The global variable owner-ID is then unnecessary. If you carry this through the rest of the code, your second problem may solve itself.
BUT, in general it is best not to use who numbers at all, but rather refer to the agent directly. (You have actually taken that approach implicitly when you initialize owner to nobody, which is "no agent".) I don't see where you ask a patch to set its owner, but if a smallholder is on a patch, the smallholder would
ask patch-here [set owner myself]
and the line above would now read
ask smallholders [move-to one-of patches with [owner = myself]]
The NetLogo gurus suggest that we use who numbers only when there is no other approach.

NetLogo - Getting the 'who' of another turtle in the same patch

I'm looking to get the 'who'/turtle ID of a turtle that occupies the same patch as another, and then add this as an item into a list for both turtles.
For example, say turtle A and turtle B are on the same patch, I'd like to store the who of turtle A in the list for turtle B and the who for turtle B in the list for turtle A.
I realise this may be quite a trivial thing to do, so I attempted to do this with the following code:
if not any? turtles-on neighbors[
if who != who[
set collision-list fput (list (who)) collision-list
]
]
Here, I'm checking the patch to see if it contains another turtle, if it does then I'm trying to store the who (using a condition for if the who is not the same as the current who) and if it isn't, then store this in the collision-list for each agent.
Ordinarily it is a mistake to work with who numbers instead of the turtles themselves. So I'll illustrate how you might augment a "collision list" of turtles.
turtles-own [clist]
to setup
ca
crt 100 [
setxy random-xcor random-ycor
set clist []
]
ask turtles [adjust-clist]
end
to adjust-clist ;turtle proc
let _ts [self] of (other turtles-here)
set clist (sentence _ts clist)
end