From Event Rates to a Simulation Step
A continuous-time Markov chain can change state at irregular times, and its possible moves may have different rates at different states. The Gillespie direct method simulates such a path one event at a time. At the current state, it combines the event rates into one total rate, draws a waiting time, chooses which event occurs, and updates the state. The key practical point is that rates must be recalculated after every state change.
Let \((\Omega,\mathcal{F},\mathbb{P})\) be a probability space carrying the random draws used by the simulation. Let \((X_t)_{t\ge0}\) be the simulated process with state space \(S\), where \(S\) is finite or countable, and let the time index \(t\) be continuous. Suppose there are \(R\) event channels. At state \(x\in S\), channel \(r\) has propensity \(a_r(x)\ge0\) and state-change vector \(\nu_r\); if that channel is selected, the new state is \(x+\nu_r\). A channel that is impossible at \(x\) has propensity zero. The total propensity is \(a_0(x)=\sum_{r=1}^R a_r(x)\), assumed finite at every state visited. The propensities are rates, not probabilities: they need not sum to one.
After the update, the method returns to the rate calculation using the new state. Thus the waiting time and event choice are based on the propensities at the state currently occupied, not on the propensities from the start of the simulation. For a simulation up to a fixed time \(T\), stop if the next event time would exceed \(T\): record the state as unchanged from the current time through \(T\), and do not apply that event.
Why the Two Random-Number Conversions Work
The waiting-time calculation is an inverse-transform step. The exponential distribution with rate \(a>0\) has survival probability \(e^{-as}\) at \(s\ge0\). The event-choice calculation is a categorical draw with weights proportional to the propensities. These facts justify the two random-number transformations themselves; connecting them to the waiting time and event identity of a continuous-time Markov chain is a separate question.
Proof. Since \(U\) is uniform on \((0,1)\), for any \(s\ge0\), \(\mathbb{P}(W>s)=\mathbb{P}(-\ln(U)/a>s)=\mathbb{P}(U<e^{-as})=e^{-as}\). The last equality follows because \(e^{-as}\in(0,1]\) and a uniform random variable on \((0,1)\) lies below a threshold \(c\in[0,1]\) with probability \(c\). This is the exponential survival function, including \(\mathbb{P}(W>0)=1\). \(\square\)
Proof. Define \(c_0=0\) and \(c_r=\sum_{j=1}^{r}a_j/a_0\) for \(r=1,\ldots,R\). Then \(0=c_0\le c_1\le\cdots\le c_R=1\). Event \(r\) is selected exactly when \(c_{r-1}\le U<c_r\), apart from endpoints, which have probability zero under a continuous uniform distribution. The interval has length \(c_r-c_{r-1}=a_r/a_0\), so that is the probability of selecting event \(r\). If \(a_r=0\), the interval has length zero. These intervals cover \((0,1)\) except for their shared endpoints, so one event is selected with probability one. \(\square\)
In implementation, the strict inequality in the selection rule gives a definite convention at a cumulative boundary: a value exactly on the boundary goes to the next positive-width interval. Since a continuous uniform draw equals any one of the finitely many boundaries with probability zero, this convention does not alter the probabilities. A random-number generator should supply values strictly between zero and one for the waiting-time formula; if an implementation can return zero, it should use a documented endpoint-safe conversion rather than evaluate \(\ln(0)\).
Worked Simulations
Worked Example: Two Competing Reactions
At state \(x=(A,B)=(2,1)\), suppose one channel changes \(A\) to \(B\), with propensity \(3\), and a second changes \(B\) to \(A\), with propensity \(1\). Their state-change vectors are \(\nu_1=(-1,1)\) and \(\nu_2=(1,-1)\). Use \(U_1=e^{-2}\) and \(U_2=\tfrac12\) for one simulation step.
The total propensity is \(a_0=3+1=4\), which is positive and finite. The waiting time is \(\tau=-\ln(e^{-2})/4=2/4=\tfrac12\). For event selection, \(U_2a_0=(\tfrac12)(4)=2\). The first cumulative propensity is \(3\), and \(2<3\), so channel 1 is selected. The new state is \((2,1)+(-1,1)=(1,2)\), at time \(t+\tfrac12\).
Check: The two possible event probabilities are \(3/4\) and \(1/4\), which sum to \(1\). The draw \(U_2=\tfrac12\) lies in the first interval \((0,\tfrac34)\), so it selects channel 1 as found. Also \(A+B=2+1=3\) before the event and \(1+2=3\) afterward, consistent with the specified state change.
Worked Example: Infection or Recovery
Consider a susceptible-infected-recovered state \(x=(S,I,R)=(4,2,0)\). Suppose infection has propensity \(\tfrac{1}{10}SI\) and changes the state by \((-1,1,0)\); recovery has propensity \(\tfrac12 I\) and changes it by \((0,-1,1)\). Use \(U_1=e^{-9/10}\) and \(U_2=\tfrac13\).
The infection propensity is \((\tfrac{1}{10})(4)(2)=\tfrac45\). The recovery propensity is \((\tfrac12)(2)=1\). Therefore \(a_0=\tfrac45+1=\tfrac95\). The waiting time is \(\tau=-\ln(e^{-9/10})/(\tfrac95)=(\tfrac9{10})(\tfrac59)=\tfrac12\). The event-selection threshold is \(U_2a_0=(\tfrac13)(\tfrac95)=\tfrac35\). The first cumulative propensity is \(\tfrac45\), and \(\tfrac35<\tfrac45\), so infection is selected. The updated state is \((4,2,0)+(-1,1,0)=(3,3,0)\).
Check: The selection probability for infection is \((\tfrac45)/(\tfrac95)=\tfrac49\), and \(\tfrac13<\tfrac49\), agreeing with the selected event. The total population is \(4+2+0=6\) before and \(3+3+0=6\) after infection. The propensities for the next step must be evaluated at \((3,3,0)\), not reused from \((4,2,0)\).
Worked Example: Recalculate Rates After Each Event
Let the state be a nonnegative integer \(n\), with a birth event of constant propensity \(2\), changing \(n\) to \(n+1\), and a death event of propensity \(n\), changing \(n\) to \(n-1\). At \(n=0\), the death propensity is zero. Start at \(n=2\), time \(0\), and use the following successive pairs of uniform draws: \((e^{-3},\tfrac12)\), then \((e^{-1},\tfrac14)\).
At \(n=2\), the birth and death propensities are \(2\) and \(2\), so \(a_0=4\). The first waiting time is \(-\ln(e^{-3})/4=3/4\). The event-selection threshold is \((\tfrac12)(4)=2\). The first cumulative propensity is \(2\), and the strict test \(2<2\) is false; the second cumulative propensity is \(4\), and \(2<4\) is true. Thus death occurs, and the state becomes \(1\) at time \(3/4\).
At the new state \(n=1\), the birth propensity is \(2\), the death propensity is \(1\), and the new total is \(3\). The second waiting time is \(-\ln(e^{-1})/3=1/3\), so the next event time is \(3/4+1/3=9/12+4/12=13/12\). The selection threshold is \((\tfrac14)(3)=\tfrac34\), which is less than the first cumulative propensity \(2\). Thus birth occurs, and the state becomes \(2\).
Check: The two successive total propensities were \(4=2+2\) and \(3=2+1\); using the original total \(4\) for the second waiting time would be incorrect. The second event occurs at \(13/12\), which is later than the first event time \(3/4=9/12\), as required. The state sequence is \(2\to1\to2\), with one death and one birth.
Implementing the Method Reliably
A direct implementation follows the same order at every step. Let \(t\) and \(x\) denote the current time and state. If the requested simulation horizon is \(T\), the implementation should first ensure \(t\le T\), then evaluate every propensity at \(x\). The following checklist makes the order explicit:
Compute each \(a_r(x)\), confirm it is nonnegative and finite, and sum to obtain \(a_0(x)\).
If \(a_0(x)=0\), no event has positive propensity. Keep the state fixed through the remaining simulation horizon and stop.
Draw independent uniforms \(U_1,U_2\) in \((0,1)\). Calculate \(\tau=-\ln(U_1)/a_0(x)\), then choose the first event whose cumulative propensity exceeds \(U_2a_0(x)\).
If \(t+\tau>T\), stop without applying the event. Otherwise set \(t\leftarrow t+\tau\), apply \(x\leftarrow x+\nu_r\), and return to Step 1.
The state space and event updates must be compatible: a selected event should not produce an invalid state. Often this is ensured by assigning zero propensity to a reaction whenever its reactants or required population are unavailable. The algorithm also assumes that the total propensity can be computed at each visited state. In models where infinitely many events might occur before a finite time, additional care is needed: the event-by-event procedure could require infinitely many updates before reaching the horizon. A finite or suitably controlled simulation requires that such accumulation of event times does not occur.
Common mistake: treating rates as probabilities. In the infection example, a mistaken calculation might use \(\tfrac45\) and \(1\) directly as event probabilities. They sum to \(\tfrac95\), not \(1\), so they cannot be probabilities. The corrected probabilities are \((\tfrac45)/(\tfrac95)=\tfrac49\) for infection and \(1/(\tfrac95)=\tfrac59\) for recovery; their sum is \(\tfrac49+\tfrac59=1\). Another error is to divide the waiting-time numerator by the selected event's propensity. The waiting time uses the total rate \(a_0\), because one first uses the combined rate to draw the time and then uses the relative propensities to choose an event.
Finally, a simulated event time is not itself a fixed time step. The method advances the clock by the random waiting time generated at the current state. If an event changes the state, the rate landscape changes with it, so the next step begins with a fresh total propensity and fresh random draws. Keeping those two operations—advance by a waiting time, then recompute rates after the state update—separate is central to a correct implementation.
Check Your Understanding
For each question, state the rate calculation and the strict event-selection comparison you would use.
- At a state with propensities \(2\), \(0\), and \(6\), what is the total propensity and what are the three event-selection probabilities?
- If the total propensity is \(5\) and the waiting-time uniform draw is \(e^{-10}\), what waiting time does the direct method produce?
- For propensities \(1\) and \(3\), which event is selected when \(U_2=\tfrac12\), using the rule that selects the first cumulative propensity strictly greater than \(U_2a_0\)?
- Why must all propensities be recalculated after a state update?
- What should the algorithm do if the next proposed event time is greater than a fixed horizon \(T\)?