mixle.enumeration.hmm_paths module¶
Descending-probability enumeration AND unranking of HMM state paths (list-Viterbi / A* + count-DP).
The count-budget index handles the decomposable families (Sequence / Composite / MarkovChain). An HMM is non-decomposable – the latent state couples emissions across time – so it is not served by the count semiring. Two complementary tools live here:
hmm_best_paths()– exact, lazy enumeration in nonincreasing joint log-probability by A* search with the backward Viterbi value as an admissible (in fact tight) heuristic. The right tool for the head, but rankkcostsO(k)expansions: there is no random access.HMMPathIndex– the quantized precomputation structure: a forward count DP over integer score buckets (oneO(T * K^2 * W)build,W= bit budget in fine buckets) that then answerscount/unrank/threshold/mass_aboveinO(T * K)per query – random access into the ranked path list at any depth, which A* structurally cannot do. Ordering is exact up to the fine bucket width (bin_width_bits / oversamplebits; raiseoversampleto sharpen); every returned path carries its exact joint log-probability.
For a path z_{1..T} the joint log-probability of the latent path with the observed emissions is
log_pi[z_1] + log_b[0, z_1] + sum_{t>1} (log_A[z_{t-1}, z_t] + log_b[t, z_t]) where log_b[t, k]
is the emission log-likelihood log p(x_t | z_t = k). The completion heuristic
h[t, s] = max over z_{t+1..T} of the remaining transition+emission score is computed once by a
backward max-product pass, so g + h is the exact score of the best path through (t, s) – an
admissible bound that makes best-first emit paths in exactly nonincreasing joint log-probability.
- hmm_best_paths(log_pi, log_A, log_b, k=None)[source]
Enumerate HMM state paths in nonincreasing joint log-probability.
- Parameters:
log_pi (ndarray) –
(K,)log initial-state distribution.log_A (ndarray) –
(K, K)log transition matrix (rowj-> columnkislog p(z_t=k | z_{t-1}=j)).log_b (ndarray) –
(T, K)per-position emission log-likelihoodslog p(x_t | z_t=k).k (int | None) – stop after the
kbest paths;Noneenumerates allK**Tlazily.
- Yields:
(path, joint_log_prob)withpatha length-Ttuple of state indices, highest first. The first yield is the Viterbi (MAP) path.- Return type:
- class CertifiedCount(value, certified)[source]
Bases:
objectA path count from
HMMPathIndex, honest about whether it is the complete answer.HMMPathIndexis built to a finite quantized-bucket budget; when a query needs to look beyond that budget on a genuinely truncated index, the stored tables cannot answer it exactly – paths beyond the budget were never counted. Returning the in-budget count as a bare number would look identical to a complete answer with no way to tell the two apart (MXR-080-0230); this return type makes the distinction explicit instead.- value
the count of indexed (in-budget) paths satisfying the query. Always a sound LOWER bound on the true count – every path counted here genuinely qualifies, so this can only under-, never over-, state the truth. Exact (up to the ordinary quantization smear documented on
HMMPathIndex.count(), unrelated to truncation) whencertified.- Type:
- certified
True when
valueis provably the complete answer – no path beyond the built budget could also qualify. False when the query reaches beyond the built budget on a truncated index, so additional qualifying paths may exist beyondvalue.- Type:
- class CertifiedMassBound(lower, upper, certified)[source]
Bases:
objectA joint probability/density mass bracket from
HMMPathIndex.mass_above().- lower
sound lower bound on the true mass above the threshold. Valid regardless of
certified– paths beyond a truncated budget can only ADD mass, never invalidate a lower bound derived purely from the paths this index actually has.- Type:
- upper
sound upper bound when
certified;math.infwhen not. A truncated index’s stored histogram cannot certify any FINITE upper bound on mass that might live beyond the built budget without deepening it – reporting the in-budget figure anyway would be an unsound bound wearing a sound bound’s shape (MXR-080-0230).- Type:
- certified
True when both bounds are provably sound answers to the exact query; False when the threshold reaches beyond the built budget on a truncated index.
- Type:
- class HMMPathIndex(log_pi, log_A, log_b, *, bin_width_bits=1.0, oversample=8, budget_bits=None)[source]
Bases:
objectQuantized random-access index over an HMM’s state paths for one observation sequence.
log_pi/log_A/log_bare validated at construction (MXR-080-0228): shapes must be(K,)/(K, K)/(T, K)with a consistentK, every score must be finite-or-impossible (-inf, never NaN or+inf), andlog_pi/log_Amust describe at most one unit of total probability each (sub-stochastic rows – e.g. from forbidding individual transitions without renormalizing – are allowed;log_bis an emission LOG-LIKELIHOOD and may be positive/unnormalized – seehmm_best_paths()). An all-impossible initial vector or a position with no finite score at all is not an error: it is represented explicitly viaempty_support(andtotal()reporting a certified zero), rather than crashing.Precompute (once,
O(T * K^2 * W)): quantize every step score –log_pi[s] + log_b[0, s]andlog_A[s, s'] + log_b[t, s'], one floor per step so the accumulated smear is at mostTfine buckets – and run a forward count DP:C_t[s']is the histogram, over integer total-score buckets, of the number of length-t+1prefixes ending in states'. Counts are EXACT Python arbitrary-precision integers, never float64 (MXR-080-0229): the number of paths isK**T, which exceeds float64’s 2**53 exact-integer range for even modestT, and every operation this DP performs on a count is addition – no rounding is ever actually needed here.Query (each
O(T * K)):unrank(i)walks the stored tables backward – pick the final state whose bucket count covers the offset, then repeatedly the predecessor whose shifted prefix bucket does – returning thei-th best path by quantized score and its exact joint log-probability, exactly for anyiwithin the built support.total/count/mass_aboveread the pooled final histogram and report aCertifiedCount/CertifiedMassBound: a query that reaches beyond a truncated index’s built budget gets a sound bound withcertified=Falserather than a bare number indistinguishable from a complete answer (MXR-080-0230).Ordering contract: paths are ordered by their quantized bucket (width
bin_width_bits/oversamplebits); within a bucket the order is deterministic but unspecified – exactly the count-index semantics elsewhere inmixle.enumeration.hmm_best_paths()remains the exact-order tool for the head; this index is the random-access tool for depth (rank 1e6 costs one table walk, not 1e6 A* expansions).- Parameters:
- bucket_of(log_joint)[source]
The index’s bucket frame for a true joint score (bits behind the per-position optimum).
- total()[source]
Number of state paths within the budget (== K**T when nothing truncated; exact integer count).
certifiedis False when the index is truncated:valueis then only a sound LOWER bound on the true number of paths – some paths exceed the built budget and were never counted (MXR-080-0230). Deepenbudget_bits(or omit it for the default, which is sized to cover every finite-score path) to certify a larger/complete total.- Return type:
CertifiedCount
- count(min_log_joint)[source]
How many paths have quantized joint log-probability at least
min_log_joint.Counts every true qualifier (the structural bucket never over-states a path’s bits) plus at most the paths within the
T-floor smear band below the threshold – this ordinary quantization smear applies regardless ofcertified.certifiedis True whenever this query’s own bucket stays within the built budget: bucket costs only accumulate along a path (never decrease), so every bucket the index does hold is a complete, exact count regardless of the index’s globaltruncatedflag. It is False only when the query needs to look beyond the built budget on a genuinely truncated index (MXR-080-0230):valueis then a sound LOWER bound (every indexed path is a real qualifier), not the complete answer – more qualifying paths may live beyond the budget.- Parameters:
min_log_joint (float)
- Return type:
CertifiedCount
- mass_above(min_log_joint)[source]
A bracket on the total joint probability/density of paths above the threshold.
Bucket arithmetic with the
T-floor smear: a path in bucketbcarries betweenexp(total_offset) * 2**-((b + T) / fpb)andexp(total_offset) * 2**-(b / fpb)of joint mass (the offset restores the per-position shift, so unnormalized emission likelihoods work).certifiedfollows the same rule ascount(): True unless this query reaches beyond the built budget on a truncated index. When not certified,lowerremains a sound bound (unindexed paths can only add mass) butupperis replaced withmath.inf– the in-budget figure is not a valid upper bound once qualifying mass may exist beyond the budget, so reporting it as one would be unsound, not just imprecise (MXR-080-0230).- Parameters:
min_log_joint (float)
- Return type:
CertifiedMassBound
- unrank(i)[source]
The
i-th best state path by quantized score (0-based) and its exact joint log-probability.One backward table walk –
O(T * K)– regardless of how deepiis. Every table read along the walk is an exact Python int (MXR-080-0229), soiresolves exactly for supports far beyond float64’s 2**53 exact-integer range – adjacent ranks never alias to the same stored offset the way they would under float64 accumulation.
- threshold(rank)[source]
Exact joint log-probability of the
rank-th best (quantized-order) path.