Represents tree node of genetic programming tree.

In genetic programming a chromosome is represented by a tree, which is represented by GPTreeChromosome class. The GPTreeNode class represents single node of such genetic programming tree.

Each node may or may not have children. This means that particular node of a genetic programming tree may represent its sub tree or even entire tree.

Inheritance: ICloneable
        /// <summary>
        /// Generate chromosome's subtree of specified level.
        /// </summary>
        ///
        /// <param name="node">Sub tree's node to generate.</param>
        /// <param name="level">Sub tree's level to generate.</param>
        ///
        protected void Generate(GPTreeNode node, int level)
        {
            // create gene for the node
            if (level == 0)
            {
                // the gene should be an argument
                node.Gene = root.Gene.CreateNew(GPGeneType.Argument);
            }
            else
            {
                // the gene can be function or argument
                node.Gene = root.Gene.CreateNew();
            }

            // add children
            if (node.Gene.ArgumentsCount != 0)
            {
                node.Children = new List <GPTreeNode>();
                for (var i = 0; i < node.Gene.ArgumentsCount; i++)
                {
                    // create new child
                    var child = new GPTreeNode();
                    Generate(child, level - 1);
                    // add the new child
                    node.Children.Add(child);
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Get tree representation of the chromosome.
        /// </summary>
        ///
        /// <returns>Returns expression's tree represented by the chromosome.</returns>
        ///
        /// <remarks><para>The method builds expression's tree for the native linear representation
        /// of the GEP chromosome.</para></remarks>
        ///
        protected GPTreeNode GetTree( )
        {
            // function node queue. the queue contains function node,
            // which requires children. when a function node receives
            // all children, it will be removed from the queue
            Queue functionNodes = new Queue( );

            // create root node
            GPTreeNode root = new GPTreeNode(genes[0]);

            // check children amount of the root node
            if (root.Gene.ArgumentsCount != 0)
            {
                root.Children = new List <GPTreeNode>( );
                // place the root to the queue
                functionNodes.Enqueue(root);

                // go through genes
                for (int i = 1; i < length; i++)
                {
                    // create new node
                    GPTreeNode node = new GPTreeNode(genes[i]);

                    // if next gene represents function, place it to the queue
                    if (genes[i].GeneType == GPGeneType.Function)
                    {
                        node.Children = new List <GPTreeNode>( );
                        functionNodes.Enqueue(node);
                    }

                    // get function node from the top of the queue
                    GPTreeNode parent = (GPTreeNode)functionNodes.Peek( );

                    // add new node to children of the parent node
                    parent.Children.Add(node);

                    // remove the parent node from the queue, if it is
                    // already complete
                    if (parent.Children.Count == parent.Gene.ArgumentsCount)
                    {
                        functionNodes.Dequeue( );

                        // check the queue if it is empty
                        if (functionNodes.Count == 0)
                        {
                            break;
                        }
                    }
                }
            }
            // return formed tree
            return(root);
        }
 /// <summary>
 /// Generate random chromosome value.
 /// </summary>
 ///
 /// <remarks><para>Regenerates chromosome's value using random number generator.</para>
 /// </remarks>
 ///
 public override void Generate()
 {
     // randomize the root
     root.Gene.Generate();
     // create children
     if (root.Gene.ArgumentsCount != 0)
     {
         root.Children = new List <GPTreeNode>();
         for (var i = 0; i < root.Gene.ArgumentsCount; i++)
         {
             // create new child
             var child = new GPTreeNode();
             Generate(child, rand.Next(maxInitialLevel));
             // add the new child
             root.Children.Add(child);
         }
     }
 }
Exemple #4
0
        /// <summary>
        /// Clone the tree node.
        /// </summary>
        ///
        /// <returns>Returns exact clone of the node.</returns>
        ///
        public object Clone( )
        {
            GPTreeNode clone = new GPTreeNode( );

            // clone gene
            clone.Gene = this.Gene.Clone( );
            // clone its children
            if (this.Children != null)
            {
                clone.Children = new List <GPTreeNode>( );
                // clone each child gene
                foreach (GPTreeNode node in Children)
                {
                    clone.Children.Add((GPTreeNode)node.Clone( ));
                }
            }
            return(clone);
        }
        /// <summary>
        /// Clone the tree node.
        /// </summary>
        /// 
        /// <returns>Returns exact clone of the node.</returns>
        /// 
        public object Clone( )
        {
            GPTreeNode clone = new GPTreeNode( );

            // clone gene
            clone.Gene = this.Gene.Clone( );
            // clone its children
            if ( this.Children != null )
            {
                clone.Children = new List<GPTreeNode>( );
                // clone each child gene
                foreach ( GPTreeNode node in Children )
                {
                    clone.Children.Add( (GPTreeNode) node.Clone( ) );
                }
            }
            return clone;
        }
        /// <summary>
        /// Crossover operator.
        /// </summary>
        ///
        /// <param name="pair">Pair chromosome to crossover with.</param>
        ///
        /// <remarks><para>The method performs crossover between two chromosomes – interchanging
        /// randomly selected sub trees.</para></remarks>
        ///
        public override void Crossover(IChromosome pair)
        {
            var p = (GPTreeChromosome)pair;

            // check for correct pair
            if (p != null)
            {
                // do we need to use root node for crossover ?
                if ((root.Children == null) || (rand.Next(maxLevel) == 0))
                {
                    // give the root to the pair and use pair's part as a new root
                    root = p.RandomSwap(root);
                }
                else
                {
                    var node = root;

                    for (; ;)
                    {
                        // choose random child
                        var r     = rand.Next(node.Gene.ArgumentsCount);
                        var child = node.Children[r];

                        // swap the random node, if it is an end node or
                        // random generator "selected" this node
                        if ((child.Children == null) || (rand.Next(maxLevel) == 0))
                        {
                            // swap the node with pair's one
                            node.Children[r] = p.RandomSwap(child);
                            break;
                        }

                        // go further by tree
                        node = child;
                    }
                }
                // trim both of them
                Trim(root, maxLevel);
                Trim(p.root, maxLevel);
            }
        }
 /// <summary>
 /// Trim tree node, so its depth does not exceed specified level.
 /// </summary>
 private static void Trim(GPTreeNode node, int level)
 {
     // check if the node has children
     if (node.Children != null)
     {
         if (level == 0)
         {
             // remove all children
             node.Children = null;
             // and make the node of argument type
             node.Gene.Generate(GPGeneType.Argument);
         }
         else
         {
             // go further to children
             foreach (var n in node.Children)
             {
                 Trim(n, level - 1);
             }
         }
     }
 }
        /// <summary>
        /// Crossover helper routine - selects random node of chromosomes tree and
        /// swaps it with specified node.
        /// </summary>
        private GPTreeNode RandomSwap(GPTreeNode source)
        {
            GPTreeNode retNode = null;

            // swap root node ?
            if ((root.Children == null) || (rand.Next(maxLevel) == 0))
            {
                // replace current root and return it
                retNode = root;
                root    = source;
            }
            else
            {
                var node = root;

                for (; ;)
                {
                    // choose random child
                    var r     = rand.Next(node.Gene.ArgumentsCount);
                    var child = node.Children[r];

                    // swap the random node, if it is an end node or
                    // random generator "selected" this node
                    if ((child.Children == null) || (rand.Next(maxLevel) == 0))
                    {
                        // swap the node with pair's one
                        retNode          = child;
                        node.Children[r] = source;
                        break;
                    }

                    // go further by tree
                    node = child;
                }
            }
            return(retNode);
        }
 /// <summary>
 /// Trim tree node, so its depth does not exceed specified level.
 /// </summary>
 private static void Trim( GPTreeNode node, int level )
 {
     // check if the node has children
     if ( node.Children != null )
     {
         if ( level == 0 )
         {
             // remove all children
             node.Children = null;
             // and make the node of argument type
             node.Gene.Generate( GPGeneType.Argument );
         }
         else
         {
             // go further to children
             foreach ( GPTreeNode n in node.Children )
             {
                 Trim( n, level - 1 );
             }
         }
     }
 }
        /// <summary>
        /// Mutation operator.
        /// </summary>
        ///
        /// <remarks><para>The method performs chromosome's mutation by regenerating tree's
        /// randomly selected node.</para></remarks>
        ///
        public override void Mutate()
        {
            // current tree level
            var currentLevel = 0;
            // current node
            var node = root;

            for (; ;)
            {
                // regenerate node if it does not have children
                if (node.Children == null)
                {
                    if (currentLevel == maxLevel)
                    {
                        // we reached maximum possible level, so the gene
                        // can be an argument only
                        node.Gene.Generate(GPGeneType.Argument);
                    }
                    else
                    {
                        // generate subtree
                        Generate(node, rand.Next(maxLevel - currentLevel));
                    }
                    break;
                }

                // if it is a function node, than we need to get a decision, about
                // mutation point - the node itself or one of its children
                var r = rand.Next(node.Gene.ArgumentsCount + 1);

                if (r == node.Gene.ArgumentsCount)
                {
                    // node itself should be regenerated
                    node.Gene.Generate();

                    // check current type
                    if (node.Gene.GeneType == GPGeneType.Argument)
                    {
                        node.Children = null;
                    }
                    else
                    {
                        // create children's list if it was absent
                        if (node.Children == null)
                        {
                            node.Children = new List <GPTreeNode>();
                        }

                        // check for missing or extra children
                        if (node.Children.Count != node.Gene.ArgumentsCount)
                        {
                            if (node.Children.Count > node.Gene.ArgumentsCount)
                            {
                                // remove extra children
                                node.Children.RemoveRange(node.Gene.ArgumentsCount, node.Children.Count - node.Gene.ArgumentsCount);
                            }
                            else
                            {
                                // add missing children
                                for (var i = node.Children.Count; i < node.Gene.ArgumentsCount; i++)
                                {
                                    // create new child
                                    var child = new GPTreeNode();
                                    Generate(child, rand.Next(maxLevel - currentLevel));
                                    // add the new child
                                    node.Children.Add(child);
                                }
                            }
                        }
                    }
                    break;
                }

                // mutation goes further to one of the children
                node = node.Children[r];
                currentLevel++;
            }
        }
		/// <summary>
		/// Get tree representation of the chromosome.
		/// </summary>
		/// 
		/// <returns>Returns expression's tree represented by the chromosome.</returns>
		/// 
		/// <remarks><para>The method builds expression's tree for the native linear representation
		/// of the GEP chromosome.</para></remarks>
		/// 
		protected GPTreeNode GetTree( )
		{
			// function node queue. the queue contains function node,
			// which requires children. when a function node receives
			// all children, it will be removed from the queue
			Queue<GPTreeNode> functionNodes = new Queue<GPTreeNode>();

			// create root node
			GPTreeNode root = new GPTreeNode(genes[0]);

			// check children amount of the root node
			if ( root.Gene.ArgumentsCount != 0 )
			{
				root.Children = new List<GPTreeNode>( );
				// place the root to the queue
				functionNodes.Enqueue( root );

				// go through genes
				for ( int i = 1; i < length; i++ )
				{
					// create new node
					GPTreeNode node = new GPTreeNode( genes[i] );

					// if next gene represents function, place it to the queue
					if ( genes[i].GeneType == GPGeneType.Function )
					{
						node.Children = new List<GPTreeNode>( );
						functionNodes.Enqueue( node );
					}

					// get function node from the top of the queue
					GPTreeNode parent = (GPTreeNode) functionNodes.Peek( );

					// add new node to children of the parent node
					parent.Children.Add( node );

					// remove the parent node from the queue, if it is
					// already complete
					if ( parent.Children.Count == parent.Gene.ArgumentsCount )
					{
						functionNodes.Dequeue( );

						// check the queue if it is empty
						if ( functionNodes.Count == 0 )
							break;
					}
				}
			}
			// return formed tree
			return root;
		}
 /// <summary>
 /// Generate random chromosome value.
 /// </summary>
 /// 
 /// <remarks><para>Regenerates chromosome's value using random number generator.</para>
 /// </remarks>
 ///
 public override void Generate( )
 {
     // randomize the root
     root.Gene.Generate( );
     // create children
     if ( root.Gene.ArgumentsCount != 0 )
     {
         root.Children = new List<GPTreeNode>( );
         for ( int i = 0; i < root.Gene.ArgumentsCount; i++ )
         {
             // create new child
             GPTreeNode child = new GPTreeNode( );
             Generate( child, rand.Next( maxInitialLevel ) );
             // add the new child
             root.Children.Add( child );
         }
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="GPTreeChromosome"/> class.
 /// </summary>
 /// 
 /// <param name="source">Source genetic tree to clone from.</param>
 /// 
 /// <remarks><para>This constructor creates new genetic tree as a copy of the
 /// specified <paramref name="source"/> tree.</para></remarks>
 /// 
 protected GPTreeChromosome( GPTreeChromosome source )
 {
     root = (GPTreeNode) source.root.Clone( );
     fitness = source.fitness;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="GPTreeChromosome"/> class.
 /// </summary>
 ///
 /// <param name="source">Source genetic tree to clone from.</param>
 ///
 /// <remarks><para>This constructor creates new genetic tree as a copy of the
 /// specified <paramref name="source"/> tree.</para></remarks>
 ///
 protected GPTreeChromosome(GPTreeChromosome source)
 {
     root    = (GPTreeNode)source.root.Clone();
     fitness = source.fitness;
 }
        /// <summary>
        /// Generate chromosome's subtree of specified level.
        /// </summary>
        /// 
        /// <param name="node">Sub tree's node to generate.</param>
        /// <param name="level">Sub tree's level to generate.</param>
        /// 
        protected void Generate( GPTreeNode node, int level )
        {
            // create gene for the node
            if ( level == 0 )
            {
                // the gene should be an argument
                node.Gene = root.Gene.CreateNew( GPGeneType.Argument );
            }
            else
            {
                // the gene can be function or argument
                node.Gene = root.Gene.CreateNew( );
            }

            // add children
            if ( node.Gene.ArgumentsCount != 0 )
            {
                node.Children = new List<GPTreeNode>( );
                for ( int i = 0; i < node.Gene.ArgumentsCount; i++ )
                {
                    // create new child
                    GPTreeNode child = new GPTreeNode( );
                    Generate( child, level - 1 );
                    // add the new child
                    node.Children.Add( child );
                }
            }
        }
        /// <summary>
        /// Mutation operator.
        /// </summary>
        /// 
        /// <remarks><para>The method performs chromosome's mutation by regenerating tree's
        /// randomly selected node.</para></remarks>
        ///
        public override void Mutate( )
        {
            // current tree level
            int			currentLevel = 0;
            // current node
            GPTreeNode	node = root;

            for ( ; ; )
            {
                // regenerate node if it does not have children
                if ( node.Children == null )
                {
                    if ( currentLevel == maxLevel )
                    {
                        // we reached maximum possible level, so the gene
                        // can be an argument only
                        node.Gene.Generate( GPGeneType.Argument );
                    }
                    else
                    {
                        // generate subtree
                        Generate( node, rand.Next( maxLevel - currentLevel ) );
                    }
                    break;
                }

                // if it is a function node, than we need to get a decision, about
                // mutation point - the node itself or one of its children
                int r = rand.Next( node.Gene.ArgumentsCount + 1 );

                if ( r == node.Gene.ArgumentsCount )
                {
                    // node itself should be regenerated
                    node.Gene.Generate( );

                    // check current type
                    if ( node.Gene.GeneType == GPGeneType.Argument )
                    {
                        node.Children = null;
                    }
                    else
                    {
                        // create children's list if it was absent
                        if ( node.Children == null )
                            node.Children = new List<GPTreeNode>( );

                        // check for missing or extra children
                        if ( node.Children.Count != node.Gene.ArgumentsCount )
                        {
                            if ( node.Children.Count > node.Gene.ArgumentsCount )
                            {
                                // remove extra children
                                node.Children.RemoveRange( node.Gene.ArgumentsCount, node.Children.Count - node.Gene.ArgumentsCount );
                            }
                            else
                            {
                                // add missing children
                                for ( int i = node.Children.Count; i < node.Gene.ArgumentsCount; i++ )
                                {
                                    // create new child
                                    GPTreeNode child = new GPTreeNode( );
                                    Generate( child, rand.Next( maxLevel - currentLevel ) );
                                    // add the new child
                                    node.Children.Add( child );
                                }
                            }
                        }
                    }
                    break;
                }

                // mutation goes further to one of the children
                node = (GPTreeNode) node.Children[r];
                currentLevel++;
            }
        }
        /// <summary>
        /// Crossover helper routine - selects random node of chromosomes tree and
        /// swaps it with specified node.
        /// </summary>
        private GPTreeNode RandomSwap( GPTreeNode source )
        {
            GPTreeNode retNode = null;

            // swap root node ?
            if ( ( root.Children == null ) || ( rand.Next( maxLevel ) == 0 ) )
            {
                // replace current root and return it
                retNode = root;
                root = source;
            }
            else
            {
                GPTreeNode node = root;

                for ( ; ; )
                {
                    // choose random child
                    int r = rand.Next( node.Gene.ArgumentsCount );
                    GPTreeNode child = (GPTreeNode) node.Children[r];

                    // swap the random node, if it is an end node or
                    // random generator "selected" this node
                    if ( ( child.Children == null ) || ( rand.Next( maxLevel ) == 0 ) )
                    {
                        // swap the node with pair's one
                        retNode = child;
                        node.Children[r] = source;
                        break;
                    }

                    // go further by tree
                    node = child;
                }
            }
            return retNode;
        }
        /// <summary>
        /// Crossover operator.
        /// </summary>
        /// 
        /// <param name="pair">Pair chromosome to crossover with.</param>
        /// 
        /// <remarks><para>The method performs crossover between two chromosomes – interchanging
        /// randomly selected sub trees.</para></remarks>
        ///
        public override void Crossover( IChromosome pair )
        {
            GPTreeChromosome p = (GPTreeChromosome) pair;

            // check for correct pair
            if ( p != null )
            {
                // do we need to use root node for crossover ?
                if ( ( root.Children == null ) || ( rand.Next( maxLevel ) == 0 ) )
                {
                    // give the root to the pair and use pair's part as a new root
                    root = p.RandomSwap( root );
                }
                else
                {
                    GPTreeNode node = root;

                    for ( ; ; )
                    {
                        // choose random child
                        int r = rand.Next( node.Gene.ArgumentsCount );
                        GPTreeNode child = (GPTreeNode) node.Children[r];

                        // swap the random node, if it is an end node or
                        // random generator "selected" this node
                        if ( ( child.Children == null ) || ( rand.Next( maxLevel ) == 0 ) )
                        {
                            // swap the node with pair's one
                            node.Children[r] = p.RandomSwap( child );
                            break;
                        }

                        // go further by tree
                        node = child;
                    }
                }
                // trim both of them
                Trim( root, maxLevel );
                Trim( p.root, maxLevel );
            }
        }