-
Notifications
You must be signed in to change notification settings - Fork 5
RIA via Index Management
I recently revisited Routine Immunization at 9 months in my C-accelerated numpy model, since I've gotten all the other features integrated in what we think is a fairly performant manner.
The most naive approach to RIA at 9mo is to check for all individuals in the 9-month-ish age range each timestep, and apply the vaccine intervention updates to the specified fraction in the specified node. This requires doing some kind of check over the entire modeled population.
The seemingly smarter approach we prototyped a month ago used priority queue callbacks. When a new agent is born/reconstituted, schedule them to be processed for RIA in 9 months. This skips the "check everybody every timestep" -- even if it's fast-ish using numpy. The problem with this approach, however, is that the individuals get serviced individually from the callback, and doing all those individual updates loses all possibility of getting vector-based speedups. It's theoretically possible to batch up the indices from the callbacks, but this is almost certainly going to require adding a bunch of complexity to the design and implementation. Callbacks by their nature don't know when they are the last one in a batch.
The "USEIRD" experiment points to another possible solution using index management. Here we know that our U's are adjacent in memory and feeding into our S's. Another thing is that we have to make sure that our modeled population (vs our EULA population) is age-ordered. In my prototypes, this was not the case previously, but was easily achieved with a modification to the upstream population creation pipeline.
Now we can have an index to our "oldest 9month old" agent, if you will. We have to find that person the first time. We do this by initializing the index to the "max index of modeled pop", and seeking down by age. Then each time we call "do_RIA", we start at that index, vaccinate them (modulo node and coverage constraints), and keep decrementing our index until the age of the next agent is "less than 9 months". Next time the RIA function is called, assuming everyone is being aged regularly, we do the same thing over again. Rinse and repeat ad infinitum.
(Note that "9 months old" is really a range from a software pov. Agents have ages in floating point precision, so we have to have some lower and upper threshold for what we're really considering to be a 9-month old.)
(Also note that we can do "how-old-are-you?" via now-dob instead of updating ages all the time, but that's a separate question.)
This approach actually worked great. It's hard to imagine a more efficient solution.
There are some downsides, however. It's really rather specific and pedantic. It's not necessarily obvious how one would make the code flexible to variations in RIA regimes.
I think we should consider this an open topic. We often need to have a distribution of RI timings -- it's not obvious how one would combine the index management approach with the "jitter" we want in practice so that RIA happens across a range of times. Perhaps by doing RIA every 30 days, instead of every day, and vaxxing infants who crossed the 9mo threshold during that time, we accomplish that?