public CNFGrammar NextCNF(int numNonterminals, int numProductions, IList<Terminal> terminals, bool useNull = true) {
if (numNonterminals < 1) {
throw new ArgumentOutOfRangeException("Need at least one nonterminal");
}
var start = RandomNonterminal(1);
double producesEmptyWeight = 0.0;
if (useNull) {
if (numProductions > 0) {
if (_rand.Next(2) == 1) {
producesEmptyWeight = 100 * _rand.NextDouble();
numProductions--;
}
}
}
var numNontermProductions = _rand.Next(numProductions);
var numTermProductions = numProductions - numNontermProductions;
var productions = new List<Production>();
for (int i = 0; i < numNontermProductions; i++) {
productions.Add(NextCNFNonterminalProduction(numNonterminals));
}
for (int i = 0; i < numTermProductions; i++) {
var terminal = RandomTerminal(terminals);
productions.Add(NextCNFTerminalProduction(numNonterminals, terminals, terminal));
}
productions.Add(new Production(start, new Sentence(), producesEmptyWeight));
return new CNFGrammar(productions, start);
}