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: