Viterbi algorithm
Background
The Viterbi algorithm is dynamic programming for hidden Markov models: given a sequence of observations, it finds the single most likely sequence of hidden states. Rather than enumerating exponentially many state paths, it carries forward, for each state and time step, the probability of the best path ending there — together with a back-pointer so the optimal path can be recovered by tracing back.
Problem statement
Implement viterbi(obs, start_p, trans_p, emit_p) returning the most likely hidden-state path as a list of state indices.
For observations and states:
Store back[t][s] = argmax, then backtrack from .
Input
obs— list ofintobservation indices, length .start_p—np.ndarrayshape(N,), initial state probabilities .trans_p—np.ndarrayshape(N, N),trans_p[i, j]= .emit_p—np.ndarrayshape(N, M),emit_p[s, o]= .
Output
A list[int] of length : the most likely hidden-state sequence.
Examples
Example 1
States: 0 = Healthy, 1 = Fever
start_p = [0.6, 0.4]
trans_p = [[0.7, 0.3], [0.4, 0.6]]
emit_p = [[0.5, 0.4, 0.1], # Healthy: P(normal/cold/dizzy)
[0.1, 0.3, 0.6]] # Fever
obs = [0, 1, 2] # normal, cold, dizzy
Output: [0, 0, 1] # Healthy, Healthy, Fever
Explanation: the best path keeps the patient Healthy through the first two (mild) observations, then switches to Fever for "dizzy", which Fever emits with high probability.
Constraints
- Use a max (not a sum) at each step — Viterbi finds the single best path, not the total likelihood.
- Keep back-pointers and reconstruct the path by tracing from the best final state.
- Break ties by lowest state index (NumPy
argmaxbehavior).
Notes
- Replacing
max/argmaxwith a sum turns Viterbi into the forward algorithm, which computes the observation likelihood instead of the best path. - Production implementations run in log space (sums of log-probabilities) to avoid numerical underflow on long sequences.
This problem ships 4 hidden tests. They run in your browser via Pyodide — no backend, no submission queue. Press ▶ Run tests to execute.
- •Reference HMM (healthy/fever) example
- •Single observation picks argmax(start * emit)
- •Deterministic transitions force the path
- •Returns a path of the same length as the observations