NetLogo: How To Code Conditional "asks" - netlogo

I'm trying to make it so turtles that have "immune = 0" and "sick = 0" will have a chance of getting sick when colliding with a turtle with "sick = 1".
ask turtles with [immune = 0 and sick = 0]
[if any? turtles-on patch-ahead 1 with [sick = 1]
[if (random 100) < infection-rate
[set sick 1]
]
]
However, the error given is "WITH expected this input to be an agentset, but got a number instead". Is there any way to do this?

What you're doing is fine, NetLogo just got confused. This code passes the syntax checker - I added some brackets to the offending line.
globals [infection-rate]
turtles-own [immune sick]
to testme
ask turtles with [immune = 0 and sick = 0]
[if any? (turtles-on patch-ahead 1) with [sick = 1]
[if (random 100) < infection-rate
[set sick 1]
]
]
end

Related

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

Compare two variables from two breeds

I still haven't learned how to compare two attributes from two different breeds.
In my example, I want to ask the breeds (healthy shops and unhealthy shops) to compare their revenues. The type of shop with the least revenues will close and the other type of shop will open in his place. The command to "compare-revenue" is the one that doesn't work. I know I shouldn't use breed, but I don't know how to formulate it differently without getting the "tick" error.
Thanks!
breed[healthy-shops healthy-shop]
breed[unhealthy-shops unhealthy-shop]
healthy-shops-own[
total-earnings-h
]
unhealthy-shops-own[
total-earnings-nh
]
to setup
create-healthy-shops 50
create-unhealthy-shops 50
ask healthy-shop [set total-earnings-n 2000 + random 2000]
ask unhealthy-shop [set total-earnings-nn 2000 + random 2000]
end
to go
compare-revenue
end
;;;;;;;;;
to compare-revenue
let minhealth one-of healthy-shops with-min [total-earnings-h]
let minunhealth one-of unhealthy-shops with-min [total-earnings-nh]
ask breed [ifelse (total-earnings-nh < total-earnings-h
[ask minunhealth [die hatch-healthy-shops 1]]
[ask minhealth [die hatch-unhealthy-shops 1]]]
end
Another version using the let command (not sure if it is right)
to compare-revenue
let minhealth one-of healthy-shops with-min [total-earnings-h]
let minunhealth one-of unhealthy-shops with-min [total-earnings-nh]
if minhealth > minunhealth [ask minunhealth [die hatch-healthy-shops 1]]
if minhealth < minunhealth [ask minhealth [die hatch-unhealthy-shops 1]]
end
When you correct the typos: ask healthy-shops [set total-earnings-h 2000 + random 2000] and ask unhealthy-shops [set total-earnings-nh 2000 + random 2000] I get an error "You can't use go in an observer context, because go is turtle/link-only".
That is because of the usage of minhealth/minunhealth without giving the respective shop. You can correct that by writing:
([total-earnings-nh] of minunhealth < [total-earnings-h] of minhealth)
This will make the code run until there are no healty or unhealty shops left and then crash.
You can change that by using
if any? unhealthy-shops and any? healthy-shops
[compare-revenue]
Also, you have to change the order of die and hatch. Right now, no new shops are created, because the shop, it should hatch from is already deleted.
This would be the full code:
breed[healthy-shops healthy-shop]
breed[unhealthy-shops unhealthy-shop]
healthy-shops-own[
total-earnings-h
]
unhealthy-shops-own[
total-earnings-nh
]
to setup
create-healthy-shops 50
[
setxy random-xcor random-ycor
set total-earnings-h 2000 + random 2000
]
create-unhealthy-shops 50
[
setxy random-xcor random-ycor
set total-earnings-nh 2000 + random 2000
]
end
to go
if any? unhealthy-shops and any? healthy-shops
[compare-revenue]
end
to compare-revenue
let minhealth one-of healthy-shops with-min [total-earnings-h]
let minunhealth one-of unhealthy-shops with-min [total-earnings-nh]
ifelse ([total-earnings-nh] of minunhealth < [total-earnings-h] of minhealth)
[ask minunhealth [hatch-healthy-shops 1 die]]
[ask minhealth [hatch-unhealthy-shops 1 die]]
end

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

"Can't use XXX in an observer context because patch only"

I am havig some diffuculties with a part of my code. Netlogo reort "Can't use GO in an observer context because patch only"
My guess is that this is because in the go part I ask for a procedure (CACULATEWILANDATRAC) that does not begin with "ask Patches". However the (CACULATEWILANDATRAC) produce is to calculate one of the patches own-variables, so ask patches does not seem fit here.
I still tried to solve it with putting ask patches before the procure but then
I get another error when running the model : " only the observer can ASK the set of all patches.
error while patch 1079 509 running ASK
called by (anonymous command: [ [the-Land-use the-Senario] -> ask patches [ if count patches with [ the-Land-use ] > the-Senario [ set Willingstochange True ] ] ]) called by procedure CACULATEWILANDATRAC"
The problem thus lies with where to call for the CACULATEWILANDATRAC procedure?
It is now part of the go procedure but this thus gives the error "Can't use XXX in an observer context because turtle only".
My entire code:
> extensions [gis]
globals
[
land-use-map
Senario1N ;; the count of patches senario 1 describes
Senario1L
Senario1A
Senario1B
Senario1I
Senario1R
Senario1W
%landusetypeN ;; the amount patches
%landusetypeL
%landusetypeA
%landusetypeB
%landusetypeI
Willingstochange ;; If true a patch would like to change (if true the count of patches has a surplus comparing to the sneario, if false they have a shortage)
atractiveness ;; if a patch type is attractive to change in <1 = yess
Atractiveneighbor
]
patches-own
[ Land-use ;; Wat kind og landusetype a patch has
]
to setup
clear-all
load-gis ;;load the maps
setup-constants
update-global-variables
update-display
reset-ticks
end
to load-gis ;;load the maps
set land-use-map gis:load-dataset "a_LANDUSE_cellsize5.asc" ;;loads the land use map
gis:set-world-envelope-ds gis:envelope-of land-use-map ;;sets the envelope of the world to match that of the GIS dataset
gis:apply-raster land-use-map Land-use ;;patches in the land-use-map have a specific land-use now
ask patches [
if Land-use = 1 [ set pcolor Green ] ; Green = Nature ;; patches have a certain color now
if Land-use = 2 [ set pcolor red ] ; Dark red = Leisure
if Land-use = 3 [ set pcolor Yellow ] ; Yellow = Agriculture
if Land-use = 4 [ set pcolor brown ] ; brouwn = Buildup
if Land-use = 5 [ set pcolor grey ] ; grey = roads
if Land-use = 6 [ set pcolor pink ] ; pink = industry
if Land-use = 7 [ set pcolor blue ] ; Blue = water
]
resize-world 0 1633 0 780
set-patch-size 1
end
to setup-constants
set Senario1N 49174 ;; the count of patches senario 1 describes
set Senario1L 17871
set Senario1A 569970
set Senario1B 34202
set Senario1I 5540
set Senario1R 34968
set Senario1W 65594
end
to go ;; this asks the model to caculate certain variables defined below
givecountlansusetypes
askforchange
caculateWILandAtrac
tick
end
to givecountlansusetypes ;; here the cuurent amount of patches is shown
show count patches with [Land-use = 1]
show count patches with [Land-use = 2]
show count patches with [Land-use = 3]
show count patches with [Land-use = 4]
show count patches with [Land-use = 5]
show count patches with [Land-use = 6]
show count patches with [Land-use = 7]
end
to update-display
ask patches
[
if Land-use = 1 [ set pcolor Green ] ;; Green = Nature ;; patches have a certain color now
if Land-use = 2 [ set pcolor red ] ;; Dark red = Leisure
if Land-use = 3 [ set pcolor yellow ] ;; Yellow = Agriculture
if Land-use = 4 [ set pcolor brown ] ;; brouwn = Buildup
if Land-use = 5 [ set pcolor grey ] ;; grey = roads
if Land-use = 6 [ set pcolor pink ] ;; pink = industry
if Land-use = 7 [ set pcolor blue ] ;; Blue = water
]
end
to update-global-variables
if count patches > 0
[ set %landusetypeN (count patches with [ Land-use = 1 ] / count patches) * 100
set %landusetypeL (count patches with [ Land-use = 2 ] / count patches) * 100
set %landusetypeA (count patches with [ Land-use = 3 ] / count patches) * 100
set %landusetypeB (count patches with [ Land-use = 4 ] / count patches) * 100
set %landusetypeI (count patches with [ Land-use = 6 ] / count patches) * 100
]
end
to caculateWILandAtrac
;; Sets Willingness to change true if patches are with more fellowpatches than the senario decribes
(foreach list (Land-use = 1) (Land-use = 2)[49174 17871]
[ [the-Land-use the-Senario] -> ask patches [if count patches with [the-Land-use] > the-Senario [ set Willingstochange True ] ] ])
;; gives score to the patches attractiveness based on the ratio patches/senario
(foreach list (Land-use = 1) (Land-use = 2)[49174 17871]
[ [the-Land-use the-Senario] -> ask patches [ set atractiveness (count patches with [the-Land-use]/ the-Senario) ] ])
end
to askforchange
ask patches [
if Willingstochange = true [change] ;; this ask the patches that are willing to change (have a surpuls) to go and change
]
end
to change
ask neighbors with [Willingstochange = false ] ;; this asks if the patch had neigbors with a shortage
[set Atractiveneighbor min-one-of patches [atractiveness]] ;; this asks to give the neigbor with the lowest patchcount/senario ratio
ask patches [set Land-use ([Land-use] of Atractiveneighbor)] ;; this asks the patches to change their land-use to the land-use of neigbor with the lowest patchcount/senario ratio
end
In your last line of code the current asked patch (asked in askforchange) asks all patches to set their Land-use accordingly. I think that there lies your problem.
Maybe it solves your problem, if you replace the last line with the following:
set Land-use ([Land-use] of Atractiveneighbor)
With this, the currently asked patch changes its land-use accordingly. But I am not quite sure, if that is what you want the procedure to do there?

Netlogo, how to delete link between turtles based on value they own

I am writing simulation where i am trying to simlate recruiting process for terrorost organization. In this model turtles have groups of friends i.e other turtles they are connected to with links. The model includes the forming of new bonds(links) with turtles they meet if their world view is similar and is supposed to have a mechanism for disconectiong from friends with world view most different from them among their friends.
Tried to solve the issue with following block of code which does not seem to work properly, often get the error message
"OF expected input to be a turtle agentset or turtle but got NOBODY instead."
related to value of friend_dif
ask turtles with [(connections > 0) and (color = blue)][
let friends_inverse ( 1 / connections )
if friends_inverse > random-float 1[
let friend_dif abs([world_view] of self - [world_view] of one-of other link-neighbors)
ask max-one-of links [friend_dif][
die
]
]
set connections count link-neighbors
]
Below is the whole code for the mentioned simulation. The aim is to comparetwo strategies one where recriters focus on turtles with most radical world view, the second where they first targets the most central turtles in the net.
turtles-own [connections world_view]
to setup
ca
crt potential_recruits [setxy random-xcor random-ycor set color blue]
ask turtles with [color = blue][
let przypisania random max_start_recruits_connections
;; 0-0.4 non interested, 0.4-0.7 moderate, 0.7-0.9 symphatizing, >0.9 radical - can be recrouted
set world_view random-float 1
if count my-links < 10 [
repeat przypisania [
create-link-with one-of other turtles with [(count link-neighbors < 10) and (color = blue)]
]
]
show link-neighbors
set connections count link-neighbors
]
crt recruiters [setxy random-xcor random-ycor set color orange]
ask turtles with [color = orange][
set world_view 1
if strategy = "world view"[
recruit_view
]
if strategy = "most central"[
recruit_central
]
]
;;show count links
reset-ticks
setup-plots
update-plots
end
to go
;;creating new links with turtles they meet and movement which is random
ask turtles [
rt random-float 360
fd 1
if any? other turtles-here[
let world_view1 [world_view] of one-of turtles-here
let world_view2 [world_view] of one-of other turtles-here
let connection_chance abs(world_view1 - world_view2)
if connection_chance <= 0.2 [
;;show connection_chance
create-links-with other turtles-here
]
]
;;show link-neighbors
set connections count link-neighbors
]
;;how recruiting works in this model
ask turtles with [world_view > 0.9][
if count in-link-neighbors with [color = orange] > 0[
set color orange
set world_view 1
]
]
;; friend's influence on turtles
ask turtles with [(count link-neighbors > 0) and (color = blue)][
let friends_view (sum [world_view] of link-neighbors / count link-neighbors)
let view_dev (friends_view - world_view)
;;show world_view show view_dev
set world_view world_view + (view_dev / 2)
]
;; removing turtles from with most different opinion from our colleagues
ask turtles with [(connections > 0) and (color = blue)][
let friends_inverse ( 1 / connections )
if friends_inverse > random-float 1[
let friend_dif abs([world_view] of self - [world_view] of one-of other link-neighbors)
ask max-one-of links [friend_dif][
die
]
]
set connections count link-neighbors
]
;show count links
tick
update-plots
end
to recruit_view
ask max-n-of start_recruiters_connections turtles with [ color = blue][world_view][
repeat start_recruiters_connections[
create-link-with one-of other turtles with [ color = orange]
]
]
ask turtles with [color = orange][
set connections count link-neighbors
]
end
to recruit_central
ask max-n-of start_recruiters_connections turtles with [ color = blue][count my-links][
repeat start_recruiters_connections[
create-link-with one-of other turtles with [ color = orange]
]
]
ask turtles with [color = orange][
set connections count link-neighbors
]
end
to batch
repeat 50 [
go
]
end
Your problem is that you aren't switching contexts (that is, whether the code is 'currently' in the perspective of a turtle or a link) correctly.
You start with ask turtles - pretend you are now the first turtle being asked. First a value is calculated and then compared to a random number - assume that the if is satisfied. The code is still in the turtle context, so the code inside the [] is applied to this first turtle.
The code creates a variable called friend_dif and assigns its value as the difference in worldviews between itself and one randomly selected network neighbours. In your code, you then have max-one-of links [friend_dif]. However, that only selects the link with the maximum value of friend_dif if (1) friend_dif is a links-own attribute and (2) the value of friend_dif has been set for all links. Neither is true. Furthermore, by asking for max-one-of links [friend_dif], you are asking for the link with the highest value from all links in the model, not just the ones with the turtle of interest at one end.
So you need to get your turtle to calculate the difference for all its link-neighbors and then switch contexts to the link that connects the two turtles, before asking that link to die.
This is not tested. What it is supposed to do is identify the network neighbour that returns the biggest difference in worldview values and then use the name of the link (which is given by the two ends) to ask it to die.
ask turtles with [ count my-links > 0 and color = blue]
[ if random-float 1 < 1 / count my-links
[ let bigdif max-one-of link-neighbours [abs ([worldview] - [worldview] of myself)
ask link self bigdif [die]
]
]
Alternatively (and easier to read), you can create a link attribute that stores the value of the differences in worldviews (called dif below), then do something like:
ask links [ set dif abs ([worldview] of end1 - [worldview] of end2) ]
ask turtles with [ count my-links > 0 and color = blue]
[ if random-float 1 < 1 / count my-links
[ ask max-one-of my-links [dif] [die]
]
]