/*
states = ('Rainy', 'Sunny')
 
observations = ('walk', 'shop', 'clean')
 
start_probability = {'Rainy': 0.6, 'Sunny': 0.4}
 
transition_probability = {
   'Rainy' : {'Rainy': 0.7, 'Sunny': 0.3},
   'Sunny' : {'Rainy': 0.4, 'Sunny': 0.6},
   }
 
emission_probability = {
   'Rainy' : {'walk': 0.1, 'shop': 0.4, 'clean': 0.5},
   'Sunny' : {'walk': 0.6, 'shop': 0.3, 'clean': 0.1},
   }
*/

#define MAX_OBS 100 // we don't need one hundreds, but feel comfortable
#define N_STATES 2	// we only have two states
#define N_EMITS 3	//

#include <stdio.h> // printf
#include <stdlib.h> // itoa
#include <string.h> // memset
#include <conio.h> // getch

enum {walk, shop, clean}; // emissions
enum {Rainy, Sunny}; // states

double V[MAX_OBS][N_STATES]; // V[t][k] is the probability of the most probable state sequence responsible for the first t+1 observations.
double start_p[N_STATES] = {0.6, 0.4}; // start probability
double trans_p[N_STATES][N_STATES] = {0.7, 0.3, 0.4, 0.6}; // transmisstion probability
double emit_p[N_STATES][N_EMITS] = {0.1, 0.4, 0.5, 0.6, 0.3, 0.1}; // emission probability
int obs[] = {walk, shop, clean}; // orginal observation
//int obs[] = {walk, shop, clean, walk, shop, clean, clean, walk, shop, clean}; // for testing to compare the same result to the output from python version, it worked.
int states[N_STATES] = {Rainy, Sunny};
char path[][MAX_OBS] = {"", ""};
char newpath[][MAX_OBS] = {"", ""};

void viterbi()
{
	int nobs, nstates;
	int t, y, y0;
	double prob, prob_max;
	int state_max;
	char buf[10]; // for hold a integer

	// Initialize
	nobs = sizeof(obs)/sizeof(obs[0]);
	nstates = sizeof(states)/sizeof(states[0]);
	for(y=0; y<nstates; y++)
	{
		V[0][y] = start_p[y] * emit_p[y][obs[0]]; // V[0]k]
		strcat(path[y], itoa(y, buf, 10)); // path inizilize
	}
	
	// Run Viterbi for t > 0
	for(t=1; t<nobs; t++)
	{
		for(y=0; y<nstates; y++) // y0->y
		{
			prob_max = 0;
			state_max = 0;
			for(y0=0; y0<nstates; y0++) // find max prob and state
			{
				prob = V[t-1][y0] * trans_p[y0][y] * emit_p[y][obs[t]];
				if(prob > prob_max) // find max prob
				{
					prob_max = prob;
					state_max = y0; // update the max state number
				}
			}
			// update the maximum values
			V[t][y] = prob_max;
			strcpy(newpath[y], path[state_max]); 
			strcat(newpath[y], itoa(y, buf, 10)); // newpath = max_path + current_state
		}
		// path update
		for(y=0; y<nstates; y++)
			strcpy(path[y], newpath[y]);
	}

	// Done. let's see the result
	prob_max = 0;
	state_max = 0;
	for(y=0; y<nstates; y++)
	{
		if(prob > prob_max)
		{
			prob_max = prob;
			state_max = y;
		}
	}

	printf("Max prb %f, path = %s", V[nobs-1][state_max], path[state_max]);
}

void main()
{
	viterbi();
	getch();
}
 
wiki_viterbi.c.txt · Last modified: 2011/11/09 13:38 by admin
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki