06
Gillespie’s direct algorithm step by step
Gillespie’s direct algorithm repeatedly combines exact exponential waiting times with rate-weighted event selection to generate one complete continuous-time Markov-chain trajectory.
What the algorithm does
Gillespie’s direct algorithm, also called the stochastic simulation algorithm, generates the next CTMC jump directly from the current event rates. It advances from event to event rather than through small fixed time steps.
The jump times satisfy \(t_0<t_1<t_2<\cdots\), but the gaps are random and generally unequal.
The complete algorithm
The rates are recalculated after every event because they depend on the newly updated state.
Why recalculation is essential
Suppose an infection occurs. Then \(S\) decreases and \(E\) increases. Consequently, both the future infection rate and progression rate may change.
Do not calculate the rates once outside the loop and reuse them. That would simulate a different process whose event intensities ignore the changing epidemic state.
No fixed time step
DTMC or Euler calculation
Time advances by a chosen fixed increment such as dt = 0.1.
Gillespie CTMC
Time advances by a newly generated positive waiting time \(\tau\) after every state.
time = time + waiting_time
The code therefore has no numerical time-step parameter. The observation horizon limits how long to simulate, but it does not set jump times.
Why use a while loop?
The number of events is not known before simulation. A while loop is appropriate because repetition continues while biological and time conditions remain true:
while time < max_time:
# calculate and execute the next event
The loop may stop after very few events because of early extinction or after many events in a large outbreak.
Stopping conditions
max_time.The total-rate test is the most general absorbing-state check. The \(E=I=0\) test gives its biological meaning for this SEIR model.
Do not execute an event beyond the horizon
After generating \(\tau\), first check:
if time + waiting_time > max_time:
stopping_reason = "time horizon reached"
break
If the event lies outside the observation window, do not update the state and do not store it as an observed event.
The state remains unchanged from the last jump until the horizon. A plotting copy can be extended to max_time without pretending that another biological event occurred.
Store two related datasets
Store initial time and state, then every post-event time and state. This produces the step plot.
Store one row per actual jump: event number, waiting time, event type, new time and post-event state.
The initial state is part of the path but is not an event. Label it separately rather than counting it as infection, progression or recovery.
Scenario
Use a closed SEIR population:
The observation horizon is 200 days. The simulation stops earlier if both exposed and infectious populations reach zero.
Interactive Python laboratory
Click Run code to generate one complete event-driven trajectory. The output includes a summary, first and last events, event counts, a compartment step plot and the sequence of random waiting times.
Output
Run the code to see the result.
Understand the new loop code
| Code | Meaning |
|---|---|
while time < max_time | Repeats events while the process remains inside the observation window. |
rates = seir_rates(...) | Recalculates all event rates from the current post-event state. |
time += waiting_time | Advances time by a random rather than fixed increment. |
event_rows.append({...}) | Adds one labelled record for each actual biological event. |
times.copy() | Creates separate plotting lists so extending the plotted state does not falsify the event log. |
.value_counts() | Counts how many infection, progression and recovery events occurred. |
Why the step plot is still correct
Time is continuous, but compartment counts remain constant between jumps. A step plot shows this piecewise-constant path accurately.
The difference from the DTMC step plot is the horizontal spacing: DTMC jumps are considered at fixed grid times, whereas Gillespie jumps occur at irregular random times.
Try these experiments
- Change the seed and compare the number of events, peak and extinction time.
- Use \((S,E,I,R)=(197,3,0,0)\). Confirm that progression can create infectious people.
- Use \((S,E,I,R)=(190,0,0,10)\). Confirm immediate absorption with zero events.
- Shorten
max_timeand observe safe stopping before an event beyond the horizon. - Temporarily move the rate calculation outside the loop. Explain why the resulting process is biologically incorrect, then restore it.
Biological interpretation
The trajectory is one possible epidemic history. Event times cluster when the current total rate is large and become more widely separated when the total rate is small.
Infection, progression and recovery counts reflect the particular random path. Another seed can produce early extinction or a substantially different peak even with identical biological parameters.
What this lesson has—and has not—done
You can now:
- implement every step of Gillespie’s direct algorithm;
- recalculate rates after every event;
- advance through unequal continuous waiting times;
- store both a state path and event log;
- stop at absorption, biological extinction or a horizon; and
- plot a piecewise-constant continuous-time trajectory.
Next: Lessons 7–9 reuse this generic algorithm while focusing on the distinctive state structures and biological outcomes of SIS, SIR and SEIR CTMC models.