# Simulating an aging population

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.

• 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? – user1430 Jul 5 '18 at 15:39
• In bulk (talking about millions) and being able to plot it in a graph. – WhiteGlove Jul 5 '18 at 15:43
• @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? – Philipp Jul 5 '18 at 15:45
• The pop obj obviously stores more things such as culture and religion. – WhiteGlove Jul 5 '18 at 15:46
• @WhiteGlove So everyone age 57 has the same culture and religion and everyone age 58 has another culture and religion? – Philipp Jul 5 '18 at 15:48

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.

• 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). – WhiteGlove Jul 11 '18 at 15:15

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?