1
\$\begingroup\$

Introduction:

The main idea is to "classify population as they age". Let me further explain it with an example:

Example:

There are 50k population (we are not going to care about if male or female for now). Inside these number there are kids [0 - 16], fertile[16 - 40], non-fertile [40 - 100].

Question

Which would be a nice implementation to represent an evolving population data that is better or at least not too resource intensive as my example below?

My Idea

(Pseudo code)

Population[] // Array
   Age [0 -> 5] //Array
       a pop obj that stores data
   Age [5 -> 10]
       pop obj
   . 
   .
   .
   Age[95 - 100]
      pop obj

This would be the structure and each tick happens this calculation:

FertilePop.count * fertility rate * (some other stuff) = numberOfBirths

where numberOfBirths are added to the Age[0-5].obj.count

and the rest of Age[rang] are subtracted a number and added onto the next Age[rang] until Age[95 - 100] where they "die of old age".

Notes:

This is purely background data and i am asking for a better solution/implementation that could be less complex, more dynamic and learn from it.

I expect to be able to do a graph plot so the user sees the pop evolution.

I took my interest in the matter from this link here to a population simulator.

https://niko.roorda.nu/computer-programs/popsim-population-simulation/

Thanks for your interest in this question.

\$\endgroup\$
  • 2
    \$\begingroup\$ What do you need from this? Do you ever need to be concerned with an individual person's age, and tracking that age change over time? Or are you purely simulating this in bulk and only need the aggregate count of each age group? \$\endgroup\$ – user1430 Jul 5 '18 at 15:39
  • \$\begingroup\$ In bulk (talking about millions) and being able to plot it in a graph. \$\endgroup\$ – WhiteGlove Jul 5 '18 at 15:43
  • \$\begingroup\$ @WhiteGlove Is that really everything? Because then you wouldn't need "a pop obj that stores data" but only an integer. Do you handle the population of each age as a simple number or do you have an actual object for each individual person? \$\endgroup\$ – Philipp Jul 5 '18 at 15:45
  • \$\begingroup\$ The pop obj obviously stores more things such as culture and religion. \$\endgroup\$ – WhiteGlove Jul 5 '18 at 15:46
  • \$\begingroup\$ @WhiteGlove So everyone age 57 has the same culture and religion and everyone age 58 has another culture and religion? \$\endgroup\$ – Philipp Jul 5 '18 at 15:48
2
\$\begingroup\$

Myself, I'd be tempted just to make an array with 100+ entries, one for each year of age. (Assuming your game mostly runs in a granularity of years. You could boil it down to seasons or months if needed)

It may seem overkill, but an array with a few hundred entries (particularly if they're simple structs) is really nothing for modern processors to chew through. They love working on big swaths of contiguous data like that.

And this way we don't have to worry about variation inside a multi-year age bucket, which can lead to some complicated situations.

For example, let's say we have 5-year buckets. To simulate aging we could assume that each year, 20% of the people in one bucket graduate to the next one. So our aging formulas might look something like:

Age_0_to_4_new = Age_0_to_4_old * 0.8 + birthrate;
Age_5_to_9_new = Age_5_to_9_old * 0.8 + Age_0_to_4_old * 0.2;
...

Now imagine a calamity sterilizes the population, so birthrate goes to zero. In five years' time we should have emptied the Age_0_to_4 bucket, and no more people should graduate into the Age_5_to_9 bucket, but instead...

  Years After Calamity     Population in Age_0_to_4
  -------------------------------------------------

          0                     10 000
          1                      8 000
          2                      6 400
          3                      5 120
          4                      4 096
          5                      3 277
          6                      2 621
          7                      2 097
          8                      1 677
          9                      1 342
         10                      1 074

The lack of a within-age-group distribution model means we've still got babies well after they all should have grown up to the next age group! This creeps in more subtly even without sudden calamities, where any change to your population's circumstances gets smeared out, with the previous conditions lingering on longer than they should and biasing the results.

If we instead just store one record per year, we don't even need fancy a formula to graduate the population to the next bucket each year: we can simply treat the array as a ring buffer and move our start point back by one, while all the data stays where it is. Then all that remains is a mortality pass to diminish numbers in-place, and a birthrate pass to initialize the new starting entry.

When you want to query totals over an age range, you just iterate over the years in question. Again, modern processors are optimized for exactly this kind of consecutive number crunching, so even if it seems wastefully inefficient, the simple repeated adding is likely to be faster in practice than more sophisticated chunked models that treat the population more abstractly.

\$\endgroup\$
  • \$\begingroup\$ Really interesting and helpful! Some idea i had for the "graduates" was that each month we apply a formula to each aging group so people grow and have kids. That way i can simulate that each month is someone "birthday" without being too specific on the true day (that would be outside my scope and irrelevant). \$\endgroup\$ – WhiteGlove Jul 11 '18 at 15:15
1
\$\begingroup\$

I wonder if you really need to have a pop object. What speaks against using a matrix type of structure to store demographic values (e.g. amount of fertile) and model how those evolve over time?

Adding from the discussion below

Ok, so two possibilities come to my mind. First, you keep it the way you have right now. Depending on what you want to model, memory or performance should not be a big issue and you could always iterate over the objects to get a cross sectional snapshot of your population. The second possibility is that you do not use individual data structures at all, but a set of equation modeling population evolution. In this scenario, your population distribution (i.e. how many of which age, from what gender, background, etc) at time point t would be mathematically calculated from time point t-1. An example of such modeling: https://www.inf.ethz.ch/personal/cellier/Pubs/BG/springer_chap10.pdf

\$\endgroup\$
  • \$\begingroup\$ I stated in a previous comment that i classify population by Age and inside Age by Quantity, Culture and Religion. I didn't talk much about the pop.obj i thought i was not that necessary. The pop object contains that information. \$\endgroup\$ – WhiteGlove Jul 5 '18 at 16:00
  • \$\begingroup\$ I see. What I still don't get though is why millions of those objects. I'll try to illustrate what I mean. One such pop.obj could represent fertile population of cultural background A, and then, inside the object you would also have just a population counter. Thus, you would have a single object per possible combination of attributes and age (which is maybe hundreds or thousands even), or am I missing something? \$\endgroup\$ – TGonzo Jul 5 '18 at 16:04
  • \$\begingroup\$ Actually, if we consider only 1 culture and 1 religion thus 1 obj. When we classify it inside our array thing, that goes from 0 to 100 (5 by 5), that would be 20 objs, not millions. There could be 1 million people from a culture A and religion A that has (aprox) same age as 1 million people from Culture B and Religion B. \$\endgroup\$ – WhiteGlove Jul 5 '18 at 16:11
  • \$\begingroup\$ Ok, so two possibilities come to my mind. First, you keep it the way you have right now. Depending on what you want to model, memory or performance should not be a big issue and you could always iterate over the objects to get a cross sectional snapshot of your population. The second possibility is that you do not use individual data structures at all, but a set of equation modeling population evolution. In this scenario, your population distribution (i.e. how many of which age, from what gender, background, etc) at time point t would be mathematically calculated from time point t-1 \$\endgroup\$ – TGonzo Jul 5 '18 at 16:15
  • \$\begingroup\$ Could you EDIT your solution with the Cross Sectional. So people sees it. \$\endgroup\$ – WhiteGlove Jul 5 '18 at 16:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.