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