Esempio n. 1
0
        /// <summary>
        /// Clonar el nodo
        /// </summary>
        public object Clone()
        {
            TreeNode clone = new TreeNode();

            clone.Gene = this.Gene.Clone();
            // se clonan los hijos tambien
            if (this.Children != null)
            {
                clone.Children = new ArrayList();
                // de cada hijo clonamos sus genes
                foreach (TreeNode node in Children)
                {
                    clone.Children.Add(node.Clone());
                }
            }
            return clone;
        }
        /// <summary>
        /// Rutina helper para el operador de cruce
        /// Selecciona un nodo random de un arbol y lo intercambia con otro 
        /// nodo random de otro arbol
        /// </summary>
        private TreeNode RandomSwap(TreeNode source)
        {
            TreeNode retNode = null;

            // swappeamos la raiz?
            if ((root.Children == null) || (rand.Next(maxLevel) == 0))
            {
                // intercambiamos
                retNode = root;
                root = source;
            }
            else
            {
                TreeNode node = root;

                for (; ; )
                {
                    // se elije un hijo random
                    int r = rand.Next(node.Gene.ArgumentsCount);
                    TreeNode child = (TreeNode)node.Children[r];

                    // swappeamos el hijo
                    if ((child.Children == null) || (rand.Next(maxLevel) == 0))
                    {
                        // con el nodo del amigo
                        retNode = child;
                        node.Children[r] = source;
                        break;
                    }

                    // seguimos recorriendo el arbol
                    node = child;
                }
            }
            return retNode;
        }
 /// <summary>
 /// Constructor de copia
 /// </summary>
 protected TreeIndividual(TreeIndividual source)
 {
     root = (TreeNode)source.root.Clone();
     fitness = source.fitness;
 }
 /// <summary>
 /// Poda el arbol, para que no se pase del nivel provisto
 /// </summary>
 private static void Trim(TreeNode node, int level)
 {
     // checkear si tiene hijos
     if (node.Children != null)
     {
         if (level == 0)
         {
             // se quitan todos
             node.Children = null;
             // se hace que el nodo sea hoja
             node.Gene.Generate(GeneType.Argument);
         }
         else
         {
             // recorriendo los hijos
             foreach (TreeNode n in node.Children)
             {
                 Trim(n, level - 1);
             }
         }
     }
 }
        /// <summary>
        /// Genera un subarbol del nivel especificado
        /// </summary>
        protected void Generate(TreeNode node, int level)
        {
            if (level == 0)
            {
                // si el nivel es 0, deberia ser un argumento, pues
                // una expresion no puede contener solo un operador
                node.Gene = root.Gene.CreateNew(GeneType.Argument);
            }
            else
            {
                // si level > 0, puede ser operador o variable
                node.Gene = root.Gene.CreateNew();
            }

            // agregar hijos
            if (node.Gene.ArgumentsCount != 0)
            {
                node.Children = new ArrayList();
                for (int i = 0; i < node.Gene.ArgumentsCount; i++)
                {
                    // nuevo hijo
                    TreeNode child = new TreeNode();
                    Generate(child, level - 1);
                    // agregar el hijo
                    node.Children.Add(child);
                }
            }
        }
        /// <summary>
        /// Operador de mutacion
        /// </summary>
        public virtual void Mutate()
        {
            // nivel actual
            int currentLevel = 0;
            // nodo actual
            TreeNode node = root;

            for (; ; )
            {
                // regenerar nodo si no tiene hijos
                if (node.Children == null)
                {
                    if (currentLevel == maxLevel)
                    {
                        // si llegamos al maximo nivel, en las hojas
                        // solo puede haber variables
                        node.Gene.Generate(GeneType.Argument);
                    }
                    else
                    {
                        // no llegamos al maximo nivel, generar subarbol
                        Generate(node, rand.Next(maxLevel - currentLevel));
                    }
                    break;
                }
                // Si es un nodo operador, debemos elegir el punto de mutacion,
                // el nodo mismo o uno de sus hijos
                int r = rand.Next(node.Gene.ArgumentsCount + 1);

                if (r == node.Gene.ArgumentsCount)
                {
                    // el nodo mismo se regenera
                    node.Gene.Generate();

                    // chequeamos el tipo
                    if (node.Gene.GeneType == GeneType.Argument)
                    {
                        node.Children = null;
                    }
                    else
                    {
                        // crear lista de hijos si no tiene
                        if (node.Children == null)
                            node.Children = node.Children = new ArrayList();

                        // nos fijamos si le faltan argumentos al operador,
                        //en tal caso agregamos hijos
                        if (node.Children.Count != node.Gene.ArgumentsCount)
                        {
                            if (node.Children.Count > node.Gene.ArgumentsCount)
                            {
                                // quitamos hijos de mas
                                node.Children.RemoveRange(node.Gene.ArgumentsCount, node.Children.Count - node.Gene.ArgumentsCount);
                            }
                            else
                            {
                                // agregamos hijos faltantes
                                for (int i = node.Children.Count; i < node.Gene.ArgumentsCount; i++)
                                {
                                    TreeNode child = new TreeNode();
                                    Generate(child, rand.Next(maxLevel - currentLevel));
                                    node.Children.Add(child);
                                }
                            }
                        }
                    }
                    break;
                }

                node = (TreeNode)node.Children[r];
                currentLevel++;
            }
        }
 /// <summary>
 /// Generar arbol aleatorio
 /// </summary>
 public virtual void Generate()
 {
     // se aleatoriza la raiz
     root.Gene.Generate();
     // y se crean hijos
     if (root.Gene.ArgumentsCount != 0)
     {
         root.Children = new ArrayList();
         for (int i = 0; i < root.Gene.ArgumentsCount; i++)
         {
             // nuevo hijo
             TreeNode child = new TreeNode();
             Generate(child, rand.Next(maxInitialLevel));
             // se agrega al nuevo nodito
             root.Children.Add(child);
         }
     }
 }
        /// <summary>
        /// Operador de cruce
        /// </summary>
        public virtual void Crossover(IIndividual pair)
        {
            TreeIndividual p = (TreeIndividual)pair;

            if (p != null)
            {
                // necesitamos cruzar en la raiz?
                if ((root.Children == null) || (rand.Next(maxLevel) == 0))
                {
                    // le damos la raiz al individuo, y lo usamos parte
                    // suya como nueva raiz (seria como un injerto)
                    root = p.RandomSwap(root);
                }
                else
                {
                    TreeNode node = root;

                    for (; ; )
                    {
                        // elegimos un hijo al azar
                        int r = rand.Next(node.Gene.ArgumentsCount);
                        TreeNode child = (TreeNode)node.Children[r];

                        // swappeamos en un nodo al azar
                        if ((child.Children == null) || (rand.Next(maxLevel) == 0))
                        {
                            // con el del individuo provisto
                            node.Children[r] = p.RandomSwap(child);
                            break;
                        }

                        // continuamos por el arbol
                        node = child;
                    }
                }
                // podamos un poco
                //TODO: Comentar???
                Trim(root, maxLevel);
                Trim(p.root, maxLevel);
            }
        }