Tutorials › Stochastic Processes › Validating Gillespie Simulations with Rate and Time Checks

Simulation of Stochastic Processes · Tutorial 994 of 994

Validating Gillespie Simulations with Rate and Time Checks

Use rate, time, and generator-based checks to distinguish implementation errors from ordinary simulation variability.

Intermediate 12 min read

What You'll Learn

  • Derive the exponential waiting-time and categorical event-type predictions from the propensities.
  • Check holding-time samples using their rate, mean, survival probabilities, and transformed values.
  • Compare event-type counts with state-specific categorical probabilities.
  • Use a finite-state generator to calculate exact transient and stationary benchmarks.
  • Diagnose common validation errors, including pooling events across different states.

What a Gillespie Validation Check Can Tell You

A Gillespie simulation produces both a waiting time and an event type at each step. These outputs provide two distinct checks: at a fixed state, holding times should follow an exponential distribution with rate equal to the sum of the propensities, while the event type should follow a categorical distribution proportional to those propensities. A third check is to compare summaries of a small simulated model with calculations from its generator.

These checks are diagnostic, not demands for exact agreement. A finite sample fluctuates, so a discrepancy is evidence to investigate rather than automatic proof of a coding error. In particular, compare each simulated event with the predictions at the state before that event, and separate sampling variability from errors in rates, state updates, or bookkeeping.

Consider a continuous-time process \((X_t)_{t\ge0}\) on a state space \(S\), defined on a probability space \((\Omega,\mathcal{F},\mathbb{P})\). Let \((\mathcal{F}_t)_{t\ge0}\) denote the history of the process up to time \(t\). At state \(i\), suppose there are \(r\) possible reaction channels with propensities \(a_1(i),\ldots,a_r(i)\), all finite and nonnegative. Write \(a_0(i)=\sum_{\ell=1}^r a_\ell(i)\). The direct Gillespie step is defined when \(a_0(i)>0\): it draws a holding time \(\tau\) and an event label \(J\in\{1,\ldots,r\}\). If \(a_0(i)=0\), no event can occur from \(i\), so the process remains there.

Theorem (Gillespie rate and event checks): At a state \(i\) with \(a_0(i)>0\), the Gillespie step has \( \mathbb{P}(\tau>t\mid X\text{ is at }i)=e^{-a_0(i)t}\) for \(t\ge0\), and \( \mathbb{P}(J=\ell\mid X\text{ is at }i)=a_\ell(i)/a_0(i)\). Moreover, \(\tau\) and \(J\) are conditionally independent given the current state.

Proof. Fix the state \(i\), and abbreviate \(a_\ell=a_\ell(i)\) and \(a_0=a_0(i)>0\). One construction of the direct step assigns independent exponential clocks with rates \(a_1,\ldots,a_r\) to the channels with positive rates; a zero-rate channel never rings. For \(t\ge0\), the event that the minimum clock exceeds \(t\) is the event that every positive-rate clock exceeds \(t\). Independence and the exponential survival formula give \(\mathbb{P}(\tau>t)=\prod_{\ell:a_\ell>0}e^{-a_\ell t}=e^{-a_0t}\). For a channel \(\ell\) with \(a_\ell>0\), the joint density that its clock rings at time \(u\) and all other clocks exceed \(u\) is \(a_\ell e^{-a_0u}\) for \(u>0\). Integrating gives \(\mathbb{P}(J=\ell)=\int_0^\infty a_\ell e^{-a_0u}\,du=a_\ell/a_0\); for \(a_\ell=0\), the probability is zero, also equal to \(a_\ell/a_0\). The joint density of \(\tau=u,J=\ell\) is \(a_\ell e^{-a_0u}=(a_0e^{-a_0u})(a_\ell/a_0)\). This factors into the density of \(\tau\) and the probability of \(J=\ell\), proving conditional independence. \(\square\)

The theorem turns implementation details into concrete tests. At each recorded pre-event state, save the propensities, their sum, the holding time, and the event label. Check times against that state’s total rate, and labels against that state’s propensity proportions. Pooling observations with different rates can conceal an error or create an apparent discrepancy.

Checking Holding Times

For a fixed rate \(a_0>0\), an exponential holding time has mean \(1/a_0\), variance \(1/a_0^2\), and survival probability \(e^{-a_0t}\). Thus, across \(n\) holding times generated at the same state (or at states with the same total rate), a natural rate estimate is \(n/\sum_{k=1}^n\tau_k\). The exponential model also implies that \(1-e^{-a_0\tau_k}\) has a uniform distribution on \([0,1]\): for \(0\le u\le1\), its cumulative probability is \(\mathbb{P}(1-e^{-a_0\tau_k}\le u)=u\). This transform provides a diagnostic beyond the sample mean.

These checks require care about which intervals are included. Include the holding time ending in an event, but do not treat a simulation’s final, unfinished interval as a completed exponential observation without accounting for its censoring. A state with total rate zero contributes no event-terminated holding time. When rates change from state to state, use \(a_0(i)\) for each interval’s pre-event state rather than one pooled rate.

Worked Example: A Small Holding-Time Sample

Suppose six events are recorded from states whose total propensity is \(a_0=3\), and the six holding times are \(\tfrac16,\tfrac13,\tfrac12,\tfrac14,\tfrac13,\tfrac5{12}\). Check the sample mean and the fraction of holding times strictly greater than \(1/3\).

First compute the sum using denominator \(12\): \(\tfrac16+\tfrac13+\tfrac12+\tfrac14+\tfrac13+\tfrac5{12} =\tfrac2{12}+\tfrac4{12}+\tfrac6{12}+\tfrac3{12}+\tfrac4{12}+\tfrac5{12} =\tfrac{24}{12}=2\). The sample mean is \(2/6=1/3\), equal to the exponential mean \(1/a_0=1/3\). The rate estimate is \(6/2=3\), equal to the specified total rate.

Using the strict comparison \(>1/3\), exactly two observations qualify: \(\tfrac12>1/3\) and \(\tfrac5{12}>1/3\). The two observations equal to \(1/3\) do not qualify. The empirical fraction is \(2/6=1/3\), while the predicted survival probability is \(e^{-3(1/3)}=e^{-1}\). The two fractions need not match in a sample of six. The mean and survival check agree with the model at this sample size, but neither is enough to establish that an implementation is correct.

Checking Event-Type Frequencies

At state \(i\), the expected relative frequency of channel \(\ell\), conditional on an event occurring there, is \(a_\ell(i)/a_0(i)\). For \(n_i\) recorded departures from that state, the expected count for that channel is \(n_i a_\ell(i)/a_0(i)\). The events need not be independent across an entire changing-state trajectory; the useful comparison is conditional on the pre-event state. Repeated visits to the same state provide repeated categorical draws with the same probabilities, provided the propensities are unchanged there.

Worked Example: Event Counts at One State

At a particular state, two channels have propensities \(2\) and \(1\). Suppose 120 departures from that state are recorded, with 82 events of channel 1 and 38 of channel 2. Compute the predicted counts and compare the discrepancy with the binomial standard deviation for channel 1.

The total propensity is \(2+1=3\), so the channel probabilities are \(2/3\) and \(1/3\). The predicted counts are \(120(2/3)=80\) and \(120(1/3)=40\). The observed proportions are \(82/120=41/60\) and \(38/120=19/60\), summing to \(1\). Channel 1 exceeds its predicted count by \(82-80=2\).

For 120 categorical draws with channel-1 probability \(2/3\), the count variance is \(120(2/3)(1/3)=80/3\), so its standard deviation is \(\sqrt{80/3}\), approximately \(5.16\). The observed difference of \(2\) is smaller than one such standard deviation. This is not a formal goodness-of-fit test, but it illustrates why a small count difference alone is not a compelling failure signal. A systematic or much larger difference warrants checking the propensity calculation, channel ordering, and state update.

Event labels can also reveal bookkeeping bugs that waiting times will not detect. For example, the holding-time law depends on the sum of propensities, so two different errors in channel-specific rates could leave that sum unchanged. The event-type check can expose the incorrect allocation. Conversely, correct event proportions do not validate the total rate used to draw times.

Generator-Based Checks for a Small Model

For a finite-state continuous-time Markov chain, the generator \(Q=(q_{ij})\) records the rates of transitions between distinct states; its diagonal entries make every row sum to zero. In a reaction model, rates for channels that move from \(i\) to \(j\) are added to obtain \(q_{ij}\). A generator can give benchmarks beyond individual Gillespie steps, including state probabilities and expected occupation times.

Theorem (Finite-state generator benchmark): For a finite-state continuous-time Markov chain with generator \(Q\), initial row distribution \(\mu_0\), and transition semigroup \(P(t)=e^{tQ}\), the distribution at time \(t\) is \(\mu(t)=\mu_0e^{tQ}\). For a state \(j\) and \(T\ge0\), the expected occupation time is \(\mathbb{E}\!\left[\int_0^T\mathbf{1}_{\{X_t=j\}}\,dt\right]=\int_0^T\mu_j(t)\,dt\). If a transition \(i\to j\) occurs at rate \(q_{ij}\), its expected number of occurrences by time \(T\) is \(q_{ij}\int_0^T\mu_i(t)\,dt\).

Proof. For a finite-state chain, the semigroup property and the definition of the generator give \(P(h)=I+hQ+o(h)\) as \(h\downarrow0\), entry by entry. Thus the row distribution \(\mu(t)=\mu_0P(t)\) satisfies \(\mu'(t)=\mu(t)Q\) and \(\mu(0)=\mu_0\). The matrix exponential \(e^{tQ}\), defined by its convergent power series, satisfies this differential equation and initial condition. Uniqueness for a finite-dimensional linear differential equation gives \(\mu(t)=\mu_0e^{tQ}\).

For occupation time, the indicator is nonnegative, so integration and expectation can be interchanged; its expectation at time \(t\) is \(\mathbb{P}(X_t=j)=\mu_j(t)\). This gives the stated integral. For transition counts, conditional on the history at time \(t\) and \(X_t=i\), the probability of a transition \(i\to j\) in an interval of length \(h\) is \(q_{ij}h+o(h)\); the probability of two or more jumps is \(o(h)\) for a finite-state chain with bounded rates. Summing these conditional expected increments over a partition of \([0,T]\) and taking the mesh to zero gives the integral of \(q_{ij}\mathbb{P}(X_t=i)\). Hence the expected count is \(q_{ij}\int_0^T\mu_i(t)\,dt\). \(\square\)

Worked Example: A Two-State Generator Benchmark

Consider states \(S=\{0,1\}\), with rate \(2\) from \(0\) to \(1\) and rate \(1\) from \(1\) to \(0\). The generator and row sums are \(Q=\begin{bmatrix}-2&2\\1&-1\end{bmatrix}\); the first row sums to \(-2+2=0\), and the second to \(1-1=0\). Start in state \(0\). Find the stationary distribution, the probability of state \(1\) at time \(1\), and the expected occupation times and transition counts over \([0,1]\).

Write \(p_0(t)=\mathbb{P}(X_t=0)\). The forward equation from the generator is \(p_0'(t)=-2p_0(t)+p_1(t)\), with \(p_1(t)=1-p_0(t)\). Therefore \(p_0'(t)=1-3p_0(t)\), and \(p_0(0)=1\). Solving gives \(p_0(t)=\tfrac13+\tfrac23e^{-3t}\), so \(p_1(t)=\tfrac23(1-e^{-3t})\). At \(t=1\), the state-1 probability is \(\tfrac23(1-e^{-3})\), approximately \(0.6335\).

For stationarity, solve \(\pi Q=0\) with \(\pi_0+\pi_1=1\). The first coordinate gives \(-2\pi_0+\pi_1=0\), so \(\pi_1=2\pi_0\). Normalization gives \(3\pi_0=1\), hence \(\pi=(1/3,2/3)\). Checking both coordinates, \((1/3,2/3)Q=(-2/3+2/3,\ 2/3-2/3)=(0,0)\), and \(1/3+2/3=1\).

The expected occupation time in state \(1\) is \(\int_0^1\tfrac23(1-e^{-3t})\,dt =\tfrac23-\tfrac29(1-e^{-3}) =\tfrac49+\tfrac29e^{-3}\), approximately \(0.4555\). The occupation time in state \(0\) is \(1-(\tfrac49+\tfrac29e^{-3})=\tfrac59-\tfrac29e^{-3}\), approximately \(0.5445\); the two expectations sum to \(1\). The expected number of \(0\to1\) transitions is rate \(2\) times expected state-0 occupation: \(2(\tfrac59-\tfrac29e^{-3})=\tfrac{10}{9}-\tfrac49e^{-3}\), approximately \(1.0890\). The expected number of \(1\to0\) transitions is rate \(1\) times expected state-1 occupation: \(\tfrac49+\tfrac29e^{-3}\), approximately \(0.4555\).

As a possible simulation summary over 1000 independent runs of length \(1\), suppose the observed fraction in state \(1\) at time \(1\) is \(0.634\), the mean state-1 occupation time is \(0.456\), and the mean transition counts are \(1.09\) for \(0\to1\) and \(0.46\) for \(1\to0\). These rounded summaries are close to the respective generator benchmarks \(0.6335\), \(0.4555\), \(1.0890\), and \(0.4555\). Such agreement is a useful cross-check, not an exact equality requirement; repeated simulation can differ through ordinary sampling variation.

Common Mistakes and a Practical Checklist

Common mistake: pooling state-specific event probabilities. Suppose there are two channels. At state \(A\), their rates are \(2\) and \(1\), so the first-channel probability is \(2/3\). At state \(B\), their rates are \(1\) and \(3\), so that probability is \(1/4\). If a validation set contains 60 departures from each state, the conditional expected first-channel count is \(60(2/3)+60(1/4)=40+15=55\), or \(55/120=11/24\) of the events. An incorrect calculation pools the channel rates to get \(60(2+1)=180\) and \(60(1+3)=240\), then reports \(180/(180+240)=3/7\). That calculation weights states by their total rates instead of comparing the observed event labels conditional on the recorded states. Keep the states separate and use the propensity proportions at each one.

Before trusting a Gillespie output, check the following:

  • At each state, recompute all propensities and verify that the total rate is their sum.
  • Compare holding times with the exponential rate for their own pre-event state.
  • Compare event counts with the categorical probabilities for their own pre-event state.
  • For a small model, check that the generator rows sum to zero and compare simulated summaries with generator-based benchmarks.
  • Use a suitable amount of simulation and interpret finite-sample differences as variability unless there is a persistent or substantial mismatch.

A good validation plan uses independent checks: waiting times, event types, and model-level summaries test different parts of the implementation. Agreement across them is stronger evidence than agreement with any single statistic; disagreement helps locate whether the issue lies in rates, event selection, state changes, or simulation-time accounting.

Check Your Understanding

For each question, use the rates and state specified rather than a pooled value from another state.

  1. At a state with propensities \(4\) and \(2\), what are the holding-time rate and the probability of choosing channel 2?
  2. For an exponential holding time with rate \(5\), compute the probability that it is strictly greater than \(1/5\).
  3. A simulation records 30 departures from a state with channel probabilities \(1/4\) and \(3/4\). What are the expected event counts?
  4. For a two-state model with rates \(3\) from state 0 to state 1 and \(2\) from state 1 to state 0, write its generator and check both row sums.
  5. Why should event labels from two states with different propensities not be checked against one common categorical distribution?