dannerz
dannerz

Reputation: 1

Procedure with "foreach" command crashes model occasionally. Does "ask turtles with [x]" affect each turtle individually?

My NetLogo model starts with an initial population of turtles with species = 1 that are randomly distributed on a world with 5 habitats (called sectors in the model). The turtles can move freely across all sectors and reproduce but have variables that control their diet and phenotype. My procedure for check-speciation is based on the phenotype variables (pheno-value) of turtles and the sector they are on. It calculates the average pheno-value in each sector then calculates the difference in average pheno-value between each sector. If this difference exceeds a set threshold, than all turtles in that sector become a new species and their species value increases.

I get different variations of this error "Can't find element 5 of the list [0 0 0 0 0], which is only of length 5" every 2-4 model run because of the "foreach" command I use in this code. Are there any edits I can make to have it run more consistently?

To update the turtles' species, I use "ask turtles with [sector = s]". I'm wanting it to change the species of every turtle in that sector resulting in 1 new species composed of turtles in that sector; however, I think its giving each individual turtle in that sector a new distinct species value resulting in as many new species as there are turtles. How does "ask turtles with" work on groups of turtles? Is there a way to make all turtles in a sector change the same way?

This is my code:

to check-speciation
  let sector-list sort remove-duplicates [sector] of patches with [ any? turtles-here ]
  let turtle-counts-per-sector []
  let avg-pheno-per-sector []
  let max-turtle-count 0
  let max-sector 0
  let sector-differences []
  foreach sector-list [
    s ->
    let count-turtles count turtles with [sector = s]
    set turtle-counts-per-sector lput count-turtles turtle-counts-per-sector
    let avg-pheno mean [ pheno-value ] of turtles with [ sector = s ]
    set avg-pheno-per-sector lput avg-pheno avg-pheno-per-sector
    if count-turtles > max-turtle-count [
      set max-turtle-count count-turtles
      set max-sector s
    ]
    let difference ( max avg-pheno-per-sector ) - item (s - 1) avg-pheno-per-sector  
    set sector-differences lput difference sector-differences
    if item ( s - 1 ) sector-differences >= speciation-threshold
    [ask turtles with [ sector = s ] [
      let new-species ( 1 + max species-list )
      set species new-species
      set species-list lput new-species species-list
      set pheno-value 0
      ]
    ]
  ]
end

I changed "item s" to "item ( s - 1 )" because I would get the "can't find element of list" error on every model run. This fixed the issue for most model runs but I will keep getting the error every so often and I can't figure out how to stop it.

species-list holds all the species values are present in the model and using "1 + max species-list" makes sure a new species value is used when speciation occurs (otherwise if 2 sectors of turtles initially have species = 1, they'd both change to species = 2 despite being different sectors). This is why I think "[ask turtles with [ sector = s ] [" is affecting each turtle within a sector individually because I will randomly get an absurd amount of new species. How do I get all the turtles in a sector to have the same new species value?

Upvotes: 0

Views: 51

Answers (2)

Alan
Alan

Reputation: 9610

The ask problem: create the new species number as the first thing you do in the if, before the ask, and then use it inside the ask. Otherwise, each asked turtle will increment the number.

The s problem: you have values in your sector list too large for the length of the lists you use item on. Use print (word s " vs " lst) (where lst should be your list) before each call to item in order to see this. In NetLogo, debugging typically starts with print commands.

Upvotes: 1

Steve Railsback
Steve Railsback

Reputation: 1736

I didn't take time to look at your code carefully, but my immediate suspicion is that the problem statement is:

let sector-list sort remove-duplicates [sector] of patches with [ any? turtles-here ]

Could it be that occasionally there are no turtles on one or more sectors, so this list has fewer than 5 members? If so:

  • Try making sector-list a global variable that always holds the sector values

  • Change this code:

    foreach sector-list [ s -> let count-turtles count turtles with [sector = s] set turtle-counts-per-sector lput count-turtles turtle-counts-per-sector let avg-pheno mean [ pheno-value ] of turtles with [ sector = s ]

so it deals with sector numbers that have no turtles on them:

let turtles-on-sector turtles with [sector = s]
ifelse any? turtles-on-sector
[ do this ]
[ or do this if no turtles ]

Otherwise, your approach seems generally very good!

Steve R.

Upvotes: 1

Related Questions