public static string ToNormalNotation(GPTreeNode curNode) { var sb = new StringBuilder(); if ((curNode.Children != null) && (curNode.Children.Count > 0)) { sb.Append("("); if (curNode.Children.Count == 1) { //if node's gene is a 1-arg function, write (op child1) sb.AppendFormat("{0} {1}", curNode.Gene, ToNormalNotation(curNode.Children[0])); } else { //else, write expression (child1 op child2) sb.AppendFormat("{0} {1} {2}", ToNormalNotation(curNode.Children[0]), curNode.Gene, ToNormalNotation(curNode.Children[1])); } sb.Append(")"); } else { //else just write the gene string rep sb.Append(curNode.Gene.ToString()); } return(sb.ToString()); }
protected static void ProcessNode(GPTreeNode curNode, Stack <GPTreeNode> nodeStack) { //processes each expected child node var argumentsCount = curNode.Gene.ArgumentsCount; for (var i = 0; i < argumentsCount; i++) { if (nodeStack.Count == 0) { return; } //gets child node from stack, if possible, and processes that node var childNode = nodeStack.Pop(); if (curNode.Children == null) { curNode.Children = new List <GPTreeNode>(argumentsCount); } curNode.Children.Add(childNode); ProcessNode(childNode, nodeStack); } //reverse order of children for correct order if (argumentsCount == 0) { return; } curNode.Children.Reverse(); }
public static uint GetDepth(GPTreeNode curNode, uint curDepth) { //for each child determines depth by adding one level, return max child depth if ((curNode.Children != null) && (curNode.Children.Count > 0)) { return(curNode.Children.Max(child => GetDepth(child, curDepth + 1))); } //or else just return current depth return(curDepth); }
public static List <GPTreeNode> GetAllChildren(GPTreeNode node) { var children = new List <GPTreeNode> { node }; if ((node.Children != null) && (node.Children.Count > 0)) { foreach (var child in node.Children) { children.AddRange(GetAllChildren(child)); } } return(children); }
public static HashSet <ChromosomeParameters> GenerateAllCombinations(GPTreeNode node) { var combChromosomes = new HashSet <ChromosomeParameters>(); //tests end condition, ie no more children, add node itself if ((node.Children == null) || (node.Children.Count == 0)) { combChromosomes.Add(new ChromosomeParameters { ProgramExpression = node.ToString() }); return(combChromosomes); } //add all combinations from each child foreach (var child in node.Children) { combChromosomes.UnionWith(GenerateAllCombinations(child)); } //for one argument functions, gets children var children0 = GetAllChildren(node.Children[0]); //creates combinations for all children foreach (var child0 in children0) { var newNode = (GPTreeNode)node.Clone(); newNode.Children[0] = child0; combChromosomes.Add(new ChromosomeParameters { ProgramExpression = newNode.ToString() }); } //for two argument functions if (node.Children.Count < 2) { return(combChromosomes); } //gets children from both sides var children1 = GetAllChildren(node.Children[1]); //creates combinations between the different children foreach (var child0 in children0) { foreach (var child1 in children1) { var newNode = (GPTreeNode)node.Clone(); newNode.Children[0] = child0; newNode.Children[1] = child1; combChromosomes.Add(new ChromosomeParameters { ProgramExpression = newNode.ToString() }); } } //if function is subtraction if (!node.Gene.ToString().Equals(RewardGeneFunction.GetFunctionTypeString(FunctionType.Subtract))) { return(combChromosomes); } //consider right side negative by adding "0 - 'childNode'" foreach (var child1 in children1) { var newNode = (GPTreeNode)node.Clone(); newNode.Children[0] = ZeroNode; newNode.Children[1] = child1; combChromosomes.Add(new ChromosomeParameters { ProgramExpression = newNode.ToString() }); } return(combChromosomes); }
/// <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> /// 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> /// 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> /// 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> /// 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> /// 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> /// 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> /// 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; }