Add characteristic to with Netlogo procedure - netlogo

I am trying to run the following Netlogo procedure:
to spread-virus
ask turtles with [infected?]
[ ask link-neighbors with [not infected?]
[ if random-float 100 < virus-spread-chance
[ become-infected ] ] ]
end
I'd like to not only ask turtles with [infected?], but also those with [immune?]. How can I add a second characteristic (immune) in addition to infected?

credit #alan, with [infected? or immune?]

Related

Stopping turtles from having negative resources

My model creates a relationship between employees and citizens. Whereby the employees obtain office and then distribute to the employees:
globals [
office-space
]
breed [ offices office ]
breed [ service-desks service-desk ]
breed [ employees employee ]
breed [ citizens citizen ]
offices-own [ money ]
employees-own [ money ]
citizens-own [ money ]
to setup
clear-all
create-offices 1 [
set shape "building institution"
set size 4
set color yellow
set money num-of-money
]
create-employees num-of-employees [
set shape "person"
set size 1.5
set color blue
setxy random-xcor random-ycor
]
create-citizens num-of-citizens [
set shape "person"
set size 1.5
set color white
setxy random-xcor random-ycor
]
;; create 4 service desks
let service-desk-patches (patch-set patch 0 8 patch 8 0 patch 0 -8 patch -8 0)
ask service-desk-patches [
sprout-service-desks 1 [
set shape "building institution"
set color pink
set size 3
]
]
;; create office space
set office-space patches with [pxcor <= 8 and pxcor >= -8 and pycor <= 8 and pycor >= -8 ]
ask office-space [set pcolor grey]
;; set all employees randomly within the grey box
place-on-color-employees
;; set all citizens randomly outside of the grey box
place-on-color-citizens
reset-ticks
end
to place-on-color-employees
let _patches (patches with [pcolor = grey])
ask employees [
move-to one-of (_patches with [not any? turtles-here])
]
end
to place-on-color-citizens
let _patches (patches with [pcolor = black])
ask citizens [
move-to one-of (_patches with [not any? turtles-here])
]
end
to go
ask employees [
set label money
]
ask citizens [
set label money
]
employee-movement-without-money
employee-take-money
employee-movement-with-money
citizens-movement
citizen-take-money
tick
end
to employee-movement-with-money
ask employees [
ifelse [ pcolor ] of patch-ahead 1 = black
[ rt random-float 360 ]
[ forward 1 ]
let target min-one-of citizens [ distance myself ]
if money > 0 [
face target
fd 1
]
]
end
to employee-movement-without-money
ask employees [
let target patch 0 0
if ( money = 0 ) or ( money < 0 ) [
face target
fd 1
]
]
end
to citizens-movement
ask citizens [
ifelse [pcolor] of patch-ahead 1 = grey
[ rt random-float 360 ]
[ forward 1 ]
let target min-one-of service-desks [ distance myself ]
if money = 0 [
set heading (towards target )
]
]
end
to employee-take-money
ask employees [
if any? offices-here [
set money money + 1
set color green
;set label money
]
]
end
to citizen-take-money
ask citizens [
if any? employees in-radius 0.5 [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
When this model is run, the employees collect money and go to meet citizens, however, in the citizen-take-money procedure, I have not found a way to prevent the citizens from taking money from the employees so they don't have negative values. I tried adding the employee-movement-without-money to force the employees to turn move away from the citizens, but they just congregate on patch 0 0.
I also tried adjusting the citizens-take-money procedures by creating an if and arugment:
to citizen-take-money
ask citizens [
if (any? employees in-radius 0.5) and (employees money > 0) [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
But that didn't work either.
First piece of advice, build NetLogo models gradually. You need to make sure each piece works before adding the slightly more complicated behaviour. You should never have more than one thing wrong in a NetLogo model at the same time, very hard to debug.
Here, the basic problem appears to be that you are acting on all turtles instead of just the relevant turtle. Here is your supplementary code that tries to introduce a check:
to citizen-take-money
ask citizens [
if (any? employees in-radius 0.5) and (employees money > 0) [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
First, have a look at your check - conceptually, what are you testing with the second part employees money > 0. That doesn't actually look like valid NetLogo code to me, are you trying to ask if there are any employees with with money > 0?
Regardless, let's say it gets past that check, the next line is ask employees - at this point you are telling EVERY employee in the model to reduce their money.
What you need to do is just find the right employees and have those ones reduce their money. Something more like:
to citizen-take-money
ask citizens
[ let nearby employees in-radius 0.5 with [money > 0]
if any? nearby
[ ask nearby [ set money money - 1 ]
set money money + 1
set color orange
]
]
end
Also, this procedure is asking every citizen to do this and you have named it as if only one citizen is doing it. So think about which way you actually want the process to work.
Finally, what happens if you have several citizens close to several employees. Say 3 citizens reduce their money because they are close to the same employee - at the moment, the employee only increases their money by 1 and the remaining 2 disappears. This is an example of what I mean by build gradually and check it works before adding in the next thing. Perhaps you could have them just change colours if the condition is met before trying to add in the money transfers. That would help you spot that you had lots of people triggered at once.

Netlogo: "expected a literal value" in a "ifelse" block

I want to check if the turtle is a sheep or wolf, and set commands seperately. But Netlogo highlights the set and tells me
expected a literal value
Here is edited code, I added more basic information and did some simplification for quick understanding.
breed [sheep a-sheep]
breed [wolves wolf]
sheep-own [SEnergy]
wolves-own [WEnergy]
to setup
clear-all
create-sheep 100
ask sheep [set SEnergy 100]
create-wolves 100
ask wolves [set SEnergy 100]
reset-ticks
end
to go
ask turtles[
(ifelse
is-a-sheep? [set SEnergy SEnergy - 1]
is-wolf? [set WEnergy WEnergy - 1])
]
tick
end
I've red the example in Netlogo dictionary
(ifelse boolean1 [ commands1 ] boolean2 [ commands2 ] ... [ elsecommands ])
Thus I think [set SEnergy SEnergy - 1] in my code is expected a command. Why Netlogo tells me a literal value is needed?
Thanks in advance.
The problem lies in your syntax for the is-a-sheep? and is-wolf? statements. is-breed? takes a single argument, the identity of the agent you are testing. Your code should therefore be
to go
ask turtles[
(ifelse
is-a-sheep? self [ set SEnergy SEnergy - 1 ]
is-wolf? self [ set WEnergy WEnergy - 1 ])
]
end
Then each turtle is asking itself what it is.
Of course, you could just ask each agentset separately.
ask sheep [set SEnergy SEnergy - 1]
ask wolves [set WEnergy WEnergy -1]
Charles

Catch nobody for target patch

I want to check if target patches fulfil a condition. If a patch is found that fulfils the condition,
then the turtles should move there. If 'nobody' fulfils this condition, then an error message should be printed.
The condition is that a patch should have in radius 10 2 turtles of the same breed.
I try to achieve this with ifelse and nobody. However, at the moment I always get the error message, even though the
target variable is not empty (you can check this with the if loop).
breed [ breed1s breed1 ]
breed [ breed2s breed2 ]
globals [target1 target2]
to setup
ca
create-breed1s 1000 [
setxy random-xcor random-ycor
]
create-breed1s 1000 [
setxy random-xcor random-ycor
]
end
to go
ask turtles [
set target1 ( count turtles in-radius 10 with [breed = breed1s] ) >= 2
set target2 ( count turtles in-radius 10 with [breed = breed2s] ) >= 2
new-position
]
end
to new-position
ifelse target1 != nobody
[ if (breed = breed1s) [ move-to one-of patches with [ target1 ] ] ]
[ print "Not enough agents in the neighborhood" ]
ifelse target2 != nobody
[ if (breed = breed2s) [ move-to one-of patches with [ target2 ] ] ]
[ print "Not enough agents in the neighborhood" ]
; if (breed = breed1s)
; [ move-to one-of patches with [ target1 ] ]
end
A remark to the efficiency of the model: as I want to add turtles later in every tick, target has to be reevaluated
in every tick (therefore it is in "go" and not in "setup").
Another question: is there a possibility to do something like [ breed = myself ] instead of [ breed = breed1s ], so
I don't have to type the breed for every breed?
Edit:
the turtles that move to the target patch should have the same breed that is also addressed in the target patch.
The problem is actually how you are creating target1, not the check as to whether it is nobody. You have:
set target1 ( count turtles in-radius 10 with [breed = breed1s] ) >= 2
This line first identifies all the nearby turtles with the appropriate breed and counts them. If the count is 2 or higher, then the variable target1 is set to true and to false if the count is 0 or 1. So you are comparing a boolean true or false to nobody (a special type of agent). That will always be a mismatch and therefore print the error.
Just a note on debugging - when you get this sort of problem, it's always useful to have a print statement for each side of the check just before doing the check. You would have immediately spotted that target1 wasn't what you thought it was.
Since you are asking to move to one-of the patches, you probably really want to store the available patches that are within 10 distance (I think) and have enough of the right type of turtles. So, you need something like:
to go
ask turtles [
set target1 patches in-radius 10 with [count breed1s-here >= 2]
set target2 patches in-radius 10 with [count breed2s-here >= 2]
new-position
]
end
Then your emptiness test is any?
to new-position
ifelse any? target1
[ move-to one-of target1 ]
[ print "Not enough agents in the neighborhood" ]
ifelse any? target2
[ move-to one-of target2 ]
[ print "Not enough agents in the neighborhood" ]
end
Assuming I have correctly interpreted that you want patches within 10 of the asking turtle (as compared to any patch with sufficient turtles within a distance of 10) and all you care about is the number of turtles of its own breed, then:
to go
ask turtles [
let target-breed [breed] of myself
set targets patches in-radius 10 with [count turtles-here with [breed = target-breed] >= 2]
new-position
]
end
to new-position
ifelse any? targets
[ move-to one-of targets ]
[ print "Not enough agents in the neighborhood" ]
end
On the efficiency, it depends on how many turtles you have. If you have quite a lot of turtles, then asking each to count its own neighbourhood will be expensive. Instead, you could have patchsets for each breed. That is, set up target1 as patches with [count breed1s-here >= 2] at the beginning of the go procedures. Then you can just do:
to go
let targets1 patches with [count breed1s-here >= 2]
let targets2 patches with [count breed2s-here >= 2]
ask turtles
[ set targets targets1 in-radius 10
new-position
]
end
However, you can no longer use the breed of the turtle and the myself trick to pick the correct patchset. There are ways to get around this (for example, using a list with two items, breed at first position and the patchset as second position) but that's getting well off track for this answer.
to new-position
ifelse any? targets
[ move-to one-of targets ]
[ print "Not enough agents in the neighborhood" ]
end

Subtract. SET variableX-variableY only once

I'm trying to set a resource variable. It will be time and will function like sugar in sugarscape. Its setup is: ask agentes [set time random-in-range 1 6].
The thing is... I want the agentesto participate in activities linking like we said here. But, with each participation, it should subtract a unity of agentes's time. I imagine it must be with foreachbut I seem to be unable to grasp how this works.
ask n-of n-to-link agentes with [n-t-activity = [n-t-activity] of myself] in-radius sight-radius [
while [time >= 2] [
create-participation-with myself [ set color [color] of myself ] ]
foreach (command I don't know)[
set time time - count participations]]
Essentially, I want the agentes to look if they have time to participate. If they do, they create the link and subtract 1 to their time. Only ONE per participation. If they have 3 time, they'll have 2 participations and 1 time. If they have 1 time, they won't have links at all.
EDIT
You're right. I don't need while. About foreach, every place I looked said the same thing but I can't think of other way. About colors, they're only for show purpose.
The relationship between time and participation counts is as follows: the agentes have time they can spend in activities. They participate if time>=2. But every participation (link with activity) consumes 1 time when the link is active (I didn't write the decay code yet; they'll regain their time when it is off).
EDIT V2
Nothing, it keeps subtracting even with the []. Maybe the best choice is if I give you the code so you can try it. You'll have to set 5 sliders: prob-female (53%), initial-people (around 200), num-activity (around 20), n-capacity (around 25) and sight-radius (around 7). And two buttons, setup and go. I also set a patch size of 10 with 30 max-pxcor and max-pycor. Here is the code. Sorry if I'm not clear enough!
undirected-link-breed [participations participation]
turtles-own [
n-t-activity
]
breed [activities activity]
activities-own [
t-culture-tags
shared-culture
]
breed [agentes agente]
agentes-own [
gender
time
culture-tags
shared-culture
]
to setup
clear-all
setup-world
setup-people-quotes
setup-activities
reset-ticks
END
to setup-world
ask patches [set pcolor white]
END
to setup-people-quotes
let quote (prob-female / 100 * initial-people)
create-agentes initial-people
[ while [any? other turtles-here ]
[ setxy random-xcor random-ycor ]
set gender "male" set color black
]
ask n-of quote agentes
[ set gender "female" set color blue
]
ask agentes [
set culture-tags n-values 11 [random 2]
set shared-culture (filter [ i -> i = 0 ] culture-tags)
]
ask agentes [
set time random-in-range 1 6
]
ask agentes [
assign-n-t-activity
]
END
to setup-activities
create-activities num-activity [
set shape "box"
set size 2
set xcor random-xcor
set ycor random-ycor
ask activities [
set t-culture-tags n-values 11 [random 2]
set shared-culture (filter [i -> i = 0] t-culture-tags)
]
ask activities [
assign-n-t-activity]
]
END
to assign-n-t-activity
if length shared-culture <= 4 [
set n-t-activity ["red"]
set color red
]
if length shared-culture = 5 [
set n-t-activity ["green"]
set color green
]
if length shared-culture = 6 [
set n-t-activity ["green"]
set color green
]
if length shared-culture >= 7 [
set n-t-activity ["black"]
set color black
]
END
to go
move-agentes
participate
tick
end
to move-agentes
ask agentes [
if time >= 2 [
rt random 40
lt random 40
fd 0.3
]
]
end
to participate
ask activities [
if count my-links < n-capacity [
let n-to-link ( n-capacity - count my-links)
let n-agentes-in-radius count (
agentes with [
n-t-activity = [n-t-activity] of myself ] in-radius sight-radius)
if n-agentes-in-radius < n-to-link [
set n-to-link n-agentes-in-radius
]
ask n-of n-to-link agentes with [
n-t-activity = [n-t-activity] of myself] in-radius sight-radius [
if time >= 2 [
create-participation-with myself [
set color [color] of myself ]
ask agentes [set time time - count my-participations] ]
]
ask activities [
if not any? agentes in-radius sight-radius [
ask participations [die]
]
]
]
]
end
to-report random-in-range [low high]
report low + random (high - low + 1)
END
EDIT V3
I asked Bill Rand to help me and he solved the problem. The issue was in this line: let candidates agentes with [ n-t-activity = [n-t-activity] of myself ] in-radius sight-radius. He solved the problem this way: let candidates agentes with [ n-t-activity = [n-t-activity] of myself and not participation-neighbor? myself ] in-radius sight-radius. Being this and not participation-neighbor? myself the condition to make sure that the agente is not already a part of that activity.
You almost never need foreach in NetLogo. If you find yourself thinking you need foreach, your immediate reaction should be that you need ask. In particular, if you are iterating through a group of agents, this is what ask does and you should only be using foreach when you need to iterate through a list (and that list should be something other than agents). Looking at your code, you probably don't want the while loop either.
UPDATED FOR COMMENTS and code - you definitely do not need while or foreach.
Your problem is the following code. You ask agentes that satisfy your conditions to create the links, but then you ask ALL AGENTES to change their time (line I have marked), not just the agentes that are creating participation links.
ask n-of n-to-link agentes with [
n-t-activity = [n-t-activity] of myself] in-radius sight-radius [
if time >= 2 [
create-participation-with myself [
set color [color] of myself ]
ask agentes [set time time - count my-participations] ] ; THIS LINE
]
The following code fixes this problem. I have also done something else to simplify reading and also make the code more efficient - I created an agentset (called candidates) of the agentes that satisfy the conditions. In this code, the candidates set is only created once (for each activity) instead of twice (for each activity) because you are creating it to count it and then creating it again to use for participation link generation.
to participate
ask activities
[ if count my-links < n-capacity
[ let candidates agentes with [
n-t-activity = [n-t-activity] of myself ] in-radius sight-radius
let n-to-link min (list (n-capacity - count my-links) (count candidates ) )
ask n-of n-to-link candidates
[ if time >= 2
[ create-participation-with myself [ set color [color] of myself ]
set time time - count my-participations ] ; REPLACED WITH THIS LINE
]
ask activities [
if not any? agentes in-radius sight-radius [
ask participations [die]
]
]
]
]
end

Preferential attachment: Selecting a node to attach

I've been struggling with this one for the last 24 hours or so I feel like I'm missing something relatively simple here.
to setup-scale-free-network
clear-all
;; Make a circle of turtles
set num-nodes (num-children + num-adults + num-toddlers)
create-children num-children
create-adults num-adults
create-toddlers num-toddlers
layout-circle turtles (max-pxcor - 8)
ask turtles[
create-links-with turtles with [self > myself and random-float 5 < probability]
]
setup
end
to-report find-partner
report [one-of both-ends] of one-of links
end
The above code creates a set number of turtles of various breeds and creates a number of links between these breeds.
to go
reset-ticks
make-link find-partner
tick
end
The two procedures would be called until the needed level of degree distribution as been met.
What I want to do is use the find-partner procedure to move towards preferential attachment to do this I need to modify this code to create a link from the node find partner has selected to one of each of the other three types of breeds in my network.
to make-node [old-node]
crt 1
[
set color red
if old-node != nobody
[ create-link-with old-node [ set color green ]
;; position the new node near its partner
move-to old-node
fd 8
]
]
end
My own attempts have lead no where to be honest. I know I'm asking for a lot of help but I'm at my wits end here, thank you for your help and patience.
I was unable to completely understand your question. I am guessing that you wish to create another type of link which you call preferential attachment (with green color) between turtles who are already a part of the network.
One thing you might want in this situation is that you do not pick turtles which are already in a preferential attachment network. [this is just my assumption]
I have modified your code (as follows) to get the desired network with preferential attachment shown with green colored links, have added a turtle-variable already-attached which is used to exclude turtles which are already preferentially attached to others.
Hope this helps!
breed [ children child ]
breed [ adults adult ]
breed [ toddlers toddler ]
children-own [ already-attached ]
adults-own [ already-attached ]
toddlers-own [ already-attached ]
to setup-scale-free-network
clear-all
let num-children 5
let num-adults 5
let num-toddlers 5
let probability 1
;; Make a circle of turtles
create-children num-children [ set color orange ]
create-adults num-adults [ set color green ]
create-toddlers num-toddlers [ set color blue ]
layout-circle turtles (max-pxcor - 8)
ask turtles
[
create-links-with turtles with [self > myself and random-float 5 < probability]
]
end
to go
setup-scale-free-network
ask turtles with [already-attached = 0]
[
attach-to-one-of-each-breed self
]
end
to attach-to-one-of-each-breed [ source-node ]
ask source-node
[
if any? other children with [ already-attached = 0 ]
[
ask one-of other children
[
set already-attached 1
create-link-with source-node [ set color green ]
]
]
if any? other adults with [ already-attached = 0 ]
[
ask one-of other adults
[
set already-attached 1
create-link-with source-node [ set color green ]
]
]
if any? other toddlers with [ already-attached = 0 ]
[
ask one-of other toddlers
[
set already-attached 1
create-link-with source-node [ set color green ]
]
]
]
end