/// <summary> /// Parses each of a rule's production choices. /// </summary> void ParseProductions(IEvolutionState state, GrammarRuleNode retResult, IGELexer lexer, GPFunctionSet gpfs) { do { var token = lexer.NextToken(); if (lexer.MatchingIndex == RULE) { retResult.AddChoice(GetRule(_rules, token)); token = lexer.NextToken(); } else { if (lexer.MatchingIndex != LPAREN) //first expect '(' { state.Output.Fatal("GE Grammar Error - Unexpected token for rule: " + retResult.Head + "Expecting '('."); } token = lexer.NextToken(); if (lexer.MatchingIndex != FUNCTION) //now expecting function { state.Output.Fatal("GE Grammar Error - Expecting a function name after first '(' for rule: " + retResult.Head + " Error: " + token); } else { if (!gpfs.NodesByName.ContainsKey(token)) { state.Output.Fatal("GPNode " + token + " is not defined in the function set."); } var grammarfuncnode = new GrammarFunctionNode(gpfs, token); token = lexer.NextToken(); while (lexer.MatchingIndex != RPAREN) { if (lexer.MatchingIndex != RULE) //this better be the name of a rule node { state.Output.Fatal( "GE Grammar Error - Expecting a rule name as argument for function definition: " + grammarfuncnode.Head + " Error on : " + token); } grammarfuncnode.AddArgument(GetRule(_rules, token)); token = lexer.NextToken(); } retResult.AddChoice(grammarfuncnode); } //after right paren, should see either '|' or newline token = lexer.NextToken(); if (lexer.MatchingIndex != PIPE && lexer.MatchingIndex != Constants.GE_LEXER_FAILURE) { state.Output.Fatal("GE Grammar Error - Expecting either '|' delimiter or newline. Error on : " + token); } } } while (lexer.MatchingIndex == PIPE); }
GPNode MakeSubtree(IList <int> index, IList <int> genome, IEvolutionState es, GPFunctionSet gpfs, GrammarRuleNode rule, int treeNum, int threadNum, IDictionary <int, GPNode> ercMapsForFancyPrint, IGPNodeParent parent, byte argPosition) { //have we exceeded the length of the genome? No point in going further. if (index[0] >= genome.Count) { throw new BigTreeException(); } //expand the rule with the chromosome to get a body element int i; //non existant rule got passed in if (rule == null) { es.Output.Fatal("An undefined rule exists within the grammar."); } //more than one rule to consider, pick one based off the genome, and consume the current gene // avoid mod operation as much as possible if (rule.GetNumChoices() > 1) { i = (genome[index[0]] - (int)GetMinGene(index[0])) % rule.GetNumChoices(); } else { i = 0; } index[0]++; GrammarNode choice = rule.GetChoice(i); // if body is another rule head //look up rule if (choice is GrammarRuleNode) { var nextrule = (GrammarRuleNode)choice; return(MakeSubtree(index, genome, es, gpfs, nextrule, treeNum, threadNum, ercMapsForFancyPrint, parent, argPosition)); } else //handle functions { GrammarFunctionNode funcgrammarnode = (GrammarFunctionNode)choice; GPNode validNode = funcgrammarnode.GetGPNodePrototype(); int numChildren = validNode.Children.Length; //index 0 is the node itself int numChildrenInGrammar = funcgrammarnode.GetNumArguments(); //does the grammar contain the correct amount of children that the GPNode requires if (numChildren != numChildrenInGrammar) { es.Output.Fatal("GPNode " + validNode.ToStringForHumans() + " requires " + numChildren + " children. " + numChildrenInGrammar + " children found in the grammar."); } //check to see if it is an ERC node if (validNode is ERC) { // have we exceeded the length of the genome? No point in going further. if (index[0] >= genome.Count) { throw new BigTreeException(); } // ** do we actually need to maintain two vlaues ? key and originalVal ? // ** there is no problem if we use the originalVal for both ERCBank and // ** ercMapsForFancyPrint, moreover, this will also make the reverse-mapping case // ** easier -- khaled // these below two lines are from the original code -- // key for ERC hashtable look ups is the current index within the genome. Consume it. //int key = genome[index[0]] - (int)GetMinGene(index[0]); //int originalVal = genome[index[0]]; // this single line is khaled's mod -- int genomeVal = genome[index[0]]; index[0]++; validNode = ObtainERC(es, genomeVal, threadNum, validNode, ercMapsForFancyPrint); } //non ERC node else { validNode = validNode.LightClone(); } //get the rest. for (int j = 0, childNumber = 0; j < funcgrammarnode.GetNumArguments(); j++) { //get and link children to the current GPNode validNode.Children[childNumber] = MakeSubtree(index, genome, es, gpfs, (GrammarRuleNode)funcgrammarnode.GetArgument(j), treeNum, threadNum, ercMapsForFancyPrint, validNode, (byte)childNumber); if (validNode.Children[childNumber] == null) { return(null); } childNumber++; } validNode.ArgPosition = argPosition; validNode.Parent = parent; return(validNode); } }