BehaviorSpace Netlogo- Measure runs using these reporters - netlogo

I am simulating a classroom and calculating the energy consumed by lights, fans and ACs. Now I am running my simulation in behavior space so that after each run the energy consumed is shown. The energy consumed is in a procedure.
to energy-calculation
ask lights [ ifelse ( l-on? ) [ set l-energy (light-on-duration * light-
wattage) ][ set l-energy 0 ] ]
ask fans [ ifelse ( f-on? ) [ set f-energy ( fan-on-duration * fan-wattage
)] [ set f-energy 0 ] ]
ask acs [ ifelse ( a-on? ) [ set a-energy (ac-on-duration * ac-wattage) ] [
set a-energy 0 ] ]
let light-e sum [l-energy] of lights
let fan-e sum [f-energy] of fans
let ac-e sum [a-energy] of acs
set t-light ( light-e / (60000))
set t-fan ( fan-e / (60000))
set t-ac ( ac-e / ( 60000 ) )
show (word "sum of ac energy = " ac-e )
set t-energy ( t-light + t-fan + t-ac )
end
In the 'Measure runs using these reporters' section if I am giving energy-calculation then it shows error experiment aborted due to syntax error.
What should I do to solve this?

Related

Choice based on other turtles' variables

I'm stuck with my ABM. The situation is very simple: there are some turtles, producers, and others, choosers. Producers produce a product with a certain quality, choosers choose based on perceived quality.
Perceived quality is a function "quality-of-product-of-producers - beta-of-chooser", where beta is an individual adaptive variable. All these variables are turtles-own, and they all own them (at each round roles are switched).
I'd like the following to happen: quality-of-product is a producers' variable, beta is a choosers' variable. How to code the operation?
I've tried the following things:
ask turtles with [group = "producers"] [
set perceived-product-quality ((product-quality - beta))
]
However, like beta is producers' one (incorrect, should be choosers).
Then I've tried this:
ask turtles with [group = "choosers"] [
let quality [product-quality] of turtles with [ group = "producers" ]
set perceived-product-quality quality - beta
]
However, it doesn't work, runtime error: “expected input to be a number but got the list“.
How can I do it?
I'm not sure what your exact use case is, if you're trying to query the mean product quality / beta from all producers and choosers, but the general answer I think is that you need to be explicit with which turtles you're actually trying to pull values from. When you use ask, the agent that you are asking to do something will default to using its own variables if it owns them. So, if you are needing to stick with turtles-own variables rather than making breeds and breed-specific variables, you'll need to explicitly state which turtle you're trying to reference. Here is a toy example that has choosers pick the product quality of whatever producer is nearest for use in the formula:
turtles-own [ group product-quality beta perceived-product-quality]
to setup
ca
ask n-of 10 patches [
sprout 1 [
set group one-of [ "producers" "choosers" ]
]
]
ask turtles [
ifelse group = "producers" [
set product-quality random 500 + 500
set beta random 200 + 100
set color red
] [
set product-quality random 50 + 50
set beta random 20 + 10
set color blue
]
]
reset-ticks
end
to set-perceived
let current-producers turtles with [ group = "producers" ]
let current-choosers turtles with [ group = "choosers" ]
ask current-choosers [
; Pick the closest producer
let closest-producer min-one-of current-producers [ distance myself ]
; Pull the product quality of that closest producer
let closest-product-quality [ product-quality ] of closest-producer
; Set MY perceived product quality to be closest-product-quality - MY beta
set perceived-product-quality closest-product-quality - beta
show (
word "I used the turtle " closest-producer
" to determine my perceived product quality of: " perceived-product-quality
)
]
end
Edit:
Comment update:
I'd like the following to happen: choosers do the operation “perceived-product-quality - beta“ for all turtles in the Moore neighbour. After doing this, they are going to choose the product with highest value of perceived-product-quality.
In this version, there is a to-report procedure that reports the perceived product quality from the perspective of from-who. This can then be used with max-one-of to return the turtle with the highest perceived value.
turtles-own [ group product-quality beta perceived-product-quality]
to setup
ca
resize-world 0 5 0 5
set-patch-size 40
ask patches [
sprout 1 [
set group one-of [ "producers" "choosers" ]
]
]
ask turtles [
ifelse group = "producers" [
set product-quality random 500 + 500
set beta random 200 + 100
set color red
] [
set product-quality random 50 + 50
set beta random 20 + 10
set color blue
]
]
reset-ticks
end
to choose-best-moore
let current-choosers turtles with [ group = "choosers" ]
ask current-choosers [
let current-producers ( turtles-on neighbors ) with [ group = "producers" ]
ifelse any? current-producers [
let turtle-with-highest-perceived max-one-of current-producers [ perceived-target-value myself ]
let real-product-quality [product-quality] of turtle-with-highest-perceived
let false-product-quality [ perceived-target-value myself ] of turtle-with-highest-perceived
show ( word "I surveyed " count current-producers " and found that " turtle-with-highest-perceived
" had the best product quality (real: " real-product-quality ", perceived: " false-product-quality ")" )
] [
show "I found no producers in my neighboring cells"
]
]
end
to-report perceived-target-value [ from-who ]
let target-product-quality product-quality
let target-perceived-quality ( target-product-quality - [beta] of from-who )
report target-perceived-quality
end

How can we count agents according to specific variables?

We are trying to solve the following problem:
Each agent has its specific code and at each iteration the list of agents alive in that iteration is updated. We want to calculate how many agents are die of each code present in the list per iteration.
We have these procedures below (code). Obs: We need to use the profile list because of the outputs that are exported by turtle profile
Sorry for the big code below, but we tried our best to reduce it to be reproducible code
Thanks in advance
globals [ ListProfiles Death ]
turtles-own [ profiles-code metabolism-code reproduction-code metabolism reproduction resource-turtle ]
patches-own [ resources ]
to setup
ca
prepare
ask patches [ set resources random 100 ]
let list1 ( list 2 4 )
let list2 ( list 5 10 )
(
foreach list1
[
this-metabolism ->
foreach list2
[
this-reproduction ->
ask n-of 1 patches
[
sprout 1
[
set metabolism this-metabolism
set reproduction this-reproduction
setup-turtles
]
]
]
]
)
reset-ticks
end
to setup-turtles
(
ifelse
metabolism = 2 [ set metabolism-code "M1" ]
metabolism = 4 [ set metabolism-code "M2" ]
)
(
ifelse
reproduction = 5 [ set reproduction-code "R1" ]
reproduction = 10 [ set reproduction-code "R2" ]
)
set profiles-code ( word metabolism-code reproduction-code )
print ( word "profiles-code: " profiles-code )
end
to go
ListProfilesProc
MetaboProc
ProbDieProc
output
tick
end
to ListProfilesProc
set ListProfiles [ ]
ask turtles [
set ListProfiles lput profiles-code ListProfiles
]
set ListProfiles remove-duplicates ListProfiles
end
to MetaboProc
ask turtles [
(
ifelse
metabolism = 2
[
set resource-turtle ( resources - metabolism )
if resource-turtle <= 60 [ DieProc ]
(
ifelse
reproduction = 5
[
if resource-turtle >= 5 [ hatch 1 ]
]
reproduction = 10
[
if resource-turtle >= 10 [ hatch 1 ]
]
)
]
)
]
end
to DieProc
let code profiles-code
foreach ListProfiles [ lp -> ;; I think, here's the problem... I can't individualize the kills by code. I've already tried several things. And therefore I can't get the output of the deaths by code. It is always repeated (general calculation)...
if lp = code
[
set Death Death + 1
]
]
die
end
to ProbDieProc
ask turtles
[
let prob-die random-float 1.01
if prob-die < 0.77 [ DieProc ]
]
end
to prepare
carefully
[ file-delete ( word "output.csv" ) ]
[ ]
file-open ( word "output.csv" )
file-print ( word "code_profile,death,tick" )
file-close
end
to output
file-open ( "output.csv" )
foreach ListProfiles
[
t ->
file-print ( word t "," Death "," ticks )
]
file-close
end
Deaths as you have it is a global variable, which means that any time any turtle accesses it (either to update or read), they are all "sharing" the same value. Instead, you need to track deaths for each profile type. The way you have it, where profiles-code differentiates the different turtle types, you can tackle this a few ways- for example: you could create specific Death trackers for each profile type (eg. Death-M1R1, Death-M1R2... etc.) and output that as needed; or you could use a list, where you update the items in the list that correspond to a specific profile; or you could use a list of lists and use position to grab the death value for a different breed; or you could use the tables extension, which is the example I will show below because I think it's the cleanest and most explicit.
The tables extension allows what is similar to a dictionary structure if you've used that in other coding languages, where you have a {KEY: VALUE} pair such that if you enter the KEY you get out the VALUE. So the general workflow here is to build a dictionary to store the name and death count for each profile type. Then, anytime a turtle dies it will update the death count for its profile type in the dictionary.
To keep it simple, I've made only minor changes to your code above, and added comments where I made (most) updates:
extensions [ table ]
globals [ ListProfiles Death NInitial NFinal R Birth deaths-dict ]
turtles-own [ profiles-code metabolism-code reproduction-code metabolism reproduction resource-turtle ]
patches-own [ resources ]
to setup
ca
prepare
; Define deaths-list as a list
set deaths-dict table:make
ask patches [ set resources random 100 ]
let list1 ( list 2 4 )
let list2 ( list 5 10 )
(
foreach list1
[
this-metabolism ->
foreach list2
[
this-reproduction ->
ask n-of 1 patches
[
sprout 1
[
set metabolism this-metabolism
set reproduction this-reproduction
setup-turtles
; Add each metabolism / reproduction to the deaths dictionary with 0 as initial deaths value
table:put deaths-dict ( word metabolism-code reproduction-code ) 0
]
]
]
]
)
print deaths-dict
reset-ticks
end
to setup-turtles
(
ifelse
metabolism = 2 [ set metabolism-code "M1" ]
metabolism = 4 [ set metabolism-code "M2" ]
)
(
ifelse
reproduction = 5 [ set reproduction-code "R1" ]
reproduction = 10 [ set reproduction-code "R2" ]
)
set profiles-code ( word metabolism-code reproduction-code )
print ( word "profiles-code: " profiles-code )
end
to go
; Stop the model if no turtles exist
if not any? turtles [ stop ]
ListProfilesProc
MetaboProc
ProbDieProc
output
tick
end
to ListProfilesProc
; Simple way to get a sorted list of profile types
set ListProfiles sort remove-duplicates [ profiles-code ] of turtles
end
to MetaboProc
ask turtles [
(
ifelse
metabolism = 2
[
set resource-turtle ( resources - metabolism )
if resource-turtle <= 60 [ DieProc ]
(
ifelse
reproduction = 5
[
if resource-turtle >= 5 [ hatch 1 ]
]
reproduction = 10
[
if resource-turtle >= 10 [ hatch 1 ]
]
)
]
)
]
end
to ProbDieProc
print "Running die proc..."
ask turtles
[
let prob-die random-float 1
if prob-die < 0.4 [
DieProc
]
]
end
to DieProc
; Pull current death count for this profile
let current-profile-death-count table:get deaths-dict profiles-code
; Increase that death count by one
let current-profile-new-death-count current-profile-death-count + 1
; Update the death count in the master dictionary
table:put deaths-dict profiles-code current-profile-new-death-count
die
end
to prepare
carefully
[ file-delete ( word "output.csv" ) ]
[ ]
print "opening..."
file-open ( word "output.csv" )
file-print ( word "code_profile,death,tick" )
file-close
end
to output
file-open ( "output.csv" )
foreach ListProfiles
[
t ->
let profile-deaths table:get deaths-dict t
file-print ( word t "," profile-deaths "," ticks )
]
file-close
end
Output then looks something like:

How to update a proportion used to select among turtles in a loop?

In my model the turtles have two sexes and there are two potential strategies "0" and "1". The females count the number of males in a set radius and choose among that pool based on their strategies.
The females have a limit to their pool of potential mates and they loop through this pool to select the males according to their strategy. This is all in the to-choose procedure.
One issue that a colleague picked up on is that the following line of code should be updated every time a female chooses another mate so that the proportion reflects the remaining potential mates and not the n-max which was set outside of the loop.
set prop_B ( count availa-males with [ strategy = 0 ] ) / n-max
To state the issue another way for clarity if the n-max is 5 and a female sets the prop_B using this value for the first mate then in the next iteration of the loop n-max should deprecate by 1 because there are only 4 remaining males.
So it should be something like: set prop_B ( count availa-males with [ strategy = 0 ] ) / (n-max - count mates-already-chosen)
Please see below for a working example of the model. Hope you can help.
turtles-own [sex availa-males mates mate-count max-mate-count strategy n-max prop_B proba_B]
breed [males male]
breed [females female]
to setup
clear-all
create-males 50
create-females 1
ask turtles [
setxy random-xcor random-ycor
ifelse random 2 = 1 [set strategy 1] [set strategy 0]
]
ask males [set color red]
ask females [set color blue]
reset-ticks
end
to go
ask males [
; fd 1
]
ask turtles [
set mates ( turtle-set )
]
ask females [choose]
tick
end
to choose
; set a cap on possible mates for females; 5, or the number
; available within the radius if less than 5
set availa-males males in-radius 5
set n-max count availa-males
set max-mate-count ifelse-value ( n-max < 5 ) [ n-max ] [ 5 ] ; 5 5
; Until a female has chosen up to her maximum number of mates:
while [ mate-count < max-mate-count ]
[; determine which available males are not already in her 'mates' agentset
set availa-males availa-males with [ not member? self [mates] of myself ]
; assess the proportion of the '0' strategy in remaining available males
set prop_B ( count availa-males with [ strategy = 0 ] ) / n-max
; example probability choice, just meant to choose '0 strategy' males
; with a frequency disproportionate to availability
set proba_B ifelse-value ( prop_B <= 0.1 ) [ 0.8 ] [ 0.2 ]
; use a random float to determine which strategy type is chosen
set mates ( turtle-set mates
ifelse-value ( random-float 1 < proba_B )
[ one-of availa-males with [ strategy = 0] ]
[ one-of availa-males with [ strategy = 1]] )
; count the current mates to break the while loop once
; the maximum number of mates is reached
set mate-count count mates
]
; have the female's males add her to their own mates agentset
ask mates [ set mates ( turtle-set mates myself ) ]
if n-max < count mates [ print "Fewer available males than mates" ]
end
Since you don't need them to be selected sequentially, then one option you should think about is the weighted equivalent of n-of from the rnd extension. The following code is a complete model that uses weighted selection, to show you how it could work. But it won't give quite the same results as your approach. Your mathematics basically forces one choice or the other based on the proportion of each. I thought that might work for you anyway, as the weighting is just a demonstration of disproportional.
extensions [rnd]
turtles-own
[ sex
mates
strategy
]
breed [males male]
breed [females female]
to setup
clear-all
create-males 50 [set color red set sex "M"]
create-females 1 [set color blue set sex "F"]
ask turtles
[ setxy random-xcor random-ycor
set strategy one-of [1 0]
set mates nobody
]
reset-ticks
end
to go
ask males
[ ; fd 1
]
ask females [choose]
tick
end
to choose
let availa-males males in-radius 5
let max-mate-count min (list 5 count availa-males)
if max-mate-count < 5 [ print "Fewer available males than mates" ]
let new-mates rnd:weighted-n-of max-mate-count availa-males [ strategy-weight strategy ]
set mates (turtle-set mates new-mates)
ask new-mates
[ set mates (turtle-set mates myself)
]
end
to-report strategy-weight [ #strategy ]
if #strategy = 1 [ report 0.2 ]
if #strategy = 0 [ report 0.8 ]
report 0
end
You will notice I also removed a bunch of turtle variables. You don't need to have a permanent variable, just create a temporary one with let. I also noticed you have sex as a turtle variable, but you are actually handling sex with different breeds, but I left it in just in case it has some other purpose.

How to select up to a maximum number of turtles using roulette wheel selection

In my model the turtles have two sexes where the males have two potential tactics. The females count the number of males in a set radius.
I want the females to weight their probability of selecting from the group of males (without replacement) depending on the relative frequency of the two male tactics.
I already have the code for the probability of selecting from the males (matingPoolProbAnad and matingPoolProbRes) but I don't know how to implement it, though the rnd extension seems the way to go, specifically rnd:weighted-n-of size agentset [ reporter ].
It's complicated by three things (1) the males can mate with more than one female but (2) only once with a given female and (3) females can only mate with a maximum of five males.
to count-mates ; ask the females to count the number of males in a 10 patch radius & then
; determine the frequency of the resident males in their patch
ask turtles with [sex = "female"]
[
if any? turtles with [sex = "male"] in-radius 10
[ set potentialMates turtles with [sex = "male"] in-radius 10
ifelse any? potentialMates with [anadromousM = 1]
[ set FA count potentialMates with [anadromousM = 1] / count potentialMates ]
[ set FA 0]
ifelse any? potentialMates with [anadromousM = 0]
[ set FR count potentialMates with [anadromousM = 0] / count potentialMates ]
[ set FR 0]
]
]
end
to mating-pool-prob ; negative frequency dependency which is based on the number of male
; resident turtles
ask turtles with [sex = "female"]
[
ifelse (FA = 1) and (FR = 0)[
set matingPoolProbAnad 1
set matingPoolProbRes 0
]
[ifelse (FA > 0) and (FR < 1)
[
set matingPoolProbRes exp(a - b * (FR - c ))/(1 + exp(a - b * (FR - c)))
set matingPoolProbAnad 1 - matingPoolProbRes
]
[
set matingPoolProbAnad 0
set matingPoolProbRes 1
]
]
]
end
This example may approach what you're getting at, but obviously would need to be adapted from this toy version. This setup sprouts 75% of males with strategy A and the rest with strategy B, and gives all turtles an empty agentset of mates to start off:
breed [ males male ]
breed [ females female ]
turtles-own [ mates ]
males-own [ strategy ]
females-own [ max-mate-count mate-count ]
to setup
ca
ask n-of 200 patches [
sprout-males 1 [
ifelse random-float 1 < 0.75 [
set strategy "A"
set color orange
] [
set strategy "B"
set color violet
]
]
]
ask n-of 50 patches with [ not any? turtles-here ] [
sprout-females 1 [
set color green
]
]
ask turtles [
set mates ( turtle-set )
]
reset-ticks
end
Use a while loop to have each female iteratively assess the strategy proportions of the males available to her, then add them to her 'mates' list. More detail in comments:
to choose-mates
ask females [
; set a cap on possible mates for females; 5, or the number
; available within the radius if less than 5
let availa-males males in-radius 10
let n-max count availa-males
set max-mate-count ifelse-value ( n-max < 5 ) [ n-max ] [ 5 ]
; Until a female has chosen up to her maximum number of mates:
while [ mate-count < max-mate-count ] [
; determine which available males are not already in her 'mates' agentset
set availa-males availa-males with [ not member? self [mates] of myself ]
; assess the proportion of B strategy in remaining available males
let prop_B ( count availa-males with [ strategy = "B" ] ) / n-max
; example probability choice, just meant to choose B males
; with a frequency disproportionate to availability
let proba_B ifelse-value ( prop_b * 2 < 0.6 ) [ prop_b * 2 ] [ 0.6 ]
; use a random float to determine which strategy type is chosen
set mates ( turtle-set mates ifelse-value ( random-float 1 < proba_B )
[ one-of availa-males with [ strategy = "B" ] ]
[ one-of availa-males with [ strategy = "A" ] ] )
; count the current mates to break the while loop once
; the maximum number of mates is reached
set mate-count count mates
]
; have the female's males add her to their own mates agentset
ask mates [
set mates ( turtle-set mates myself )
]
]
end
To check that 'B' males are being chosen disproportionately to their availability:
to check-values
let all-mates map [ i -> [strategy] of i ] [mates] of females
print word "Average proportion of 'B' mates chosen: " mean map b-proportion all-mates
print word "Actual proportion of 'B' males: " ( ( count males with [ strategy = "B" ] ) / count males )
end
to-report b-proportion [ input_list ]
let tot length input_list
let nb length filter [ i -> i = "B" ] input_list
report nb / tot
end
I'm not 100% sure that that's what you're after- maybe you can use the rnd package to clean up the loop.
Edit in response to comment
If you modify the end of the `choose-mates like so:
...
...
; have the female's males add her to their own mates agentset
ask mates [
set mates ( turtle-set mates myself )
]
if n-max < count mates [
print "Fewer available males than mates"
]
]
end
And your go looks like:
to go
choose-mates
end
You can run setup and go as many times as you like and you should never see the printout "Fewer available males than mates":
to repeat-1000
repeat 1000 [
setup
go
]
end
I ran that a few times and never had count availa-males be less than the count of mates. However, if you add in movement without allowing the females to reset their mates agentset, you do start to see it- for example, try running this a few times:
to go
choose-mates
ask turtles [ fd 1 ]
end
Now, because the turtles are moving around, you have some cases where females held on to their mates from the previous function call and then moved into a space where there were fewer availa-males. The quick and easy fix is to have females clear their mates each time. Where you do that depends on your model goals (how often do females choose mates? Do they only forget some of their previous ones? etc), but here's a very simple way:
to go
ask turtles [ set mates ( turtle-set ) ]
choose-mates
ask turtles [ fd 1 ]
end
Now you can run that as many times as you like and shouldn't see the "Fewer available males than mates" printout.

Netlogo - Divide world equally between n agents

I'm creating an inspection model in Netlogo, and each inspector is responsible for n patches. That is, I need to divide the world in areas that are exclusive for each inspector.
I tried it with
set range (world-width * world-height / inspectors) ^ 0.5
But their range is higher than expected, and it allows one inspector to "invade" the area of other inspectors, which is not desirable.
This approach is probably way over-complicated but may do what you need- it splits the world into even vertical bands of "territory." Note that it only works properly if the world's minimum xcor is 0, and if the world-width is divisible by the number of inspectors- otherwise one inspector will have an inspection area that is different from all the others. For example, using this setup:
breed [ inspectors inspector ]
inspectors-own [ my-territory ]
to setup
ca
resize-world 0 29 0 29
create-inspectors ninspectors [
set my-territory nobody
]
split
reset-ticks
end
Make lists to store the minimum and maximum xcor values, then use those to section off patches to assign as territories to different inspectors. More explanation in comments:
to split
; get a count of the inspectors
let n count inspectors
; get section widths
let n-xcor ( max-pxcor - min-pxcor ) / n
; build lists to define min-maxes of sections
let n-min ( range min-pxcor max-pxcor n-xcor )
let n-max lput ( max-pxcor + 1 ) n-min
set n-max but-first n-max
; Foreach of the min-max pairs, set patches within
; the min-max boundary be set to the territory of one
; of the inspectors that currently has no territory
( foreach n-min n-max [
[ _min _max ] ->
set _min ceiling _min
set _max ceiling _max
let cur_inspector one-of inspectors with [ my-territory = nobody ]
ask patches with [ pxcor >= _min and pxcor < _max ] [
ask cur_inspector [
ifelse my-territory = nobody [
set my-territory myself
] [
set my-territory ( patch-set my-territory myself )
]
]
set pcolor ( [color] of cur_inspector ) - 2
]
])
; Move inspectors to their territory
ask inspectors [
setxy ( mean [pxcor] of my-territory ) ( mean [pycor] of my-territory )
show my-territory
pd
]
end
To check that it's working, you can have your inspectors wander around:
to go
ask inspectors [
face one-of neighbors with [ member? self [my-territory] of myself ]
fd 1
]
tick
end