All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.chen0040.gp.treegp.program.TreeGenerator Maven / Gradle / Ivy

package com.github.chen0040.gp.treegp.program;


import com.github.chen0040.gp.services.RandEngine;
import com.github.chen0040.gp.treegp.TreeGP;
import com.github.chen0040.gp.treegp.enums.TGPInitializationStrategy;


/**
 * Created by xschen on 14/5/2017.
 */
public class TreeGenerator {

   /// 
   /// Method that creates a subtree of maximum depth
   /// 
   /// The root node of the subtree
   /// The maximum depth
   /// The method used to build the subtree
   public static void createWithDepth(Program program, TreeNode x, int allowableDepth, TGPInitializationStrategy method, RandEngine randEngine) {

      int child_count = x.arity();

      for (int i = 0; i != child_count; ++i)
      {
         Primitive primitive = anyPrimitive(program, allowableDepth, method, randEngine);
         TreeNode child = new TreeNode(primitive);
         x.getChildren().add(child);

         if (!primitive.isTerminal())
         {
            createWithDepth(program, child, allowableDepth - 1, method, randEngine);
         }
      }
   }

   /// 
   /// Method that creates a GP tree with a maximum tree depth
   /// 
   /// TreeGP config
   public static TreeNode createWithDepth(Program program, int allowableDepth, TreeGP manager, TGPInitializationStrategy method)
   {
      OperatorSet operatorSet = program.getOperatorSet();
      RandEngine randEngine = manager.getRandEngine();

      TreeNode root;

      //  Population Initialization method following the "RandomBranch" method described in "Kumar Chellapilla. Evolving computer programs without subtree crossover. IEEE Transactions on Evolutionary Computation, 1(3):209–216, September 1997."
      if (method == TGPInitializationStrategy.INITIALIZATION_METHOD_RANDOM_BRANCH)
      {
         int s = allowableDepth; //tree size
         Primitive non_terminal = program.anyOperatorWithArityLessThan(s, randEngine);
         if (non_terminal == null)
         {
            root = new TreeNode(program.anyTerminal(randEngine));
         }
         else
         {
            root = new TreeNode(non_terminal);
            int b_n = non_terminal.arity();
            s = (int)Math.floor((double)s / b_n);
            randomBranch(program, root, s, randEngine);
         }
      }
      // Population Initialization method following the "PTC1" method described in "Sean Luke. Two fast tree-creation algorithms for genetic programming. IEEE Transactions in Evolutionary Computation, 4(3), 2000b."
      else if(method==TGPInitializationStrategy.INITIALIZATION_METHOD_PTC1)
      {
         // TODO: Change this one later back to use tag
         int expectedTreeSize = 20; //Convert.ToInt32(tag);

         int b_n_sum=0;
         for(int i=0; i < operatorSet.size(); ++i)
         {
            b_n_sum+=operatorSet.get(i).arity();
         }
         double p= (1- 1.0 / expectedTreeSize) / ((double)b_n_sum / operatorSet.size());

         Primitive data = null;
         if(randEngine.uniform() <= p)
         {
            data = program.anyOperator(randEngine);
         }
         else
         {
            data = program.anyTerminal(randEngine);
         }

         root = new TreeNode(data);
         PTC1(program, root, p, allowableDepth-1, randEngine);


      }
      else // handle full and grow method
      {
         root = new TreeNode(anyPrimitive(program, allowableDepth, method, randEngine));

         createWithDepth(program, root, allowableDepth - 1, method, randEngine);
      }

      return root;
   }

   /// 
   /// Population Initialization Method described in "Kumar Chellapilla. Evolving computer programs without subtree crossover. IEEE Transactions on Evolutionary Computation, 1(3):209–216, September 1997."
   /// 
   /// 
   /// 
   /// 
   private static void randomBranch(Program program, TreeNode x, int s, RandEngine randEngine)
   {
      int child_count = x.arity();

      for (int i = 0; i != child_count; i++)
      {
         Primitive non_terminal= program.anyOperatorWithArityLessThan(s, randEngine);
         if (non_terminal == null)
         {
            TreeNode child = new TreeNode(program.anyTerminal(randEngine));
            x.getChildren().add(child);
         }
         else
         {
            TreeNode child = new TreeNode(non_terminal);
            x.getChildren().add(child);
            int b_n=non_terminal.arity();
            int s_pi = (int)Math.floor((double)s / b_n);
            randomBranch(program, child, s_pi, randEngine);
         }
      }
   }

   /// 
   /// Population Initialization method following the "PTC1" method described in "Sean Luke. Two fast tree-creation algorithms for genetic programming. IEEE Transactions in Evolutionary Computation, 4(3), 2000b."
   /// 
   /// The node for which the child nodes are generated in this method
   /// expected probability
   /// The maximum tree depth
   private static void PTC1(Program program, TreeNode parent_node, double p, int allowableDepth, RandEngine randEngine)
   {
      int child_count = parent_node.arity();

      for (int i = 0; i != child_count; i++)
      {
         Primitive data;
         if (allowableDepth == 0)
         {
            data = program.anyTerminal(randEngine);
         }
         else if (randEngine.uniform() <= p)
         {
            data = program.anyOperator(randEngine);
         }
         else
         {
            data = program.anyTerminal(randEngine);
         }

         TreeNode child = new TreeNode(data);
         parent_node.getChildren().add(child);

         if(!data.isTerminal())
         {
            PTC1(program, child, p, allowableDepth - 1, randEngine);
         }
      }
   }



   /// 
   /// Method that follows the implementation of GP initialization in Algorithm 2.1 of "A Field Guide to Genetic Programming"
   /// 
   /// Maximum depth of the GP tree
   /// The initialization method, currently either "Grow" or "Full"
   /// 
   public static Primitive anyPrimitive(Program program, int allowableDepth, TGPInitializationStrategy method, RandEngine randEngine)
   {
      int terminal_count = (program.getVariableSet().size() + program.getConstantSet().size());
      int function_count = program.getOperatorSet().size();

      double terminal_prob=(double)terminal_count / (terminal_count + function_count);
      if (allowableDepth <= 0 || (method == TGPInitializationStrategy.INITIALIZATION_METHOD_GROW && randEngine.uniform() <= terminal_prob))
      {
         return program.anyTerminal(randEngine);
      }
      else
      {
         return program.anyOperator(randEngine);
      }
   }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy