Simulator concepts and exceptions

Exceptions

rdmini::operation_not_supported

Derives from std::logic_error

Some operations described in the API below may be optional, in that they may not be practical to support in every implementation, and are not crucial in providing SSA functionality. Such operations may thus instead throw an exception of this type.

rdmini::invalid_value

Derives from std::runtime_error

Implementations are not obliged to perform range checking; should they do so, however, they must throw this exception when a supplied value is invalid.

rdmini::ssa_error

Derives from std::runtime_error

Represents an internal error in an SSA implementation.

Simulator engine interface

Any instance s of a simulator implementation S should provide the following interface to callers.

An SSA simulator engine may be comprised of an SSA selector and SSA process system, as described below.

Types

name type description
S::count_type integral type represents population counts

Constants

name type description
S::max_process_order unsigned integral type maximum order of an (elementary) reaction
S::max_participants unsigned integral type maximum number of distinct populations affected by one reaction
S::max_instances unsigned integral type maximum number of simulation instances
S::dynamic_range unsigned integral type maximum (base 2) logarithm of ratios of propensities

Methods

In the following,

expression return type description
s.initialise(n,M,t0) set up simulator to simulate n instances of the given rd_model M with initial simulation time t0
s.count(s,c,j) count_type population count of species index s in cell c in instance j
s.count(s,c) count_type equivalent to s.count(s,c,0)
s.counts(j) implementaiton specific return population counts of instance j as an iterable collection
s.set_count(s,c,k,j) set population count of species index s in cell c to k in instance j
s.set_count(s,c,k) equivalent to s.set_count(s,c,k,0)
s.advance(g) double [optional] advance simulator state by minimum time step, returning new simulation time
s.advance(t,g) double advance simulator up to time t, returning new simulation time

Population counts returned by s.counts(j) are ordered such that the population of species s in cell c is stored in the c·S+s element, where S is the number of species. Note that non-const operations on s may invalidate the collection returned by s.counts(j).

SSA selector implementations

Let A denote a class implementing the SSA selector API.

Types

name type description
A::key_type implementation specific keys representing individual procesess
A::value_type floating point type represents process propensities
A::event_type implementation specific describes generated process events

Methods

In the following let a be an instance of A, ac a const instance of A, g a uniform random number generator (see section [rand.req.urng] in C++ standard), n an unsigned integral value, k a value of type A::key_type, r a value of type A::value_type, and ev an event of type A::event_type returned by the next method.

expression return type description
a.reset(n) initialise state to represent n processes, with initially zero propensity
a.update(k,r) set propensity of process k to r; may throw rdmini::invalid_value
ac.size() unsigned integral type total number of represented processes
ac.propensity(k) A::value_type [optional] retrieve propensity of process k; may throw rdmini::invalid_value
ac.total_propensity() A::value_type [optional] retrieve propensity of process k; may throw rdmini::invalid_value
a.next(g) A::event_type generate next event drawing uniformly distributed numbers from g
ev.key() A::key_type identifier of process in event
ev.dt() floating point type event time delta

In practice, A::key_type should generally be an unsigned integral type, taking values from the range [0, a.size()).

SSA process system implementation

A process system encapsulates the dependency relations between populations and processes, and maintains the state of populations and processes across one or more independent instances.

For a process system of type Y, instance y.

Types

name type description
Y::key_type implementation specific keys representing individual procesess
Y::value_type floating point type represents process propensities
Y::pop_type integral type represents population indices
Y::count_type integral type represents population counts

As for an SSA selector, Y::key_type and Y::pop_type should likely be unsigned integral types.

Individual processes are described by a process description p which offers methods according to the following:

expression type description
p.left() collection of Y::pop_type (multi-)set of population indices consumed by process
p.right() collection of Y::pop_type (multi-)set of population indices produced by process
p.rate() Y::value_type elementary process rate

Constants

name type description
Y::max_population_index unsigned integral maximum population index
Y::max_process_order unsigned integral maximum process order
Y::max_participants unsigned integral maximum disrinct populations involved in a process
Y::max_count unsigned integral maximum population count
Y::max_instances integral type maximum number of system instances

Methods

In the following,

expression return type description
y.initialise(n) initialise state for n instances and
y.clear() remove all processes
y.add(q) add process with description q
y.add(b,e) add processes described by iterator interval [b,e)
y.define_processes(b,e) configure system with processes described by iterator interval [b,e)
y.size() size_t number of processes in system
y.n_instances() size_t number of instances
y.reset() zero population counts across all instances
y.propensity(k,j) Y::value_type calculate propensity for process k in instance j
y.count(p,j) Y::count_type population count for population p in instance j
y.count(p) Y::count_type equivalent to y.count(p,0)
y.counts(j) implementaiton specific return population counts of instance j as an iterable collection
y.set_count(p,c,notify,j) set count for population p to c in instance j; call notify(u) for each affected process u
y.set_count(p,c,notify) equivalent to y.set_count(p,c,notify,0)
y.apply(k,notify,j) apply process k to state of instance j; call notify(u) for each affected process u.
y.apply(k,notify) equivalent to y.apply(k,notify,0)

As for an SSA selector, Y::key_type should likely be an unsigned integral type. Adding a process to a process system may or may not preserve population counts — this is a quality of implementation issue.

Note that non-const operations on y may invalidate the collection returned by y.counts(j).