Part C — Modelling with complexity · Chapter 12

Stochastic simulation: kinetic Monte Carlo and Alchemist

~40 min read7 interactive widgets9 plates

In this chapter

  1. From model checking to Monte Carlo
  2. Simulation, reproducibility and time models
  3. Kinetic Monte Carlo: the chemistry problem
  4. The mathematics of the next reaction
  5. The Gillespie algorithm
  6. Speeding up: dependency graphs and the next-reaction method
  7. Slepoy’s constant-time algorithm
  8. Alchemist: from chemistry to pervasive computing
  9. The engine: spatial dependencies and non-Markovian events
  10. The SAPERE incarnation and YAML simulations
  11. Lab: operational steps and R&D directions
  12. Test your knowledge

1. From model checking to Monte Carlo

Chapter 11 ended with a stairway: simulation, approximate model checking, exact model checking. This chapter climbs down to the first rung and makes it industrial. Deck 10, "Stochastic Simulation in Alchemist" (Pianini & Viroli), starts where model checking stops:

"Pros [of model checking]: complete exploration of the system, exact verification of property values. Cons: in general extremely costly in terms of memory and time; complexity quickly grows with states; normally only feasible with simple, small systems."

When the state space is too large to explore exhaustively, the Monte Carlo method takes over: "when it's impossible to explore the whole system, find a procedure that randomly explores a part of it, apply it repeatedly, aggregate the result." The name is a trivia with a purpose: "the name is after the famous Casino of Monte Carlo, and refers to the exploration of the probabilities that gamblers can perform by repeatedly playing and recording results."

The crucial precision of the lecture: the procedure can possibly — not compulsorily — be a simulation. The canonical example is geometric: given a rectangle of known area AR containing some irregular figures, sample N points uniformly inside the rectangle, count how many fall inside the figures (say n), and estimate the combined area as AF ≈ (n/N)·AR. "This is not a simulation": no process evolves over time — the same statistical machinery, however, will later drive the simulation of chemical systems, where the "procedure" is a run of the system. The widget below lets you watch the estimate converge.

2. Simulation, reproducibility and time models

With the method in place, the lecture fixes the vocabulary. Simulation is, by the standard definition of Banks et al. (2010), "imitation of the operation of a real-world process or system over time" — and it is not necessarily run on computers: "putting a Formula 1 model into a wind tunnel is a sort of simulation". The model is the imitation itself: "a simplified version of the reality", where simplification is often a requirement because the original process "requires too much time, is not replicable in controlled environments, is too dangerous to replicate, is beyond our technical capacity". One constraint keeps the simplification honest: "elements relevant to the experiment must be retained in the model".

Reproducibility "measures the degree of agreement between two repetitions of the same experiment", and the deck splits it into three notions:

"A good simulation should be repeatable and replicable. A good computer simulation should be strictly reproducible": randomness must be kept under control — and "parallelism is a source of randomness too!" — a warning that will matter when Alchemist runs large simulations on many cores.

Modelling time

How does a simulation advance time? Two archetypal answers:

The distinction is not cosmetic: chemical reactions, message deliveries and node failures do not happen on a shared clock, and the kinetic Monte Carlo of the next sections is fundamentally event-driven — Alchemist is, by design, "a discrete-event simulator: events are forced to be ordered, even if they happen at the same time".

3. Kinetic Monte Carlo: the chemistry problem

The lecture now builds a simulator from scratch: "we have a container with a precise number of molecules that may react with each other. We want to forecast the evolution of the system in the future." Classic chemistry "relax[s] to continuous": differential-equation methods "suppose the concentration of each reactant to be ∈ ℝ", which "is an approximation: you cannot have a quarter of a molecule!", and "these methods are accurate only for a high number of molecules".

What if the system contains "a few thousand molecules"? The Monte Carlo way: "let's start with the system in initial state, let it run and see how it behaves. Repeat." In a real setup this is "very hard to do", so "here it comes the simulation". The system is composed of molecules and reactions of the form

      k
A + B −→ C

where A and B are reactants, k is the reaction-rate constant and C the product. The solution was "first proposed in [Gillespie, 1977] (Gillespie algorithm or Kinetic Monte Carlo)":

  1. Compute the propensity ar of each reaction. For a simple bimolecular reaction between distinct species, ar = k[A][B].
  2. Execute it, changing the concentrations.
  3. Update the propensities which may have changed.

The propensity is the bridge between the model and the math: it is the rate at which the reaction is currently ready to fire — proportional to how often the reactants meet, which is why it is proportional to the product of the concentrations. In the course's own terms, this is the same rate that labels the transitions of a CTMC (chapter 10, section 5): a system of reacting molecules is a CTMC whose state is the vector of molecule counts.

4. The mathematics of the next reaction

To simulate, the algorithm must answer two questions at each step: which reaction fires next, and when. The lecture derives both from a single joint density. For τ ≥ 0, p(τ, μ)dτ is the probability that "no reaction fires in the interval [0, τ) and reaction μ fires in the interval [τ, τ + dτ)". The derivation:

From the joint density everything else follows by integration. The probability that μ is the next reaction to fire:

P(next = μ) = ∫₀^∞ a_μ e^(−a_0 τ) dτ = a_μ / a_0

— the propensity, normalised by the total propensity: a weighted coin flip. The waiting time until some reaction fires sums over all reactions, giving the density p(τ) = a0 e−a0τ; its cumulative distribution is F(t) = 1 − e−a0t. Inverting it — "inverse transform sampling" — turns a uniform random number ρ in (0, 1] into an exponential draw:

1 − e^(−a_0 t) = ρ  ⇒  t = −ln(1 − ρ) / a_0 ≡ −ln(ρ) / a_0

The lecture's comment fixes the intuition: "the exponential term comes from the waiting time of the minimum of independent exponential clocks" — each reaction is a Poisson process, and the next firing is the earliest of all the clocks. This is exactly the CTMC view of chapter 10, section 4: the memoryless property is what makes the whole construction valid.

5. The Gillespie algorithm

Everything is in place for the base algorithm. With U(0, 1) denoting the uniform distribution on (0, 1):

  1. Set the simulation time T = 0.
  2. For each reaction r ∈ R, compute ar, then compute a0 = Σj∈R aj.
  3. Draw ρ1 ∼ U(0,1) and select the next reaction μ so that Σj=1μ aj > ρ1 a0 — the cumulative-sum scan.
  4. Execute the reaction, changing the concentrations.
  5. Draw ρ2 ∼ U(0,1) and advance the simulation time to T = Tprev + (−ln ρ2)/a0.
  6. Repeat from step 2.

The data structure of the naive implementation: "choose the next reaction with a cumulative-sum scan over the propensities: sample ρ2a0 and select the first reaction whose cumulative propensity exceeds it (linear time)". Linearity in the number of reactions is the cost that the next two sections attack.

Key idea — simulation as exact CTMC sampling

The Gillespie algorithm does not approximate the stochastic process: it draws from it. Each run is one path of the CTMC of chapter 10 — the same object that PRISM analyses exhaustively in chapter 11, section 6. The deck's stairway again: one run (simulation), many runs (approximate model checking with ε, δ), all runs (model checking). The widget of section 1 showed Monte Carlo without simulation; this widget shows simulation as Monte Carlo.

6. Speeding up: dependency graphs and the next-reaction method

Recomputing all propensities at every step is wasteful: "not every reaction affects the speed of every other: for instance, if A + B −k1→ C executes, the propensity of D + E −k2→ F will not be affected." The first optimisation is the dependency graph: "we can improve consistently the performance of the algorithm by keeping in memory which reactions influence which other, and updating only those required" — "a map that connects each reaction to a set of reactions that must be updated".

The deck's example network — five reactions with tangled dependencies:

R1: A + B → C      R2: B + C → D      R3: E + G → A
R4: D + E → E + F   R5: F → D + G

The second optimisation, the next-reaction method (Gibson & Bruck, 2000): "instead of choosing the next reaction probabilistically by propensity, generate a putative time for each reaction; sort the reactions by putative time, and take the first; at each step, for each reaction whose putative time has changed, re-sort the element." The dependency graph is reused to know whose putative time changed. Data structure: "we only need that the first element is the next to be executed — the best solution is a binary heap, which can be accessed in O(1) and sorted in log(n), but with a much smaller average complexity" (in the original work, an "Indexed priority queue").

The third optimisation, random reuse, addresses the cost of generating random numbers — "in a purely chemical simulator, it is often the heaviest task [Gibson and Bruck, 2000]; reducing the number of generated random numbers is key". The trick: "if a dependent reaction did not fire but its propensity changed from ap to ac, update its putative time without drawing a new random number":

τ_c = T + (a_p / a_c) · (τ_p − T)

where T is the current simulation time and τp, τc are the old and new putative times. "This follows from memorylessness: conditioning on survival up to T leaves an exponential residual waiting time, rescaled by the new propensity." The annotation matters: the random reuse is NOT allowed for non-exponential events — a restriction that will matter in section 9, when Alchemist admits events that are not Markovian.

7. Slepoy’s constant-time algorithm

The next-reaction method still costs log n per re-sort. Slepoy's algorithm (Slepoy, Thompson & Plimpton, 2008) pushes selection towards constant time. The idea: "group reactions by propensity magnitude: [pmin, 2pmin), [2pmin, 4pmin), ...; select a group proportionally to its total propensity; then select a reaction inside that group with rejection sampling":

  1. Pick a candidate reaction r uniformly from the group.
  2. Draw u ∼ U(0,1); accept r if u < ar/amax, where amax bounds all propensities in the group.
  3. If rejected, draw a new candidate and try again.

The cost analysis: "on average, rejection needs ≤ 2 trials (propensities in a group differ by at most a factor 2); if the number of groups G stays bounded, reaction selection is O(1)". The deck is careful about the assumptions: "the O(1) claim assumes the propensity range stays bounded; constant-time updates also require bounded coupling: each fired reaction should affect only O(1) other propensities." The lecture's lesson for the engineer: constant-time selection is achievable, but it rests on structure — bounded propensity ratios inside groups, bounded fan-out in the dependency graph — which is precisely the structure Alchemist's spatial dependency graph (section 9) tries to guarantee.

8. Alchemist: from chemistry to pervasive computing

The lecture now turns to the tool the course uses for large-scale simulation, Alchemist. The background: "pervasive computing scenarios are normally simulated by means of 'agent-based simulators' (ABS) [Wooldridge and Jennings, 1995]. ABS are extremely flexible, but they lack performance: it's the price to pay for being able to simulate a very wide spectrum of situations." The key observation that reframes the problem:

"Many pervasive computing scenarios can be modelled as mobile multi-compartmented chemical systems, where molecules are pieces of data (equivalent to a network of Petri Nets)."

This is the link with chapter 9 — a network of communicating computational devices is structurally a Petri Net with places as compartments, tokens as data and transitions as reactions. "A whole literature exists on how to make very fast kinetic Monte Carlo algorithms", so instead of optimising an ABS at the simulation level, the research question is: "can we take a kinetic Monte Carlo and extend it until it supports all the abstractions we need?"

The target scenarios: self-organising systems, pervasive computing systems, crowds of people, large-scale situated systems, smart mobility, crowd detection and steering, sensor networks, computational biology, aggregate programming. The requirements that a simulator must then meet:

These requirements rewrite the abstract model. The deck's vocabulary is precise and maps one-to-one onto the KMC ingredients: the Environment is "a Riemannian manifold where nodes live"; a Node is "a container of reactions and molecules situated in the environment"; a Molecule is "a token representing a chunk of data (think of it as a pointer)"; the Concentration is "the actual data associated with a molecule"; a Reaction is "a proactive behaviour"; and a Linking Rule is "a function of the environment that decides whether or not two nodes are connected".

A reaction, in turn, is tripartite: conditions ("node contains something", "number of neighbors < 3", any other condition about the environment), a probability distribution ("rate equation: how conditions influence the execution speed"), and actions ("change concentration of something", "move a node towards...", any other action on the environment). The propensity of section 3 is the rate equation in disguise: the conditions compute the concentration factors, the distribution turns them into a firing rate.

9. The engine: spatial dependencies and non-Markovian events

Moving from one container to many changes the dependency graph. With multiple compartments: "there are more reactions: each node has its 'copy'; a reaction may affect the propensities locally, in the neighborhood, or globally; the fewer are the bindings between reactions, the higher is the efficiency of a dependency graph". The lecture's solution is the spatial dependency graph, built on three contextual levelslocal, neighborhood, global:

The rule set is a precise engineering answer to the three challenges of multi-compartment simulation: "who decides if two compartments are communicating?" (the linking rule), "how to model a molecule moving towards a new node?" (a reaction whose action moves data — or a node), "how does the dependency graph change?" (only along the contexts above).

Non-Markovian events

The second engine extension is about time. Example: "every second, an external device injects some quantity of molecules within a compartment — this event happens precisely every second: it is not a Poisson process! Its probability distribution is a δ-Dirac comb." The basic Gillespie algorithm "is hard to modify to support such events. The main reason is that the choice is not made depending on time, but on propensity, which is an entity strictly bound to the Markovian model." The next-reaction algorithm, instead, "uses putative times: this makes it able to simulate events independently from their distribution, since we just need to correctly estimate the next time of occurrence." With the restriction already met in section 6: "the random reuse is NOT allowed for non-exponential events."

Key idea — propensity vs putative time

The choice of data structure is a choice of semantics. Gillespie's propensity-based selection is exact only for Markovian (exponential) events, because the memoryless property is what justifies recomputation from rates alone. The next-reaction method stores times, so any distribution — exponential, deterministic (Dirac comb), empirical — can drive the event queue: you only need to know when the next occurrence is. Alchemist is built on this second design, and it is why it can simulate real pervasive systems where devices do not behave like Poisson clocks.

10. The SAPERE incarnation and YAML simulations

Alchemist was "initially developed within the SAPERE EU Project; at the model level, it captures the required abstractions of a SAPERE system". In the SAPERE incarnation, "the concentration is defined as 'list of tuples matching a tuple template'. Basically, in this configuration Alchemist does not simulate a simple collection of intercommunicating compartments, but a network of (possibly mobile) programmable tuple spaces." This is "one of four incarnations, along with two aggregate programming incarnations (Protelis and Scafi) and a sketched biochemical implementation" — the last two are the subject of chapter 14.

Simulations are written in YAML: "JSON superset, compact, human-readable, supports anchoring (referencing)"; "the same syntax can be used for any incarnation"; there is "support for running batches, no intermediate compilation, no large files involved". The mini-tutorial of the deck builds a simulation from the ground up.

The minimal simulation is one line — incarnation sapere. Then come the linking rule and the node displacements. The network-model section picks the class implementing LinkingRule; deployments picks classes implementing Displacement:

incarnation sapere

network-model
  type ConnectWithinDistance   # a LinkingRule implementation
  parameters [5]               # connect nodes within distance 5

deployments
  - type Point                 # a Displacement implementation
    parameters [0, 0]
  - type Point
    parameters [0, 1]

Scaling up: Circle [10000, 0, 0, 10] scatters 10 000 nodes around the origin within radius 10; Grid [-5, -5, 5, 5, 0.25, 0.25, 0, 0] lays a regular grid of step 0.25, and the last two parameters add jitter for an irregular grid. Note the constructor convention: "search a class implementing Displacement with this name; use a constructor that can take parameters deducible from context and the given ones".

Nodes start with contents — molecules everywhere, or restricted to a shape. Then programs attach reactions. The default time distribution is the SAPERE ExponentialTime (Markovian rate); if unspecified, the incarnation assumes an "ASAP" behaviour (rate = Infinity):

incarnation sapere

network-model
  type ConnectWithinDistance
  parameters [0.5]

deployments
  type Grid
  parameters [-5, -5, 5, 5, 0.25, 0.25, 0.1, 0.1]
  contents
    - molecule hello              # everywhere
    - in                          # restrict the area...
        type Rectangle
        parameters [-1, -1, 2, 2] # ...to this rectangle
      molecule token

programs
  -
    - time-distribution 1         # Markovian rate 1
      program >                   # '>' begins a multiline string
        { token } --> { firing }
    - program "{ firing } --> +{ token }"   # ASAP reaction

{ token } --> { firing } reads a token and writes firing; +{ token } creates a new molecule. Code reuse uses YAML anchors: define _send & send once, then reference it with programs: - *send.

Diffusion is two reactions: spawn a copy towards a neighbor (*{ token }), then merge duplicates back. The gradient pattern combines emission, propagation with accumulated distance, and min-keeping — the same computation that chapter 14 expresses with rep/nbr:

incarnation sapere
network-model
  type ConnectWithinDistance
  parameters [0.5]

_send & send                       # anchor: a named program list
  - time-distribution 1
    program >
      { token } --> { token } * { token }    # send a copy to a neighbor
  - program >
      { token }{ token } --> { token }       # merge duplicates

deployments
  type Grid
  parameters [-5, -5, 5, 5, 0.25, 0.25, 0.1, 0.1]
  contents
    in
      type Rectangle
      parameters [-0.5, -0.5, 1, 1]
    molecule token
  programs *send

The gradient variant adds the distance field. The special variable #D is the distance to the selected neighbor; def N2 >= N guards the merge on comparable values; the last reaction deletes gradients past 30:

_grad & grad
  - time-distribution 0.1
    program "{ source } --> { source } { gradient, 0 }"
  - time-distribution 1
    program "{ gradient, N } --> { gradient, N } *{ gradient, N +# D }"
  - program >
      { gradient, N }{ gradient, def N2 >= N } --> { gradient, N }
  - time-distribution 0.1
    program "{ gradient, N } --> { gradient, N + 1 }"
  - program "{ gradient, def N > 30 } -->"

The synthetic variables of the SAPERE incarnation: #ID (unique LSA id), #NODE (this node), #O (the orientation — the local node id when an operation involves the neighborhood), #D (distance to the neighbor), #T (current time), #RANDOM, #NEIGHBORHOOD (all neighbor ids), #SELECTEDNEIGH (neighbor selected by a + operation), #ROUTE (distance using routes, with maps).

Time distributions are pluggable classes. A deterministic every-0.5-seconds injection — the δ-Dirac comb of section 9 — is a DiracComb:

programs
  - time-distribution
      type DiracComb
      parameters [0.5]
    program "{ token, N, L } --> { token, N, L } *{ token, N +# D, L add [#NODE;] }"
  - program "{ token, N, L }{ token, def N2 >= N, L2 } --> { token, N, L }"

"The syntax is a shortcut for the desired Java class' constructor. You can implement your own classes implementing TimeDistribution and model arbitrary distributions." The same {type, parameters} map loads any simulation element, and "the Alchemist loader automatically assigns values to arguments of type Environment, Incarnation, RandomGenerator, Node, Reaction, TimeDistribution depending on the context".

Finally, the variables section parametrises whole simulations — "very useful for running batches". Variables implement the Variable interface; dependent variables declare a formula "interpreted by an internal Javascript engine". The deck's movement example declares rate (a GeometricVariable [2, 0.1, 10, 9]), size (min 1, max 10, step 1, default 5), and derived values mSize = size, sourceStart = mSize/10, sourceSize = size/5, all referenced in deployments and programs via *size etc. A batch run is then a sweep over the declared variables.

Editor's note — one engine, four incarnations

The SAPERE incarnation instantiates the abstract model of section 8: concentration becomes "list of tuples matching a tuple template", so molecules are tuples and reactions rewrite them. The Protelis and Scafi incarnations reuse the same engine for aggregate programs — Alchemist is how chapter 14 validates field computations at scale — which is why this course can move from chemistry, through Petri Nets, to pervasive computing without changing the simulation machinery.

For the exam

Be able to explain, with the grad YAML program as the running example, how the SAPERE reactions implement a gradient: { source } --> { source } { gradient, 0 } seeds the source; { gradient, N } --> ... *{ gradient, N +# D } propagates the distance to a neighbor; the guarded merge keeps the minimum; #D and def guards make the pattern declarative. And be able to justify each engine choice: multiple compartments (nodes), spatial dependency graphs (performance), putative times (non-Markovian events), YAML with anchors (reusability).

11. Lab: operational steps and R&D directions

Deck 10 has no separate lab deck: the tutorial is the lab, and the lecture's UI notes close the operational picture. The Alchemist GUI keyboard shortcuts: P pause/play, L toggles link painting, R realtime mode ("tries to sync the simulation with the real time, always ensuring at least 25fps"), / speed up / slow down (fewer / more UI updates), M marker for the node closest to the mouse, S select mode, O manual move of selected nodes.

Operational steps

R&D tasks

TaskWhat it asks
ALCHEMIST-VS-PRISMModel the stochastic Readers & Writers Petri Net of chapter 10, section 7 in the SAPERE incarnation (tokens as tuples, transitions as reactions with rate distributions) and compare the behaviour with the PRISM CTMC of chapter 11, section 6: same qualitative properties, quantitative agreement within statistical error. This is the simulation rung of the stairway against the exact one.
GILLESPIE-IN-SCALAThe course toolkit of chapter 10, section 6 (CTMCSimulation) already performs Gillespie simulation on CTMCs. Extend it with the dependency-graph and next-reaction optimisations of section 6, benchmark the speed-up on a growing reaction network, and verify that the statistics are unchanged (same distribution, fewer random draws).
NON-MARKOVIAN-INJECTIONIn the course's CTMC simulation framework, model an external injector that fires deterministically every T time units (a Dirac comb). Explain why the basic Gillespie loop cannot represent it and how a putative-time schedule would; implement the minimal extension and show the difference in the event sequence.
TOWARD-AGGREGATEUse the Scafi incarnation (or Protelis) of Alchemist to simulate a gradient field over 10 000 nodes and compare it with the SAPERE gradient of section 10. This is the bridge to chapter 14 and to the RL-driven control of chapter 13.
For the exam

The arc of this chapter is the arc of the stairway's first rung: when model checking is impossible, simulate — and do it fast. A strong presentation walks one system (say, a crowd of nodes with a spreading gradient) through the whole chain: Petri-Net reading of the system (chapter 9), CTMC reading (chapter 10), the p(τ, μ) mathematics, the Gillespie loop, the three speed-ups, and finally the Alchemist YAML that makes it run on 10 000 nodes — with the ε, δ statistical reasoning of chapter 11, section 8 justifying how many runs you need.

Test your knowledge

What is the Monte Carlo method, and why is the area-estimation example not a simulation?

When it is impossible to explore the whole system: find a procedure that randomly explores a part of it, apply it repeatedly, aggregate the result. In the area example you sample N points uniformly in a rectangle of area A_R, count n inside the figures, and estimate A_F ≈ (n/N)·A_R: no process evolves over time, so the procedure is statistical but not simulative — "the procedure can POSSIBLY (not compulsorily) be a simulation".

Give the three notions of reproducibility and the definition of simulation.

Simulation: "imitation of the operation of a real-world process or system over time" (Banks et al., 2010), not necessarily on computers. Repeatability: the experiment can be executed multiple times in the same conditions. Replicability: it can be executed again in slightly different conditions. Strict reproducibility: exact same output on exact same input data — randomness under control; parallelism is a source of randomness too.

What is the difference between time-driven and event-driven simulation?

Time-driven: discrete ticks; at every tick the model is updated; all changes within a tick are simultaneous. Event-driven (DES): events are simulated one by one, time is shifted forward per event; events are strictly ordered, and for same-time events one executes first and its outcome may influence the rest. Alchemist is a discrete-event simulator.

What is a propensity, and what is the three-step Gillespie loop?

For a bimolecular reaction between distinct species, the propensity is a_r = k[A][B] — the current firing rate, proportional to how often the reactants meet. Gillespie (1977), a.k.a. kinetic Monte Carlo: (1) compute the propensity a_r of each reaction; (2) execute it, changing the concentrations; (3) update the propensities which may have changed.

Derive p(τ, μ) and P(next = μ) for a reaction network with total propensity a_0.

Each reaction j is an exponential clock with rate a_j; by independence P(no reaction before τ) = Π e^(−a_j τ) = e^(−a_0 τ); μ fires in [τ, τ+dτ) with probability a_μ dτ. Hence p(τ, μ) = a_μ e^(−a_0 τ). Integrating over τ gives P(next = μ) = a_μ/a_0. The waiting time has density a_0 e^(−a_0 τ), CDF 1 − e^(−a_0 t), sampled by inverse transform t = −ln(ρ)/a_0.

Write the base Gillespie algorithm step by step.

(1) T = 0. (2) compute a_r for each reaction and a_0 = Σ a_j. (3) draw ρ₁ ∼ U(0,1), select μ such that Σ_{j≤μ} a_j > ρ₁·a_0 (cumulative-sum scan, linear time). (4) execute μ, changing concentrations. (5) draw ρ₂ ∼ U(0,1), T = T_prev + (−ln ρ₂)/a_0. (6) repeat from 2.

What are the three optimisations of the kinetic Monte Carlo, and why is random reuse valid?

(1) Dependency graph: keep a map reaction → affected reactions and recompute only those. (2) Next-reaction method (Gibson & Bruck): generate a putative time per reaction, sort, take the first, re-sort only changed ones — a binary heap gives O(1) access and log(n) re-sort. (3) Random reuse: when a dependent reaction's propensity changes from a_p to a_c, rescale its putative time τ_c = T + (a_p/a_c)(τ_p − T) without drawing again — valid because of memorylessness (conditioning on survival up to T leaves an exponential residual), and NOT allowed for non-exponential events.

How does Slepoy's algorithm achieve (near) constant-time selection?

Group reactions by propensity magnitude into doubling intervals [p_min, 2p_min), [2p_min, 4p_min), ...; select a group proportionally to its total propensity; inside the group, pick a candidate uniformly and accept with probability u < a_r/a_max (rejection sampling). Within a group rates differ by at most a factor 2, so rejection needs ≤ 2 trials on average; with a bounded number of groups selection is O(1). Caveats: bounded propensity range and bounded coupling (each firing affects O(1) other propensities).

Why are agent-based simulators insufficient for pervasive computing, and what is Alchemist's answer?

ABS are extremely flexible but lack performance — the price of simulating a very wide spectrum of situations. Since pervasive scenarios are "mobile multi-compartmented chemical systems where molecules are pieces of data (equivalent to a network of Petri Nets)", Alchemist takes a kinetic Monte Carlo and extends it: multiple compartments (nodes), molecules as data types, mobility, non-Markovian events, flexible reactions, high performance.

Describe the Alchemist abstract model in five concepts.

Environment: a Riemannian manifold where nodes live. Node: a container of reactions and molecules situated in the environment. Molecule: a token representing a chunk of data (a pointer). Reaction: a proactive behaviour with conditions, a probability distribution (rate equation) and actions. Linking rule: a function of the environment deciding whether two nodes are connected. Concentration: the actual data associated with a molecule.

What is the spatial dependency graph, and what are the three contextual levels?

With many compartments, each node has its copy of the reactions; a firing may affect propensities locally, in the neighborhood, or globally. Each reaction gets an input context (what it reads to compute its propensity) and an output context (what it modifies); r₁ influences r₂ if they share a compartment, if either side is global, or if their neighborhood contexts share a compartment. Contexts keep the dependency graph — hence the engine — small.

Why can the next-reaction method handle non-Markovian events and the basic Gillespie cannot?

Basic Gillespie chooses the next reaction by propensity, an entity strictly bound to the Markovian model — a deterministic every-second injection (a δ-Dirac comb) is not a Poisson process and cannot be represented. The next-reaction method schedules by putative times: for any distribution you only need to estimate the next time of occurrence, so arbitrary TimeDistribution implementations (e.g. DiracComb) plug in. Random reuse, however, is not allowed for non-exponential events.

What does the SAPERE incarnation change in the model, and how are simulations written?

Concentration becomes "list of tuples matching a tuple template": Alchemist simulates a network of (possibly mobile) programmable tuple spaces, one of four incarnations (SAPERE, Protelis, Scafi, biochemical). Simulations are YAML files: incarnation, network-model (linking rule), deployments (Point, Circle, Grid), contents (molecules, possibly inside shapes), programs (reactions with time distributions), anchors for reuse, synthetic variables (#D, #NODE, ...), and a variables section for batches.