ODEModel

models.ODEModel(
    states,
    interventions,
    dynamics_and_rewards,
    horizon,
    discount_rate=0.03,
    method='RK45',
    rtol=1e-08,
    atol=1e-08,
    max_step=None,
    effect='qaly',
)

Ordinary differential equation (compartmental) model engine.

discount_rate is an annual rate discounted continuously, exp(-rate * t), the convention for continuous-time accrual. The horizon is in the same time units as the derivatives (years, by convention).

Parameters

Name Type Description Default
states Sequence[str] Compartment labels; their order fixes every array’s axis order. required
interventions InterventionSpec A sequence of intervention names or heormodel.models.Intervention objects, in the order they appear in Outcomes. An Intervention may carry parameter decision levers merged into params for that intervention. required
dynamics_and_rewards Callable[[pd.Series, str], ODESpec] fn(params, intervention) -> ODESpec returning the system and reward arrays for one intervention under one parameter set. params is a draw-matrix row (a pandas.Series); intervention is the intervention name. required
horizon float Length of the analytic time horizon, in years. required
discount_rate float Annual discount rate for costs and effects (0.03 by default), applied continuously. 0.03
method str Integration method passed to scipy.integrate.solve_ivp ("RK45" by default; "LSODA" switches automatically to a stiff solver when the dynamics stiffen). 'RK45'
rtol float Relative error tolerance for the integrator. 1e-08
atol float Absolute error tolerance for the integrator. 1e-08
max_step float | None Largest step the integrator may take, in years; None (the default) lets the solver choose. Set it to force the solver through a short-lived feature, such as a narrow epidemic peak, it might otherwise step over. None
effect str Name of the primary effect column (quality-adjusted life-years by default). 'qaly'

Example

import numpy as np, pandas as pd from heormodel.models.ode import ODEModel, ODESpec def dynamics_and_rewards(params, intervention): … k = params[“decay”] … return ODESpec( … derivatives=lambda t, y: np.array([-k * y[0], k * y[0]]), … initial=np.array([1.0, 0.0]), … state_cost=np.array([params[“cost”], 0.0]), … state_effect=np.array([1.0, 0.0])) engine = ODEModel( … states=(“alive”, “dead”), interventions=(“care”,), … dynamics_and_rewards=dynamics_and_rewards, horizon=10.0) draws = pd.DataFrame({“decay”: [0.1], “cost”: [1000.0]}, … index=pd.RangeIndex(1, name=“iteration”)) engine.evaluate(draws).interventions [‘care’]

Methods

Name Description
evaluate Evaluate every intervention on every draw and return Outcomes.
trajectory Compartment occupancy over the horizon for one parameter set.

evaluate

models.ODEModel.evaluate(draws)

Evaluate every intervention on every draw and return Outcomes.

Parameters

Name Type Description Default
draws pd.DataFrame Parameter draw matrix (rows = iterations). Its index becomes the outcome iteration index. required

Returns

Name Type Description
Outcomes Outcomes indexed by (intervention, draws.index).

trajectory

models.ODEModel.trajectory(params, intervention, *, n_points=200)

Compartment occupancy over the horizon for one parameter set.

A convenience for inspection and plotting (an epidemic curve, a vaccination-coverage path); it is not part of the engine contract and does not accrue costs or effects. evaluate is what produces Outcomes.

Parameters

Name Type Description Default
params pd.Series One draw-matrix row (a pandas.Series) of parameter values. required
intervention str The intervention name passed to dynamics_and_rewards. required
n_points int Number of evenly spaced time points returned over [0, horizon]. 200

Returns

Name Type Description
pd.DataFrame A DataFrame with a time column and one column per compartment.

Example

import numpy as np, pandas as pd from heormodel.models.ode import ODEModel, ODESpec def dynamics_and_rewards(params, intervention): … return ODESpec( … derivatives=lambda t, y: np.array([-0.1 * y[0], 0.1 * y[0]]), … initial=np.array([1.0, 0.0]), … state_cost=np.zeros(2), state_effect=np.array([1.0, 0.0])) engine = ODEModel(states=(“a”, “b”), interventions=(“s”,), … dynamics_and_rewards=dynamics_and_rewards, horizon=10.0) traj = engine.trajectory(pd.Series(dtype=float), “s”, n_points=3) list(traj.columns) [‘time’, ‘a’, ‘b’]