mixle.stats.processes.ctmc module

Continuous-time Markov chain (CTMC) over fully observed trajectories.

A CTMC on K states is governed by a generator matrix Q: off-diagonal q_ij >= 0 is the rate of jumping i -> j, and q_ii = -sum_{j!=i} q_ij. A fully-observed trajectory is the initial state, the total observation horizon, and the sequence of (dwell_time, next_state) jumps up to that horizon; its log-likelihood is

log L = sum_{i!=j} n_ij * log q_ij - sum_i q_i * T_i, q_i = -q_ii = sum_{j!=i} q_ij,

where n_ij is the number of observed i->j transitions and T_i the total time spent in i including the final, right-censored dwell – from the last jump (or from time 0, if there were no jumps at all) out to the observation horizon. That final interval is real exposure with no observed exit, exactly like the tail of a birth-death or renewal-process trajectory censored at its own window (see mixle.stats.processes.birth_death): a chain that dwells in a state for the whole horizon without jumping still contributes -q_i * horizon to the log-likelihood, it just contributes no transition count. Omitting it (as an earlier version of this module did) understates every T_i by the length of each trajectory’s final interval and biases the closed-form rate MLE upward.

This is a collection of independent Poisson-rate likelihoods, so the MLE is closed form and unique: q_ij = n_ij / T_i. The estimator therefore certifies GLOBAL_UNIQUE (see mixle.inference.certify(), which classifies this family). Data type: (s0, horizon, [(dt, s1), (dt, s2), ...]) – the initial state, the total observation window length, and the observed jumps (each dt > 0, and the jumps’ dwell times may not sum to more than horizon). The horizon travels with each trajectory rather than living only on the distribution, matching BirthDeathSamplingDistribution’s (n0, T, events) convention: different trajectories in one dataset are free to have been observed for different lengths of time. The distribution’s own initial_state/horizon constructor parameters are sampling-time defaults (where sample() starts a fresh chain, and for how long) and are round- tripped through .estimator(); they are not constraints on what a trajectory being scored is allowed to contain – log_density scores whatever s0 and horizon the trajectory itself declares.

The family follows the standard Mixle distribution contract (Distribution / Sampler / Accumulator / Factory / Estimator / DataEncoder) so it composes with optimize / seq_log_density / the PPL surface like every other family.

class ContinuousTimeMarkovChainStatistics(transition_counts, dwell_times)[source]

Bases: NamedTuple

Versioned, tuple-compatible aggregate CTMC statistics.

Parameters:
transition_counts: ndarray

Alias for field number 0

dwell_times: ndarray

Alias for field number 1

property schema_version: int

Return the serialized statistic schema version.

class ContinuousTimeMarkovChainDistribution(rates, initial_state=0, horizon=10.0, name=None, keys=None, prior_shape=1.0, prior_rate=0.0)[source]

Bases: SequenceEncodableProbabilityDistribution

CTMC on K states with generator Q (off-diagonal rates); MLE is closed form (GLOBAL_UNIQUE).

Parameters:
  • rates (np.ndarray)

  • initial_state (int)

  • horizon (float)

  • name (str | None)

  • keys (str | None)

  • prior_shape (Any)

  • prior_rate (Any)

property generator: ndarray

The generator matrix Q (off-diagonal rates, diagonal = -exit rate).

density(x)[source]

Return the probability density of one fully observed trajectory.

Parameters:

x (Any)

Return type:

float

log_density(x)[source]

Return the log-likelihood of one fully observed CTMC trajectory.

Parameters:

x (Any)

Return type:

float

seq_log_density(x)[source]

Return vectorized log-likelihoods for encoded trajectory statistics.

Parameters:

x (Any)

Return type:

ndarray

sampler(seed=None)[source]

Return a Gillespie sampler for trajectories from this CTMC.

Parameters:

seed (int | None)

Return type:

ContinuousTimeMarkovChainSampler

estimator(pseudo_count=None)[source]

Return the closed-form rate estimator for this state space.

pseudo_count=c is the compatibility shorthand for independent off-diagonal Gamma(shape=1+c, rate=c) priors. With no override, the distribution’s explicit edgewise priors are preserved.

Parameters:

pseudo_count (float | None)

Return type:

ContinuousTimeMarkovChainEstimator

dist_to_encoder()[source]

Return the trajectory-statistics encoder used by vectorized methods.

Return type:

ContinuousTimeMarkovChainDataEncoder

class ContinuousTimeMarkovChainSampler(dist, seed=None)[source]

Bases: DistributionSampler

Exact Gillespie simulation of CTMC trajectories on [0, horizon].

Parameters:
  • dist (ContinuousTimeMarkovChainDistribution)

  • seed (int | None)

sample(size=None, *, batched=True)[source]

Draw one (s0, horizon, jumps) trajectory or a list of size trajectories, all observed over the distribution’s configured horizon.

Parameters:
Return type:

Any

class ContinuousTimeMarkovChainAccumulator(num_states, name=None, keys=None)[source]

Bases: SequenceEncodableStatisticAccumulator

Accumulate the CTMC sufficient statistics: transition counts n_ij and dwell times T_i.

Parameters:
  • num_states (int)

  • name (str | None)

  • keys (str | None)

update(x, weight, estimate)[source]

Update transition-count and dwell-time statistics from one trajectory.

Parameters:
Return type:

None

initialize(x, weight, rng)[source]

Initialize sufficient statistics from one trajectory.

Parameters:
Return type:

None

seq_update(x, weights, estimate)[source]

Update sufficient statistics from encoded trajectory statistics.

Parameters:
Return type:

None

seq_initialize(x, weights, rng)[source]

Initialize sufficient statistics from encoded trajectory statistics.

Parameters:
Return type:

None

combine(suff_stat)[source]

Merge transition-count and dwell-time sufficient statistics.

Parameters:

suff_stat (tuple[ndarray, ndarray])

Return type:

ContinuousTimeMarkovChainAccumulator

value()[source]

Return copies of transition counts and dwell times.

Return type:

tuple[ndarray, ndarray]

from_value(x)[source]

Restore transition-count and dwell-time sufficient statistics.

Parameters:

x (tuple[ndarray, ndarray])

Return type:

ContinuousTimeMarkovChainAccumulator

scale(c)[source]

Scale accumulated sufficient statistics by a constant.

Parameters:

c (float)

Return type:

ContinuousTimeMarkovChainAccumulator

key_merge(stats_dict)[source]

Merge this accumulator into its configured shared statistic.

Parameters:

stats_dict (dict[str, Any])

Return type:

None

key_replace(stats_dict)[source]

Replace this accumulator with its configured shared statistic.

Parameters:

stats_dict (dict[str, Any])

Return type:

None

acc_to_encoder()[source]

Return the encoder compatible with CTMC sufficient statistics.

Return type:

ContinuousTimeMarkovChainDataEncoder

class ContinuousTimeMarkovChainAccumulatorFactory(num_states, name=None, keys=None)[source]

Bases: StatisticAccumulatorFactory

Create accumulators for CTMC transition-count and dwell-time statistics.

Parameters:
  • num_states (int)

  • name (str | None)

  • keys (str | None)

make()[source]

Create an empty CTMC accumulator.

Return type:

ContinuousTimeMarkovChainAccumulator

class ContinuousTimeMarkovChainEstimator(num_states, pseudo_count=None, initial_state=0, horizon=10.0, name=None, keys=None, prior_shape=None, prior_rate=None)[source]

Bases: ParameterEstimator

Closed-form independent-edge CTMC MLE or Gamma-prior MAP estimator.

For edge i -> j, an explicit Gamma(shape_ij, rate_ij) prior gives q_ij = (n_ij + shape_ij - 1) / (T_i + rate_ij). Shapes must be at least one so the finite non-negative MAP is well defined. The default shape=1, rate=0 recovers the MLE. The legacy pseudo_count=c spelling maps coherently to shape=1+c, rate=c on every off-diagonal edge; it cannot be mixed with explicit priors.

Parameters:
  • num_states (int)

  • pseudo_count (float | None)

  • initial_state (int)

  • horizon (float)

  • name (str | None)

  • keys (str | None)

  • prior_shape (Any | None)

  • prior_rate (Any | None)

accumulator_factory()[source]

Return a factory for CTMC sufficient-statistic accumulators.

Return type:

ContinuousTimeMarkovChainAccumulatorFactory

estimate(nobs, suff_stat)[source]

Estimate off-diagonal rates with the documented Gamma-prior MAP.

Parameters:
Return type:

ContinuousTimeMarkovChainDistribution

class ContinuousTimeMarkovChainDataEncoder(num_states)[source]

Bases: DataSequenceEncoder

Encode (s0, horizon, jumps) trajectories into per-trajectory (counts, dwell) sufficient statistics, dwell including each trajectory’s final right-censored interval out to its horizon.

Parameters:

num_states (int)

seq_encode(x)[source]

Encode trajectories as per-trajectory transition counts and dwell times.

Parameters:

x (Sequence[Any])

Return type:

list[tuple[ndarray, ndarray]]

row_count(x)[source]

Return the number of validated encoded trajectory rows.

Parameters:

x (Sequence[Any])

Return type:

int