public double Evaluate(double[][] observations)
{
int T = observations.Length;
double[,] lnFwd = new double[States, T];
double[][] output = new double[States][];
// 1. Initialization
output[0] = Function(-1, observations[0]);
for (int i = 0; i < States; i++)
lnFwd[0, i] = Math.Log(output[0][i]);
// 2. Induction
for (int t = 1; t < T; t++)
{
double[] x = observations[t];
for (int i = 0; i < States; i++)
output[i] = Function(i, x);
for (int i = 0; i < States; i++)
{
double sum = Double.NegativeInfinity;
for (int j = 0; j < States; j++)
sum = Special.LogSum(sum, lnFwd[t - 1, j] + output[j][i]);
lnFwd[t, i] = sum;
}
}
double logLikelihood = Double.NegativeInfinity;
for (int i = 0; i < States; i++)
logLikelihood = Special.LogSum(logLikelihood, lnFwd[T - 1, i]);
return logLikelihood;
}