-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unstable Vital Dynamics #695
Comments
We had discussed this issue previously here: I agree with the logic that newborns have a nonzero mortality risk, so this makes sense. It's like how the population replacement rate is closer to 2.1 than 2.0 births per woman -- nonintuitive, but correct. I'm also not sure I'd call the drop "dramatic": take a look at this: import starsim as ss
import matplotlib.pyplot as plt
dems = [
ss.Births(pars=dict(birth_rate=20)),
ss.Deaths(pars=dict(death_rate=20))
]
sim = ss.Sim(demographics=dems, dur=30)
sim.run()
res = sim.results
plt.plot(res.timevec, res.n_alive)
plt.ylim(bottom=0, top=10_000)
plt.show() |
Just curious, why not have a separation of labor between - calculation/drawing of transitions (eg. n_births, n_deaths etc.) in one step and then application of transitions (eg., ΔState = n_births-n_deaths) in other? That way all transitions will based on the same denominator? |
Good question! Two main reasons:
|
Agree the drop is not dramatic, but will still come as a surprise to users. |
We should Births away from the |
We could also change example scripts to place |
I had a look at this and I think something else is going on. Partly, we wouldn't expect them to match anyway, since 1.1*0.9 != 1.0. The order shouldn't matter, but does: s1 = ss.Sim(label='Births→Deaths', demographics=[ss.Births(birth_rate=20), ss.Deaths(death_rate=20)])
s2 = ss.Sim(label='Deaths→Births', demographics=[ss.Deaths(death_rate=20), ss.Births(birth_rate=20)])
msim = ss.parallel(s1, s2)
msim.plot() |
The floor in |
This is with |
Closed by #749 |
Addressing stochasticity in Births related to dicussion in Unstable Vital Dynamics #695
Consider a simulation with the following demographics
One might expect a stable population. However, the result is a dramatically declining population.
This result is for two reasons:
Births
takes the floor when deterministically adding agents.n_new = int(np.floor(sim.people.alive.count() * scaled_birth_prob))
Module order matters. Because
Births
comes beforeDeaths
in the list ofdems
, agents are added to the population (resulting in a larger population), and thenDeaths
applies the death rate to all agents, including the new agents. A 1% increase followed by a 1% decrease results in a net decline.Switching the order of demographic module updates (and changing the Births floor to something like
sc.randround
) resolves the issue. Why? BecauseDeaths
simply schedules agents for death viati_death
without actually removing them from the population. TheBirths
module then adds agents considering the same denominator as used for deaths.We cannot expect users to know they have to put
Deaths
beforeBirths
to get a stable population.Next Steps:
Births
away fromfloor
. It could apply a probability per-agentBirthDeath
module that would act on the same denominator.Pregnancy
) at the end of the time step, although that will likely create other problems.Deaths
followsBirths
.Thanks to Deven for raising this issue in the context of SEIRD in TBsim.
The text was updated successfully, but these errors were encountered: