Reputation: 33
I'm currently working on a project with NetLogo. Long story short: I have a certain number of turtles spread across the first half of my world. The objective is to make the turtles move on the other half of the world if they satisfy a certain condition (a mathematical one). The problem that i'm ecountering is that I want just the turtles who satisfy the condition to move to the other half (so I assume it will be a subgroup of turtles whom dimension will depend on which value of "free income" I select through the slider), but in reality what happens is that if at least one of them satisfy the condition then ALL the turtles move. That's not what I want. I was thinking to use the function "breed" but I am not sure how to implent it. Here is the code :
globals
[
lazyness-coefficient
fatigue-of-work ; cost associated with looking for work and the activity of working
free-income
working-income
]
turtles-own
[
condition ; condition = 1 if the subject works, 0 if the subject is unemployed
utility-value-working-income ; utility associated with working or being unemployed while receiving a subsidy
utility-value-free-income
]
;;;
;;;
;;;
to setup
clear-all
set free-income free-income-slider ; mettere slider
set working-income working-income-slider ; mettere slider
setup-turtles
setup-patches
reset-ticks
end
to setup-patches
ask patches [ set pcolor black]
end
to setup-turtles
create-turtles 500
[
set shape "person"
set color green
set size 1.5
set condition 0
setxy random 64 random 32
set utility-value-free-income free-income ^ 2 + free-income + random-float 1000
set utility-value-working-income 0
]
end
to go
let target any? turtles with [utility-value-free-income > 14000]
if utility-value-free-income > 14000
[move-target]
end
to move-target
setxy random 64 random 64
set color blue
end
The condition in this case is the following: If the turtle has an utility value (which is of the type: x^2 + x + r, where r is a random factor) higher than 14000 then set color blue and move to the other half. This condition is just a try, in the final project the condition will be: if the ration of the free income utility and the working income utility is higher than 1 then move to the other half and set the colour of that particular turtle blue.
I hope I have explained it clearly, thanks everybody.
Upvotes: 2
Views: 774
Reputation: 2926
The answer by Jumboman addressed the most practical aspect and told you what to do, but I want to include some further perspective to let you understand what is going on, given that it is something which is easy to struggle with at the beginning.
The heart of the problem is your to go
but, as you can see, NetLogo is not warning you with any syntax error - because actually there is none! This is very much linked to the nature of your problem, i.e. all of the turtles performing the action (instead of just those that satisfy the condition).
To understand why, we should take a step back: you should always pay particular attention to the context from which procedures are executed (i.e. which type of agents is performing the action).
In NetLogo, there are four types of agents: turtles, patches, links, and the observer. The code is always written from the perspective of the observer (i.e. you). This is why, if you want other agents to do things, there is the need for you to ask those agents to do those things. You can ask turtles to ask patches to ask links to ask some turtles to do things but, ultimately, every chain of ask
starts from the observer.
NetLogo, however, also tries to guess who you want to perform your procedures. In this case, given that to go
uses turtles-own variables (i.e. utility-value-free-income
and color
, the latter from within move-target
) and calls a primitive that can be used only by turtles (i.e. setxy
from within move-target
), NetLogo is assuming that to go
belongs to the turtle context.
This means that, when performing to go
, every single turtle will do what to go
says. More specifically, this means that every single turtle will evaluate the let target
statement, and then every single turtle will perform to move-target
.
However this also means that, although to go
does not give any syntax error as it is, you should have probably noticed something else weird going on in the first place. Being to go
a turtle-only procedure as of now, you should see that if you add a go
button in the Interface (which is standard practice) you'll get an error. The Interface, in fact, is observer-only context (so buttons are observer-context by default, i.e. unless you don't change their context manually). You would get an error typing go
in the Command Center too (observer-only context by default too) as well as trying to insert go
in setup
.
This will be solved by making to go
observer context, i.e. by calling it from anywhere which is observer context + using ask turtles
as Jumboman showed.
Another thing that is implicit in Jumboman's answer but which you need to explicitely understand, is what's wrong with the actual lines of code inside to go
.
The issue with any?
was hinted at by JenB:
You clearly had the intention of creating an agentset called target
; however, any? only ever reports true/false. This means that, as JenB said, target
will not store any agentset but just a true/false value.
Regardless of this, however, it remains the fact that your code creates this target
variable but never really uses it. In fact, the fact that you included the word "target" in the name of a procedure (move-target
), doesn't make this procedure automatically use the variable named target
. So, even if target
was an agentset, move-target
would not automatically refer to target
(for that matter, you could have given these two elements totally random names and it would have been the same).
To do so, you would have to do
to move-target
ask target ...
end
However, as you've already been suggested, with
is the tidiest way to do the job.
Overall, the sum of all these things above is why you should just do:
to go
ask turtles with [utility-value-free-income > 14000] [
setxy random 64 random 64
set color blue
]
end
PS: As for the context thing, I developed the habit of always writing a comment, next to the declaration of each procedure, specifying the context that such procedure belongs to. This becomes particularly useful for speeding up the readability of your code and for some debugging, as your model builds up with lots and lots of procedures.
Upvotes: 1
Reputation: 551
You're making it too complicated. The Ask keyword allows you to specify a filter.
to go
ask turtles with [utility-value-free-income > 14000]
[
setxy random 64 random 64
set color blue
]
end
should do the trick.
Upvotes: 2
Reputation: 17678
This is the key procedure:
to go
let target any? turtles with [utility-value-free-income > 14000]
if utility-value-free-income > 14000
[move-target]
end
Working through each line:
true
or false` depending on whether there are any turtles with high enough incomeI usually recommend that novice NetLogo modellers avoid breaking things across too many procedures. Think about this conceptually, what you want is to move the turtles that meet some condition. It's one concept, make it one procedure. Something like this:
to go
move-rich-turtles
end
to move-rich-turtles
let movers turtles with [utility-value-free-income > 14000]
ask movers
[ setxy random 64 random 64
set color blue
]
end
Upvotes: 0