Fast, extensible Julia library for simulating epidemic processes on graphs.
Implements four epidemic models — ZIM, SIR, Maki-Thompson, and Chase-Escape — on a rich collection of graph types, with exact Gillespie scheduling, 2D/3D visualization, animation, and parallel Monte Carlo analysis. Based on research by Bethuelsen, Broman & Modée (2024).
| Type | Constructor | Description |
|---|---|---|
ZIMProcess |
create_zim_process |
Zombie Infection Model |
SIRProcess |
create_sir_process |
SIR epidemic model |
MakiThompsonProcess |
create_maki_thompson_process |
Rumor-spreading model |
ChaseEscapeProcess |
create_chase_escape_process |
Predator–prey chase-escape model |
All processes share a common interface: step!, reset!, run_simulation, is_active, has_escaped, get_statistics.
Implicit graphs — no adjacency lists are stored; neighbors are computed by O(1) coordinate arithmetic. Memory is O(n) (state vector only).
| Type | Alias / Constructor | Description |
|---|---|---|
HypercubicLattice{2} |
SquareLattice / create_square_lattice |
2D square lattice (4 neighbors) |
HypercubicLattice{3} |
CubeLattice / create_cube_lattice |
3D cubic lattice (6 neighbors) |
HypercubicLattice{D} |
create_hypercubic_lattice |
Arbitrary-dimension lattice; D is a type parameter |
TriangularLattice |
create_triangular_lattice |
2D triangular lattice (6 neighbors) |
HexagonalLattice |
create_hexagonal_lattice |
2D honeycomb lattice (3 neighbors) |
Boundary conditions: ABSORBING (default) or PERIODIC (torus via create_torus).
Implicit like lattices — only the state vector is stored.
| Type | Constructor | Description |
|---|---|---|
CompleteGraph |
create_complete_graph |
Every pair connected |
PathGraph |
create_path_graph |
Linear chain |
CycleGraph |
create_cycle_graph |
Ring |
StarGraph |
create_star_graph |
Hub-and-spoke |
RegularTree |
create_regular_tree / create_dary_tree |
Cayley tree / balanced d-ary tree |
create_regular_tree(d, height) gives the graph-theory regular tree (every internal node has degree d; branching ratio d − 1). create_dary_tree(k, height) gives the CS convention (k children per internal node, including root).
Explicit adjacency-list representation for arbitrary topologies.
| Constructor | Description |
|---|---|
create_graph_from_matrix |
From adjacency matrix |
create_graph_from_edges |
From edge list |
create_erdos_renyi / create_gnp / create_gnm |
Erdős–Rényi random graphs |
Real-world settlements connected by labeled transport layers (roads, railways,
ferries, flights), loaded from a data bundle. Wraps an AdjacencyGraph (built from
the union of the selected layers) and adds names, populations, [lon, lat]
coordinates and a map backdrop — so simulations run on it exactly as on any other
graph, and visualizations draw it on a basemap. The package ships one example
country, :norway_mock — a small hand-authored placeholder (15 settlements) until
the data builder (see below) produces real bundles.
| Constructor / function | Description |
|---|---|
load_geograph(name; edges) |
Load a bundle (e.g. :norway_mock); edges selects layers (:all or e.g. [:road, :flight]) |
with_layers(g, layers) |
Re-select active edge layers (cheap; no re-read) |
available_country_graphs() |
List bundles found in the data directory |
country_edge_sets(name) |
The (symbol, label) layers a bundle offers |
find_node(g, "Oslo") |
Node id of a settlement by name (e.g. for seeding) |
g = load_geograph(:norway_mock; edges = [:road, :rail])
sir = create_sir_process(g, 3.0, 1.0; initial_infected = [find_node(g, "Oslo")])
run_simulation(sir)The bundle format is specified in docs/country-graph-format.md;
the (separate) tool that generates bundles from OpenStreetMap / GeoNames /
OpenFlights is specified in docs/builder-spec.md.
using GraphEpimodels
# ZIM on a 100×100 square lattice
zim = create_zim_process(100, 100, 2.0) # λ = 2.0
results = run_simulation(zim; max_time=50.0)
println("Escaped: ", has_escaped(zim))
# SIR on a regular tree (Cayley tree, degree 4, height 8)
tree = create_regular_tree(4, 8)
sir = create_sir_process(tree, 0.6, 1.0)
run_simulation(sir)
# Erdős–Rényi graph
er = create_erdos_renyi(500, 0.01)Visualization requires CairoMakie (loaded as a package extension — the core package stays lightweight without it).
using GraphEpimodels, CairoMakie
# Static snapshot — lattice heatmap
sir = create_sir_process(50, 50, 0.6, 1.0; initial_infected=:center)
run_simulation(sir)
fig = visualize_state(create_auto_visualizer(sir), sir)
save_plot("sir_final.png", fig)
# Animate every transition (small lattice)
sir = create_sir_process(30, 30, 0.6, 1.0; initial_infected=:center, rng_seed=1)
animate_simulation(sir; sampler=EveryStep(), color_scheme=:sir, filename="sir.gif")
# Equal-time sampling (large lattice — faithful temporal playback)
big = create_sir_process(200, 200, 0.6, 1.0; initial_infected=:center, rng_seed=1)
animate_simulation(big; sampler=TimeInterval(0.5), max_time=40.0, filename="sir_large.mp4")Visualizer dispatch (visualizer_for / create_auto_visualizer) picks the right visualizer automatically:
- Lattices →
LatticeVisualizer(dual-tiling cells; square cells forSquareLattice, hexagonal cells forTriangularLattice, triangular cells forHexagonalLattice) - General graphs →
NetworkVisualizer(node-link diagram)
Layout dimensions: SquareLattice, TriangularLattice, HexagonalLattice have 2D layouts; CubeLattice, RegularTree, StarGraph, CompleteGraph have both 2D and 3D closed-form layouts. Higher-dimensional HypercubicLattice{D} (D ≥ 4) falls back to a computed layout.
Parallel Monte Carlo estimation of survival probabilities, using Julia threads.
# Start Julia with multiple threads for parallel analysis:
# julia --threads=4
using GraphEpimodels
# Sweep λ over a range, 1000 simulations each, on a 100×100 lattice
λ_values = 1.0:0.1:3.0
results = run_zim_lattice_survival_analysis(λ_values, 100, 100; num_simulations=1000)
# Lower-level: estimate survival probability for a single parameter
p = estimate_survival_probability(zim_process; num_simulations=500,
criterion=EscapeCriterion(),
mode=DETAILED)
check_threading_setup() # confirm thread countSurvival criteria: EscapeCriterion (reached boundary), PersistenceCriterion (still active at end), ThresholdCriterion(k) (cluster size ≥ k).
CSV/JSON serialization requires CSV and DataFrames (loaded as an extension).
using GraphEpimodels, CSV, DataFrames
info = extract_process_info(process)
config_str = process_info_to_config_string(info)
json_str = process_info_to_json(info)
# Append/update a survival result in a CSV file
update_or_append_survival_result("results.csv", params, survival_prob)# Check available threads
check_threading_setup()
get_recommended_threads()
# The Gillespie loop is single-threaded per simulation;
# parallelism comes from running independent replicas concurrently.
# Start Julia with --threads=N (N ≥ 4 recommended for sweep analysis).