using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Viterbi
{
class Program
{
//Weather states
static String HEALTHY = "Healthy";
static String FEVER = "Fever";
//Dependable actions (observations)
static String DIZZY = "dizzy";
static String COLD = "cold";
static String NORMAL = "normal";
static void Main(string[] args)
{
//initialize our arrays of states and observations
String[] states = { HEALTHY, FEVER };
String[] observations = { DIZZY, COLD, NORMAL };
var start_probability = new Dictionary<String, float>();
start_probability.Add(HEALTHY, 0.6f);
start_probability.Add(FEVER, 0.4f);
//Transition probability
var transition_probability = new Dictionary<String, Dictionary<String, float>>();
var t1 = new Dictionary<String, float>();
t1.Add(HEALTHY, 0.7f);
t1.Add(FEVER, 0.3f);
Dictionary<String, float> t2 = new Dictionary<String, float>();
t2.Add(HEALTHY, 0.4f);
t2.Add(FEVER, 0.6f);
transition_probability.Add(HEALTHY, t1);
transition_probability.Add(FEVER, t2);
//emission_probability
var emission_probability = new Dictionary<String, Dictionary<String, float>>();
var e1 = new Dictionary<String, float>();
e1.Add(DIZZY, 0.1f);
e1.Add(COLD, 0.4f);
e1.Add(NORMAL, 0.5f);
Dictionary<String, float> e2 = new Dictionary<String, float>();
e2.Add(DIZZY, 0.6f);
e2.Add(COLD, 0.3f);
e2.Add(NORMAL, 0.1f);
emission_probability.Add(HEALTHY, e1);
emission_probability.Add(FEVER, e2);
Object[] ret = forward_viterbi(observations, states, start_probability, transition_probability, emission_probability);
Console.WriteLine((float)ret[0]);
Console.WriteLine((String)ret[1]);
Console.WriteLine((float)ret[2]);
Console.ReadLine();
}
public static Object[] forward_viterbi(String[] obs, String[] states, Dictionary<String, float> start_p, Dictionary<String, Dictionary<String, float>> trans_p, Dictionary<String, Dictionary<String, float>> emit_p)
{
var T = new Dictionary<String, Object[]>();
foreach (String state in states)
{
T.Add(state, new Object[] { start_p[state], state, start_p[state] });
}
foreach (String output in obs)
{
var U = new Dictionary<String, Object[]>();
foreach (String next_state in states)
{
float total = 0;
String argmax = "";
float valmax = 0;
float prob = 1;
String v_path = "";
float v_prob = 1;
foreach (String source_state in states)
{
Object[] objs = T[source_state];
prob = ((float)objs[0]);
v_path = (String)objs[1];
v_prob = ((float)objs[2]);
float p = emit_p[source_state][output] * trans_p[source_state][next_state];
prob *= p;
v_prob *= p;
total += prob;
if (v_prob > valmax)
{
argmax = v_path + "," + next_state;
valmax = v_prob;
}
}
U.Add(next_state, new Object[] { total, argmax, valmax });
}
T = U;
}
float xtotal = 0;
String xargmax = "";
float xvalmax = 0;
float xprob;
String xv_path;
float xv_prob;
foreach (String state in states)
{
Object[] objs = T[state];
xprob = ((float)objs[0]);
xv_path = ((String)objs[1]);
xv_prob = ((float)objs[2]);
xtotal += xprob;
if (xv_prob > xvalmax)
{
xargmax = xv_path;
xvalmax = xv_prob;
}
}
return new Object[] { xtotal, xargmax, xvalmax };
}
}
}