Signature
m_(T_1,t+1) = sum_(i=1)^n_S_tunnels [m_(i,t) * p_(i,T_1)]; m_(T_(k+1),t+1) = m_(T_k,t) * s_k; m_(L,t+1) = m_(T_K,t) * s_K + m_(L,t) * s_L
| Inputs | Definition | Unit |
|---|---|---|
m_(i,t) | Proportion of the cohort in state i of the expanded model at the end of cycle t | proportion of cohort |
p_(i,T_1) | Probability per cycle of moving from state i into T_1, for example an infarction while event-free; zero for states with no route into the tunnel | probability per cycle |
m_(T_k,t) | Proportion of the cohort in tunnel state T_k at the end of cycle t | proportion of cohort |
s_k | Probability of neither dying nor leaving by another route in the kth cycle since entry, for k from 1 to K | probability per cycle |
m_(T_K,t) | Proportion of the cohort in the last one-cycle tunnel state T_K at the end of cycle t | proportion of cohort |
s_K | Probability of neither dying nor leaving by another route in the Kth cycle since entry, which moves people from T_K into L | probability per cycle |
m_(L,t) | Proportion of the cohort in the long-term state L at the end of cycle t | proportion of cohort |
s_L | Probability of remaining in L for one more cycle, once the duration effect has run its course | probability per cycle |
m_(T_1,t+1) | Proportion of the cohort in the first tunnel state T_1 at the end of cycle t+1, all of whom entered during that cycle | proportion of cohort |
|---|---|---|
m_(T_(k+1),t+1) | Proportion of the cohort in tunnel state T_(k+1) at the end of cycle t+1, for k from 1 to K minus 1 | proportion of cohort |
m_(L,t+1) | Proportion of the cohort in the long-term state L at the end of cycle t+1 | proportion of cohort |
KNumber of one-cycle tunnel states, equal to the number of cycles over which the duration effect changes (count)tThe numbered model cycle, counted from the start of the model rather than from entry to the tunnel (cycle)n_S_tunnelsNumber of states in the expanded model, over which tunnel entrants are summed (HE-FM-TUN-002) (count)
Function
Tunnel-state expansion of a cohort state-transition model
Maps a clinical state whose risks, costs or utilities depend on time since entry into a chain of K one-cycle tunnel states followed by a long-term state, so that a cohort model carries time in the state as well as the state itself. The expanded matrix P_tunnels is run with the cohort update s_(t+1) = s_t P of the Markov Model page (HE-FM-MM-001), which is not restated. Three existing records complete the method: tunnel probabilities from a survival curve for time since entry come from the rise in cumulative hazard across each cycle (HE-FM-CUMH-002), with the clock restarting on entry as HE-AS-CUMH-004 notes; the constant probability of a memoryless comparator calibrated to the same three-year survival is the rescaling formula HE-FM-TP-003 (p_old = 0.29344, Delta_old = 3 and Delta_new = 1 give 0.10933, as in the article); and life years from the expanded trace under a counting rule are HE-FM-CSIM-001 and HE-CF-CSIM-001. Notation follows the Tunnel State article.
Computational function
Computational function: expanded tunnel transition matrix from death probabilities by cycle since entry, with its cohort trace
Builds the expanded transition matrix for a model with one origin state, one tunnelled clinical state and death, from the death probability in each cycle since entry, and runs the cohort trace with the update HE-FM-MM-001. It returns the matrix, the trace and, for each cycle, the average death probability of the tunnelled state (HE-FM-TUN-003). The inputs differ from the formula's symbols: HE-FM-TUN-001 takes occupancies and continuation probabilities one cycle at a time, whereas the function takes a vector of death probabilities by duration and an entry probability and fills the zero-diagonal tunnel rows itself, as Algorithm 1 of the tutorial by Alarid-Escudero and colleagues does by iterating through the tunnel states.
Inputs and outputs:
p_entry: Probability per cycle of moving from the origin state into T1; required, from 0 to 1. Unit: probability per cycle.;q_origin: Probability per cycle of death from the origin state; required, with p_entry plus q_origin at most 1. Unit: probability per cycle.;q_dur: Vector of K+1 death probabilities, one for each of the K tunnel cycles and the last for the long-term state; required, each from 0 to 1. Unit: probability per cycle.;m0: Starting distribution over the K+3 states in the order origin, T1 to TK, L and Dead; required. Unit: proportion or number of the cohort.;n_cycles: Number of cycles to run; required, a positive integer. Unit: cycles.;P: Expanded transition matrix with K+3 states, the size HE-FM-TUN-002 gives for three states before expansion. Unit: probability per cycle.;trace: Cohort trace with n_cycles+1 rows, the first being m0. Unit: as m0.;q_bar: Average death probability for the next cycle among people in T1 to L, one value per trace row; undefined (NaN) when no one is in the tunnel. Unit: probability per cycle.Assumption: Death is the only exit from the tunnel other than moving along it, every entrant comes from the origin state and a repeat event does not restart the tunnel. Death probabilities by duration may come from a survival curve for time since entry with HE-FM-CUMH-002, the clock restarting on entry.
Worked example (Single-entry cohort of the article): With no origin state in use and 1,000 people starting in T1, the trace reproduces the article: 800, 736 and 706.56 alive after one, two and three years and 664.80 in L after five years.
p_entry = 0; q_origin = 0; q_dur = [0.20, 0.08, 0.04, 0.03]; m0 = [0, 1000, 0, 0, 0, 0]; n_cycles = 5; trace[5] = [0, 0, 0, 0, 664.80, 335.20]Worked example (Staggered entry at 5 per cent incidence): Starting 1,000 people event-free with an infarction probability of 0.05 and a death probability of 0.01, the year 4 row matches the article and the average death probability for year 5 is 0.0925, against 0.20 after one year when all post-infarction people are in T1.
p_entry = 0.05; q_origin = 0.01; q_dur = [0.20, 0.08, 0.04, 0.03]; m0 = [1000, 0, 0, 0, 0, 0]; n_cycles = 4; trace[4] = [780.75, 41.53, 35.34, 34.59, 35.33, 72.46]; q_bar[1] = 0.20; q_bar[4] = 0.0925Worked example (Staggered entry at 10 per cent incidence): The same model at an incidence of 0.10 gives an average of 0.0885 after four years, and 0.0940 at 0.03, as in the article.
p_entry = 0.10; q_origin = 0.01; q_dur = [0.20, 0.08, 0.04, 0.03]; m0 = [1000, 0, 0, 0, 0, 0]; n_cycles = 4; q_bar[4] = 0.0885Excel:
=MMULT(PrevTraceRow,ExpandedMatrix)Entered across the cells of a trace row (as an array formula in older versions) with the expanded matrix laid out as in the article's table: each tunnel row holds 1 minus its death probability one column to the right of the diagonal and its death probability in the Dead column, and the L row holds its stay probability on the diagonal. The average is HE-FM-TUN-003.R:
tunnel_model <- function(p_entry, q_origin, q_dur, m0, n_cycles) { K1 <- length(q_dur); n <- K1+2; P <- matrix(0, n, n); P[1, 1] <- 1-p_entry-q_origin; P[1, 2] <- p_entry; P[1, n] <- q_origin; for (k in 1:K1) { P[k+1, min(k+2, K1+1)] <- 1-q_dur[k]; P[k+1, n] <- q_dur[k] }; P[n, n] <- 1; tr <- matrix(0, n_cycles+1, n); tr[1, ] <- m0; for (t in 1:n_cycles) tr[t+1, ] <- tr[t, ] %*% P; occ <- tr[, 2:(K1+1), drop = FALSE]; list(P = P, trace = tr, q_bar = as.vector(occ %*% q_dur) / rowSums(occ)) }Base R only; row t+1 of the trace and element t+1 of q_bar belong to cycle t.Python:
def tunnel_model(p_entry, q_origin, q_dur, m0, n_cycles): q_dur = np.asarray(q_dur, float); K1 = len(q_dur); n = K1+2; P = np.zeros((n, n)); P[0, 0] = 1-p_entry-q_origin; P[0, 1] = p_entry; P[0, n-1] = q_origin; k = np.arange(K1); P[k+1, np.minimum(k+2, K1)] = 1-q_dur; P[k+1, n-1] = q_dur; P[n-1, n-1] = 1; tr = np.vstack([np.asarray(m0, float) @ np.linalg.matrix_power(P, t) for t in range(n_cycles+1)]); occ = tr[:, 1:K1+1]; tot = occ.sum(axis=1); return {"P": P, "trace": tr, "q_bar": np.divide(occ @ q_dur, tot, out=np.full(len(tot), np.nan), where=tot > 0)}Needsimport numpy as np; returns the same values as the R function, with index t for cycle t.Test (Expanded matrix is stochastic with zero tunnel diagonals): Every row of the expanded matrix sums to 1 and the diagonal entries of the tunnel rows, in a range named TunnelDiag, are all zero. Expected result: TRUE. Excel check:
=AND(MAX(ABS(MMULT(ExpandedMatrix,OnesCol)-1))<1E-9,SUMSQ(TunnelDiag)=0)Test (First-year average equals the first tunnel probability): For a cohort that starts in the origin state, everyone in the tunnel after one cycle is in T1, so q_bar for cycle 1 equals the first element of q_dur. Expected result: TRUE. Excel check:
=ABS(AvgExitCycle1-INDEX(DurationDeathProbs,1))<1E-9Common error (Duration probabilities one cycle out of step): Starting q_dur at the second-year value, for example by reading a survival curve from the end of the first cycle rather than from entry, removes the high early risk. With the article's figures, 1,000 entrants have 920 survivors after one year in place of 800 (computed here for illustration). Checking that the first element of q_dur equals the first-year probability from the source (0.20 in the article) catches it; the second test above does not, because q_bar for cycle 1 equals whatever q_dur[1] holds.
Source: Alarid-Escudero F, Krijkamp E, Enns EA, Yang A, Hunink MGM, Pechlivanoglou P, Jalal H. A tutorial on time-dependent cohort state-transition models in R using a cost-effectiveness analysis example. Medical Decision Making. 2023;43(1):21-41. Section 3 and Algorithm 1 on populating the transition array for a state expanded with tunnel states, and section 4.2 on aggregating the tunnel states of the trace for reporting.
P[T_k, T_(k+1)] = 1 - q_dur[k]; P[T_k, Dead] = q_dur[k]; trace[t+1] = trace[t] P
Try this function
Implementations
Excel
Tunnel columns of a cohort trace
In a trace with one column per state and one row per cycle, the first formula fills the T1 column from the previous row and a row of entry probabilities, the second fills each later tunnel column from the previous tunnel column in the row above, and the third fills the long-term column. Named cells refer to the row above; copied down, the formulas shift each tunnel cohort one column to the right per row.
=SUMPRODUCT(PrevRow,EntryProbRow); =PrevTunnel*TunnelSurv; =PrevLastTunnel*LastTunnelSurv+PrevLongTerm*LongTermSurv
Assumptions
Each tunnel state lasts exactly one cycle
A tunnel state has transitions only to the next state in the chain and to exits such as death, never to itself, so its diagonal entry is zero and a person spends at most one cycle in it. Each row of the expanded matrix still sums to 1.
Duration effect over a whole number of cycles
Risks, costs or utilities change over the first K cycles since entry and are constant from cycle K+1 onwards, which is the long-term state. An effect that changes over a period that is not a whole number of cycles has to be approximated by one that is.
Every route into the clinical state enters the first tunnel state
All entrants, whatever state they come from, start the clock in T_1. Whether a repeat event sends people back to T_1 is a modelling decision; if it does, p_(i,T_1) is above zero for the tunnel states and L, and s_k excludes that route.
Worked examples
Single-entry cohort handed from the last tunnel state to the long-term state
In the article's example 1,000 people enter T1 just after a myocardial infarction, with annual death probabilities of 0.20, 0.08 and 0.04 in the three tunnel years and 0.03 afterwards. At the end of year 2 all 736 survivors are in T3, so in year 3 the long-term state receives 736 × 0.96 = 706.56; in year 4 it keeps 706.56 × 0.97 = 685.36. The cohort here has no origin state, so the entry vector p_(i,T_1) is all zero over T1, T2, T3, L and Dead.
n_S_tunnels = 5; m_(i,t) = [0, 0, 736, 0, 264]; p_(i,T_1) = [0, 0, 0, 0, 0]; m_(T_k,t) = 0; s_k = 0.80; m_(T_K,t) = 736; s_K = 0.96; m_(L,t) = 0; s_L = 0.97; m_(T_1,t+1) = 0; m_(T_(k+1),t+1) = 0; m_(L,t+1) = 706.56
Staggered entry from an event-free state, year 3 to year 4
In the article's staggered-entry example 1,000 people start event-free, and each year 5 per cent have an infarction and 1 per cent die. At the end of year 3 there are 830.584 event-free, 44.18 in T1, 37.6 in T2 and 36.8 in T3 (computed here from the same model). One more cycle gives 830.584 × 0.05 = 41.53 new entrants, 44.18 × 0.80 = 35.34 in T2, 37.6 × 0.92 = 34.59 in T3 and 36.8 × 0.96 = 35.33 in L, the year 4 figures in the article. States are ordered event-free, T1, T2, T3, L and Dead.
n_S_tunnels = 6; m_(i,t) = [830.584, 44.18, 37.6, 36.8, 0, 50.836]; p_(i,T_1) = [0.05, 0, 0, 0, 0, 0]; m_(T_k,t) = 44.18; s_k = 0.80; m_(T_K,t) = 36.8; s_K = 0.96; m_(L,t) = 0; s_L = 0.97; m_(T_1,t+1) = 41.5292; m_(T_(k+1),t+1) = 35.344; m_(L,t+1) = 35.328
Common errors
Giving a tunnel row the diagonal pattern of an ordinary state
Putting the probability of surviving T1 on the T1 diagonal rather than in the T2 column keeps survivors in T1 at the first-year risk for ever. In the article's example 512 people are alive after three years in place of 706.56 (computed here for illustration).
Too few tunnel states for the duration effect
Ending the tunnel after two states starts the long-term risk a cycle early. With the article's probabilities, two tunnel states followed by a long-term state at 0.03 leave 713.92 people alive after three years in place of 706.56 (computed here for illustration), and the error grows with each missing state.
Entrants reaching the clinical state without passing through the first tunnel state
If one route into the clinical state, such as a second strategy's event pathway, sends people to L or to a later tunnel state, those people skip the high early risk and their clock is wrong. Every column of entry probabilities has to point at T1.
Sources
Alarid-Escudero and colleagues on tunnel states in cohort models
Alarid-Escudero F, Krijkamp E, Enns EA, Yang A, Hunink MGM, Pechlivanoglou P, Jalal H. A tutorial on time-dependent cohort state-transition models in R using a cost-effectiveness analysis example. Medical Decision Making. 2023;43(1):21-41. Section 3: the cohort resides in each tunnel state for exactly one cycle, after which it either exits the tunnel or moves to the next tunnel state; the last tunnel state typically keeps some probability of remaining; Algorithm 1 populates the transition array by iterating through the tunnel states.
Sonnenberg and Beck on temporary states arranged as a tunnel
Sonnenberg FA, Beck JR. Markov models in medical decision making: a practical guide. Medical Decision Making. 1993;13(4):322-338. Section on Markov states: temporary states have transitions only to other states and not to themselves, and a tunnel is an array of temporary states visited only in a fixed sequence, illustrated by three post-infarction states with successively lower risks followed by a state with constant risk.
Canonical Identity
Stable URI · Machine-readable · Resolvable · CC BY 4.0