/// <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 or constant node.Gene = root.Gene.CreateNew((rand.Next(4) >= 2) ? GPGeneType.Constant : GPGeneType.Argument); //GPGeneType.Argument } else { // the gene can be function or argument or constant 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> /// 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 = null; try { child = (GPTreeNode)node.Children[r]; } catch (ArgumentOutOfRangeException e) { child = node; } // 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; try { node.Children[r] = source; } catch (ArgumentOutOfRangeException e) { node.Children.Add(source); //node = source; } break; } // go further by tree node = child; } } return(retNode); }
/// <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> /// 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> /// 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> /// 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> /// 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> /// 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 = null; try { child = (GPTreeNode)node.Children[r]; } catch (ArgumentOutOfRangeException e) { child = node; } // testado mas alterou a forma de trabalho do cross-over //GPTreeNode child = (r <= 0) ? node : (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 try { node.Children[r] = p.RandomSwap(child); } catch (ArgumentOutOfRangeException e) { node.Children.Add(p.RandomSwap(child)); //node = p.RandomSwap(child); } break; } // go further by tree node = child; } } // trim both of them Trim(root, maxLevel); Trim(p.root, maxLevel); } }
/// <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> /// 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; }