1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math.genetics;
18  
19  import static org.junit.Assert.*;
20  
21  import java.util.LinkedList;
22  import java.util.List;
23  import org.junit.Test;
24  
25  
26  public class FitnessCachingTest {
27      
28      // parameters for the GA
29      private static final int DIMENSION = 50; 
30      private static final double CROSSOVER_RATE = 1;
31      private static final double MUTATION_RATE = 0.1;
32      private static final int TOURNAMENT_ARITY = 5;
33      
34      private static final int POPULATION_SIZE = 10;
35      private static final int NUM_GENERATIONS = 50;
36      private static final double ELITISM_RATE = 0.2;
37  
38      // how many times was the fitness computed
39      public static int fitnessCalls = 0;
40  
41  
42      @Test
43      public void testFitnessCaching() {
44          // initialize a new genetic algorithm
45          GeneticAlgorithm ga = new GeneticAlgorithm(
46                  new OnePointCrossover<Integer>(),
47                  CROSSOVER_RATE, // all selected chromosomes will be recombined (=crosssover)
48                  new BinaryMutation(),
49                  MUTATION_RATE, // no mutation
50                  new TournamentSelection(TOURNAMENT_ARITY)
51          );
52          
53          // initial population
54          Population initial = randomPopulation();
55          // stopping conditions
56          StoppingCondition stopCond = new FixedGenerationCount(NUM_GENERATIONS);
57          
58          // run the algorithm
59          ga.evolve(initial, stopCond);
60          
61          int neededCalls =
62              POPULATION_SIZE /*initial population*/ +
63              (NUM_GENERATIONS - 1) /*for each population*/ * (int)(POPULATION_SIZE * (1.0 - ELITISM_RATE)) /*some chromosomes are copied*/
64              ;
65          assertTrue(fitnessCalls <= neededCalls); // some chromosomes after crossover may be the same os old ones
66      }
67  
68  
69      /**
70       * Initializes a random population.
71       */
72      private static ElitisticListPopulation randomPopulation() {
73          List<Chromosome> popList = new LinkedList<Chromosome>();
74          
75          for (int i=0; i<POPULATION_SIZE; i++) {
76              BinaryChromosome randChrom = new DummyCountingBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(DIMENSION));
77              popList.add(randChrom);
78          }        
79          return new ElitisticListPopulation(popList, popList.size(), ELITISM_RATE);
80      }
81      
82      private static class DummyCountingBinaryChromosome extends DummyBinaryChromosome {
83  
84          public DummyCountingBinaryChromosome(List<Integer> representation) {
85              super(representation);
86          }        
87  
88          @Override
89          public double fitness() {
90              fitnessCalls++;
91              return 0;
92          }
93      }
94  }