/ benchmark / genetics / Reproduction.java
Reproduction.java
 1  package genetics;
 2  
 3  import java.util.HashMap;
 4  import java.util.Map;
 5  
 6  /**
 7   * The Reproduction class defines how a parent population reproduces
 8   *
 9   * Offspring of a parent population are generated according to the fitness of the individuals in the parent population
10   * The genes of children are generated using crossing over and mutation
11   */
12  public class Reproduction {
13  
14      private static final double CROSSOVER_RATE = 0.5;
15      private static final double MUTATION_RATE = 0.025;
16      private static final double NEW_MUTATION_RATE = 0.025;
17      private static final int TOURNAMENT_SIZE = 4;
18      private static final boolean ELITISM = true;
19  
20      /**
21       * @return The offspring of the input population
22       */
23      public static Population reproduce(Population population, Map<String, Gene> genes) {
24          Population offspring = new Population(population.size(), population.getGeneration() + 1);
25  
26          // Keep our best individual
27          if (ELITISM) {
28              offspring.setIndividual(0, population.getFittest());
29              offspring.getIndividual(0).setFitness(0.0);
30          }
31          int elitismOffset = ELITISM ? 1 : 0;
32  
33          // Cross the individuals
34          for (int i = elitismOffset; i < population.size(); i++) {
35              Individual indiv1 = tournamentSelection(population);
36              Individual indiv2 = tournamentSelection(population);
37              offspring.setIndividual(i, crossover(indiv1, indiv2));
38          }
39  
40          // Mutate new individuals
41          for (int i = elitismOffset; i < offspring.size(); i++) {
42              mutate(offspring.getIndividual(i), genes);
43          }
44  
45          return offspring;
46      }
47  
48      private static Individual crossover(Individual indA, Individual indB) {
49          HashMap<String, Double> chromosome = new HashMap<>();
50          for (String gene : indA.getChromosome().keySet()){
51              if (Math.random() <= CROSSOVER_RATE) {
52                  chromosome.put(gene, indA.getAllele(gene));
53              } else {
54                  chromosome.put(gene, indB.getAllele(gene));
55              }
56          }
57          return new Individual(chromosome);
58      }
59  
60      private static void mutate(Individual individual, Map<String, Gene> genes) {
61          HashMap<String, Double> chromosome = new HashMap<>();
62          for (HashMap.Entry<String, Double> allele : individual.getChromosome().entrySet()){
63              Double value = allele.getValue();
64              if (Math.random() <= MUTATION_RATE){
65                  Gene gene = genes.get(allele.getKey());
66                  value =  gene.mutate(value);
67              } else if (Math.random() <= NEW_MUTATION_RATE){
68                  Gene gene = genes.get(allele.getKey());
69                  value =  gene.generateAllele();
70              }
71              chromosome.put(allele.getKey(), value);
72          }
73          individual.setChromosome(chromosome);
74      }
75  
76      /**
77       * Creates a tournament population and returns the fittest individual in that population
78       */
79      private static Individual tournamentSelection(Population population) {
80          Population tournament = new Population(TOURNAMENT_SIZE, 0);
81          for (int i = 0; i < TOURNAMENT_SIZE; i++) {
82              int randomId = (int) (Math.random() * population.size());
83              tournament.setIndividual(i, population.getIndividual(randomId));
84          }
85          return tournament.getFittest();
86      }
87  }