/// <summary> /// Cloneable interface /// </summary> /// <returns>Clone of the program branch</returns> public Object Clone() { GPProgramBranch obj = (GPProgramBranch)this.MemberwiseClone(); if (m_Root != null) { obj.m_Root = (GPNode)m_Root.Clone(); } obj.m_DepthInitial = m_DepthInitial; obj.m_Depth = m_Depth; obj.m_CountNodes = m_CountNodes; obj.m_CountLeafNodes = m_CountLeafNodes; obj.m_CountADFNodes = m_CountADFNodes; obj.m_CountADLNodes = m_CountADLNodes; obj.m_CountADRNodes = m_CountADRNodes; if (m_TreeArrayNew != null) { obj.m_TreeArrayNew = new List <byte>(m_TreeArrayNew.Count); foreach (byte Value in m_TreeArrayNew) { obj.m_TreeArrayNew.Add(Value); } } return(obj); }
/// <summary> /// Performs a crossover operation with this program and the sibling program. /// Crossover is performed on like branches, i.e. RCBs only crossover with sibling /// RCBs. /// </summary> /// <param name="sibling">Which sibling to crossover with</param> public override void Crossover(GPProgramBranch sibling) { GPProgramBranchADR rightADR = (GPProgramBranchADR)sibling; // // Select a branch byte WhichBranch = (byte)GPUtilities.rngNextInt(4); switch (WhichBranch) { case 0: Crossover(ref m_BranchADR.m_RCB, m_BranchADR.NodeCountRCB, ref rightADR.m_RCB, rightADR.NodeCountRCB); break; case 1: Crossover(ref m_BranchADR.m_RBB, m_BranchADR.NodeCountRBB, ref rightADR.m_RBB, rightADR.NodeCountRBB); break; case 2: Crossover(ref m_BranchADR.m_RUB, m_BranchADR.NodeCountRUB, ref rightADR.m_RUB, rightADR.NodeCountRUB); break; case 3: Crossover(ref m_BranchADR.m_RGB, m_BranchADR.NodeCountRGB, ref rightADR.m_RGB, rightADR.NodeCountRGB); break; } // // Make sure the program stats get updated for both programs m_Branch.UpdateStats(); sibling.UpdateStats(); }
/// <summary> /// Returns the value located at the memory cell. A mod function is used /// to prevent from accessing a value out of bounds. /// </summary> /// <param name="tree"></param> /// <param name="execBranch"></param> /// <returns></returns> public override double EvaluateAsDouble(GPProgram tree, GPProgramBranch execBranch) { // // return the memory value double p1 = Math.Abs(this.Children[0].EvaluateAsDouble(tree, execBranch)); int Pos = Math.Abs(((int)p1) % tree.CountMemory); return(GPProgram.m_Memory[Pos]); }
/// <summary> /// A Function node really acts as a reference to make a call into /// a Function program branch. What this method does is to first crawl /// through each of the Function parameter subtrees and get their values /// computed up. These values are stored internal to the function /// to act as a sort of stack, because each of the subtrees could /// make calls to the same Function and we don't want the results to get /// overwritten. Once all the subtrees have been evalutated, the /// results are written into the Function parameters and the Function program /// branch is called. /// </summary> /// <param name="tree">Program tree this Function belongs to</param> /// <param name="execBranch">Program Branch this Function is executing within</param> public override double EvaluateAsDouble(GPProgram tree, GPProgramBranch execBranch) { GPProgramBranchADF adf = tree.ADF[this.WhichFunction]; base.PrepareFunctionParameters(tree, execBranch, adf); // // Evalute the Function program branch return(adf.EvaluateAsDouble(tree)); }
/// <summary> /// Stores the value in memory. /// </summary> /// <param name="tree"></param> /// <param name="execBranch"></param> /// <returns>The value just stored in memory</returns> public override double EvaluateAsDouble(GPProgram tree, GPProgramBranch execBranch) { // // Set the memory value double p1 = Math.Abs(this.Children[0].EvaluateAsDouble(tree, execBranch)); double p2 = this.Children[1].EvaluateAsDouble(tree, execBranch); GPProgram.m_Memory[Math.Abs(((int)p1) % tree.CountMemory)] = p2; return(p2); }
/// <summary> /// This method directs the construction of an RPB /// </summary> /// <param name="Branch"></param> /// <param name="TreeBuild"></param> /// <returns></returns> public override bool Build(GPProgramBranch Branch, GPEnums.TreeBuild TreeBuild) { m_Branch = Branch; // // Call the recursive method to create the tree m_Branch.Root = BuildInternal(TreeBuild, m_Branch.DepthInitial, 0, false); // // Update the tree stats m_Branch.UpdateStats(); // // Convert the program into array representation m_Branch.ConvertToArray(m_Config.FunctionSet); return(true); }
/// <summary> /// Evaluates the parameters to a function before the function is called. /// </summary> /// <param name="tree">Program tree this Function belongs to</param> /// <param name="execBranch">Program Branch this Function is executing within</param> public void PrepareFunctionParameters(GPProgram tree, GPProgramBranch execBranch, GPProgramBranchADRoot ADFunction) { // // Compute the parameters to the Function short nNumberArgs = ADFunction.NumberArgs; double[] argResult = new double[nNumberArgs]; for (int nParam = 0; nParam < nNumberArgs; nParam++) { argResult[nParam] = ((GPNode)m_Children[nParam]).EvaluateAsDouble(tree, execBranch); } // // Place the results into the Function program branch for (int nParam = 0; nParam < nNumberArgs; nParam++) { ADFunction.ParamResults[nParam] = argResult[nParam]; } }
/// <summary> /// Construct the four branching structures /// </summary> /// <param name="Branch">Reference to the ADR branch</param> /// <param name="TreeBuild">Tree building technqiue</param> /// <returns>True if the branch was correctly constructed</returns> public override bool Build(GPProgramBranch Branch, GPEnums.TreeBuild TreeBuild) { m_Branch = m_BranchADR = (GPProgramBranchADR)Branch; // // We create 4 different branching structures: RCB, RBB, RUB, RGB m_BranchADR.RCB = BuildInternal(TreeBuild, m_Branch.DepthInitial, false); m_BranchADR.RBB = BuildInternal(TreeBuild, m_Branch.DepthInitial, true); m_BranchADR.RUB = BuildInternal(TreeBuild, m_Branch.DepthInitial, false); m_BranchADR.RGB = BuildInternal(TreeBuild, m_Branch.DepthInitial, false); // // Update the tree stats m_Branch.UpdateStats(); // // Convert the program into array representation m_Branch.ConvertToArray(m_Config.FunctionSet); return(true); }
/// <summary> /// Recursively work through the nodes in the tree, checking the children /// first and then checking the current node. If a node is able to be combined, /// then a new terminal node is created and it is returned, instead of the /// original subtree. /// </summary> public override GPNode Edit(GPProgram tree, GPProgramBranch execBranch) { // // Can not use a 'foreach' structure here because we need to replace // the child with whatever it returns of itself. for (int Child = 0; Child < m_Children.Count; Child++) { m_Children[Child] = m_Children[Child].Edit(tree, execBranch); } // // If all the children to this node are numbers, a simplification // can be performed. bool AllNumbers = true; foreach (GPNode child in m_Children) { if (!(child is GPNodeTerminalDouble || child is GPNodeTerminalInteger)) { AllNumbers = false; break; } } // // The test to see if there are more than 0 arguments was added because // the time series functions may not have any parameters and they shouldn't // be converted to numeric terminals. if (AllNumbers && this.NumberArgs > 0) { // // Exec the function and replace with a new terminal node double result = this.EvaluateAsDouble(tree, execBranch); // // Create a new terminal node GPNodeTerminalDouble NodeNew = new GPNodeTerminalDouble(result); return(NodeNew); } return(this); }
/// <summary> /// This method performs crossover on the result producing branch. /// 90% of the time internal nodes are selected and 10% of the time /// leaf nodes are selected. /// TODO: Parameterize those percentages /// /// If either one of the selected nodes is a function that accepts only /// terminals as parameters, no crossover is performed. /// /// </summary> /// <param name="sibling"></param> public override void Crossover(GPProgramBranch sibling) { GPProgramBranchRPB rightRPB = (GPProgramBranchRPB)sibling; // // 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(m_Branch.CountNodes); findLeft = FindNode(null, m_Branch.Root, NodeLeft); if (TypeLeft < 0.90 && (findLeft.Node is GPNodeFunction)) { DoneLeft = true; } else if (TypeLeft >= 0.90 && (findLeft.Node is GPNodeTerminal)) { DoneLeft = true; } else if (TypeLeft >= 0.90 && (findLeft.Node is GPNodeFunction) && ((GPNodeFunction)findLeft.Node).Children.Count == 0) { // // This if statement accounts for the possibility of functions that // are constant values...because I didn't use a terminal type for them DoneLeft = true; } else if (m_Branch.CountNodes == 1) { DoneLeft = true; } } // // If the node is a function that only accepts terminal inputs, then crossover is not allowed if (findLeft.Node is GPNodeFunction && ((GPNodeFunction)findLeft.Node).TerminalParameters) { return; } if (findLeft.Parent != null && findLeft.Parent is GPNodeFunction && ((GPNodeFunction)findLeft.Parent).TerminalParameters) { return; } // // 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(rightRPB.CountNodes); findRight = FindNode(null, rightRPB.Root, NodeRight); if (TypeRight < 0.90 && (findRight.Node is GPNodeFunction)) { DoneRight = true; } else if (TypeRight >= 0.90 && (findRight.Node is GPNodeTerminal)) { DoneRight = true; } else if (TypeRight >= 0.90 && (findRight.Node is GPNodeFunction) && ((GPNodeFunction)findRight.Node).Children.Count == 0) { // // This if statement accounts for the possibility of functions that // are constant values...because I didn't use a terminal type for them DoneRight = true; } else if (rightRPB.CountNodes == 1) { DoneRight = true; } } // // If the node is a function that only accepts terminal inputs, then crossover is not allowed if (findRight.Node is GPNodeFunction && ((GPNodeFunction)findRight.Node).TerminalParameters) { return; } if (findRight.Parent != null && findRight.Parent is GPNodeFunction && ((GPNodeFunction)findRight.Parent).TerminalParameters) { return; } // // Step 3: Swap the references if (findLeft.Parent == null) { m_Branch.Root = findRight.Node; } else { findLeft.Parent.Children[findLeft.ChildNumber] = findRight.Node; } if (findRight.Parent == null) { rightRPB.Root = findLeft.Node; } else { findRight.Parent.Children[findRight.ChildNumber] = findLeft.Node; } // // Update the stats for these trees m_Branch.UpdateStats(); rightRPB.UpdateStats(); }
/// <summary> /// Terminals require no editing /// </summary> public override GPNode Edit(GPProgram tree, GPProgramBranch execBranch) { return(this); }
public GPProgramBranchFactory(GPProgramBranch Branch, GPModelerServer Config) { m_Branch = Branch; m_Config = Config; }
/// <summary> /// Override from GPNode for implicit evaluation /// </summary> /// <param name="tree"></param> /// <param name="execBranch"></param> /// <returns></returns> public override double EvaluateAsDouble(GPProgram tree, GPProgramBranch execBranch) { return((double)this.Value); }
/// <summary> /// Override from GPNode for implicit evaluation /// </summary> /// <param name="tree"></param> /// <param name="execBranch"></param> /// <returns>value of the terminal</returns> public override double EvaluateAsDouble(GPProgram tree, GPProgramBranch execBranch) { return(((GPProgramBranchADL)execBranch).ParamResults[this.WhichParameter]); }
// // Override from GPNode for implicit evaluation public override double EvaluateAsDouble(GPProgram tree, GPProgramBranch execBranch) { return(tree.UserTerminals[this.WhichUserDefined]); }
// // All derived classes must implement the following methods public abstract bool Build(GPProgramBranch Branch, GPEnums.TreeBuild TreeBuild);
public abstract void Crossover(GPProgramBranch sibling);
/// <summary> /// All derived classes must implement the editing genetic operator /// </summary> public abstract GPNode Edit(GPProgram tree, GPProgramBranch execBranch);
/// <summary> /// These are the base "evaluate" methods that provide the implicit interpreter /// </summary> public abstract double EvaluateAsDouble(GPProgram tree, GPProgramBranch execBranch);