Sampling with SamplingContext

This is the main interface to the package.

  1. Build the SamplingContext. The SamplerBuilder helps choose what hierarchical samplers to use within the SamplingContext. You will see the builder gives you options for debugging output, calculation of likelihoods, use of variance reduction (common random numbers), and more.
using CompetingClocks
using Random

ClockKey = Int64
Time = Float64
rng = Xoshiro(899987987)
builder = SamplerBuilder(ClockKey, Time)
sampling = SamplingContext(builder, rng)

You can configure the builder by adding specific samplers for different kinds of clock keys. Each set of keys specified in an add_group! goes to its own sampler in the hierarchy.

  1. Write a sampling loop. The sampler will tell you what event comes next and then you choose that event using fire!. However, you write your own state for the system and update that state according to the event. Firing the event disables that event.
function one_epoch(model, sampler)
    observer = Observer()
    step_model!(model, sampler, (:on, 0), time(sampler))
    when, which = next(sampler)
    while !isnothing(which)
        fire!(sampler, which, when)
        step_model!(model, sampler, which, when)
        when, which = next(sampler)
        observer(model, when, which)
    end
    return observer
end
  1. Enable/disable events during state update. When updating the model state, you might enable or disable events. Here is an example from an assembly line.
function assemble_widget(model, sampler, individual, when, θ)
    pre_event_total = count(x -> x[2], model.part)
    model.widget += 1
    if pre_event_total > 0
        transrate = Exponential(inv(θ[:assemble] * pre_event_total))
        enable!(sampler, (:assemble, 0), transrate)
    end
end