private static double GetProductionProbability(Production production, Dictionary<Nonterminal, int> nonterminalToIndex, double[] previousEstimates) {
if (production.Rhs.Count == 0) {
return 1.0;
}
// if it contains a terminal, then it always is non-empty
if (!production.Rhs.OnlyNonterminals()) {
return 0.0;
}
var product = 1.0;
foreach (var word in production.Rhs) {
var nt = (Nonterminal)word;
var rhsIndex = nonterminalToIndex[nt];
var previous = previousEstimates[rhsIndex];
// if this is the first iteration, we assume that the previous values were 100% chance of yielding null
if (previous == _magicStartProbability) {
previous = 1.0;
}
product *= previous;
}
if (double.IsNaN(product)) {
throw new Exception("Didn't expect to get NaN probability");
}
return product;
}