/// <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)); } }
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); } }