/// <summary> /// Internal method to get the mutation done. This method returns a reference /// to the root node of the branch. If the first node is selected for mutation, /// that node will change, therefore, it needs to be updated in the calling method. /// </summary> /// <param name="BranchRoot">Root node of the recursion branch we are mutating</param> /// <param name="CountNodes">Number of nodes in the branch</param> /// <param name="DepthInitial">Initial depth the branch was created with</param> private void Mutate(ref GPNode BranchRoot, int NodeCount, int DepthInitial) { // // Step 1: Select a node randomly int NodeLabel = GPUtilities.rngNextInt(NodeCount); // // Step 2: Find this node, its parent and which child of the parent it is GPProgramBranchFactory.FindResult find = FindNode(null, BranchRoot, NodeLabel); // // Step 3: Build a new subtree that will replace the selected node GPNode SubTreeNew = BuildInternal(GPEnums.TreeBuild.Grow, DepthInitial, BranchRoot == m_BranchADR.m_RBB); // // If the parent of the result is null, then we are replacing the root node, // otherwise we are replacing a child of the parent. if (find.Parent == null) { BranchRoot = SubTreeNew; } else { find.Parent.Children[find.ChildNumber] = SubTreeNew; } }
/// <summary> /// Counts the number of leaf nodes in the branch /// </summary> /// <param name="node">Root of the tree</param> /// <returns>Number of leaf nodes in the branch</returns> protected ushort DoCountLeafNodes(GPNode node) { if (node == null) { return(0); } // // If a terminal node, that's it, plus, it's also a leaf node by definition if (node is GPNodeTerminal) { return(1); } // // Otherwise, we have a functional node, so count up leafs in the children GPNodeFunction nodeFunc = (GPNodeFunction)node; ushort countChild = 0; for (int nChild = 0; nChild < nodeFunc.Children.Count; nChild++) { countChild += DoCountLeafNodes(nodeFunc.Children[nChild]); } // // If this is a functional node with no children, it is a terminal, so count it. if (nodeFunc.Children.Count == 0) { return((ushort)(countChild + 1)); } return(countChild); }
/// <summary> /// Converts the tree into an array based representation. The purpose /// of the array representation is that it takes up FAR LESS memory and /// allows for a larger popuplation. This comes at the expense of some /// compute time, however. /// </summary> /// <param name="FunctionSet"></param> public void ConvertToArray(IGPFunctionSet FunctionSet) { // // If the array already exists, reuse it. The reason it would already exist // is if the conversion to a tree was don't for fitness computations and not // for altering the tree sturcture. A simple optimization technique if (m_TreeArrayNew != null) { m_Root = null; return; } // // Allocate the nodes we need try { m_TreeArrayNew = new List <byte>(m_CountNodes); } catch (Exception) { System.Console.WriteLine("ConvertToArray: " + m_CountNodes); return; } // // Use a recursive technique to work through the nodes and get // them stored into the array m_ArrayPos = 0; StoreNode(m_Root, FunctionSet); // // Get rid of the tree m_Root = null; }
/// <summary> /// Computes the max depth of the tree /// </summary> /// <param name="node">Root of the tree</param> /// <returns>Depth of the tree</returns> protected int ComputeDepth(GPNode node) { int nMaxChild = 0; if (node == null) { return(0); } // // Only need to probe further if we have a function node with children if (node is GPNodeFunction) { GPNodeFunction nodeFunc = (GPNodeFunction)node; // // Determine the child with the maximum depth for (int nChild = 0; nChild < nodeFunc.Children.Count; nChild++) { int nCurrentChild = ComputeDepth(nodeFunc.Children[nChild]); if (nCurrentChild > nMaxChild) { nMaxChild = nCurrentChild; } } } return(nMaxChild + 1); // +1 is the current node depth }
/// <summary> /// This method randomly creates a new GPNode appropriate for an ADR branch. /// </summary> private GPNode CreateNode(GPEnums.TreeBuild TreeBuild, int Depth, bool UseRecursion) { // // For the 'full' type growth, we want to select a function // at every node except for the final leaf nodes, which will be chosen // from the list of terminals. if (TreeBuild == GPEnums.TreeBuild.Full && Depth > 0) { // // Allow the recursion to call ADFs // TODO: Add ability to call ADLs (low priority) return(CreateNodeFunction(false, 0, false, 0, UseRecursion, 0)); } // // If the depth is 0, then this MUST be a terminal node, no choice if (Depth == 0) { return(CreateNodeTerminal()); } // // We should only get here for the 'grow' type approach, here we make a uniform // random selection from among the combined list of operations and terminals // to decide the node type. double rnd = GPUtilities.rngNextDouble(); double cumulative = m_Config.Profile.ProbabilityTerminalD; // // Start with terminal probability if (rnd <= cumulative) { return(CreateNodeTerminal()); } // // Next, probability of it being a function cumulative += m_Config.Profile.ProbabilityFunctionD; if (rnd <= cumulative) { // // Same note as above - can allow other ADFs to be called from here //return CreateNodeFunction(true, 0, false, 0, true,0); // TODO: Add ability to call ADLs (low priority) GPNode node = CreateNodeFunction(false, 0, false, 0, UseRecursion, 0); if (node is GPNodeFunctionADR) { return(node); } return(node); } // // Throw an exception that something really, really bad happened! return(null); }
/// <summary> /// Counts the number of nodes in the branch. While the nodes are /// being counted, give each one a label so it can be later used for /// searching. This method also takes care of getting the count of ADF /// and ADL nodes updated. /// </summary> /// <param name="node"></param> /// <returns></returns> protected ushort DoCountNodes(GPNode node) { // // Reset all the stats to zip m_CountADFNodes = 0; m_CountADLNodes = 0; m_CountADRNodes = 0; m_CountLabel = 0; DoCountNodesInternal(node); return(m_CountLabel); }
/// <summary> /// Handles mutation of the RPB branch. A node is randomly selected /// for mutation and a new branch is built from that location. /// </summary> public override void Mutate() { // // Step 1: Select a node randomly int NodeLabel = GPUtilities.rngNextInt(m_Branch.CountNodes); // // Step 2: Find this node, its parent and which child of the parent it is GPProgramBranchFactory.FindResult find = FindNode(null, m_Branch.Root, NodeLabel); // // Step 3: Build a new subtree that will replace the selected node // Assign a current depth of 2, to allow a terminal to mutate into the location GPNode newSubtree = null; if (find.Node is GPNodeFunction) { newSubtree = BuildInternal(GPEnums.TreeBuild.Grow, m_Branch.DepthInitial, 2, ((GPNodeFunction)find.Node).TerminalParameters); } else { // // Now, even if this node is a terminal, it's parent might be a function that can only accept // terminal parameters. If that is the case, can only mutate by create a new terminal node if (find.Parent is GPNodeFunction) { newSubtree = BuildInternal(GPEnums.TreeBuild.Grow, m_Branch.DepthInitial, 2, ((GPNodeFunction)find.Parent).TerminalParameters); } else { newSubtree = BuildInternal(GPEnums.TreeBuild.Grow, m_Branch.DepthInitial, 2, false); } } // // If the parent of the result is null, then we are replacing the root node, // otherwise we are replacing a child of the parent. if (find.Parent == null) { m_Branch.Root = newSubtree; } else { find.Parent.Children[find.ChildNumber] = newSubtree; } // // Update the stats for this tree m_Branch.UpdateStats(); }
// // Create the Element entry for a single node in the progam private void WriteProgramNode(GPNode node) { m_xmlWriter.WriteStartElement("GPNode"); // // Terminal or function node? if (node is GPNodeTerminal) { GPNodeTerminal nodeTerminal = (GPNodeTerminal)node; m_xmlWriter.WriteAttributeString("Type", "Terminal"); // // Write the type m_xmlWriter.WriteStartElement("Terminal"); m_xmlWriter.WriteValue(nodeTerminal.ToValueTypeString()); m_xmlWriter.WriteEndElement(); // // Write the value m_xmlWriter.WriteStartElement("Value"); if (node is GPNodeTerminalADRoot) { m_xmlWriter.WriteValue(((GPNodeTerminalADRoot)node).WhichParameter); } else if (node is GPNodeTerminalUserDefined) { m_xmlWriter.WriteValue(((GPNodeTerminalUserDefined)node).WhichUserDefined); } else if (node is GPNodeTerminalInteger) { m_xmlWriter.WriteValue(((GPNodeTerminalInteger)node).Value); } else if (node is GPNodeTerminalDouble) { m_xmlWriter.WriteValue(((GPNodeTerminalDouble)node).ToString()); } m_xmlWriter.WriteEndElement(); } else if (node is GPNodeFunction) { m_xmlWriter.WriteAttributeString("Type", "Function"); WriteFunctionNodeBody(node); } m_xmlWriter.WriteEndElement(); }
/// <summary> /// Restores the program from the array representation back into a tree structure. /// </summary> /// <param name="FunctionSet"></param> /// <param name="ForFitness"></param> public void ConvertToTree(IGPFunctionSet FunctionSet, bool ForFitness) { // // Recursively build the tree out of the array m_ArrayPos = 0; GPNode root = ConvertNode(FunctionSet); m_Root = root; // // Remove the array - unless this is for a fitness computation if (!ForFitness) { m_TreeArrayNew = null; } this.UpdateStats(); }
/// <summary> /// Internal method to get the mutation done. This method returns a reference /// to the root node of the branch. If the first node is selected for mutation, /// that node will change, therefore, it needs to be updated in the calling method. /// </summary> /// <param name="BranchRoot">Root node of the loop branch we are mutating</param> /// <param name="CountNodes">Number of nodes in the branch</param> /// <param name="DepthInitial">Initial depth the branch was created with</param> private void Mutate(ref GPNode BranchRoot, int NodeCount, int DepthInitial) { // // Step 1: Select a node randomly int NodeLabel = GPUtilities.rngNextInt(NodeCount); // // Step 2: Find this node, its parent and which child of the parent it is GPProgramBranchFactory.FindResult find = FindNode(null, BranchRoot, NodeLabel); // // Step 3: Build a new subtree that will replace the selected node GPNode newSubtree = null; if (find.Node is GPNodeFunction) { newSubtree = BuildInternal(GPEnums.TreeBuild.Grow, DepthInitial, ((GPNodeFunction)find.Node).TerminalParameters); } else { // // Now, even if this node is a terminal, it's parent might be a function that can only accept // terminal parameters. If that is the case, can only mutate by creating a new terminal node if (find.Parent is GPNodeFunction) { newSubtree = BuildInternal(GPEnums.TreeBuild.Grow, DepthInitial, ((GPNodeFunction)find.Parent).TerminalParameters); } else { newSubtree = BuildInternal(GPEnums.TreeBuild.Grow, DepthInitial, false); } } // // If the parent of the result is null, then we are replacing the root node, // otherwise we are replacing a child of the parent. if (find.Parent == null) { BranchRoot = newSubtree; } else { find.Parent.Children[find.ChildNumber] = newSubtree; } }
/// <summary> /// Unfortunately, this is essentially a linear search, I should really label each /// node so we have a BST tree to speed up the search. /// </summary> /// <param name="parent"></param> /// <param name="node"></param> /// <param name="nFindLabel"></param> /// <returns></returns> protected FindResult FindNode(GPNode parent, GPNode node, int nFindLabel) { // // Termination Criteria: If FindLabel and the node label match if (node.Label == nFindLabel) { FindResult find = new FindResult(); find.Parent = (GPNodeFunction)parent; find.Node = node; // // Figure out which child of the parent this is if (parent != null) { GPNodeFunction nodeFunc = (GPNodeFunction)parent; for (int nChild = 0; nChild < nodeFunc.Children.Count; nChild++) { if (node == nodeFunc.Children[nChild]) { find.ChildNumber = nChild; } } } return(find); } // // Search the children if (node is GPNodeFunction) { GPNodeFunction nodeFunc = (GPNodeFunction)node; for (int nChild = 0; nChild < nodeFunc.Children.Count; nChild++) { FindResult find = FindNode(nodeFunc, nodeFunc.Children[nChild], nFindLabel); if (find != null) { return(find); } } } return(null); }
/// <summary> /// Writes a function for the passed in loop branch /// </summary> /// <param name="adl">Parent ADL tree</param> /// <param name="ADLBranch">Root name for the function</param> /// <param name="BranchRoot">Root GPNode of the loop branch</param> private void WriteADLBranch(GPProgramBranchADL adl, String ADLBranch, GPNode BranchRoot) { // // Write the function declaration m_Writer.WriteLine(BuildADLPrototype(adl, ADLBranch, "GeneticProgram::")); m_Writer.WriteLine("{"); m_Writer.Write("\tdouble Result="); WriteProgramBody(BranchRoot); m_Writer.WriteLine(";"); // // Close the function m_Writer.WriteLine(); m_Writer.WriteLine("return Result;"); m_Writer.WriteLine("}"); m_Writer.WriteLine(); }
/// <summary> /// Internal recursive method that does the actual work of counting the /// nodes in the tree. /// </summary> /// <param name="node"></param> private void DoCountNodesInternal(GPNode node) { if (node == null) { return; } // // If we made it this far, count the node node.Label = m_CountLabel++; // // Update the ADF and ADL counts if (node is GPNodeFunctionADF) { m_CountADFNodes++; } if (node is GPNodeFunctionADL) { m_CountADLNodes++; } if (node is GPNodeFunctionADR) { m_CountADRNodes++; } // // If a terminal node, that's it, just count the node if (node is GPNodeTerminal) { return; } // // Otherwise, we have a functional node, so count up the children GPNodeFunction nodeFunc = (GPNodeFunction)node; for (int nChild = 0; nChild < nodeFunc.Children.Count; nChild++) { DoCountNodesInternal(nodeFunc.Children[nChild]); } }
/// <summary> /// Custom build function that creates the result producing branch /// of the genetic program. /// </summary> /// <param name="TreeBuild"></param> /// <param name="MaxDepth"></param> /// <param name="CurrentDepth"></param> /// <param name="TerminalParameters"></param> /// <returns></returns> private GPNode BuildInternal(GPEnums.TreeBuild TreeBuild, int MaxDepth, int CurrentDepth, bool TerminalParameters) { // // Randomly create this node GPNode newNode = CreateNode(TreeBuild, MaxDepth, CurrentDepth, TerminalParameters); // // If we just created a function, build its children if (newNode is GPNodeFunction) { GPNodeFunction node = (GPNodeFunction)newNode; // // Need to generate the appropriate number of nodes for the operation for (int Child = 0; Child < node.NumberArgs; Child++) { node.Children.Add(BuildInternal(TreeBuild, MaxDepth - 1, CurrentDepth + 1, node.TerminalParameters)); } } return(newNode); }
/// <summary> /// Writes a function for the passed in loop branch /// </summary> /// <param name="adl">Parent ADL tree</param> /// <param name="BranchName">Root name for the function</param> /// <param name="BranchRoot">Root GPNode of the loop branch</param> private void WriteADLBranch(GPProgramBranchADL adl, String BranchName, GPNode BranchRoot) { WriteFunctionPrototype(BranchName + adl.WhichFunction, adl.NumberArgs, "p"); // // Add the common blocks WriteFortranString(" REAL Memory(" + m_Program.CountMemory + ")"); WriteFortranString(" COMMON /idxmemory/ Memory"); // // Declare the function types WriteFortranString(" REAL SetMem"); WriteFortranString(" REAL GetMem"); foreach (KeyValuePair <String, GPLanguageWriter.tagUserDefinedFunction> kvp in m_FunctionSet) { if (!IsFortranIntrinsic(kvp.Key)) { WriteFortranString(" REAL " + ((GPLanguageWriter.tagUserDefinedFunction)kvp.Value).Name); } } // // Declare any ADFs foreach (GPProgramBranchADF adf in m_Program.ADF) { WriteFortranString(" REAL ADF" + adf.WhichFunction); } m_Writer.Write(" " + BranchName + adl.WhichFunction + "="); WriteFortranString(""); WriteProgramBody(BranchRoot); WriteFortranString(""); WriteFortranString(""); // // Close the function WriteFortranString(""); WriteFortranString(" RETURN"); WriteFortranString(" END"); WriteFortranString(""); }
/// <summary> /// Writes a function for the passed in loop branch /// </summary> /// <param name="adl">Parent ADL tree</param> /// <param name="BranchName">Root name for the function</param> /// <param name="BranchRoot">Root GPNode of the loop branch</param> private void WriteADLBranch(GPProgramBranchADL adl, String BranchName, GPNode BranchRoot) { // // Write the function declaration m_Writer.Write("double " + BranchName + adl.WhichFunction + "("); // // Write the function parameters WriteADLParameters(adl, true); m_Writer.WriteLine(")"); m_Writer.WriteLine("{"); m_Writer.Write("\tdouble Result="); WriteProgramBody(BranchRoot); m_Writer.WriteLine(";"); // // Close the function m_Writer.WriteLine(); m_Writer.WriteLine("return Result;"); m_Writer.WriteLine("}"); m_Writer.WriteLine(); }
/// <summary> /// Writes a function for the passed in loop branch /// </summary> /// <param name="adl">Parent ADL tree</param> /// <param name="BranchName">Root name for the function</param> /// <param name="BranchRoot">Root GPNode of the loop branch</param> private void WriteADLBranch(GPProgramBranchADL adl, String BranchName, GPNode BranchRoot) { // // Write the function declaration m_Writer.Write("\tPrivate Function " + BranchName + adl.WhichFunction + "("); // // Write the function parameters WriteADLParameters(adl, true); m_Writer.WriteLine(") As Double"); m_Writer.WriteLine(); m_Writer.WriteLine("\t\tDim Result As Double"); m_Writer.Write("\t\tResult="); WriteProgramBody(BranchRoot); m_Writer.WriteLine(); // // Close the function m_Writer.WriteLine(); m_Writer.WriteLine("\t\tReturn Result"); m_Writer.WriteLine("\tEnd Function"); m_Writer.WriteLine(); }
/// <summary> /// Perform the genetic operation of editing on the program branch. If /// anything custom needs to be done, derived classes can override. /// </summary> public virtual void Edit(GPProgram tree) { m_Root = m_Root.Edit(tree, this); }
/// <summary> /// Given a tree node, the node is translated into code, this method is /// recursively called for each of the node's children. /// </summary> /// <param name="node">The node to translate</param> protected void WriteProgramBody(GPNode node) { // // Recursively work through the nodes if (node is GPNodeTerminal) { m_Writer.Write(((GPNodeTerminal)node).ToString()); // // There are no children, so don't need to make a recursive call } else if (node is GPNodeFunction) { if (node is GPNodeFunctionADF) { GPNodeFunctionADF adf = (GPNodeFunctionADF)node; m_Writer.Write(" _\n\t\tADF" + adf.WhichFunction); m_Writer.Write("("); // // The parameters to the ADF are its children for (int Param = 0; Param < adf.NumberArgs; Param++) { if (Param > 0) { m_Writer.Write(","); } WriteProgramBody(((GPNodeFunction)node).Children[Param]); } m_Writer.Write(") _\n\t\t"); } else if (node is GPNodeFunctionADL) { GPNodeFunctionADL adl = (GPNodeFunctionADL)node; m_Writer.Write(" _\n\t\tADL" + adl.WhichFunction); m_Writer.Write("("); // // The parameters to the ADL are its children for (int Param = 0; Param < adl.NumberArgs; Param++) { if (Param > 0) { m_Writer.Write(","); } WriteProgramBody(((GPNodeFunction)node).Children[Param]); } m_Writer.Write(") _\n\t\t"); } else if (node is GPNodeFunctionSetMem) { m_Writer.Write(" _\n\t\tSetMem("); WriteProgramBody(((GPNodeFunction)node).Children[0]); m_Writer.Write(","); WriteProgramBody(((GPNodeFunction)node).Children[1]); m_Writer.Write(")"); } else if (node is GPNodeFunctionGetMem) { m_Writer.Write(" _\n\t\tGetMem("); WriteProgramBody(((GPNodeFunction)node).Children[0]); m_Writer.Write(")"); } else { m_Writer.Write(" _\n\t\t" + node.ToString() + "("); // // The parameters to the function are its children for (short Param = 0; Param < m_FunctionSet[node.ToString().ToUpper()].Arity; Param++) { if (Param > 0) { m_Writer.Write(","); } WriteProgramBody(((GPNodeFunction)node).Children[Param]); } m_Writer.Write(")"); } } else { Console.WriteLine("Have an undefined node we are tying to write"); } }
/// <summary> /// Converts a tree node into an array based representation. For functions /// an byte lookup is used into the FunctionSet, for terminals, the type /// is recorded along with whatever extra data may be needed. /// TODO: Get rid of the unsafe code. I know there is a bit conversion /// function, I just couldn't find it quickly. /// </summary> /// <param name="Node">The node to convert</param> /// <param name="FunctionSet"></param> private void StoreNode(GPNode Node, IGPFunctionSet FunctionSet) { // // Figure out what kind of node we have and store it accordingly. if (Node is GPNodeFunction) { GPNodeFunction NodeFunction = (GPNodeFunction)Node; if (NodeFunction is GPNodeFunctionADF) { GPNodeFunctionADF adf = (GPNodeFunctionADF)NodeFunction; // // For an ADF node,record it as value 255 and then store the which // ADF it refers to and the number of arguments. m_TreeArrayNew.Add((byte)255); m_TreeArrayNew.Add((byte)adf.WhichFunction); m_TreeArrayNew.Add(adf.NumberArgs); } else if (NodeFunction is GPNodeFunctionADL) { GPNodeFunctionADL adl = (GPNodeFunctionADL)NodeFunction; // // For an ADL node,record it as value 254 and then store the which // ADL it refers to and the number of arguments. m_TreeArrayNew.Add((byte)254); m_TreeArrayNew.Add((byte)adl.WhichFunction); m_TreeArrayNew.Add(adl.NumberArgs); } else if (NodeFunction is GPNodeFunctionADR) { GPNodeFunctionADR adr = (GPNodeFunctionADR)NodeFunction; // // For an ADR node,record it as value 253 and then store the which // ADR it refers to and the number of arguments. m_TreeArrayNew.Add((byte)253); m_TreeArrayNew.Add((byte)adr.WhichFunction); m_TreeArrayNew.Add(adr.NumberArgs); } else { // // Store the index of the function and then the number of children // for this function m_TreeArrayNew.Add((byte)FunctionSet.IndexOfKey(NodeFunction.ToStringUpper())); m_TreeArrayNew.Add((byte)((GPNodeFunction)Node).Children.Count); } // // Store each of the children foreach (GPNode NodeChild in NodeFunction.Children) { StoreNode(NodeChild, FunctionSet); } } else // Terminal Node { // // Depending upon the type of the terminal, set the appropriate value if (Node is GPNodeTerminalADFParam) { m_TreeArrayNew.Add(200); m_TreeArrayNew.Add((byte)((GPNodeTerminalADFParam)Node).WhichParameter); } else if (Node is GPNodeTerminalUserDefined) { m_TreeArrayNew.Add(201); m_TreeArrayNew.Add((byte)((GPNodeTerminalUserDefined)Node).WhichUserDefined); } else if (Node is GPNodeTerminalDouble) { m_TreeArrayNew.Add(202); double dValue = ((GPNodeTerminalDouble)Node).Value; unsafe { byte *ptr = (byte *)&dValue; for (int pos = 0; pos < sizeof(double); pos++) { m_TreeArrayNew.Add(ptr[pos]); } } } else if (Node is GPNodeTerminalInteger) { m_TreeArrayNew.Add(203); int dValue = ((GPNodeTerminalInteger)Node).Value; unsafe { byte *ptr = (byte *)&dValue; for (int pos = 0; pos < sizeof(int); pos++) { m_TreeArrayNew.Add(ptr[pos]); } } } } }
/// <summary> /// Internal method that actually does the crossover operation. 90% of the /// time a functional node is selected, 10% of the time a terminal is selected. /// TODO: Think about parameterizing those percentages /// </summary> /// <param name="LeftBranchRoot">Root node of the left sibling</param> /// <param name="LeftNodeCount">Number of nodes in the left sibling</param> /// <param name="RightBranchRoot">Root node of the right sibling</param> /// <param name="RightNodeCount">Number of nodes in the right sibling</param> private void Crossover(ref GPNode LeftBranchRoot, int LeftNodeCount, ref GPNode RightBranchRoot, int RightNodeCount) { // // Step 1: Find a node in the left tree double TypeLeft = GPUtilities.rngNextDouble(); GPProgramBranchFactory.FindResult findLeft = null; bool DoneLeft = false; while (!DoneLeft) { int NodeLeft = GPUtilities.rngNextInt(LeftNodeCount); findLeft = FindNode(null, LeftBranchRoot, NodeLeft); if (TypeLeft < 0.90 && (findLeft.Node is GPNodeFunction)) { DoneLeft = true; } else if (TypeLeft >= 0.90 && (findLeft.Node is GPNodeTerminal)) { DoneLeft = true; } else if (LeftNodeCount == 1) { DoneLeft = true; } } // // Step 2: Find a node in the right tree double TypeRight = GPUtilities.rngNextDouble(); GPProgramBranchFactory.FindResult findRight = null; bool DoneRight = false; while (!DoneRight) { int NodeRight = GPUtilities.rngNextInt(RightNodeCount); findRight = FindNode(null, RightBranchRoot, NodeRight); if (TypeRight < 0.90 && (findRight.Node is GPNodeFunction)) { DoneRight = true; } else if (TypeRight >= 0.90 && (findRight.Node is GPNodeTerminal)) { DoneRight = true; } else if (RightNodeCount == 1) { DoneRight = true; } } // // Step 3: Swap the references if (findLeft.Parent == null) { LeftBranchRoot = findRight.Node; } else { findLeft.Parent.Children[findLeft.ChildNumber] = findRight.Node; } if (findRight.Parent == null) { RightBranchRoot = findLeft.Node; } else { findRight.Parent.Children[findRight.ChildNumber] = findLeft.Node; } }
/// <summary> /// Given a tree node, the node is translated into code, this method is /// recursively called for each of the node's children. /// </summary> /// <param name="node">The node to translate</param> protected void WriteProgramBody(GPNode node) { // // Recursively work through the nodes if (node is GPNodeTerminal) { if (node is GPNodeTerminalDouble || node is GPNodeTerminalInteger) { // // Put doubles on their own line, helps prevent the lines // from getting too long m_Writer.WriteLine(); m_Writer.Write(" . "); } m_Writer.Write(((GPNodeTerminal)node).ToString()); // // There are no children, so don't need to make a recursive call } else if (node is GPNodeFunction) { if (node is GPNodeFunctionADF) { GPNodeFunctionADF adf = (GPNodeFunctionADF)node; m_Writer.Write("\n . ADF" + adf.WhichFunction); m_Writer.Write("("); // // The parameters to the ADF are its children for (int Param = 0; Param < adf.NumberArgs; Param++) { if (Param > 0) { m_Writer.Write(","); } WriteProgramBody(((GPNodeFunction)node).Children[Param]); } m_Writer.Write(")\n . "); } else if (node is GPNodeFunctionADL) { GPNodeFunctionADL adl = (GPNodeFunctionADL)node; m_Writer.Write("\n . ADL" + adl.WhichFunction); m_Writer.Write("("); // // The parameters to the ADL are its children for (int Param = 0; Param < adl.NumberArgs; Param++) { if (Param > 0) { m_Writer.Write(","); } WriteProgramBody(((GPNodeFunction)node).Children[Param]); } m_Writer.Write(")\n . "); } else if (node is GPNodeFunctionSetMem) { m_Writer.Write("\n . SetMem("); WriteProgramBody(((GPNodeFunction)node).Children[0]); m_Writer.Write(","); WriteProgramBody(((GPNodeFunction)node).Children[1]); m_Writer.Write(")"); } else if (node is GPNodeFunctionGetMem) { m_Writer.Write("\n . GetMem("); WriteProgramBody(((GPNodeFunction)node).Children[0]); m_Writer.Write(")"); } else { m_Writer.Write("\n . " + node.ToString() + "("); // // The parameters to the function are its children for (short Param = 0; Param < m_FunctionSet[node.ToString().ToUpper()].Arity; Param++) { if (Param > 0) { m_Writer.Write(","); } WriteProgramBody(((GPNodeFunction)node).Children[Param]); } m_Writer.Write(")"); } } else { Console.WriteLine("Have an undefined node we are tying to write"); } }
// // Gets the function nodes written out private void WriteFunctionNodeBody(GPNode node) { GPNodeFunction nodeFunc = (GPNodeFunction)node; String sType = node.GetType().ToString(); if (node is GPNodeFunctionADF) { GPNodeFunctionADF nodeADF = (GPNodeFunctionADF)nodeFunc; m_xmlWriter.WriteStartElement("Function"); m_xmlWriter.WriteValue("ADF"); m_xmlWriter.WriteEndElement(); // // Write out "which" ADF function this is m_xmlWriter.WriteStartElement("WhichFunction"); m_xmlWriter.WriteValue(nodeADF.WhichFunction); m_xmlWriter.WriteEndElement(); for (int nParam = 0; nParam < nodeADF.NumberArgs; nParam++) { WriteProgramNode(nodeADF.Children[nParam]); } } else if (node is GPNodeFunctionADL) { GPNodeFunctionADL nodeADL = (GPNodeFunctionADL)nodeFunc; m_xmlWriter.WriteStartElement("Function"); m_xmlWriter.WriteValue("ADL"); m_xmlWriter.WriteEndElement(); // // Write out "which" ADL function this is m_xmlWriter.WriteStartElement("WhichFunction"); m_xmlWriter.WriteValue(nodeADL.WhichFunction); m_xmlWriter.WriteEndElement(); for (int nParam = 0; nParam < nodeADL.NumberArgs; nParam++) { WriteProgramNode(nodeADL.Children[nParam]); } } else if (node is GPNodeFunctionADR) { GPNodeFunctionADR nodeADR = (GPNodeFunctionADR)nodeFunc; m_xmlWriter.WriteStartElement("Function"); m_xmlWriter.WriteValue("ADR"); m_xmlWriter.WriteEndElement(); // // Write out "which" ADR function this is m_xmlWriter.WriteStartElement("WhichFunction"); m_xmlWriter.WriteValue(nodeADR.WhichFunction); m_xmlWriter.WriteEndElement(); for (int nParam = 0; nParam < nodeADR.NumberArgs; nParam++) { WriteProgramNode(nodeADR.Children[nParam]); } } else { m_xmlWriter.WriteStartElement("Function"); m_xmlWriter.WriteValue(nodeFunc.ToString()); m_xmlWriter.WriteEndElement(); // // Write out its children for (int nParam = 0; nParam < nodeFunc.NumberArgs; nParam++) { WriteProgramNode(nodeFunc.Children[nParam]); } } }