Interface
These are methods which are defined for any samplers subtyping <:SSA
, the abstract sampler type.
Use a Sampler
CompetingClocks.enable!
— Functionenable!(sampler, clock, distribution, enablingtime, currenttime, RNG)
Tell the sampler to start a clock.
sampler::SSA{KeyType,TimeType}
- The sampler to tell.clock::KeyType
- The ID of the clock. Can be a string, integer, tuple, etc.distribution::Distributions.UnivariateDistribution
enablingtime::TimeType
- The zero time for the clock's distribution, in absolute time. Usually equal towhen
.when::TimeType
- The current time of the simulation.rng::AbstractRNG
- A random number generator.
enable!(dc::DirectCall, clock::T, distribution::Exponential, when, rng)
Tell the DirectCall
sampler to enable this clock. The clock
argument is an identifier for the clock. The distribution is a univariate distribution in time. In Julia, distributions are always relative to time t=0
, but ours start at some absolute enabling time, $t_e$, so we provide that here. The when
argument is the time at which this clock is enabled, which may be later than when it was first enabled. The rng
is a random number generator.
If a particular clock had one rate before an event and it has another rate after the event, call enable!
to update the rate.
CompetingClocks.disable!
— Functiondisable!(sampler, clock, when)
Tell the sampler to forget a clock. We include the current simulation time because some Next Reaction methods use this to optimize sampling.
disable!(dc::DirectCall, clock::T, when)
Tell the DirectCall
sampler to disable this clock. The clock
argument is an identifier for the clock. The when
argument is the time at which this clock is enabled.
CompetingClocks.next
— Functionnext(sampler, when, rng)
Ask the sampler for what happens next, in the form of (when, which)::Tuple{TimeType,KeyType}
. rng
is a random number generator.
next(dc::DirectCall, when::TimeType, rng::AbstractRNG)
Ask the sampler what clock will be the next to fire and at what time. This does not change the sampler. You can call this multiple times and get multiple answers. Each answer is a tuple of (when, which clock)
. If there is no clock to fire, then the response will be (Inf, nothing)
. That's a good sign the simulation is done.
next(multiple_direct, when, rng)
Selects the next transition to fire and when it fires.
There are two main algorithms for this selection. This implementation handles the case when there are a lot of clocks or when some clocks have much smaller hazards. It first draws a random number to choose which subset of hazards will be used, and then it asks that subset to draw a random number to choose which particular hazard is used. When there are many hazards, it is possible that a random number generator will never choose a particular value because there is no guarantee that a random number generator covers every combination of bits. Using more draws decreases the likelihood of this problem.
For the first reaction sampler, you can call next() multiple times and get different, valid, answers. That isn't the case here. When you call next() on a CombinedNextReaction sampler, it returns the key associated with the clock that fires and marks that clock as fired. Calling next() again would return a nonsensical value.
CompetingClocks.reset!
— Functionreset!(sampler)
After a sampler is used for a simulation run, it has internal state. This function resets that internal state to the initial value in preparation for another sample run.
reset!(recorder::CommonRandomRecorder)
The common random recorder records the state of the random number generator for each clock, but the same clock can be enabled multiple times in one simulation, so it records the generator state for each (clock, index of the enabling of that clock). The reset!
function says we are starting a new simulation run, so all clocks haven't been seen.
Query a Sampler
Base.getindex
— Functiongetindex(sampler, clock::KeyType)
Return stored state for a particular clock. If the clock does not exist, a KeyError
will be thrown.
getindex(sampler::FirstReaction{K,T}, clock::K)
For the FirstReaction
sampler, returns the distribution object associated to the clock.
getindex(sampler::FirstToFire{K,T}, clock::K)
For the FirstToFire
sampler, returns the stored firing time associated to the clock.
getindex(sampler::DirectCall{K,T}, clock::K)
For the DirectCall
sampler, returns the rate parameter associated to the clock.
getindex(sampler::CombinedNextReaction{K,T}, clock::K)
For the CombinedNextReaction
sampler, returns the stored firing time associated to the clock.
Base.keys
— Functionkeys(sampler)
Return all stored clocks as a vector.
Base.keytype
— Functionkeytype(sampler)
Return the type of clock keys.
Base.length
— Functionlength(sampler)::Int64
Return the number of stored clocks.