-
Notifications
You must be signed in to change notification settings - Fork 5
Some Thoughts on Aging
Not every epi ABM needs to model agent ages. But it's likely that epi modeling over space and time will include some notion of agents aging.
It's also worth noting that even if our agents have an age property, we can sometimes do all the math we need to with that age property during initialization, without needing to update or do any age math during the sim.
Note that LASER per se doesn't have a baked-in, hard-coded or predetermined way of modeling ages. It's up to the modeler to decide that they need and add a property and associated code.
Because we have so far done a lot of modeling with countdown timers, we haven't needed to use the agent age much. For example, maternal immunity and routine immunization is being done with countdown timers, without referring to age. (Are SIAs age-targeted?)
Death modeling can be done by using current age, or can be done by pre-scheduling people for death one way or another.
We have so far explored two ways of modeling age:
- An age property which gets updated each timestep. And an age can either be integer days or floating point years.
- A negative date-of-birth which is compared to the current timestep if the agent age is needed.
Updating every living agent's age every timestep has some cost to it. Tho the way we've optimized step functions makes this pretty fast. See lower down for some data on that.
Using a date-of-birth eliminates the need to update ages for everyone all the time, but means the timestep has to be passed around as an argument to most of the step functions. Or if we're standardizing the "step" call, to all the step functions, even if most don't use it. It also means our model becomes more of an absolute time simulation rather than an elapsed time model, which is really what EMOD always was.
Ultimately the choice probably comes down to how many simulation steps make use of agent age. If it's a lot, all the calculations to calculated ages from dob and timestep start to add up. But if it's only a few, the overhead of maintaining everyone's age is cost with little benefit. In our measles modeling to date, only SIAs have been using age and these by their very nature are intermittent and occasional.
Age is fairly important at an implementation level when doing EULA optimizations at startup. Age as negative d.o.b. means that a regular ascending sort of the population by age will the oldest first. This means that splitting the population at a certain age to keep the youngest means compressing the first/left-most large block, and keeping the right-most smaller block. It also means that adding new babies "on the right" will retain age order. Age as literal age means that an ascending sort puts the youngest first, and splitting and compressing the older ones means keeping the left, small block and discarding/compressing the right block. But it also means that our newborns will need to be added on the left to keep age order. Also note that simply doing a reverse sort to harmonize these two approaches doesn't work because the np.splitsearch
function (which we're likely to use) assumes ascending order.
All that is to say that the choice of age or dob means that the modeler probably has to own details of the EULA code as well instead of getting that all for free.
And then there is the issue of datatypes: integers or floats.
When modeling a EULA-gized initial pop of 5e6, and a total modeled pop of 5e7 after 10 years, updating integer ages takes about 8 additional seconds total. Floating point ages takes about 10 seconds, so 2 more than integers.
The one feature we have envisioned which would need to know most/all agent ages every timestep is age-based mixing or HINT to use EMOD terminology. We haven't attempted to implement that yet.