I want to do the following.
to some-function
let agent-set turtles with [some-criteria]
ask agent-set [do-this]
end
But I also want each turtle to update its owner variables after each agent does do-this.
Something like,
to some-function
let agent-set turtles with [some-criteria]
ask agent-set [
do-this
ask turtles [update-owned-variables]
]
end
But of course, you can't ask turtles inside an agent's local command.
I am guessing that I have to loop through each of agent-set, but I don't know how to do that either. I would prefer to not do that.
Related
I'm trying to design a model for the spread of infection from person to environment.
Turtles have a hand contamination variable that shows the percentage of their hands that are contaminated. I'd like to give this number to patches that they're passing, but I'm getting an error saying it's a turtle-only variable.
Is it possible to give a hand contamination number to the patch?
This is part of my code:
turtles-own [hand contamination]
patches-own [p-contamination]
ask patches [set p-contamination hand-contamination]
A patch can't ever refer to turtle variables directly: What if there is more than one turtle there...which one? What if there are none?
However, a turtle can access the variables of the patch it is standing on. So you would probably do this from the turtle's point of view: I think this also makes sense, logically, since it is the turtle visiting the patch, and contaminating it.
;; turtles contaminate the patch they are standing on
ask turtles [ set p-contamination hand-contamination]
Note that if there is more than one turtle on a patch, they will overwrite each other's values. So, you may need to add the amount, or otherwise blend the two values, rather than replace it.
If there are more turtles than patches, or you really want the patch to be the thing that in control, the patch can look for turtles and acess their variables with OF:
ask patches
[ let visitors turtles-here
if any? visitors
[ set p-contamination ..some expression..
So, there it depends on your needs, and you have to decide what that value is.
There is only ever at most one turtle:
[ Contamination ] of one-of visitors
Even if many turtles, pick one at random:
[ contamination ] of one-of visitors
Use the value of the most-contaminated visitor:
(max (sentence [ contamination ] of visitors))
Average the values of contamination
(mean (sentence [ contamination ] of visitors))
...or some other expression that you choose
Again, this is all overwriting the patch variable. If you need to take the patchs' current values for that variable, you need to decide how:
If already contaminated, should it:
leave value alone
add turtle value to current value of P-Contamination
save the max of the two values
save the mean of the two values
blend them in some other way
This is the code of a 2 player game that I manipulated
o play-the-game
if (any-friends-nearby?) [gain-energy]
if (any-opponents-nearby?) [fight-opponent]
end
to-report any-friends-nearby?
report (any? (turtles-on neighbors4) with [breed = [breed] of myself])
end
to-report any-opponents-nearby?
report (any? (turtles-on neighbors4) with [breed != [breed] of myself])
end
to gain-energy
set similar-nearby count ( turtles-on neighbors4 )
with
[color = [color] of myself]
set total-nearby count (turtles-on neighbors)
;
;
if (similar-nearby >= total-nearby - similar-nearby)
[set energy energy + 5]
end
to fight-opponent
let my-breed [breed] of green-players
let my-color [color] of green-players
let opponent-breed [breed] of red-players
;
;;
ask my-breed
[check-random-winner]
end
to check-random-winner
let pick random-float 2
let winner nobody
ask turtles
[if winner = nobody
[ ifelse size > pick
[set winner self ]
[set pick pick - size] ] ]
end
to change-opponent
ask red-players
[ set breed green-players
set color green ]
end
Sorry if it's a bit long but when I setup up and then press go "ASK expected input to be an agent or agentset but got the list [green-players...]"
How can I fix this?
Also I'm very new to Netlogo and StackOverflow, apologies if I haven't asked my question properly.
The error message tells you that you are passing a list (more specifically, a list of breeds) to ask, when it comes to ask my-breed.
This is because the my-breed local variable is determined by
let my-breed [breed] of green-players
Let's see what we have there:
breed is a turtles-own variable: it holds the turtle's breed, and being an agents' variable can be used as a reported in the of construct (see below).
of is a reporter: it takes a reporter (normally an agents' variable) on its left (in your case: breed) and either an agent or an agentset on its right (in your case: green-players). What of reports (i.e. what it outputs) is...
... a single value if there is an agent on the right.
... a list of values if there is an agentset on the right*.
*Think about it: if I ask the color of your eyes (you are a single person, i.e. a single agent), you will tell me a single color. But if I ask the color of your friends' eyes (your friends are a group of people, i.e. an agentset), the only way for you to answer my question is to tell me a list of colors.
green-players is an agentset: all of the agents whose breed is green-players (note that for NetLogo green-players is an agentset even if it contains 1 or 0 agents).
From this, we can see that in this case of reports a list of breeds, because it reports the breed of every agent that is part of green-players, hence it will report the list [green-players green-players green-players green-players ... ] which is as long as the number of green-players in the model. You can verify this by clicking setup and then running [breed] of green-players in the Command Center.
This is a list of breeds (which can also be seen as a list of agentsets), which is not an agent or an agentset (which are the only possible targets of ask).
((note that the exact same thing happens with let my-color [color] of green-players and let opponent-breed [breed] of red-players))
So, how do you construct an agentset based on a variable? The most common way to do it is by using with (read here why).
But how can you fix your code? I don't know because I don't understand what you want to achieve.
I am not sure how you would want to use it in the code you posted, as I'm not even sure you need to use ask in fight-opponent (let alone ask an agentset).
Your fight-opponent procedure is such that, apart from the problem we just discussed, the "my-" things (i.e. my-breed and my-color) always refer to the green players while opponent-breed always refers to the red players - even if fight-opponent is run by a red player! And also, it is not clear what you want to achieve with the check-random-winner procedure and if you want this procedure to be ran by an entire breed. These things make it quite confusing to understand how you could want to fix the fight-opponent procedure.
For example: who do you want to run the check-random-winner command?
A combination of two things would be beneficial: develop your model one step at a time and make sure that every new little piece of code does exactly what you expect it to do; also, when you ask for how to fix something it is useful that you explain what you want your code to do. By doing these two things I believe it will be a lot easier to answer your questions
I know that there are a lot of questions (and answers) about this error, but unfortunately I have not fixed the error in my code, not yet, even following the past answers. I hope you can help me on this. I know that something does not work because of ask one-of A, but I have no any other idea how implement it in a different way, in order to ask an agent to create a new object.
The error messages comes when I call the procedure create_object in go.
The breed A is owner of agenda.
The breed object is owner of att1
to go
ifelse random-float 1 < 0.5
[ ask one-of A
[
ifelse empty? agenda
[ ifelse random-float 1 < 0.5
[create_object] ;; this returns the error message
[remove_object]
]
]
]
[...]
end
The error comes from create_object.
This is defined as follows
to create_object
create-object 1[
hide-turtle
set att1 random-float 1
let this-post myself ; is it the same object that I am creating?
if (condition1= TRUE)
[set agenda fput this-post agenda] ; this should add the object in the agent A's list
]
end
I do not know if you require more code.
Feel free to comment it if you need more information.
Thanks
Are 'A' and 'object' both breeds of turtles? If so, you have a turtle (of breed A) calling a procedure in which it is trying to create a turtle (of breed object). However, if you look at the Netlogo dictionary, you will see that create-turtles (and other forms like create-object) is only valid when used by the observer, not when used by a turtle.
If you want a turtle to create a new turtle, you need the hatch command. Note that the newly hatched turtle will have the same attributes (such as position) as the parent turtle.
I need to know if it is possible to add the same item to more than one list a time. Specifically, I want to add items to one turtle's list and to the lists of all the turtles connected to that turtle.
Something like this:
set list lput item list (turtle's list)
set list lput item list (neighbours' lists)
The item it's supposed to be the same. You could image a graph: turtles are nodes and each turtle has its own list.
My approach was:
ask one-of turtle[
set list lput item list
foreach [in-link-neighbors] of turtles-here
[ item -> set list lput item list ]
]
Thank you for your help
Short answer - yes, it is possible.
Here is a complete model with printout so you can see what it is doing.
turtles-own [mylist]
to setup
clear-all
create-turtles 10
[ set color blue
set mylist (list random 10)
]
ask turtles [ create-links-with n-of 2 other turtles ]
layout-circle turtles 7
ask turtles [show mylist]
ask one-of turtles [add-item-egonet]
ask turtles [show mylist]
reset-ticks
end
to add-item-egonet
let new-value 3
let targets (turtle-set self link-neighbors)
ask targets
[ set color red
set mylist lput new-value mylist
]
end
You didn't say what happened when you tried your code, but you would have received an error because item and list are NetLogo keywords. You also have a logic error - when you ask a turtle, you switch perspective (or 'context' in NetLogo terminology) to that turtle, the subsequent turtles-here will pick up all turtles on that same patch.
The big difference between our approaches is that I have used agentsets rather than lists. It could be done by iterating through a list of turtles, but if you find yourself writing NetLogo code that runs foreach over a list of turtles, the first thing you should do is rethink your approach. There are specific situations where you need lists of turtles, for example if you need to track the sequence of other turtles that a turtle has met. However, unless you are in one of those situations, it is better to use agentsets and ask.
So, switching to the paradigm of agentsets, my code creates the agentset of turtles that I want to change (the selected turtle and its network neighbours) and then simply tells them to add the new value at the end of their own lists of values.
Note that within a model, this could be achieved with a single line by constructing the turtle-set at the same time as asking it, but it would be more typical to do something like (from within an ask so the perspective is that of some selected turtle):
set mylist lput new-value mylist
ask link-neighbors [ set mylist lput new-value mylist ]
I have a breed of turtle that owns another breed of turtle.
I need to do something like:
set my-turtle-set breed1 "owned by" breed2 with [some-attribute = 1]
So i need to put in a turtleset some turtle of the breed1 if they are owned by the turtle of the breed 2 with some characteristic.
Clarifying
Maybe thre was a misunderstanding:
I have already the breed2 owning the breed1:
breed2-own [my-owner]
and i can correctly put my breed1 turtles inside my breed2 turtles.
The problem is that i need to make hidden? some breed1 turtles basing on who onws them.
SO updating to the example (i remove my-turtle-set for being more clear):
ask breed1 ("owned by" breed2 with [some-attribute = 1]) [set hidden? true]
So the turtles already own correctly the other breed just i dont know, given a breed1 tutle, how to call its ower.
for this reason i need something like "owned by".
To Clarify even more
I have the breed2 that are part of a tree (network). At every step i set an attribute leaf? true to the leaf.
now each breed2 owns a breed1 and to every turn I need to set hidden? false toe the breed1 which are not onwed by a leaf, instead to set hidden? true to the breed1 which are owned by a leaf
If breed2 is the breed that owns, then this line:
breed2-own [my-owner]
doesn't make sense; the wording implies the relationship goes in the other direction. I'll assume you mean:
breed2-own [owned]
Then one way to solve your problem is:
ask breed1 [
set hidden? any? breed2 with [owned = myself]
]
If the number of agents in your model is fairly small, this should be fine.
If you have lots of agents, then you may start having speed problems, because in the above code, each breed1 does its own independent search through all breed2 agents.
Two possible ways to fix that:
Do what Mars suggests in his answer.
Get rid of the owned variable altogether, and use links to represent the owning relationships.
How about giving the owner breed a turtles-own variable that stores turtle-set containing the turtles it owns? You can also store a reference to the owner in each breed1, if that will make the code that uses this information simpler.
breed1-own [my-owner]
breed2-own [my-owned]
...
ask breed2 with [some-attribute = 1]
[set my-owned my-turtle-set
ask my-turtle-set [set my-owner myself]
Here myself refers to the breed2 turtle from the outer ask. (If you used self, instead, that would refer to the breed1 turtle from the inner ask.)
(Don't use both kinds of references unless you need both, though, because having breed1s and breed2s refer to each other means that when your code changes references of one kind, it has to change corresponding references of the other kind as well.)