SIR
Overview
The SIR
function numerically solves the SIR (Susceptible-Infected-Recovered) system of ordinary differential equations, a classic model for infectious disease spread in a population. The SIR model describes the time evolution of three compartments:
- Susceptible (): individuals who can contract the disease
- Infected (): individuals who are currently infected and can transmit the disease
- Recovered (): individuals who have recovered and are immune
The system is governed by:
where is the total population, is the infection rate, and is the recovery rate. The function uses scipy.integrate.solve_ivp to perform the integration, exposing only the most commonly used parameters for Excel users. The output includes a header row and a time column for clarity. This example function is provided as-is without any representation of accuracy.
Usage
To use the function in Excel:
=SIR(s_initial, i_initial, r_initial, beta, gamma, t_start, t_end, [method])
s_initial
(float, required): Initial number of susceptible individuals.i_initial
(float, required): Initial number of infected individuals.r_initial
(float, required): Initial number of recovered individuals.beta
(float, required): Infection rate parameter.gamma
(float, required): Recovery rate parameter.t_start
(float, required): Start time of integration.t_end
(float, required): End time of integration.method
(string, optional, default=RK45
): Integration method (RK45
,RK23
,DOP853
,Radau
,BDF
,LSODA
).
The function returns a 2D table with a header row: t
, S
, I
, R
. Each subsequent row contains the time and corresponding values for susceptible, infected, and recovered individuals. If the input is invalid, an error message (string) is returned.
Examples
Example 1: Basic SIR Simulation
Inputs:
s_initial | i_initial | r_initial | beta | gamma | t_start | t_end | method |
---|---|---|---|---|---|---|---|
990 | 10 | 0 | 0.3 | 0.1 | 0 | 10 | RK45 |
Excel formula:
=SIR(990, 10, 0, 0.3, 0.1, 0, 10)
Expected output:
t | S | I | R |
---|---|---|---|
0.000 | 990.000 | 10.000 | 0.000 |
0.001 | 989.996 | 10.003 | 0.001 |
0.016 | 989.954 | 10.031 | 0.016 |
0.157 | 989.527 | 10.314 | 0.159 |
1.571 | 984.548 | 13.611 | 1.841 |
6.066 | 956.200 | 32.221 | 11.579 |
10.000 | 904.494 | 65.397 | 30.109 |
Example 2: RK23 Integration Method
Inputs:
s_initial | i_initial | r_initial | beta | gamma | t_start | t_end | method |
---|---|---|---|---|---|---|---|
990 | 10 | 0 | 0.3 | 0.1 | 0 | 10 | RK23 |
Excel formula:
=SIR(990, 10, 0, 0.3, 0.1, 0, 10, "RK23")
Expected output:
t | S | I | R |
---|---|---|---|
0.000 | 990.000 | 10.000 | 0.000 |
0.001 | 989.996 | 10.003 | 0.001 |
0.016 | 989.954 | 10.031 | 0.016 |
0.157 | 989.527 | 10.314 | 0.159 |
0.786 | 987.479 | 11.671 | 0.850 |
1.841 | 983.438 | 14.345 | 2.217 |
3.195 | 976.908 | 18.655 | 4.438 |
4.756 | 967.016 | 25.154 | 7.830 |
6.469 | 952.380 | 34.707 | 12.913 |
8.318 | 930.820 | 48.635 | 20.545 |
10.000 | 904.614 | 65.322 | 30.064 |
Example 3: Longer Simulation Time
Inputs:
s_initial | i_initial | r_initial | beta | gamma | t_start | t_end | method |
---|---|---|---|---|---|---|---|
990 | 10 | 0 | 0.3 | 0.1 | 0 | 50 | RK45 |
Excel formula:
=SIR(990, 10, 0, 0.3, 0.1, 0, 50)
Expected output:
t | S | I | R |
---|---|---|---|
0.000 | 990.000 | 10.000 | 0.000 |
0.001 | 989.996 | 10.003 | 0.001 |
0.016 | 989.954 | 10.031 | 0.016 |
0.157 | 989.527 | 10.314 | 0.159 |
1.571 | 984.548 | 13.611 | 1.841 |
6.066 | 956.200 | 32.221 | 11.579 |
12.535 | 850.221 | 99.056 | 50.722 |
21.257 | 530.979 | 261.666 | 207.355 |
30.611 | 232.342 | 285.918 | 481.740 |
40.187 | 118.526 | 176.649 | 704.825 |
50.000 | 81.208 | 87.996 | 830.795 |
Example 4: BDF Integration Method
Inputs:
s_initial | i_initial | r_initial | beta | gamma | t_start | t_end | method |
---|---|---|---|---|---|---|---|
990 | 10 | 0 | 0.3 | 0.1 | 0 | 10 | BDF |
Excel formula:
=SIR(990, 10, 0, 0.3, 0.1, 0, 10, "BDF")
Expected output:
t | S | I | R |
---|---|---|---|
0.000 | 990.000 | 10.000 | 0.000 |
0.000 | 989.999 | 10.000 | 0.000 |
0.000 | 989.999 | 10.001 | 0.000 |
0.002 | 989.995 | 10.003 | 0.002 |
0.003 | 989.991 | 10.006 | 0.003 |
0.014 | 989.960 | 10.027 | 0.014 |
0.024 | 989.928 | 10.048 | 0.024 |
0.035 | 989.896 | 10.069 | 0.035 |
0.131 | 989.605 | 10.262 | 0.133 |
0.228 | 989.308 | 10.459 | 0.233 |
0.324 | 989.005 | 10.660 | 0.335 |
0.781 | 987.495 | 11.661 | 0.845 |
1.238 | 985.845 | 12.753 | 1.402 |
1.695 | 984.045 | 13.944 | 2.011 |
2.152 | 982.080 | 15.242 | 2.677 |
3.749 | 973.706 | 20.762 | 5.532 |
5.347 | 962.440 | 28.148 | 9.412 |
6.944 | 947.422 | 37.922 | 14.656 |
8.542 | 927.647 | 50.663 | 21.690 |
10.000 | 904.515 | 65.375 | 30.110 |
All outputs are rounded to 3 decimal places for display.
Python Code
from scipy.integrate import solve_ivp as scipy_solve_ivp
from typing import List, Union
def sir(
s_initial: float,
i_initial: float,
r_initial: float,
beta: float,
gamma: float,
t_start: float,
t_end: float,
method: str = 'RK45'
) -> Union[List[List[float]], str]:
"""
Solves the SIR system of ordinary differential equations for infection dynamics.
Args:
s_initial: Initial number of susceptible individuals (float).
i_initial: Initial number of infected individuals (float).
r_initial: Initial number of recovered individuals (float).
beta: Infection rate parameter (float).
gamma: Recovery rate parameter (float).
t_start: Start time of integration (float).
t_end: End time of integration (float).
method: Integration method to use (str): 'RK45', 'RK23', 'DOP853', 'Radau', 'BDF', 'LSODA'. Default is 'RK45'.
Returns:
2D list of solution values for S, I, and R at each time point, or an error message (str) if input is invalid.
This example function is provided as-is without any representation of accuracy.
"""
# Validate inputs
try:
s0 = float(s_initial)
i0 = float(i_initial)
r0 = float(r_initial)
b = float(beta)
g = float(gamma)
t0 = float(t_start)
tf = float(t_end)
except Exception:
return "Invalid input: All initial values and parameters must be numbers."
if any(x < 0 for x in [s0, i0, r0, b, g]):
return "Invalid input: Initial values and parameters must be non-negative."
if tf <= t0:
return "Invalid input: t_end must be greater than t_start."
if method not in ['RK45', 'RK23', 'DOP853', 'Radau', 'BDF', 'LSODA']:
return "Invalid input: method must be one of 'RK45', 'RK23', 'DOP853', 'Radau', 'BDF', 'LSODA'."
# SIR ODE system
def sir_ode(t, y):
S, I, R = y
N = S + I + R
dSdt = -b * S * I / N
dIdt = b * S * I / N - g * I
dRdt = g * I
return [dSdt, dIdt, dRdt]
# Integrate
try:
sol = scipy_solve_ivp(
sir_ode,
[t0, tf],
[s0, i0, r0],
method=method
)
except Exception as e:
return f"scipy.integrate.solve_ivp error: {e}"
if not sol.success:
return f"Integration failed: {sol.message}"
# Return 2D list: header row, then each row is [t, S, I, R] at each time point
header = ["t", "S", "I", "R"]
result = [header] + [[float(sol.t[i]), float(sol.y[0][i]), float(sol.y[1][i]), float(sol.y[2][i])] for i in range(len(sol.t))]
return result