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

com.github.chen0040.gp.treegp.gp.Population Maven / Gradle / Ivy

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


import com.github.chen0040.data.utils.TupleTwo;
import com.github.chen0040.gp.commons.TournamentSelection;
import com.github.chen0040.gp.commons.TournamentSelectionResult;
import com.github.chen0040.gp.services.RandEngine;
import com.github.chen0040.gp.treegp.TreeGP;
import com.github.chen0040.gp.treegp.enums.TGPPopulationReplacementStrategy;
import com.github.chen0040.gp.treegp.program.Solution;
import com.github.chen0040.gp.utils.CollectionUtils;
import com.github.chen0040.gp.utils.QuickSort;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


/**
 * Created by xschen on 15/5/2017.
 */
@Getter
@Setter
public class Population {

   private static final Logger logger = LoggerFactory.getLogger(Population.class);

   private final List solutions = new ArrayList<>();
   private final TreeGP manager;

   @Setter(AccessLevel.NONE)
   @Getter(AccessLevel.NONE)
   private Optional globalBestSolution = Optional.empty();

   private Solution bestSolutionInCurrentGeneration = null;
   private int currentGeneration;

   public Population(TreeGP manager) {
      this.manager = manager;
   }

   protected void evaluate() {

      double bestCost = Double.MAX_VALUE;
      for(int i=0; i< solutions.size(); ++i) {
         Solution p = solutions.get(i);
         evaluate(p);
         if (p.getCost() < bestCost) {
            bestSolutionInCurrentGeneration = p;
            bestCost = p.getCost();
         }
      }

      updateGlobal(bestSolutionInCurrentGeneration);
   }

   private void evaluate(Solution solution) {
      if(solution.isCostValid()) return;

      double cost = manager.evaluateCost(solution);
      solution.setCost(cost);
      solution.setCostValid(true);
   }

   private void updateGlobal(Solution solution) {
      if(!globalBestSolution.isPresent() || CollectionUtils.isBetterThan(solution, globalBestSolution.get()))
      {
         globalBestSolution = Optional.of(solution.makeCopy());
      }
   }

   public void initialize(){
      PopulationInitialization.apply(solutions, manager);
      evaluate();
   }

   public boolean isTerminated() {
      return currentGeneration >= manager.getMaxGeneration();
   }

   public void evolve(){

      TGPPopulationReplacementStrategy populationReplacement = manager.getReplacementStrategy();
      if (populationReplacement == TGPPopulationReplacementStrategy.MuPlusLambda)
      {
         muPlusLambdaEvolve();
      }
      else if (populationReplacement == TGPPopulationReplacementStrategy.TinyGP)
      {
         tinyGPEvolve();
      }

      currentGeneration++;
   }

   private void muPlusLambdaEvolve() {
      RandEngine randEngine = manager.getRandEngine();
      int iPopSize = this.manager.getPopulationSize();

      int elite_count = (int)(manager.getElitismRatio() * iPopSize);

      int crossover_count = (int)(this.manager.getCrossoverRate() * iPopSize);

      if (crossover_count % 2 != 0) crossover_count += 1;

      int micro_mutation_count = (int)(this.manager.getMicroMutationRate() * iPopSize);
      int macro_mutation_count = (int)(this.manager.getMacroMutationRate() * iPopSize);
      int reproduction_count = iPopSize - crossover_count - micro_mutation_count - macro_mutation_count;



      List offspring = new ArrayList<>();

      bestSolutionInCurrentGeneration = null;

      //do crossover
      for (int offspring_index = 0; offspring_index < crossover_count; offspring_index += 2)
      {
         TournamentSelectionResult tournament = TournamentSelection.select(solutions, randEngine);
         TupleTwo tournament_winners = tournament.getWinners();


         Solution child1 = tournament_winners._1().makeCopy();
         Solution child2 = tournament_winners._2().makeCopy();

         Crossover.apply(child1, child2, manager);

         offspring.add(child1);
         offspring.add(child2);
      }

      // do point mutation
      for (int offspring_index = 0; offspring_index < micro_mutation_count; ++offspring_index)
      {

         TournamentSelectionResult tournament = TournamentSelection.select(solutions, randEngine);
         TupleTwo tournament_winners = tournament.getWinners();

         Solution child = tournament_winners._1().makeCopy();

         MicroMutation.apply(child, manager);

         offspring.add(child);
      }

      // do subtree mutation
      for (int offspring_index = 0; offspring_index < macro_mutation_count; ++offspring_index)
      {
         TournamentSelectionResult tournament = TournamentSelection.select(solutions, randEngine);
         TupleTwo tournament_winners = tournament.getWinners();

         Solution child = tournament_winners._1().makeCopy();

         MacroMutation.apply(child, manager);

         offspring.add(child);

      }

      // do reproduction
      for (int offspring_index = 0; offspring_index < reproduction_count; ++offspring_index)
      {
         TournamentSelectionResult tournament = TournamentSelection.select(solutions, randEngine);
         TupleTwo tournament_winners = tournament.getWinners();
         Solution child = tournament_winners._1().makeCopy();

         offspring.add(child);
      }

      for (int i = 0; i < iPopSize; ++i)
      {
         Solution child = offspring.get(i);

         evaluate(child);

         if (bestSolutionInCurrentGeneration == null || child.isBetterThan(bestSolutionInCurrentGeneration))
         {
            bestSolutionInCurrentGeneration = child;
         }
      }


      updateGlobal(bestSolutionInCurrentGeneration);

      QuickSort.sort(solutions, Solution::compareTo);
      QuickSort.sort(offspring, Solution::compareTo);

      for (int offspring_index = elite_count; offspring_index < iPopSize; ++offspring_index)
      {
         solutions.set(offspring_index, offspring.get(offspring_index-elite_count));
      }
   }

   /// 
   /// Similar to Evolve2, but use offspring solution to replace bad parent, in a way similar to TinyGP as as specified in "A Field Guide to Genetic Programming"
   /// 
   /// 
   private void tinyGPEvolve()
   {
      int iPopSize = this.manager.getPopulationSize();

      double sum_rate = manager.getCrossoverRate()+manager.getMacroMutationRate()+manager.getMicroMutationRate()+manager.getReproductionRate();
      double crossover_disk = manager.getCrossoverRate() / sum_rate;
      double micro_mutation_disk = (manager.getCrossoverRate() + manager.getMicroMutationRate()) / sum_rate;
      double macro_mutation_disk = (manager.getCrossoverRate() + manager.getMicroMutationRate() + manager.getMacroMutationRate()) / sum_rate;

      RandEngine randEngine = manager.getRandEngine();

      bestSolutionInCurrentGeneration = globalBestSolution.orElse(null);
      for (int offspring_index = 0; offspring_index < iPopSize; offspring_index += 1)
      {
         double r = randEngine.uniform();
         List children = new ArrayList<>();

         List bad_parents = new ArrayList<>();

         TournamentSelectionResult tournament = TournamentSelection.select(solutions, randEngine);
         TupleTwo tournament_winners = tournament.getWinners();
         TupleTwo tournament_losers = tournament.getLosers();

         bad_parents.add(tournament_losers._1());
         bad_parents.add(tournament_losers._2());

         if (r <= crossover_disk) // do crossover
         {
            Solution child1 = tournament_winners._1().makeCopy();
            Solution child2 = tournament_winners._2().makeCopy();

            Crossover.apply(child1, child2, manager);

            children.add(child1);
            children.add(child2);
         }
         else if (r <= micro_mutation_disk) // do point mutation
         {
            Solution child = tournament_winners._1().makeCopy();
            MicroMutation.apply(child, manager);
            children.add(child);
         }
         else if (r <= macro_mutation_disk) // do subtree mutation
         {
            Solution child = tournament_winners._1().makeCopy();
            MacroMutation.apply(child, manager);
            children.add(child);
         }
         else // do reproduction
         {
            Solution child = tournament_winners._1().makeCopy();
            children.add(child);
         }


         boolean successfully_replaced = false;
         for(int i=0; i < children.size(); ++i)
         {
            Solution child = children.get(i);

            evaluate(child);

            if (bestSolutionInCurrentGeneration == null || child.isBetterThan(bestSolutionInCurrentGeneration))
            {
               bestSolutionInCurrentGeneration = child;
            }

            for (Solution bad_parent : bad_parents)
            {
               if (child.isBetterThan(bad_parent))
               {
                  successfully_replaced = true;
                  solutions.set(solutions.indexOf(bad_parent), child);
                  break;
               }
            }

            if (successfully_replaced)
            {
               break;
            }
         }

      }

      updateGlobal(bestSolutionInCurrentGeneration);
   }


   public Solution getGlobalBestSolution() {
      return globalBestSolution.get();
   }


   public double getCostInCurrentGeneration() {
      return bestSolutionInCurrentGeneration.getCost();
   }


   public int size() {
      return solutions.size();
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy