Nested Within- and Between-Host Models

The evolution of virulence rests on a trade-off between transmission and harm, but that curve is usually drawn by hand rather than derived. A nested model closes the gap: a fast within-host process sets the transmission rate β\beta and virulence α\alpha that a slow between-host SIR model treats as parameters. The trade-off then emerges from viral replication rather than being assumed, and the virulence that maximizes between-host R0R_0 is an output of the coupled system (Mideo, Alizon & Day 2008).

Three panels: fast within-host viral load trajectories for a sweep of replication rates, the transmission-virulence trade-off that emerges from that sweep, and the between-host basic reproduction number across virulence with the emergent optimum marked.
Figure 1. Three panels: fast within-host viral load trajectories for a sweep of replication rates, the transmission-virulence trade-off that emerges from that sweep, and the between-host basic reproduction number across virulence with the emergent optimum marked.

Two coupled scales#

Infection runs on two clocks that differ by orders of magnitude in speed.

Inside one host, virus replicates over hours to days. Take a minimal target-cell model with target cells TT, infected cells II, and free virus VV:

dTdt=bTVdIdt=bTVdIdVdt=pIcV.\begin{aligned} \frac{dT}{dt} &= -b\,T V \\ \frac{dI}{dt} &= b\,T V - d\,I \\ \frac{dV}{dt} &= p\,I - c\,V. \end{aligned}

The single parameter that a pathogen can evolve here is the virion production rate pp: a faster-replicating strain reaches a higher peak viral load Vˉ=maxtV(t)\bar V = \max_t V(t).

Between hosts, the pathogen spreads over days to weeks in an SIR population, where the epidemiological parameters are not free constants but functions of the within-host state.

From viral load to β\beta and α\alpha#

The nesting is the pair of maps that turn a within-host summary into between-host rates. Transmission saturates with viral load, because a host can only shed and contact so many others, so we write an increasing, saturating map

β(Vˉ)=βmaxVˉVˉ+K,\beta(\bar V) = \beta_{\max}\,\frac{\bar V}{\bar V + K},

while disease-induced mortality (virulence) climbs with the damage a high load does,

α(Vˉ)=aVˉ.\alpha(\bar V) = a\,\bar V.

Both increase with Vˉ\bar V, so raising within-host replication pp raises transmission and virulence together. This shared dependence is what generates the trade-off: β\beta and α\alpha are not independent knobs but two readouts of the same underlying viral load (Gilchrist & Coombs 2006).

The emergent trade-off and its optimum#

Feed the two maps into the between-host reproduction number for an SIR infection,

R0=β(Vˉ)α(Vˉ)+γ+μ,R_0 = \frac{\beta(\bar V)}{\alpha(\bar V) + \gamma + \mu},

with recovery rate γ\gamma and background mortality μ\mu. As pp sweeps from low to high, plotting β\beta against α\alpha traces out the classic trade-off curve as an output of the nested model, not an input. Because transmission saturates while virulence keeps rising, R0R_0 has an interior maximum at some finite replication rate: an emergent optimal virulence α\*\alpha^\*, exactly the singular strategy of the adaptive-dynamics analysis, now derived from mechanism.

Fitness across scales#

The two scales define two different notions of fitness, and they need not agree. Within a host, selection acts on competitive success among viral variants, which favors faster replication and higher peak load. Between hosts, selection acts on R0R_0, which is maximized at intermediate replication.

When within-host competition pushes replication past the between-host optimum, the pathogen evolves higher virulence than is best for its own spread: short-sighted evolution, where within-host wins cost between-host fitness (Gilchrist & Coombs 2006). The Price equation makes this conflict precise by partitioning selection into within- and between-host components with opposite signs.

Assumptions and caveats#

The nesting buys mechanism, but it hides as much as it reveals (Handel & Rohani 2015). It assumes a clean timescale separation, so the within-host trajectory reaches its summary Vˉ\bar V before between-host dynamics matter. It usually assumes a single infecting strain per host, sidestepping the within-host competition that drives short-sighted evolution. And collapsing an entire viral time course to one scalar Vˉ\bar V discards the shape of the infectiousness profile, which itself shapes transmission. Reading across the scales is a modeling choice, not a free lunch (Mideo, Alizon & Day 2008).

A worked example#

Take the within-host model with T0=106T_0 = 10^6, infection rate b=2×107b = 2\times 10^{-7}, infected-cell death d=1d = 1, and viral clearance c=5c = 5. Sweep the replication rate pp from 2 to 200 and record each peak load Vˉ\bar V. Map load to rates with βmax=3\beta_{\max} = 3, K=104K = 10^4, and a=2×105a = 2\times 10^{-5}, and set γ+μ=0.2\gamma + \mu = 0.2. The between-host R0=β/(α+0.2)R_0 = \beta/(\alpha + 0.2) rises, peaks, and falls; the emergent optimum sits near α\*0.04\alpha^\* \approx 0.04, reached at a moderate replication rate well short of the fastest strain in the sweep.

In code#

The executed block sweeps replication rate, integrates the within-host model for each, and reports the virulence that maximizes between-host R0R_0.

Python#

Python
import numpy as np
from scipy.integrate import solve_ivp

# Fast within-host target-cell model: T target cells, I infected, V virus.
T0, b, dI, c = 1e6, 2e-7, 1.0, 5.0

def peak_load(p):
    def rhs(t, y):
        T, I, V = y
        return [-b * T * V, b * T * V - dI * I, p * I - c * V]
    sol = solve_ivp(rhs, [0, 40], [T0, 0.0, 1.0], method="LSODA",
                    rtol=1e-8, atol=1e-6, dense_output=True)
    t = np.linspace(0, 40, 4000)
    return sol.sol(t)[2].max()

# Map peak viral load to between-host transmission and virulence.
beta_max, Kb, a_v, d0 = 3.0, 1e4, 2e-5, 0.2   # d0 = gamma + mu
ps = np.linspace(2, 200, 60)
Vmax = np.array([peak_load(p) for p in ps])
beta = beta_max * Vmax / (Vmax + Kb)
alpha = a_v * Vmax
R0 = beta / (alpha + d0)
i = int(np.argmax(R0))
print(f"emergent optimum: alpha* = {alpha[i]:.3f}, R0 = {R0[i]:.3f}")
print(f"peaks at replication rate p = {ps[i]:.1f} (of {ps.min():.0f}-{ps.max():.0f})")
emergent optimum: alpha* = 0.039, R0 = 2.059
peaks at replication rate p = 32.2 (of 2-200)

R#

R
library(deSolve)

T0 <- 1e6; b <- 2e-7; dI <- 1; cc <- 5
peak_load <- function(p) {
  rhs <- function(t, y, ...) {
    with(as.list(y), list(c(
      dT = -b * T * V,
      dI = b * T * V - dI * I,
      dV = p * I - cc * V)))
  }
  out <- ode(c(T = T0, I = 0, V = 1), seq(0, 40, 0.01), rhs, parms = NULL)
  max(out[, "V"])
}

beta_max <- 3; Kb <- 1e4; a_v <- 2e-5; d0 <- 0.2
ps <- seq(2, 200, length.out = 60)
Vmax <- sapply(ps, peak_load)
beta <- beta_max * Vmax / (Vmax + Kb)
alpha <- a_v * Vmax
R0 <- beta / (alpha + d0)
alpha[which.max(R0)]      # emergent optimal virulence

Julia#

Julia
using DifferentialEquations

T0, b, dI, c = 1e6, 2e-7, 1.0, 5.0
function peak_load(p)
    rhs!(du, y, _, t) = begin
        T, I, V = y
        du[1] = -b * T * V
        du[2] = b * T * V - dI * I
        du[3] = p * I - c * V
    end
    sol = solve(ODEProblem(rhs!, [T0, 0.0, 1.0], (0.0, 40.0)), Rosenbrock23())
    maximum(u[3] for u in sol.u)
end

beta_max, Kb, a_v, d0 = 3.0, 1e4, 2e-5, 0.2
ps = range(2, 200, length = 60)
Vmax = peak_load.(ps)
beta = beta_max .* Vmax ./ (Vmax .+ Kb)
alpha = a_v .* Vmax
R0 = beta ./ (alpha .+ d0)
alpha[argmax(R0)]         # emergent optimal virulence

Why it matters#

Nesting turns the trade-off hypothesis from an assumption into a prediction. Once β\beta and α\alpha both descend from viral load, the intermediate optimal virulence of adaptive dynamics is a theorem about the coupled system rather than a curve chosen to make the argument work. The framing also clarifies when interventions backfire: a therapy that suppresses within-host load moves the pathogen along the emergent trade-off, and a vaccine that blunts virulence without blocking transmission can select for strains that replicate harder (Mideo, Alizon & Day 2008). It is the mechanistic backbone under the population-scale story of pathogen evolution.