How to dynamically output value in netlogo - netlogo

I have created a model in which turtles are born and die based on certain parameters. But at any given point, lets say no more than 20 turtles are alive.
With the birth and death of each new turtle, the turtle label keeps increasing incrementally i.e. initially there are 5 turtles, the 3rd turtle dies and in the next tick a new turtle is born. The new turtle born has a label of 6 and thus old labels are retired and replaced with the next label.
If i want to output a metric associated with the turtles into the monitor, is there a way to dynamically ensure that. i.e. since there can't be more than 20 turtles at any tick, can i make netlogo display the turtle metric along with the turtle label automatically. Otherwise i will have to create 100's of monitors and then code with [metric] or turtle 0.....[metric] of turtle n which is not practical.

If you really want a separate monitor for each turtle, you can do something like this:
Using [ metric ] of item 0 sort turtles instead of [ metric ] of turtle 0 (and so on) will insure that you're not depending on the who numbers of the turtles, you're only depending on their position in the sorted list of turtles.
Note that this would be very inefficient, because each monitor would keep re-sorting the turtles over and over again.
That being said, I think there would be many different, better ways to approach this. Here is one fully working example:
turtles-own [ metric ]
to setup
clear-all
create-turtles 20 [ set metric random 10 ]
reset-ticks
end
to go
ask n-of 5 turtles [ die ]
create-turtles 5 [ set metric random 10 ]
tick
end
to-report info [ the-turtle ]
; format this however you want:
report [ (word who ": " metric ", ") ] of the-turtle
end
And then, in a monitor, put:
map info sort turtles
Which will give you something like:
If map is obscure to you, you may want to check its dictionary entry. The basic idea is that we build a new list of strings by applying the info reporter to each element of our list of turtles.
I used a monitor in the example because that's what you were talking about in your question, but for displaying information about multiple turtles like this, maybe a plot or the output widget would be more appropriate. In any case, you could use a similar approach, with either map or foreach.
One word of advice in closing. Your question shows that you're probably aware of that already, but any time you're tempted to refer to turtles by their who number (i.e., turtle 0, turtle 1, turtle 27, etc.), it probably means you're on the wrong track. NetLogo is built to manipulate agentsets and lists; take advantage of that. And when you do need to refer to a particular turtle, use a reference to that turtle (e.g., the-turtle in the example above), never (or almost never) its who number.

Related

can a turtle only variable number be assigned to patches?

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

How to have patches "belong" to turtle

I am brand new to Netlogo and am coding a world with caching animals. They will go to their caches (I set them as blue patches) if their energy value falls below 10. They can find these caches based on a random 'memory' value given to them which is used as an in-radius value. That way, they will face and go towards a cache within their in-radius memory if they are about to die. I am starting to incorporate a home-base system where the turtle remains in a smaller area with their own caches. Does anyone know how I can make a patch belong to an individual turtle? This would allow turtles to have their specific caches in their territory. I have looked into using links and breeds, but links are only between turtles and making the individual breeds for the 50+ turtles at a time seems ineffective and complex. I apologize I don't have any code attempting to have a cache (patch) belong to a turtle, I don't know where to start. Any ideas?
If you want a turtle to remember anything (patches or income or anything else), then you need to assign a variable in a turtles-own statement and then set the value appropriately. Here's some example code fragments. They won't work, and you actual code would likely look a lot different because you will need some design about the conditions under which a cache will be assigned, but they show you what a variable solution looks like.
turtles-own
[ my-caches
]
set my-caches (patch-set my-caches patch-here) ; code when a turtle finds a new cache site
If you want a patch that belongs to a turtle to make that patch unavailable to other turtles, then also set up a patch variable to store its owner.
patches-own
[ my-owner
]
ask turtles
[ if [my-owner] of patch-here = nobody [set my-caches (patch-set my-caches patch-here)]
ask patch-here [set my-owner myself]
]
I suggest you do several NetLogo tutorials, then look at some library models (and understand them) before starting your own model. You need to understand basic concepts like turtles/patches, variables, ticks before trying to build a model.

How can I change a turtle's status depending on specific conditions?

I really need your help to fix a problem with my code.
Unfortunately, I am having difficulty by updating the status of turtles once a condition is satisfied.
It is a virus spread problem: each node, called human, has its own 'bag' which contains different items (virus and medicines). The bag is made up of items from the neighbours that are linked to the chosen turtle.
The virus can come from a zombie at the beginning (t=0) and move from turtle to turtle, depending on what they decide to do. If a turtle picks up a virus (spread action), it can become infected.
The part of code that is giving me some problems is the following:
to spreading
ask one-of humans
[ let choice one-of out-link-neighbors
ifelse empty? bag
[ ifelse random-float 1 < p
[action1 set bag lput act1 bag print "act1"]
[action3 print "act3"]
]
[spread set bag lput spreadvirus bag print "spreadvirus"
if [infected?] of choice
[become-infected] ]
]
]
end
more specifically the part with spread.
What that part of code should do is to build for each randomly chosen turtle a bag made up by all the'items' from neighbours' bags, and transform that turtle according to what it chooses.
For example, as you can see in the figure below, at the beginning nodes 2,5 and 7 can be potentially infected because they are linked to the zombies. Each turtle can 'see' all its items plus all the items contained in its neighbours bags (for example, 7 can see - and potentially choose - all the items from Z, from 8 - its bag is empty in this case - and from its own bag, made by historical stored items, i.e. past choices). Let's say that 7 picks the virus from the zombie (action 2, i.e. spread) and becomes infected. Node 5, that can see all the items contained in the lists of nodes 4 and 7, can become infected as well, depending on what it chooses. If 5 prefers an item from 4, that is a node not infected because in its own list there are only uninfected items, it becomes susceptible. If it chooses, among all, the infected item from 7, it becomes infected as well. And so on...
What I suspect is that the bags are not storing information from the neighbours as I want. This explains why no humans are becoming infected from the ifelse statements, but only susceptible and they change color in white and blue depending on their choices.
I am not getting any error from the code, so it is difficult for me to understand what I am really doing wrong. I also put some print to see what is not working, and it seems that the part of code with spread as action is the problem.
What I should expect is a list that contains all the items from turtle's neighbours. At each tick the turtle can choose what to do with those items (action1, spread, action3), by adding a new item, selecting an item from neighbours, or do nothing. This choice should be added to the turtle bag. This means that the list, at each tick, should be updated, taking into account all the elements from the neighbours, plus the selected action/element from the turtle. But the turtle becomes infected only if it chooses (spread) not a medicine from the neighbours, but a virus.
UPDATED after JenB answer and to better explain how the human breed should become infected:
The possible types of items that each bags can contain are new medicines, medicines from the same turtle or from neighbours and/or virus, for humans; only virus for zombies - I do not need to add elements to zombies' bags.
To better clarify: Once there is a link between one turtle and another one, these turtles can have access to all the items in their bags, respectively. When it is time to select an action, the turtle can have access to its own bag that contains all the items stored from the neighbours’ bags, as bags are made up of items (medicines and virus) from all the turtles linked to a chosen turtle.
However, the turtle becomes infected only if it decides to select the action spread, and to select an item infected from the neighbors’ bags.
After the choice, the element chosen is added to its own bag.
I edited part of the code. What I did is to create a new bag for zombies, initialising with only "virus"; furthermore, I edited the part of code regarding 'to spread' as following:
to spread
set action1? false
set spread? true
ifelse any? out-link-neighbors with [infected?]
[ print "Virus!"
set spreadvirus spreadvirus + 1
become-infected]
[ print "Medicine from neighbour"
set spreadvirus spreadvirus + 1
become-susceptible]
end
But also in this way, I am not having humans that become infected. And I think that the bag that I am trying to build is not storing all the items from the turtle's neighbours. And this explains why turtles cannot become infected.
I hope you can help me to understand what I have done wrong.
Thank you for your time, effort and help.
That's a much clearer explanation of what should happen, but you still haven't told us what is happening. For example, you have print statements in there, is the appropriate output being printed (so the code is getting to that part) or is that bit of the code not being selected? Are you getting an error message? What does one of these lists look like?
I think you mean that the logic is not working. I suggest you put some more diagnostic prints at the top once you have selected the human:
ask one-of humans
[ type "Neighbour count: " print count out-link-neigbors
type "Bag at start: " print bag
ifelse...
Then you can see why the selected path is being selected. It will also let you know if the variable contents aren't what you expect.
You have a comment that the line set bag lput spreadvirus bag is not working. So replace:
[ show one-of bag
set bag lput spreadvirus bag ;; NOT WORKING
print "spreadvirus" ]
with
[ show bag
set bag lput spreadvirus bag
show bag
print "spreadvirus" ]
to see what it is doing.
The other thing you can do to debug is replace ask one-of human with 'ask human 10` (or some other specific human). Find humans with different situations - one with only one neighbour for example, and try them out.
UPDATED in response to comment
The [6 2] is the contents of the bag. When you put act1 or spreadvirus or whatever into the bag, you are putting a number into the bag. This is because act1 and spreadvirus are numbers. They start as 0 and you add 1 to them at various points in your code.
It seems to me that you have put the wrong things in the bag. If you want a human to become infected if they pull out an infected item from the bag, then the bag needs to contain infected and uninfected items, not numbers.

NetLogo: Using global variables with breeds and links

I have a programme that sets up a number of different breeds of turtles. Each breed needs to have a leader turtle and a follower turtle. I have assigned these as global variables as they come up a lot in the code further down.
I need to assign these variables to turtles in the breeds and then create a link from the leader to the follower. There are a lot of conditions in the interface that determine how many and which breeds are created so i cannot assign by turtle number.
I am receiving an error (not all of the time) 'turtle cannot link with itself' which i presume occurs when they overwrite the first set command and assign the same turtle to the two variables. Does anybody know a condition i can put in that will allow it to set up everytime without the error. ( I have tried if statements, is-turtle?, one-of other, other)
breed [flinks flink] ;; linked turtles that will turn away from sources
globals [
flink-leader
flink-followers]
to set-up
clear-all
setup-turtles
reset-ticks
end
to setup-turtles
create-flinks 2 [
set flink-leader one-of flinks
set flink-followers one-of other flinks
ask flink-followers [create-link-with flink-leader]
ask flink-followers [set color pink]
ask flink-leader [
setxy 10 4]
ask flink-followers [
setxy 19.5 4]
]
end
to go
fd 1
end
There would be many different ways to approach this. Here is one that doesn't stray too far from the code you have provided:
to setup-turtles
create-flinks 2
set flink-leader one-of flinks
ask flink-leader [
set flink-followers one-of other flinks
setxy 10 4
]
ask flink-followers [
create-link-with flink-leader
setxy 19.5 4
set color pink
]
end
Note that your intuition about using other to make sure that the follower(s) is/are different from the leader was correct.
To understand what was going on, you need to grasp the notion of "context" in NetLogo. Some primitives, like ask, of and create-turtles, are "context switching": one of their argument is a code block (the part between [ and ]) that runs in the context of a particular turtle. Other primitives depend on the context in which the code is running: the primitive named other, for example, will report all the agents from a given agentset, except the one in the context of which the block is running.
In your version, you wrapped most of the code inside a code block provided for create-flinks. That meant that the code block was run once for each turtle that was created. So your calls to set flink-leader, set flink-followers and so on were all run twice, each time in a different turtle context. Can you see how that was messing things up?
Keeping track of the different context in NetLogo can be challenging at first (the frequent confusion between self/myself being a case in point), but once you get it, it should become easy and natural.
One last point as an addendum. You say:
i cannot assign by turtle number
Good! Never¹ assign anything by turtle number! It leads to brittle, error prone, more complex, less general, unnetlogoish code. If you think you need to use turtle numbers anywhere in your code, come ask another question here. Someone will most likely suggest a better way to do it.
¹ Well, almost never.

NetLogo two kinds of self-reference

I want to add an agenset of turtles to the variable TurtlesICanSee of a certain turtle that depends on that turtles properties. For instance, in one application I want to add only the turtle itself to TurtlesICanSee, in another application I want to add the two turtles (if there are any) with adjacent who-numbers (the turtle's own who-number + or - 1).
If I can figure out the first application by using who-numbers I think I can extend that to second application. However, I cannot figure out the first.
I tried
ask turtles [
set TheTurtlesICanSee turtles with [who = ([who] of self)]
]
but this fills the TheTurtlesICanSee of each turtle with every turtle.
I think I understand why; NetLogo thinks that I want every turtle x that has the same who-number as itself (x), i.e. every turtle. But I don't. For every turtle x I want every turtle y that has the same who-number as x.
Can anyone help me with this? Note that the solution that I need to the first application is one that can be generalized to the second. So not any way of adding a turtle to one of its own variables will do. I need a form of self-reference involving who (or a good argument against doing it this way I guess, but preferably the former).
Your code needs only a slight alteration to work, as follows:
ask turtles [ set TheTurtlesICanSee turtles with [who = [who] of myself] ]
Note the substitution of myself for self; http://ccl.northwestern.edu/netlogo/docs/dictionary.html#myself has an explanation of the difference.
But actually there's no need to involve who numbers. It's almost never necessary to use who numbers in NetLogo; there's almost always a simpler, more direct solution. A simpler solution is:
ask turtles [ set TheTurtlesICanSee turtles with [self = myself] ]
But actually it isn't necessary to use with at all. We can use turtle-set to build the desired agentset directly:
ask turtles [ set TheTurtlesICanSee (turtle-set self) ]
This is the solution I would recommend, for clarity and brevity, but also because it will run faster, since it doesn't involve iterating over the set of all turtles, as the with-based solutions do.