Skip to main content

V-SEIR

Vaccinated SEIR: a Susceptible-Exposed-Infected-Recovered model with a parallel vaccinated branch. Every compartment has a _vax twin, and vaccine efficacy reduces susceptibility (VE_S). Pair it with the vaccination block to set vaccination rollout schedule, which adds a flow from Susceptible into Susceptible_vax compartments over a campaign window.

Use V-SEIR instead of V-SEIHR when you do not need to track hospitalizations as their own compartment, e.g. when you only care about infection dynamics and the impact of vaccination on susceptibility.

Compartments

The preset declares eight compartments: four clinical states, each with an unvaccinated and a vaccinated version.

  • Susceptible / Susceptible_vax: can be infected; the _vax branch is exposed at a reduced rate.
  • Exposed / Exposed_vax: infected but not yet infectious.
  • Infected / Infected_vax: currently infectious. Vaccinated infectious individuals transmit at the same per-contact rate as unvaccinated; the reduction sits on susceptibility, not transmissibility.
  • Recovered / Recovered_vax: recovered and (transiently) immune; waning, if enabled, returns them to the matching susceptible compartment.

Transitions

The unvaccinated and vaccinated branches mirror each other. Vaccinated susceptibles are exposed by both Infected and Infected_vax (same per-contact rate transmission_rate, attenuated by (1 - VE_S)).

FromToKindRate
SusceptibleExposedmediated by Infected and Infected_vaxtransmission_rate
ExposedInfectedspontaneousincubation_rate
InfectedRecoveredspontaneousrecovery_rate
RecoveredSusceptiblespontaneouswaning_rate (0 by default)
Susceptible_vaxExposed_vaxmediated by Infected and Infected_vaxtransmission_rate_vax = (1 - VE_S) * transmission_rate
Exposed_vaxInfected_vaxspontaneousincubation_rate
Infected_vaxRecovered_vaxspontaneousrecovery_rate
Recovered_vaxSusceptible_vaxspontaneouswaning_rate

The Susceptible → Susceptible_vax flow is not part of the preset itself; it is added when the request supplies a vaccination block. Without that block the vaccinated branch stays at zero and the model behaves like plain SEIR.

Equivalent ODE form

For each age group ii, the deterministic mean-field counterpart of the transitions above is:

Unvaccinated branch

dSidt=λiSiνiSi+ωRidEidt=λiSiσEidIidt=σEiγIidRidt=γIiωRi\begin{aligned} \frac{dS_i}{dt} &= -\lambda_i S_i - \nu_i S_i + \omega R_i \\[4pt] \frac{dE_i}{dt} &= \lambda_i S_i - \sigma E_i \\[4pt] \frac{dI_i}{dt} &= \sigma E_i - \gamma I_i \\[4pt] \frac{dR_i}{dt} &= \gamma I_i - \omega R_i \end{aligned}

Vaccinated branch

dSivdt=νiSi(1VES)λiSiv+ωRivdEivdt=(1VES)λiSivσEivdIivdt=σEivγIivdRivdt=γIivωRiv\begin{aligned} \frac{dS^v_i}{dt} &= \nu_i S_i - (1 - \text{VE}_S) \, \lambda_i S^v_i + \omega R^v_i \\[4pt] \frac{dE^v_i}{dt} &= (1 - \text{VE}_S) \, \lambda_i S^v_i - \sigma E^v_i \\[4pt] \frac{dI^v_i}{dt} &= \sigma E^v_i - \gamma I^v_i \\[4pt] \frac{dR^v_i}{dt} &= \gamma I^v_i - \omega R^v_i \end{aligned}

Age groups couple through the contact matrix in the force of infection:

λi(t)=βjCijIj(t)+Ijv(t)Nj\lambda_i(t) = \beta \sum_j C_{ij} \, \frac{I_j(t) + I^v_j(t)}{N_j}
SymbolShapeParameter
λi\lambda_iper-ageforce of infection (depends on β\beta = transmission_rate and contact matrix CijC_{ij}; see Vaccine efficacy)
σ\sigmascalarincubation_rate
γ\gammascalarrecovery_rate
ω\omegascalarwaning_rate (zero unless immunity_duration is passed)
νi\nu_iper-ageper-day vaccination rate from the vaccination block; zero outside any campaign window and outside that campaign's target_age_groups
VES\text{VE}_SscalarVE_S

The simulator is fully stochastic: at each step every source compartment is updated by a competing-risks multinomial draw over its out-edges, with leave probability 1eHidt1 - e^{-H_i\,dt} and destination weights proportional to the per-edge rates. The expected dynamics match the mean-field equations above.

Vaccine efficacy

The preset exposes one efficacy parameter, unitless and in [0,1][0, 1].

VE_S (efficacy against susceptibility) lowers the force of infection on vaccinated susceptibles, reducing their per-exposure probability of getting infected. A separate efficacy against infectiousness (VE_I) would instead reduce transmission from vaccinated infected; that is not modeled here.

λivax(t)=(1VES)λi(t),\lambda^{\text{vax}}_i(t) = (1 - \mathrm{VE_S}) \cdot \lambda_i(t),

where

λi(t)=βjCijIj(t)+Ijvax(t)Nj\lambda_i(t) = \beta \sum_j C_{ij}\,\frac{I_j(t) + I_j^{\text{vax}}(t)}{N_j}

is the standard age-structured force of infection, β\beta is transmission_rate, and CijC_{ij} is the contact matrix from the resolved population. Vaccinated infectious individuals transmit at the same per-contact rate as unvaccinated; the reduction sits entirely on the susceptibility side. Internally, the preset stores this as the calculated parameter transmission_rate_vax = (1 - VE_S) * transmission_rate.

Limit cases worth remembering:

  • VES=1\mathrm{VE_S} = 1: sterilizing immunity. The vaccinated branch has zero force of infection and never sees breakthrough infections.
  • VES=0\mathrm{VE_S} = 0: no protection against susceptibility. The vaccinated branch's transmission dynamics collapse onto the unvaccinated branch's.

If you also need to model vaccine efficacy against hospitalization (VE_H), use V-SEIHR instead.

Parameters

Some parameters can be provided in multiple forms. For example, you can provide infectious_period instead of recovery_rate and it gets automatically converted. If both are sent, the rate form wins and the source is dropped silently. See calculated parameters for the conversion machinery.

ParameterStatusDefaultDescription
R0Default2.5Basic reproduction number.
transmission_rateAlternative to R0derivedβ\beta. Default: R0 * recovery_rate / CONTACT_MATRIX_EIGENVALUE_ALL.
incubation_periodDefault3.0 (days)Days from exposure to infectiousness.
incubation_rateAlternative to incubation_periodderivedE → I rate. Default: 1 / incubation_period.
infectious_periodDefault2.5 (days)Days infectious.
recovery_rateAlternative to infectious_periodderivedI → R rate. Default: 1 / infectious_period.
waning_rateDefault0.0 (off)R → S rate. Waning is off by default.
immunity_durationAlternative to waning_rateunsetDays from R → S. Pass to enable waning via waning_rate = 1 / immunity_duration.
VE_SDefault0.7Vaccine efficacy against susceptibility, in [0,1][0, 1]. Lowers the force of infection on vaccinated susceptibles. 0 = no protection, 1 = sterilizing.

The derived parameter transmission_rate_vax is computed automatically from the inputs above and surfaces in results.parameters when output.include_parameters is set. You can override it by passing a matching name in parameters (user-supplied calc-params win on collision).

Initial conditions

If the request omits initial_conditions, V-SEIR seeds ~0.05% of each age group split evenly between Exposed and Infected (~0.025% each); the rest goes to Susceptible, and the _vax branch starts at zero.

Override the default by passing an explicit initial_conditions block, e.g.:

"initial_conditions": {
"method": "percentage",
"initial_percentages": {"Exposed": 0.025, "Infected": 0.025}
}

See Initial Conditions for other seeding options (absolute counts, multi-compartment seeding, etc.).

Examples

With a vaccination campaign

V-SEIR with a flat-count vaccination campaign over a three-month window. VE_S drives the protection on the vaccinated branch. See the Campaigns page for the full set of rollout options.

curl -X POST https://epyscenario-api.isi.it/api/v1/simulations \
-H "Content-Type: application/json" \
-d '{
"model": {
"preset": "V-SEIR",
"parameters": {
"R0": 2.5,
"incubation_period": 3.0,
"infectious_period": 2.5,
"VE_S": 0.7
}
},
"population": {"name": "United_States"},
"simulation": {"start_date": "2025-01-01", "end_date": "2025-06-30", "Nsim": 10},
"initial_conditions": {
"method": "percentage",
"initial_percentages": {"Infected": 0.1}
},
"vaccination": {
"campaigns": [
{
"start_date": "2025-02-01",
"end_date": "2025-04-30",
"rollout": {"type": "flat_count", "daily_doses": 100000}
}
]
}
}'

Without vaccination

Drop the vaccination block to get the no-intervention baseline (no vaccination rollout). The vaccinated branch stays at zero for the whole run and the model collapses to plain SEIR (compartments and rates on the unvaccinated branch only). Useful to compare against the vaccinated case above.

curl -X POST https://epyscenario-api.isi.it/api/v1/simulations \
-H "Content-Type: application/json" \
-d '{
"model": {
"preset": "V-SEIR",
"parameters": {
"R0": 2.5,
"incubation_period": 3.0,
"infectious_period": 2.5
}
},
"population": {"name": "United_States"},
"simulation": {"start_date": "2025-01-01", "end_date": "2025-06-30", "Nsim": 10},
"initial_conditions": {
"method": "percentage",
"initial_percentages": {"Infected": 0.1}
}
}'

VE_S is omitted here because it only matters once any of the population is in the vaccinated branch; with no campaign and no seeded Susceptible_vax, its value does not affect the trajectory.

With seasonality and a vaccination campaign

Apply seasonality to transmission_rate (peak January 15, trough July 15, per the Northern Hemisphere defaults in Balcan et al., 2010) and run a pre-peak vaccination campaign in autumn so the rollout finishes just before the winter wave hits. Because transmission_rate is itself derived from R0, the seasonal multiplier is applied on top of the evaluated β\beta at each step. See parameter transforms for the full transform reference.

curl -X POST https://epyscenario-api.isi.it/api/v1/simulations \
-H "Content-Type: application/json" \
-d '{
"model": {
"preset": "V-SEIR",
"parameters": {
"R0": 2.5,
"incubation_period": 3.0,
"infectious_period": 2.5,
"VE_S": 0.7
}
},
"population": {"name": "United_States"},
"simulation": {"start_date": "2025-08-01", "end_date": "2026-07-31", "Nsim": 10},
"initial_conditions": {
"method": "percentage",
"initial_percentages": {"Infected": 0.1}
},
"parameter_transforms": [
{
"target_parameter": "transmission_rate",
"method": "balcan",
"max_date": "2026-01-15",
"min_date": "2026-07-15",
"min_value": 0.85
}
],
"vaccination": {
"campaigns": [
{
"start_date": "2025-10-15",
"end_date": "2025-12-31",
"rollout": {"type": "flat_count", "daily_doses": 100000}
}
]
},
"output": {"include_parameters": true}
}'