/// <summary> /// Loads an ERC from the ERCBank given the value in the genome. /// If there is no such ERC, then one is created and randomized, then added to the bank. /// The point of this mechanism is to enable ERCs to appear in multiple places in a GPTree. /// </summary> public GPNode ObtainERC(IEvolutionState state, int genomeVal, int threadnum, GPNode node, IDictionary <int, GPNode> ercMapsForFancyPrint) { // TODO: BRS: Questionable key here because of Java -> C# conversion (hash codes) var ercList = (IList <GPNode>)ERCBank[genomeVal]; if (ercList == null) { ercList = new List <GPNode>(); ERCBank[genomeVal] = ercList; } GPNode dummy; // search array list for an ERC of the same type we want for (var i = 0; i < ercList.Count; i++) { dummy = ercList[i]; // ERC was found inside the list if (dummy.NodeEquivalentTo(node)) { if (ercMapsForFancyPrint != null) { ercMapsForFancyPrint[genomeVal] = dummy; } return(dummy.LightClone()); } } // erc was not found in the array list lets make one node = node.LightClone(); node.ResetNode(state, threadnum); ercList.Add(node); if (ercMapsForFancyPrint != null) { ercMapsForFancyPrint[genomeVal] = node; } return(node); }
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); } }