Search code examples
csvnetlogoconsumeragent-based-modeling

How to avoid creating an excess of agents when reading their characteristics from a CSV file


I have data related to 100 consumers as turtles who have rated laptops' features. The laptops have 2 kinds of features : size of the screen and battery life. Each has some levels. For example battery life has 5 hours, 12 hours, 24 hours, 30 hours. Data is stored in a csv file. For simplicity, here you see 2 consumers.

   size12  size13.5  size14  size15  Battery5  Battery12 Battery24 Battery30 
1  1        *2*         1      3        2         2           *4*       5
2  4        3           3      2        1          1           2        3

We access the data set to sum the rates of 2 levels of feature. For example for consumer 1 , what is:

The sum of rates of screen size of 13.5 + rate of battery life 24

Using the code below, this is achieved :

to CalculateSumRates
  ca
  reset-ticks
  file-close-all
  file-open "turtle_details.csv"
  let headings csv:from-row file-read-line
  set screen-headings sublist headings 0 4
  set battery-headings sublist headings 4 length headings

  let screen-to-evaluate 13.5
  let battery-to-evaluate 24

  while [ not file-at-end? ] [
    let data csv:from-row file-read-line
    create-turtles 1 [
      set turtle-screen-list sublist data 0 4
      set turtle-battery-list sublist data 4 length data
      set turtle-screen-eval turtle-screen-rating screen-to-evaluate
      set turtle-bat-eval turtle-battery-rating battery-to-evaluate
      set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
    ]
  ]
  file-close-all

end

to-report turtle-screen-rating [sc]
  let pos position sc screen-headings
  let turt-screen-rate-value item pos turtle-screen-list
  report turt-screen-rate-value
end

to-report turtle-battery-rating [bc]
  let pos position bc battery-headings
  let turt-bat-rate-value item pos turtle-battery-list
  report turt-bat-rate-value
end

Now I want to do something more. I need to consider a time interval. For example, in 20 years, how consumers change their ratings of some laptop features. To illustrate more, consumer 1 who has expressed her total ranking of size 13.5 and battery of 24, in year 2 (ticks = 2) got her laptop improved, so now we would like to know :

The sum of rates of screen size of 13.5 + rate of battery life **30**

I first created my go like this :

 to setup
      CalculateSumRates
    end


to go
repeat 20 [

   { screen-to-evaluate changes and is no longer 13.5}
   { battery-to-evaluate also changes and is no longer 24}

; EDIT

set turtle-screen-eval turtle-screen-rating screen-to-evaluate
  set turtle-bat-eval turtle-battery-rating battery-to-evaluate
  set turtle-sum-eval turtle-screen-eval + turtle-bat-eval

; EDIT

  tick
]
end

What is making trouble here is that, each time CalculateSumRates is called, it goes to this line :

 create-turtles 1 [

So every year, 100 consumers are created from scratch while I need to monitor the behvavior of those 100 consumers at the beginning.

I then wrote 2 CalculateSumRates functions, called one in the set up. Renamed the function and put the other in the go. In order not to create an excess of consumers, I substituted create-turtles 1 [ with ask consumers [, hoping that now the csv is again read, but row by row is read when I say ask consumers, so I can find different values from the dataset. However, it is executing weirdly. I do not know how to modify that to avoid creating new consumers and losing the previous ones?

By adding the lines in the edit, I encounter an error telling me that I cannot use go in an observer context; go is turtle only!! Thanks,


Solution

  • To give an example of what I meant in the comment above, check out this modified version of the setup that I suggested here.

    extensions [ csv ]
    
    globals [ screen-headings battery-headings ]
    
    turtles-own [
      turtle-screen-list
      turtle-battery-list
      turtle-screen-eval
      turtle-bat-eval
      turtle-sum-eval
      turtle-row-number
      ;; New:
      rating-each-year 
    ]
    
    to setup
      ca
      reset-ticks
      file-close-all
      file-open "turtle_details.csv"
      let headings csv:from-row file-read-line
      set screen-headings sublist headings 0 4
      set battery-headings sublist headings 4 length headings
    
      while [ not file-at-end? ] [
        let data csv:from-row file-read-line
        create-turtles 1 [
          set turtle-screen-list sublist data 0 4
          set turtle-battery-list sublist data 4 length data
          set rating-each-year []
    
        ]
      ]
    
      file-close-all
    
      ask turtles [
        update-vals 12 5
        set rating-each-year lput turtle-sum-eval rating-each-year
      ]
    
    end
    

    It's more or less the same, but there are some important changes like a new list called rating-each-year that is intended to let the turtles keep track of their rating each tick.

    The reporters are mostly unchanged as well, except that update-vals is now a turtle-specific procedure so it must be called by ask turtles (or similar). Additionally, it takes two variables, one called screen? and one called battery?. You can then call the reporter by asking a turtle to: update-vals 12 24, and that turtle will then update its values for a screen size of 12 and a battery life of 24. I include all three reporters for completeness, but the other two have not changed from my answer to your other question:

    to update-vals [ screen? battery? ]
        set turtle-screen-eval turtle-screen-rating screen?
        set turtle-bat-eval turtle-battery-rating battery?
        set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
    end
    
    to-report turtle-screen-rating [sc]
      let pos position sc screen-headings
      let turt-screen-rate-value item pos turtle-screen-list
      report turt-screen-rate-value
    end
    
    to-report turtle-battery-rating [bc]
      let pos position bc battery-headings
      let turt-bat-rate-value item pos turtle-battery-list
      report turt-bat-rate-value
    end
    

    So now, your turtles can at any time update their summed rating value according to the screen and battery combination that you have assigned them or that they have bought, however you are setting that up. Here is an example go procedure that every tick has them choose a random possible screen size and battery life to evaluate, then they add that summed rating value to their rating-each-year list. When 20 ticks go by, the procedure stops and the turtles show their lists in the command center (21 items long, since they include the value from setup as well).

    to go
      ifelse ticks < 20 [
        ask turtles [
          let screen-this-year one-of screen-headings
          let battery-this-year one-of battery-headings
          update-vals screen-this-year battery-this-year
          set rating-each-year lput turtle-sum-eval rating-each-year
        ]
      ]
      [
        ask turtles [
          show rating-each-year
        ]
        stop
      ]
      tick 
    end
    

    In your model, you probably wouldn't have them randomly pick values of course- this was more to show what they're actually doing. I should also mention that "turtle_details.csv" is the same as the one I used for an example in the last question.