function Viterbi(data) {
var V = [{}];
var path = {};
for(var i=0;i<data.states.length;i++) {
var state = data.states[i];
V[0][state] = data.start_probability[state] * data.emission_probability[state][data.observations[0]];
path[state] = [state];
}
for(var t=1;t<data.observations.length;t++) {
V.push({});
var newpath = {};
for(var i=0;i<data.states.length;i++) {
var state = data.states[i];
var max = [0,null];
for(var j=0;j<data.states.length;j++) {
var state0 = data.states[j];
var calc = V[t-1][state0]
* data.transition_probability[state0][state]
* data.emission_probability[state][data.observations[t]];
if(calc > max[0])
max = [calc,state0];
}
V[t][state] = max[0];
newpath[state] = path[max[1]].concat(state);
}
path = newpath;
}
var max = [0,null];
for(var i=0;i<data.states.length;i++) {
var state = data.states[i];
var calc = V[data.observations.length-1][state];
if(calc > max[0]) max = [calc,state];
}
return [max[0], path[max[1]]];
}