/// <summary> /// Adds to this node all the choices of another node. /// </summary> public void Merge(GrammarRuleNode other) { var n = other.GetNumChoices(); for (var i = 0; i < n; i++) { AddChoice(other.GetChoice(i)); } }
/// <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); }
/// <summary> /// Returns a rule from the hashmap. If one does not exist, creates a rule with the /// given head and stores, then returns that. /// </summary> GrammarRuleNode GetRule(Hashtable rules, String head) { if (rules.ContainsKey(head)) { return((GrammarRuleNode)rules[head]); } else { var node = new GrammarRuleNode(head); rules[head] = node; return(node); } }
/// <summary> /// Parses the rules from a grammar and returns the resulting GrammarRuleNode root. /// </summary> public GrammarRuleNode ParseRules(IEvolutionState state, TextReader reader, GPFunctionSet gpfs) { _rules = new Hashtable(); try { String line; while ((line = reader.ReadLine()) != null) { GrammarRuleNode rule = ParseRule(state, new GELexer(line.Trim(), DEFAULT_REGEXES), gpfs); if (rule != null && _root == null) { _root = rule; } } } catch (IOException) { } // do nothing state.Output.ExitIfErrors(); return(_root); }
/// <summary> /// Parses a rule, one rule per line, from the lexer. /// Adds to the existing hashmap if there's already a rule there. /// </summary> GrammarRuleNode ParseRule(IEvolutionState state, IGELexer lexer, GPFunctionSet gpfs) { GrammarRuleNode retResult = null; string token = lexer.NextToken(); if (lexer.MatchingIndex == COMMENT) { return(null); //ignore the comment } if (lexer.MatchingIndex == RULE) //rule head, good, as expected... { lexer.NextToken(); if (lexer.MatchingIndex != EQUALS) { state.Output.Fatal("GE Grammar Error: Expecting equal sign after rule head: " + token); } retResult = GetRule(_rules, token); ParseProductions(state, retResult, lexer, gpfs); } else { state.Output.Fatal("GE Grammar Error - Unexpected token: Expecting rule head.: " + token); } return(retResult); // IMPLEMENTED // Need to parse the rule using a recursive descent parser // If there was an error, then try to call state.output.error(...). // // Don't merge into any existing rule -- I do that in parseRules below. Instead, just pull out // rules and hang them into your "new rule" as necessary. // Use getRule(rules, "<rulename>") to extract the rule representing the current rule name which you // can hang inside there as necessary. // // If you have to you can call state.output.fatal(...) which will terminate the program, // but piling up some errors might be useful. I'll handle the exitIfErors() in parseRules below // // Return null if there was no rule to parse (blank line or all comments) but no errors. // Also return null if you called state.output.error(...). }
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); } }
public override void Setup(IEvolutionState state, IParameter paramBase) { base.Setup(state, paramBase); var def = DefaultBase; var p = paramBase.Push(P_GPSPECIES); GPSpecies = (GPSpecies)(state.Parameters.GetInstanceForParameterEq(p, def.Push(P_GPSPECIES), typeof(GPSpecies))); GPSpecies.Setup(state, p); // check to make sure that our individual prototype is a GPIndividual if (!(I_Prototype is IntegerVectorIndividual)) { state.Output.Fatal("The Individual class for the Species " + GetType().Name + " must be a subclass of ge.GEIndividual.", paramBase); } ERCBank = Hashtable.Synchronized(new Hashtable()); // load the grammars, one per ADF tree var gpi = (GPIndividual)(GPSpecies.I_Prototype); var trees = gpi.Trees; var numGrammars = trees.Length; ParserPrototype = (GrammarParser)state.Parameters.GetInstanceForParameterEq( paramBase.Push(P_PARSER), def.Push(P_PARSER), typeof(GrammarParser)); Grammar = new GrammarRuleNode[numGrammars]; for (var i = 0; i < numGrammars; i++) { p = paramBase.Push(P_FILE); def = DefaultBase; //var grammarFile = state.Parameters.GetFile(p, def.Push(P_FILE).Push("" + i)); Stream grammarFile = state.Parameters.GetResource(p, def.Push(P_FILE).Push("" + i)); if (grammarFile == null) { state.Output.Fatal("Error retrieving grammar file(s): " + def + "." + P_FILE + "." + i + " is undefined."); } GPFunctionSet gpfs = trees[i].Constraints((GPInitializer)state.Initializer).FunctionSet; // now we need different parser object for each of the grammars, // why? see GrammarParser.java for details -- khaled GrammarParser[i] = (GrammarParser)ParserPrototype.Clone(); StreamReader reader = new StreamReader(grammarFile); Grammar[i] = GrammarParser[i].ParseRules(state, reader, gpfs); // Enumerate the grammar tree -- khaled GrammarParser[i].EnumerateGrammarTree(Grammar[i]); // Generate the predictive parse table -- khaled GrammarParser[i].PopulatePredictiveParseTable(Grammar[i]); try { reader.Close(); } catch (IOException e) { // do nothing } } // get the initialization scheme -- khaled InitScheme = state.Parameters.GetString(paramBase.Push(P_INITSCHEME), def.Push(P_INITSCHEME)); if (InitScheme != null && InitScheme.Equals("sensible")) { state.Output.WarnOnce("Using a \"hacked\" version of \"sensible initialization\""); } else { state.Output.WarnOnce("Using default GE initialization scheme"); } // setup the "passes" parameters int MAXIMUM_PASSES = 1024; Passes = state.Parameters.GetInt(paramBase.Push(P_PASSES), def.Push(P_PASSES), 1); if (Passes < 1 || Passes > MAXIMUM_PASSES) { state.Output.Fatal("Number of allowed passes must be >= 1 and <=" + MAXIMUM_PASSES + ", likely small, such as <= 16.", paramBase.Push(P_PASSES), def.Push(P_PASSES)); } int oldpasses = Passes; Passes = NextPowerOfTwo(Passes); if (oldpasses != Passes) { state.Output.Warning("Number of allowed passes must be a power of 2. Bumping from " + oldpasses + " to " + Passes, paramBase.Push(P_PASSES), def.Push(P_PASSES)); } }