|
| 1 | +# Choosing a Sampler |
| 2 | + |
| 3 | +How to make a sampler for events in CompetingClocks.jl. |
| 4 | + |
| 5 | +## Quick Reference |
| 6 | + |
| 7 | +| Name | Distribution support | Best use cases | |
| 8 | +|----------------|----------------------|--------------------------------| |
| 9 | +| First-to-fire | All | Fastest for simple simulation | |
| 10 | +| Next Reaction | All | Best for common random numbers | |
| 11 | +| First Reaction | All | Fastest for very few events | |
| 12 | +| Direct | Exponential-only | Quicker likelihood calculation | |
| 13 | +| Petri | All | Debug rare errors | |
| 14 | + |
| 15 | +## High-level Interface |
| 16 | + |
| 17 | +Every event in a simulation has an identifying key which can be any immutable Julia |
| 18 | +type. A `Tuple` key type works fine, but it will be more performant to use a |
| 19 | +concrete type for the `KeyType`. The second argument to the `SamplerBuilder` |
| 20 | +is a type to use for time. Basic usage: |
| 21 | +```julia |
| 22 | +builder = SamplerBuilder(KeyType, Float64) |
| 23 | +sampler = SamplingContext(builder, rng) |
| 24 | +``` |
| 25 | +The sampler, itself, takes an `AbstractRNG` as its second argument. |
| 26 | + |
| 27 | +Specify features for the sampler with keyword arguments to the `SamplerBuilder`. |
| 28 | +These features determine the type of the sampler. |
| 29 | + |
| 30 | + * `step_likelihood=false`---Setting this to `true` let's you calculate the |
| 31 | + the likelihood of the next event and time before firing it. |
| 32 | + * `path_likelihood=false`---Set to true in order to calculate likelihood of a |
| 33 | + whole trajectory at any point in the simulation. This is more efficient than |
| 34 | + adding up steps in the likelihood along the way. |
| 35 | + * `likelihood_cnt=1`---Applies when likelihoods are enabled and supports |
| 36 | + importance sampling. Specifies how |
| 37 | + many event distributions will be used to calculate a vector of likelihoods. |
| 38 | + * `common_random=false`---For variance reduction, turn on recording of |
| 39 | + random number usage during sampling. |
| 40 | + * `start_time=0`---Sometimes you want a simulation to start at a different time. |
| 41 | + * `debug=false`---Whether to print debug messages using the `Logging` package. |
| 42 | + * `recording=false`---This will create a vector of every enable and disable |
| 43 | + event for test and debug. |
| 44 | + |
| 45 | +## Hierarchical Samplers |
| 46 | + |
| 47 | +For spatial simulations or for chemical simulations that aren't well-mixed, |
| 48 | +it can help to split a sampler into multiple buckets so that each bucket can |
| 49 | +update its own list of what fires next. This package does this by adding |
| 50 | +sampler groups. |
| 51 | + |
| 52 | +A sampler group is |
| 53 | + |
| 54 | + * A Symbol name for the sampler. |
| 55 | + * An inclusion function from `(ClockKey, Distribution)` to `Bool` that decides |
| 56 | + whether a given event belongs to this sampler. |
| 57 | + * An optional `sampler_spec` to say what kind of sampler this group should use. |
| 58 | + |
| 59 | +```julia |
| 60 | +builder = SamplerBuilder(KeyType, Float64) |
| 61 | +add_group!(builder, :sparky => (x,d) -> x[1] == :recover, sampler_spec=(:nextreaction,)) |
| 62 | +add_group!(builder, :forthright=>(x,d) -> x[1] == :infect) |
| 63 | +sampler = SamplingContext(builder, rng) |
| 64 | +``` |
| 65 | + |
| 66 | +The resulting sampler will be hierarchical. For every event, it will choose the |
| 67 | +soonest time among the soonest times from all sampler groups. |
0 commit comments