Skip to content

Add EpiModel as a thirteenth engine - #28

Merged
gvegayon merged 1 commit into
mainfrom
add-epimodel
Oct 9, 2026
Merged

gvegayon merged 1 commit into
mainfrom
add-epimodel

Conversation

@gvegayon

@gvegayon gvegayon commented Oct 9, 2026

Copy link
Copy Markdown
Member

Adds EpiModel 2.5.0 (CRAN, Statnet) to every scenario.

How the runner uses EpiModel

EpiModel draws its contact network from a fitted ERGM, and has no stock setting for a fixed network: resimulate.network = FALSE only draws the whole network time series before the epidemic instead of during it. The runner therefore skips both the fit and the draws:

  • Placeholder formation model: ~offset(edges) held at the shared network's density, so ergm has nothing to estimate. Fitting with target.stats ran for more than 10 minutes at 100,000 agents.
  • Fixed network: a replacement initialization module installs the shared edge list where EpiModel would put its first draw, and resim_nets.FUN does nothing. After a 100-day run the edge list is identical to the shared one.
  • Network storage: tergmLite = TRUE keeps the network as a plain edge list. EpiModel's default networkDynamic form was 31× (10k) to 39× (100k) slower on the same fixed network, with 3–5× the memory. Most of that cost is get.dyads.active() and nwupdate.net writing every agent's status into the network each day.
  • Disease: SEIRH written as EpiModel modules (infection over discord_edgelist(), progression, prevalence).
    • Scenario 01 vaccine: a protection attribute the infection module skips.
    • Scenario 02 outputs: EpiModel's transmission matrix, infTime, and per-flow epidemic statistics.

Results

Scenario Size Median simulate (s) Median attack rate (vs epiworldR)
00 10k / 100k 0.65 / 7.0 0.387 / 0.060 (+0.002 / 0.000)
01 10k / 100k 0.62 / 7.0 0.104 / 0.012 (−0.011 / −0.002)
02 10k / 100k 0.62 / 7.7 same epidemics as 01
03 1M 79 0.007 (0.000)
04 165,865 5.9 0.629 (+0.007)
  • Speed: EpiModel is the slowest engine at every Watts–Strogatz size, about 4–6× slower than epydemic. discord_edgelist() shuffles and scans every edge every day whatever the prevalence, so time scales with edges rather than with the outbreak. It is faster on scenario 04's network, which has fewer edges (376,526), than on scenario 00 at 100k (500,000).
  • Memory: about 2.2 GB peak at 1M.
  • Calibration: 0.948 at 10k and 0.940 at 100k and 1M, fitted on scenario 00. Uncalibrated medians were 0.458 and 0.086, because progression runs before infection within a day. The factor carries over imperfectly to the vaccine scenarios (about 1 point low at 10k), as noted in the docs.

Run hygiene

Records that overlapped other containers on the shared Podman VM, my own side experiments, or sustained slow windows were deleted and rerun under a guard that stops the run if another container starts. One replicate whose timing was corrupted by a VM clock step after host sleep was also rerun. R's elapsed timer follows the wall clock, so benchmarks should run with the host kept awake.

The environment records and run manifest are left as on main, as in the ABM change.

Possible follow-up

ABM's published scenario 01 records at 100,000 agents look contended: p90 is 1.52× the median, against 1.03–1.16× for other engines. Not touched here.

🤖 Generated with Claude Code

EpiModel 2.5.0 (CRAN, Statnet) simulates epidemics on networks drawn from
fitted exponential random graph models. The benchmark's network is fixed, so
the runner skips both the fit and the draws: the formation model is an edges
term held at the shared network's density (~offset(edges), which leaves ergm
nothing to estimate), a replacement initialization module installs the edge
list where EpiModel would put its first draw, and the network-resimulation
module does nothing. The network stays a tergmLite edge list; EpiModel's
default networkDynamic form was 30 to 40 times slower on the same fixed
network in a side test.

The SEIRH disease is written as EpiModel modules: infection over
discord_edgelist(), progression with daily probabilities, and a prevalence
module. The scenario 01 vaccine is a protection attribute, and the scenario 02
outputs come from EpiModel's transmission matrix, infTime, and per-flow
epidemic statistics. Calibrated against epiworldR's medians: 0.948 at 10,000
agents and 0.940 at 100,000 and 1,000,000 (uncalibrated medians 0.458 and
0.086).

Runners for scenarios 00 to 04, registration in run.py, config, tests, make
check, the Dockerfile, code regions, and the docs (engines, methods, results,
showcase plan, scenario notes); EpiModel's 640 published records and the
re-rendered reports. EpiModel moves out of the engines considered and not
included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gvegayon
gvegayon merged commit 2bc89f8 into main Oct 9, 2026
2 checks passed
@gvegayon
gvegayon deleted the add-epimodel branch October 9, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant