Signature
lambda_b = beta * I_b / N; A_stat = lambda_b * (S_b - S_p) * dt; A_dyn = beta * (S_b * I_b - S_p * I_p) / N * dt; A_ind = A_dyn - A_stat
| Inputs | Definition | Unit |
|---|---|---|
beta | Rate of contacts sufficient for transmission per person, the same in both runs | per day |
I_b | Number infectious in the no-programme run at the start of the step | people |
N | Total population, the same in both runs, above zero | people |
S_b | Number susceptible in the no-programme run at the start of the step | people |
S_p | Number susceptible in the programme run at the start of the step | people |
dt | Length of the time step | days |
I_p | Number infectious in the programme run at the start of the step | people |
lambda_b | Force of infection in the no-programme run, applied unchanged to the programme run by the static count | per day |
|---|---|---|
A_stat | Infections averted when the force of infection does not respond to the programme, the direct effect | people |
A_dyn | Infections averted when the force of infection is recalculated from the programme run, direct plus indirect | people |
A_ind | Difference between the dynamic and static counts, the infections averted through fewer infectious people | people |
Function
Compartment flow balance function of a compartmental model
Maps the numbers of people in the compartments of a population model, the flows between compartments per unit time and any inflow from or outflow to outside the model to the rate of change of each compartment, or, after a time step of length dt, to the next set of compartment counts. The flows can be fixed rates times compartment sizes, as in a static model, or can depend on the number infectious through the force of infection, which makes the model dynamic and nonlinear. A Markov cohort update (HE-FN-MM-001, HE-FM-MM-001) applies one fixed transition matrix to a closed cohort, the agent-based update HE-FN-ABM-001 with the per-contact infection probability HE-FM-ABM-001 follows individuals instead of pools, and a per-cycle probability from a constant rate follows HE-FM-TP-001. Reproduction numbers of the SIR model and of stratified models are in HE-FN-BRN-001 (HE-FM-BRN-001 to HE-FM-BRN-005 and HE-CF-BRN-001), and the final size of an epidemic and R_0 estimated from it are in HE-FN-ATR-001, HE-CF-ATR-001 and HE-FM-ATR-005, so none of them is restated here. Notation follows the Compartmental Model article.
Computational function
Computational function for an Euler run of a closed SIR model with and without vaccination counting infections averted statically and dynamically
Runs a closed SIR model forward in Euler steps of HE-FM-CMPM-004 three times, without a programme, with a programme under a dynamic force of infection and with the same programme under the static force of infection taken from the no-programme run, and sums infections averted by each count over the horizon, as HE-FM-CMPM-005 does for one step. It also returns averted infection costs, optionally discounted with a continuous rate as in HE-FM-CONT-003. The calculator line writes out the article's two one-day steps term by term, and Excel, R and Python run any number of steps.
Inputs and outputs:
betaandgammaare the transmission and recovery rates per day;Nthe population;dtthe step in days;S_0andI_0the starting susceptible and infectious counts, with everyone else immune;Vthe number of susceptible people given a perfect vaccine at the start;c_infthe cost per infection;rcthe continuous discount rate per day in the code. In the calculator lineF1b,F1pare day-1 infections without and with the programme;S1b,I1b,S1p,I1pthe counts after day 1;S0pthe programme's starting susceptibles;F2b,F2s,F2dthe day-2 infections without the programme, with it under the static force and with it under the dynamic force;A_s,A_d,A_ithe static, dynamic and indirect infections averted;C_sandC_dthe averted costs. The code returns the same totals for any horizon.Assumption: Closed, homogeneously mixing population with frequency-dependent transmission and lasting immunity, flows held constant within each step, and a perfect vaccine given before the first step. The static programme run keeps its own susceptible count but takes its force of infection from the no-programme run, so on the first step it agrees with the dynamic run. That force rises and falls with the no-programme epidemic but does not respond to the programme, the article's static count, whereas the WHO guide describes a static force of infection as constant. Costs attach to the infection flow only; costs per day spent in a compartment would be added in the same way, weighted by compartment counts as state rewards are in HE-FM-CSIM-001.
Worked example (Article's two one-day steps): Day-1 infections are 29.7 without and 23.7 with the programme. On day 2 they are about 35.44 without the programme, 28.28 under the static force and 26.87 under the dynamic force, so over two days the static count averts about 13.16 infections and the dynamic count about 14.58, and at GBP 40 per infection the averted costs are about GBP 526 and GBP 583, the article's figures.
beta = 0.3; gamma = 0.1; N = 10000; dt = 1; S_0 = 9900; I_0 = 100; V = 2000; c_inf = 40; F1b = 29.7; S1b = 9870.3; I1b = 119.7; S0p = 7900; F1p = 23.7; S1p = 7876.3; I1p = 113.7; F2b = 35.4442; F2s = 28.2838; F2d = 26.8661; A_s = 13.1605; A_d = 14.5782; A_i = 1.4177; C_s = 526.42; C_d = 583.13Worked example (Whole epidemic over 200 days, R and Python): With the same illustrative inputs run for 200 one-day steps, by which time the epidemic has ended in both runs, the static count averts about 1,893.7 infections and the dynamic count about 2,376.4, of which about 482.6 are indirect, about a fifth of the dynamic total (computed here for illustration).
sir_avert(0.3, 0.1, 10000, 9900, 100, 2000, 200)returnsA_s = 1893.75, A_d = 2376.37, A_i = 482.62.Excel: Name the inputs
TransRate,RecoveryRate,PopTotal,StepLength,InitSus,InitInf,VaccCount,CostPerInfandDiscRateCont. Row 2 holds step 0 and each later row one step. Column A holds the step number. No-programme run in B (S), C (I) and E (new infections), programme run in G (S), H (I) and I (new infections), static programme run in K (S) and L (new infections), and the discount factor in M. Row 2 startsB2 =InitSus,C2 =InitInf,G2 =InitSus-VaccCount,H2 =InitInf,K2 =InitSus-VaccCount. Each row computesE2 =TransRate*B2*C2/PopTotal*StepLength,I2 =TransRate*G2*H2/PopTotal*StepLength,L2 =TransRate*C2/PopTotal*K2*StepLength,M2 =EXP(-DiscRateCont*A2*StepLength), and the next rowB3 =B2-E2,C3 =C2+E2-RecoveryRate*C2*StepLength,G3 =G2-I2,H3 =H2+I2-RecoveryRate*H2*StepLength,K3 =K2-L2. With T steps in rows 2 to T+1, a cell namedAvertStaticTotalholds=SUM(E2:E201)-SUM(L2:L201)and a cell namedAvertDynamicTotalholds=SUM(E2:E201)-SUM(I2:I201)for 200 steps, and the discounted dynamic cost is=CostPerInf*SUMPRODUCT(M2:M201,E2:E201-I2:I201). Only classic Excel functions are used.R:
sir_avert <- function(beta, gamma, N, S0, I0, V, steps, dt = 1, cinf = 0, rc = 0) { Sb <- S0; Ib <- I0; Sp <- S0-V; Ip <- I0; Ss <- S0-V; As <- 0; Ad <- 0; Cs <- 0; Cd <- 0; for (k in seq_len(steps)) { lb <- beta*Ib/N; Fb <- lb*Sb*dt; Fp <- beta*Ip/N*Sp*dt; Fs <- lb*Ss*dt; df <- exp(-rc*(k-1)*dt); As <- As+Fb-Fs; Ad <- Ad+Fb-Fp; Cs <- Cs+cinf*df*(Fb-Fs); Cd <- Cd+cinf*df*(Fb-Fp); Ib <- Ib+Fb-gamma*Ib*dt; Sb <- Sb-Fb; Ip <- Ip+Fp-gamma*Ip*dt; Sp <- Sp-Fp; Ss <- Ss-Fs }; c(A_s = As, A_d = Ad, A_i = Ad-As, C_s = Cs, C_d = Cd) }Returns a named vector.Python:
def sir_avert(beta, gamma, N, S0, I0, V, steps, dt=1, cinf=0, rc=0): Sb, Ib, Sp, Ip, Ss = S0, I0, S0-V, I0, S0-V; As = Ad = Cs = Cd = 0.0followed by the loopfor k in range(steps): lb = beta*Ib/N; Fb = lb*Sb*dt; Fp = beta*Ip/N*Sp*dt; Fs = lb*Ss*dt; df = math.exp(-rc*k*dt); As += Fb-Fs; Ad += Fb-Fp; Cs += cinf*df*(Fb-Fs); Cd += cinf*df*(Fb-Fp); Ib, Sb = Ib+Fb-gamma*Ib*dt, Sb-Fb; Ip, Sp = Ip+Fp-gamma*Ip*dt, Sp-Fp; Ss = Ss-Fsandreturn dict(A_s=As, A_d=Ad, A_i=Ad-As, C_s=Cs, C_d=Cd), with math imported, one statement per line and the loop body indented.Test (Article's two-day counts in Excel): With the article's inputs and two steps, so that the sums run over rows 2 and 3, AvertStaticTotal and AvertDynamicTotal hold about 13.1605 and 14.5782. The expected result is TRUE. Excel check
=AND(ABS(AvertStaticTotal-13.1605)<1E-4,ABS(AvertDynamicTotal-14.5782)<1E-4). A FALSE result shows the static column L computed from the programme run's infectious count in column H, which makes AvertStaticTotal 14.5782.Test (Static count no larger than the dynamic count): With these inputs the dynamic count is at least the static count at every horizon from 1 to 300 steps, although the gap narrows after day 29, because the static run's own susceptible pool is used up faster than the programme run's and its daily infections then fall below those of the dynamic run (computed here for illustration; the one-step result of HE-FM-CMPM-005 does not carry over to a run in which the static susceptible count differs from S_p). The R check
r <- sir_avert(0.3, 0.1, 10000, 9900, 100, 2000, 200); r["A_d"] >= r["A_s"] && abs(r["A_s"]-1893.748) < 1e-3returns TRUE. A FALSE result shows the static and dynamic streams swapped in the code.Common error (Horizon cut before the programme run's epidemic ends): A programme can delay infections as well as prevent them. With the article's inputs the dynamic count of infections averted is about 3,493.3 after 30 days but about 2,376.4 once the epidemic has ended in both runs, because infections avoided early in the programme run partly occur later (computed here for illustration). Pitman and colleagues report that preventive control programmes are often very sensitive to the time horizon of the analysis and recommend sensitivity analysis on it.
Source: Pitman R, Fisman D, Zaric GS, Postma M, Kretzschmar M, Edmunds J, Brisson M. Dynamic transmission modeling. A report of the ISPOR-SMDM Modeling Good Research Practices Task Force-5. Value in Health. 2012;15(6):828-834. Section Software Options on the Euler method in spreadsheets; subsection Uncertainty in choice of economic parameters, which states that preventive control programmes are often very sensitive to the discount rate and the time horizon of the analysis; and best practice V-3, which recommends sensitivity analysis on the time horizon and the discount rate. World Health Organization. WHO guide for standardization of economic evaluations of immunization programmes, 2nd edition (WHO/IVB/19.10). Geneva, WHO, 2019. Section 6.3.1 on recalculating the force of infection in dynamic models and holding it constant in static models.
F1b = beta * S_0 * I_0 / N * dt; S1b = S_0 - F1b; I1b = I_0 + F1b - gamma * I_0 * dt; S0p = S_0 - V; F1p = beta * S0p * I_0 / N * dt; S1p = S0p - F1p; I1p = I_0 + F1p - gamma * I_0 * dt; F2b = beta * S1b * I1b / N * dt; F2s = beta * I1b / N * S1p * dt; F2d = beta * S1p * I1p / N * dt; A_s = F1b - F1p + F2b - F2s; A_d = F1b - F1p + F2b - F2d; A_i = A_d - A_s; C_s = c_inf * A_s; C_d = c_inf * A_d
Try this function
Implementations
Excel
Static and dynamic infections averted in one step from named cells
With TransRate, PopTotal and StepLength as before and the start-of-step counts of the two runs in SusBase, InfBase, SusProg and InfProg, the four cells return ForceBase, AvertStatic, AvertDynamic and AvertIndirect.
=TransRate*InfBase/PopTotal; =ForceBase*(SusBase-SusProg)*StepLength; =TransRate*(SusBase*InfBase-SusProg*InfProg)/PopTotal*StepLength; =AvertDynamic-AvertStatic
Assumptions
Both runs share parameters and differ only in their compartment counts
The runs share beta, N and dt and differ only in the counts at the start of the step, as when a perfect vaccine moves people into the immune compartment. A_ind is zero or above whenever the programme has not raised the infectious count (derived from the simplified form). The static count takes lambda_b from the no-programme run at the same step, as the article does, so it changes over time but not with the programme; the WHO guide and Jit and Brisson describe the force of infection of a static model as constant, which is the case of a no-programme run whose force does not change. Pitman and colleagues note that indirect effects can also raise complications through a higher age at infection, as for hepatitis A and varicella, which a count of infections does not show.
Worked examples
Article's day-2 infections averted counted statically and dynamically
On day 2 the article's no-programme run has 9,870.3 susceptible and 119.7 infectious people, and the programme run 7,876.3 and 113.7. The static count averts about 7.16 infections and the dynamic count about 8.58, so about 1.42 are indirect, the article's figures.
beta = 0.3; N = 10000; dt = 1; S_b = 9870.3; I_b = 119.7; S_p = 7876.3; I_p = 113.7; lambda_b = 0.003591; A_stat = 7.1605; A_dyn = 8.5782; A_ind = 1.4177
Article's day-1 counts agree when both runs start with the same infectious count
On day 1 both runs start with 100 infectious people, so the static and dynamic counts both avert 6.0 infections and the indirect effect is zero, a limiting case.
beta = 0.3; N = 10000; dt = 1; S_b = 9900; I_b = 100; S_p = 7900; I_p = 100; lambda_b = 0.003; A_stat = 6; A_dyn = 6; A_ind = 0
Common errors
Static count of infections averted reported as the whole effect of a programme
Over the article's two days the static count averts 13.16 infections and the dynamic count 14.58, so the static figure misses 1.42, about a tenth of the dynamic total, and at the article's GBP 40 per infection treated it values averted treatment costs at GBP 526 instead of GBP 583. The gap grows over the early generations of transmission, to about 2,024.6 infections by day 29 with the article's inputs, and then narrows to about 482.6 once both epidemics have ended (HE-CF-CMPM-001, computed here for illustration), so a static count from a short run understates the indirect effect by a different share from one taken over the whole epidemic.
Sources
WHO guide on static and dynamic forces of infection
World Health Organization. WHO guide for standardization of economic evaluations of immunization programmes, 2nd edition (WHO/IVB/19.10). Geneva, WHO, 2019. Section 6.3.1, Basic types of infectious disease models, which states that in a dynamic transmission model the force of infection can change over time, that a dynamic model recalculates it cyclically or continuously from the proportion of infectious people it projects at each point in time, that in a static model it remains constant and independent of the proportion of infectious people, and that dynamic models are typically solved as differential equations in continuous time, with discrete time intervals often applied for practical reasons.
Jit and Brisson on why dynamic models usually show more infections prevented
Jit M, Brisson M. Modelling the epidemiology of infectious diseases for decision analysis. A primer. PharmacoEconomics. 2011;29(5):371-386. Section 3.1, Types of Models, which defines the force of infection as the instantaneous rate at which susceptible people become infected, constant in a static model and a function of the proportion infected in a dynamic model; and section 3.2, When to Use Transmission Dynamic Models, which states that a dynamic model will usually show an intervention as more cost effective than an equivalent static model, because it predicts more infections prevented, including those indirectly protected through herd immunity, and a faster fall in infections, and that a static model may therefore be sufficient to obtain a conservative estimate of cost effectiveness.
Pitman and colleagues on indirect effects and reporting infections prevented
Pitman R, Fisman D, Zaric GS, Postma M, Kretzschmar M, Edmunds J, Brisson M. Dynamic transmission modeling. A report of the ISPOR-SMDM Modeling Good Research Practices Task Force-5. Value in Health. 2012;15(6):828-834. The section on when a dynamic approach is appropriate, with best practice V-1, which calls for a dynamic model when an intervention has an impact on disease transmission in the target population, and its subsection Indirect effects of intervention programs, which states that indirect effects are not always beneficial because a higher average age at infection increases complication risk and mortality for many diseases, for example hepatitis A and varicella; and section Reporting Results and Informing Decision Making, which states that infections can be disaggregated according to whether they are directly or indirectly prevented.
Canonical Identity
Stable URI · Machine-readable · Resolvable · CC BY 4.0
