Pandemic Simulator: Ebola with community, hospital, and burial transmission
The framework’s ebola_seihfr_burial_legrand_model, its port of Legrand et al. (2007): an SEIHFR model of the 1995 outbreak in Kikwit, in 200,000 people, with measures from 4 May 1995. See the review.
model.py is the Starsim version, and compare.py checks it against reference/, a run of the original with the central value of every input.
Comparison
| Measure | Original | Starsim | |
|---|---|---|---|
| Lines of model code | 306 | 30 | Most of the original’s lines are the declaration that also serves the web form and model card |
| One run | first 0.31 s, rerun 0.0058 s | first 0.02 s, rerun 0.0011 s (Rust) | Each is one run with the measures, and includes results. A first run excludes imports; the original’s includes compiling with JAX, and Starsim’s uses kernels already compiled. A rerun solves in about the same time on each side (the original’s solve alone is 0.98 ms); most of the original’s rerun is building its results |
| Results, without the measures | 17,044 left in S |
17,044 left in S |
Agree to 2.9e-6 of the population on every day, with a daily RK4 step against an adaptive solver |
| Results, with the measures | 179,445 left in S |
179,407 left in S |
Agree to 1.9e-4 of the population, or 3.1e-7 with the original in float64 (JAX_ENABLE_X64=1), where it leaves 179,407. See the findings for the difference |
Measured on 9 November 2026 with Starsim 4.0.0rc3 (the v4 branch, commit be38b9f6), on a 20-core Linux machine.
What was declared and what was not
Everything is declared. The split rates are expressions of parameters, so they follow any change to theta or delta; the measures are ss.modify() with a start date. The original computes the force of infection and every exit from I and H by hand in equation(), as its schema can’t state them.
Findings
- A rounding error in the original moves its measures. It compares
start_date_ordinal + twith the start date, and JAX’s default float32 resolves a number near 728,000 only to 1/16 of a day, so a measure can start up to that much away from its date. That is the whole difference in the table: 38 fewer people infected, and it does not shrink with a smaller step in Starsim. Every dated measure in the framework is compared in this way, in any model; the size of the error depends on the epidemic at that moment. - Checked against the source’s arithmetic, not the paper. The derived rates recover what they should: 80% hospitalized, a case fatality of 81%, and R0 of 2.69 (0.50 community, 0.42 hospital, and 1.77 burial), against the 2.7 in the original’s notes. The paper itself was not available when this was written, so the equations are compared with the original’s code only.
- Larger than the outbreak. The original’s notes say that the epidemic is far larger than the 315 cases observed, as the paper’s own mean-field version is. The translation keeps this.
What it exercises
- A force of infection summed over three states with their own coefficients
- Exits split by rates derived from target shares
- Three measures with a date, one reducing a rate and two removing it
- Paired runs with and without the measures
Files
model.py: the Starsim versioncompare.py: checks it againstreference/original/model.pyandoriginal/example-config.json: the model, unchanged, at commit5ec712bof the source repositoryoriginal/central-config.json: the same config with no uncertain inputsrun.py: runs it and writesreference/, withexport.pyin the framework’s environmentreference/results.csv: each state on each day, with the measures and withoutmeta.yaml: where it came fromLICENSE: the upstream license (Apache 2.0)
The model
- Compartments:
S,E,I(in the community),H(in hospital),F(dead, not yet buried),R - Transitions:
StoEat(betaI*I + betaH*H + betaF*F)*S/N;EtoI;ItoH,R, orF;HtoRorF; andFtoR - Parameters:
betaI = 0.084,betaH = 0.113,betaF = 1.093per day; incubation 7 days, burial 2 days, onset to hospital 5 days, infectious period 10 days, onset to death 9.6 days; 80% hospitalized and 81% case fatality - Measures: from 4 May 1995,
betaIfalls by 12%, andbetaHandbetaFto zero - Initial conditions: 0.0015% of 200,000 infectious, so 3 people
- Time: 6 January 1995 to 6 January 1996