private static List<Production> Nullate(Production originalProduction, Dictionary<Nonterminal, double> nullableProbabilities) {
var results = new List<Production>();
results.Add(originalProduction);
if (originalProduction.IsEmpty) {
return results;
}
for (int i = originalProduction.Rhs.Count - 1; i >= 0; i--) {
var newResults = new List<Production>();
var toRemove = new List<Production>();
foreach (var production in results) {
var word = production.Rhs[i];
var nt = word as Nonterminal;
if (nt == null) { continue; }
if (!nullableProbabilities.ContainsKey(nt)) {
continue;
}
// var with = production.Clone();
var without = production.DeepClone();
without.Rhs.RemoveAt(i);
var chanceNull = nullableProbabilities[nt];
var newWithoutWeight = without.Weight * chanceNull;
var newWithWeight = production.Weight * (1.0 - chanceNull);
if (newWithoutWeight > 0.0) {
without.Weight = newWithoutWeight;
newResults.Add(without);
}
if (newWithWeight <= 0.0) {
toRemove.Add(production);
} else {
production.Weight = newWithWeight;
}
}
results.AddRange(newResults);
// TODO: we should just make it so that if a weight is set to 0, the production gets removed from the grammar automatically, and that operation should be fast
results.RemoveMany(toRemove);
}
// NullateAux(production, nullableSet, 0, result);
if (results.Count == 0) {
return results;
}
// Get rid of productions with zero weight
//for (int i = results.Count - 1; i >= 0; i--) {
// var result = results[i];
// if (result.Weight == 0.0) {
// results.RemoveAt(i);
// }
//}
return results;
}