Exemplo n.º 1
0
        /// <summary>
        /// Recursive helper method for placing given subtree at the specific point (at node with index).
        /// </summary>
        ///
        /// <param name="node">Chromosome (or its child node) to be changed.</param>
        /// <param name="indexOfCrossoverPointOfPrimaryParent">Index of changing point.</param>
        /// <param name="crossoverSubtreeOfSecundaryParent">Subtree to be added at changing point.</param>
        /// <param name="found">Reference to a variable that represents if node with given index is found. It is used for better preformance.</param>
        /// /// <returns> New, or old, (sub)tree. </returns>
        public Tuple <SymbolicTreeNode, bool> PlaceNodeAtPoint(SymbolicTreeNode node, int indexOfCrossoverPointOfPrimaryParent, SymbolicTreeNode crossoverSubtreeOfSecundaryParent, ref bool found)
        {
            // Node is previously found - return tuple of current node and found variable.
            if (found)
            {
                return(new Tuple <SymbolicTreeNode, bool>(node, found));
            }

            // If node is null call to the method should not be preformed.
            if (node == null)
            {
                throw new Exception("[PlaceNodeAtPoint] Node is null. Not possible since all cases should be already covered.");
            }


            if (node.arity == 0)
            {
                // If terminal node.

                #region exceptions
                // Check that node type is terminal.
                if (node.type != "terminal")
                {
                    throw new Exception("[PlaceNodeAtPoint] Node has arity = 0 but his type is: " + node.type + " (not terminal).");
                }

                // Check that this node has no child node.
                if (!(node.children == null || node.children.Count == 0))
                {
                    throw new Exception("[PlaceNodeAtPoint] Node has arity = 0 but has " + node.children.Count + " child nodes.");
                }
                #endregion

                #region check if current node is the one (return if true)
                // Everything fine, check if we found right node.
                if (indexOfCrossoverPointOfPrimaryParent == node.index)
                {
                    // Save current depth.
                    int currentDepth = node.depth;
                    // Update node.
                    node = (SymbolicTreeNode)crossoverSubtreeOfSecundaryParent.Clone();
                    // Update variable found.
                    found = true;
                    // Update depths of new subtree.
                    node.CalculateDepths(currentDepth);

                    return(new Tuple <SymbolicTreeNode, bool>(node, found));
                }
                #endregion

                // Node was not found.
                return(new Tuple <SymbolicTreeNode, bool>(node, found));
            }
            else if (node.arity == 1)
            {
                // If non-terminal node with arity 1.

                #region exceptions
                // Check that node type is non-teminal.
                if (node.type != "non-terminal")
                {
                    throw new Exception("[PlaceNodeAtPoint] Node has arity = 1 but his type is: " + node.type + " (not non-terminal).");
                }

                // Check that this node has 1 child node.
                if (node.children.Count != 1)
                {
                    throw new Exception("[PlaceNodeAtPoint] Node has arity = 1 but has " + node.children.Count + " child nodes.");
                }
                #endregion

                #region check if current node is the one (return if true)
                // Everything fine, check if we found right node.
                if (indexOfCrossoverPointOfPrimaryParent == node.index)
                {
                    // Save current depth.
                    int currentDepth = node.depth;
                    // Update node.
                    node = (SymbolicTreeNode)crossoverSubtreeOfSecundaryParent.Clone();
                    // Update variable found.
                    found = true;
                    // Update depths of new subtree.
                    node.CalculateDepths(currentDepth);

                    return(new Tuple <SymbolicTreeNode, bool>(node, found));
                }
                #endregion

                #region check child (return if found)
                // Check subtree of current node since node is not yet found.
                var retVal = PlaceNodeAtPoint((SymbolicTreeNode)node.children[0].Clone(), indexOfCrossoverPointOfPrimaryParent, crossoverSubtreeOfSecundaryParent, ref found);
                // Update variable found.
                found = retVal.Item2;

                // Check if node is now found.
                if (found)
                {
                    // Update node.
                    node.children[0] = (SymbolicTreeNode)retVal.Item1.Clone();
                }
                #endregion

                // Node was not found.
                return(new Tuple <SymbolicTreeNode, bool>(node, found));
            }
            else if (node.arity == 2)
            {
                // If non-terminal node with arity 2.

                #region exceptions
                // Check that node type is non-teminal.
                if (node.type != "non-terminal")
                {
                    throw new Exception("[PlaceNodeAtPoint] Node has arity = 2 but his type is: " + node.type + " (not non-terminal).");
                }

                // Check that this node has 2 child nodes.
                if (node.children.Count != 2)
                {
                    throw new Exception("[PlaceNodeAtPoint] Node has arity = 2 but has " + node.children.Count + " child nodes.");
                }
                #endregion

                #region check if current node is the one (return if true)
                // Everything fine, check if we found right node.
                if (indexOfCrossoverPointOfPrimaryParent == node.index)
                {
                    // Save current depth.
                    int currentDepth = node.depth;
                    // Update node.
                    node = (SymbolicTreeNode)crossoverSubtreeOfSecundaryParent.Clone();
                    // Update variable found.
                    found = true;
                    // Update depths of new subtree.
                    node.CalculateDepths(currentDepth);

                    return(new Tuple <SymbolicTreeNode, bool>(node, found));
                }
                #endregion

                #region check left child (return if found)
                // Check left subtree of current node.
                Tuple <SymbolicTreeNode, bool> retValLeft = PlaceNodeAtPoint((SymbolicTreeNode)node.children[0].Clone(), indexOfCrossoverPointOfPrimaryParent, crossoverSubtreeOfSecundaryParent, ref found);

                // Update variable found.
                found = retValLeft.Item2;

                // If node now found.
                if (found)
                {
                    // Update node left child. Right child stays the same.
                    node.children[0] = (SymbolicTreeNode)retValLeft.Item1.Clone();

                    return(new Tuple <SymbolicTreeNode, bool>(node, found));
                }
                #endregion

                #region check right child (return if found)
                // Node still not found.
                // Check right subtree of current node.
                Tuple <SymbolicTreeNode, bool> retValRight = PlaceNodeAtPoint((SymbolicTreeNode)node.children[1].Clone(), indexOfCrossoverPointOfPrimaryParent, crossoverSubtreeOfSecundaryParent, ref found);

                // Update variable found.
                found = retValRight.Item2;

                // If node now found.
                if (found)
                {
                    // Update node left child. Right child stays the same.
                    node.children[1] = (SymbolicTreeNode)retValRight.Item1.Clone();
                }
                #endregion

                // Node was not found.
                return(new Tuple <SymbolicTreeNode, bool>(node, found));
            }
            else
            {
                // Node with given arity is not expected.
                throw new Exception("[PlaceNodeAtPoint] Given node arity = " + node.arity + " is not expected! Arity higher than 2 is not covered yet!");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Mehod for choosing points of crossover in parents.
        /// In other words, choosing subtrees of parents for crossover.
        /// </summary>
        ///
        /// <param name="primaryParent">Primary parent.</param>
        /// <param name="secundaryParent">Secundary parent.</param>
        /// <param name="chooseNonTerminalPointProbability">Probability for choosing non-terminal as point of crossover.</param>
        /// <param name="maxDepth">Maximal depth of trees in population.</param>
        /// <returns>Tuple of node index of primaryParent and node of secundaryParent that will be points for crossover. </returns>
        public Tuple <int, SymbolicTreeNode> ChooseSubtrees(Chromosome primaryParent, Chromosome secundaryParent, double chooseNonTerminalPointProbability, int maxDepth)
        {
            // Index of crossover point in primary parent.
            int indexOfCrossoverPointOfPrimaryParent;
            // Subtree of crossover point in secundary parent.
            SymbolicTreeNode crossoverSubtreeOfSecundaryParent = new SymbolicTreeNode();

            // Search for crossover points in parents until they that satisfy condition on depth of child.
            while (true)
            {
                #region primary parent crossover point selection
                // Make list of nonTerminal and terminal indices in primaryParent.
                List <int> nonTerminalIndicesOfPrimaryParent = new List <int>();
                List <int> terminalIndicesOfPrimaryParent    = new List <int>();
                SeparateIndices(primaryParent.symbolicTree, ref nonTerminalIndicesOfPrimaryParent, ref terminalIndicesOfPrimaryParent);

                // Randomly select non-terminal or terminal (probability of selecting non-terminal is predefined) from secundary parent.
                if ((rand.Next(100) < (chooseNonTerminalPointProbability * 100)) && (nonTerminalIndicesOfPrimaryParent.Count > 1))
                {
                    // Index of the (to-be) selected non-terminal.
                    int crossoverPointOfPrimaryParent;

                    // Do not consider crossover point at root node (index = 0) in first parent since in that way we would be cloning second parent into a child.
                    while (true)
                    {
                        // Chose index of a non-terminal node from secundary parent.
                        crossoverPointOfPrimaryParent = rand.Next(nonTerminalIndicesOfPrimaryParent.Count);
                        if (crossoverPointOfPrimaryParent != 0)
                        {
                            break;
                        }
                    }

                    // Clone selected subtree.
                    indexOfCrossoverPointOfPrimaryParent = nonTerminalIndicesOfPrimaryParent[crossoverPointOfPrimaryParent];
                }
                else
                {
                    // Chose index of a non-terminal node from secundary parent.
                    int crossoverPointOfPrimaryParent = rand.Next(terminalIndicesOfPrimaryParent.Count);

                    // Clone selected subtree.
                    indexOfCrossoverPointOfPrimaryParent = terminalIndicesOfPrimaryParent[crossoverPointOfPrimaryParent];
                }
                #endregion

                #region secundary parent crossover point selection
                // Make list of nonTerminal and terminal nodes in secundaryParent.
                List <SymbolicTreeNode> nonTerminalNodesOfSecundaryParent = new List <SymbolicTreeNode>();
                List <SymbolicTreeNode> terminalNodesOfSecundaryParent    = new List <SymbolicTreeNode>();
                SeparateNodes(secundaryParent.symbolicTree, ref nonTerminalNodesOfSecundaryParent, ref terminalNodesOfSecundaryParent);

                // Randomly select non-terminal or terminal (probability of selecting non-terminal is predefined) from secundary parent.
                if ((rand.Next(100) < (chooseNonTerminalPointProbability * 100)) && (nonTerminalNodesOfSecundaryParent.Count != 0))
                {
                    // Chose index of a non-terminal node from secundary parent.
                    int crossoverPointOfSecundaryParent = rand.Next(nonTerminalNodesOfSecundaryParent.Count);

                    // Clone selected subtree.
                    crossoverSubtreeOfSecundaryParent = (SymbolicTreeNode)nonTerminalNodesOfSecundaryParent[crossoverPointOfSecundaryParent].Clone();
                }
                else
                {
                    // Chose index of a non-terminal node from secundary parent.
                    int crossoverPointOfSecundaryParent = rand.Next(terminalNodesOfSecundaryParent.Count);

                    // Clone selected subtree.
                    crossoverSubtreeOfSecundaryParent = (SymbolicTreeNode)terminalNodesOfSecundaryParent[crossoverPointOfSecundaryParent].Clone();
                }
                #endregion

                int depth1 = primaryParent.symbolicTree.FindNodeWithIndex(indexOfCrossoverPointOfPrimaryParent).depth;
                int depth2 = crossoverSubtreeOfSecundaryParent.DepthOfSymbolicTree();
                if (depth1 + depth2 < maxDepth)
                {
                    break;
                }
            }

            return(Tuple.Create(indexOfCrossoverPointOfPrimaryParent, crossoverSubtreeOfSecundaryParent));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Recursive helper method for creating preorder list of non-terminal and terminal nodes.
        /// </summary>
        ///
        /// <param name="node">Root or current node.</param>
        /// <param name="nonTerminalNodesOfSecundaryParent">Reference of a list of non-terminal nodes.</param>
        /// <param name="terminalNodesOfSecundaryParent">Reference of a list of terminal nodes.</param>
        private void SeparateNodes(SymbolicTreeNode node, ref List <SymbolicTreeNode> nonTerminalNodesOfSecundaryParent, ref List <SymbolicTreeNode> terminalNodesOfSecundaryParent)
        {
            if (node == null)
            {
                return;
            }

            if (node.arity == 0)
            {
                // If terminal node.

                #region exceptions
                // Check that node type is terminal.
                if (node.type != "terminal")
                {
                    throw new Exception("[SeparateNodes] Node has arity = 0 but his type is: " + node.type + " (not terminal).");
                }

                // Check that this node has no child node.
                if (!(node.children == null || node.children.Count == 0))
                {
                    throw new Exception("[SeparateNodes] Node has arity = 0 but has " + node.children.Count + " child nodes.");
                }
                #endregion

                // Everything fine, add node to list of terminal nodes.
                terminalNodesOfSecundaryParent.Add(node);
                return;
            }
            else if (node.arity == 1)
            {
                // If non-terminal node with arity 1.

                #region exceptions
                // Check that node type is non-teminal.
                if (node.type != "non-terminal")
                {
                    throw new Exception("[SeparateNodes] Node has arity = 1 but his type is: " + node.type + " (not non-terminal).");
                }

                // Check that this node has 1 child node.
                if (node.children.Count != 1)
                {
                    throw new Exception("[SeparateNodes] Node has arity = 1 but has " + node.children.Count + " child nodes.");
                }
                #endregion

                // Everything fine, add node to nonTerminal list and call SeparateNodes of his child node.
                nonTerminalNodesOfSecundaryParent.Add(node);
                SeparateNodes(node.children[0], ref nonTerminalNodesOfSecundaryParent, ref terminalNodesOfSecundaryParent);
                return;
            }
            else if (node.arity == 2)
            {
                // If non-terminal node with arity 2.

                #region exceptions
                // Check that node type is non-teminal.
                if (node.type != "non-terminal")
                {
                    throw new Exception("[SeparateNodes] Node has arity = 2 but his type is: " + node.type + " (not non-terminal).");
                }

                // Check that this node has 2 child nodes.
                if (node.children.Count != 2)
                {
                    throw new Exception("[SeparateNodes] Node has arity = 2 but has " + node.children.Count + " child nodes.");
                }
                #endregion

                // Everything fine, call SeparateNodes on his left child node, add node to nonTerminal list and call SeparateNodes on his right child node.
                SeparateNodes(node.children[0], ref nonTerminalNodesOfSecundaryParent, ref terminalNodesOfSecundaryParent);
                nonTerminalNodesOfSecundaryParent.Add(node);
                SeparateNodes(node.children[1], ref nonTerminalNodesOfSecundaryParent, ref terminalNodesOfSecundaryParent);
                return;
            }
            else
            {
                // Node with given arity is not expected.
                throw new Exception("[SeparateNodes] Given node arity = " + node.arity + " is not expected! Arity higher than 2 is not covered yet!");
            }
        }