matthiasm@43: matthiasm@43: #include "viterbi.h" matthiasm@43: #include matthiasm@43: matthiasm@106: std::vector ViterbiPath(std::vector init, std::vector > trans, std::vector > obs, double *delta, vector *scale) { matthiasm@43: matthiasm@122: int nState = init.size(); matthiasm@122: int nFrame = obs.size(); matthiasm@43: matthiasm@43: // check for consistency matthiasm@122: if ((int)trans[0].size() != nState || (int)trans.size() != nState || (int)obs[0].size() != nState) { matthiasm@43: cerr << "ERROR: matrix sizes inconsistent." << endl; matthiasm@43: } mail@119: matthiasm@43: vector > psi; // "matrix" of remembered indices of the best transitions matthiasm@43: vector path = vector(nFrame, nState-1); // the final output path (current assignment arbitrary, makes sense only for Chordino, where nChord-1 is the "no chord" label) matthiasm@43: matthiasm@43: double deltasum = 0; matthiasm@43: matthiasm@43: /* initialise first frame */ matthiasm@122: for (int iState = 0; iState < nState; ++iState) { matthiasm@94: delta[iState] = init[iState] * obs[0][iState]; matthiasm@50: deltasum += delta[iState]; matthiasm@43: } matthiasm@122: for (int iState = 0; iState < nState; ++iState) delta[iState] /= deltasum; // normalise (scale) matthiasm@106: scale->push_back(1.0/deltasum); matthiasm@43: psi.push_back(vector(nState,0)); matthiasm@43: matthiasm@43: /* rest of the forward step */ matthiasm@122: for (int iFrame = 1; iFrame < nFrame; ++iFrame) { matthiasm@43: deltasum = 0; matthiasm@43: psi.push_back(vector(nState,0)); mail@119: /* every state wants to know which previous state suits it best */ matthiasm@122: for (int jState = 0; jState < nState; ++jState) { matthiasm@43: int bestState = nState - 1; matthiasm@43: double bestValue = 0; matthiasm@44: if (obs[iFrame][jState] > 0) { matthiasm@122: for (int iState = 0; iState < nState; ++iState) { matthiasm@50: double currentValue = delta[(iFrame-1) * nState + iState] * trans[iState][jState]; matthiasm@44: if (currentValue > bestValue) { matthiasm@44: bestValue = currentValue; matthiasm@44: bestState = iState; matthiasm@44: } matthiasm@43: } matthiasm@43: } mail@119: matthiasm@50: delta[iFrame * nState + jState] = bestValue * obs[iFrame][jState]; matthiasm@50: deltasum += delta[iFrame * nState + jState]; matthiasm@43: psi[iFrame][jState] = bestState; matthiasm@43: } matthiasm@43: if (deltasum > 0) { matthiasm@122: for (int iState = 0; iState < nState; ++iState) { matthiasm@50: delta[iFrame * nState + iState] /= deltasum; // normalise (scale) matthiasm@43: } matthiasm@106: scale->push_back(1.0/deltasum); matthiasm@43: } else { matthiasm@122: for (int iState = 0; iState < nState; ++iState) { matthiasm@50: delta[iFrame * nState + iState] = 1.0/nState; matthiasm@43: } matthiasm@106: scale->push_back(1.0); matthiasm@43: } matthiasm@43: matthiasm@43: } matthiasm@43: matthiasm@43: /* initialise backward step */ matthiasm@109: double bestValue = 0; matthiasm@122: for (int iState = 0; iState < nState; ++iState) { matthiasm@50: double currentValue = delta[(nFrame-1) * nState + iState]; matthiasm@109: if (currentValue > bestValue) { matthiasm@43: bestValue = currentValue; matthiasm@43: path[nFrame-1] = iState; matthiasm@43: } matthiasm@43: } matthiasm@43: matthiasm@43: /* rest of backward step */ matthiasm@43: for (int iFrame = nFrame-2; iFrame > -1; --iFrame) { matthiasm@43: path[iFrame] = psi[iFrame+1][path[iFrame+1]]; matthiasm@43: } matthiasm@43: matthiasm@43: return path; matthiasm@43: }