Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Tools/Evolution/BB2004Evo.h

Go to the documentation of this file.
00001 /**
00002 * @file BB2004Evo.h
00003 * 
00004 * This file implements a general approach to Evolutionary Algorithms.
00005 *
00006 * @author <a href="mailto:roefer@tzi.de">Thomas Röfer</a>
00007 */
00008 
00009 /**
00010 */
00011 
00012 #ifndef __BB2004Evo_h__
00013 #define __BB2004Evo_h__
00014 
00015 #include <stdlib.h>
00016 
00017 /**
00018 * The class is the abstract base class for indiviuals.
00019 * Concrete implementations only have to be derived from this class.
00020 */
00021 class BBIndividual
00022 {
00023 public:
00024   /**
00025   * The function initializes the current individual with another one.
00026   * It has to be implemented in a derived class.
00027   * @param initial The other individual the current one is initialized with.
00028   */
00029   virtual void init(const BBIndividual& initial) = 0;
00030   
00031   /**
00032   * The function interpolates between the current individual and another one.
00033   * The result is stored in the current individual.
00034   * It has to be implemented in a derived class.
00035   * @param other The other individual the current one is interpolated with.
00036   */
00037   virtual void interpolate(const BBIndividual& other) = 0;
00038 
00039   /**
00040   * The function extrapolates between the current individual and another one.
00041   * It has to be implemented in a derived class.
00042   * @param other The other individual the current one is extrapolated with.
00043   */
00044   virtual void extrapolate(const BBIndividual& other) = 0;
00045 
00046   /**
00047   * The function mutates the current individual.
00048   * It has to be implemented in a derived class.
00049   */
00050   virtual void mutate() = 0;
00051 
00052   /**
00053   * The function calculates the fitness of the individual.
00054   * It has to be implemented in a derived class.
00055   * @return The fitness as a number >= 0. A higher result means a higher fitness.
00056   */
00057   virtual double getFitness() const = 0;
00058 };
00059 
00060 /**
00061 * The class does some statistics on the number of individuals drawn.
00062 */
00063 class Statistics
00064 {
00065 private:
00066   int size; /**< The number of entries in the histogram. */
00067   int* stats; /**< A histogram that counts how often each individual was drawn. */
00068 
00069   /** 
00070   * The function compares two integers as required for qsort.
00071   * @param i1 The address of the first integer.
00072   * @param i2 The address of the second integer.
00073   * @return -1 if the first integer is larger, 1 if it smaller, otherwise 0.
00074   *         Results in a descending order.
00075   */
00076   static int compare(const int* i1, const int* i2)
00077   {
00078     return *i1 > *i2 ? -1 : *i1 < *i2;
00079   }
00080 
00081 public:
00082   /**
00083   * Constructor.
00084   * @param size The number of entries in the histogram.
00085   */
00086   Statistics(int size)
00087   {
00088     this->size = size;
00089     stats = new int[size];
00090     reset();
00091   }
00092 
00093   /**
00094   * Destructor.
00095   */
00096   ~Statistics() {delete [] stats;}
00097 
00098   /**
00099   * The function empties the histogram.
00100   */
00101   void reset()
00102   {
00103     for(int i = 0; i < size; ++i)
00104       stats[i] = 0;
00105   }
00106 
00107   /**
00108   * The function adds a single entry to the histogram.
00109   * @param index The index of the entry that is incremented by 1.
00110   */
00111   void add(int index) {++stats[index];}
00112 
00113   /**
00114   * The function analyzes the histogram and brings it into a compact form.
00115   * It removes all empty entries and sorts the others in descending order.
00116   * Please note that the function destoys the data in the histogram.
00117   * @return The number of entries remaining.
00118   */
00119   int analyze()
00120   {
00121     int dest = 0,
00122         src;
00123     for(src = 0; src < size; ++src)
00124       if(stats[src])
00125         stats[dest++] = stats[src];
00126     qsort(stats, dest, sizeof(int), (int (*)(const void*, const void*)) compare);
00127     return dest;
00128   }
00129 
00130   /**
00131   * The operator allows for accessing the entries in the histogram.
00132   * @param index The index of the entry to return.
00133   * @return The entry of the histogram with the given entry.
00134   */
00135   int operator[](int index) const {return stats[index];}
00136 };
00137 
00138 /**
00139 * The template class represents a population of indiviuals.
00140 * @param T The class of the individuals. It has to be derived from 
00141 *          class BBIndividual.
00142 */
00143 template<class T> class BBPopulation
00144 {
00145 private:
00146   Statistics statistics; /**< The object is used to do some statistics on drawing individuals. */
00147   T* current, /**< The current set of individuals. */
00148    * old; /**< The previous set of individuals. */
00149   int size; /**< The number of individuals in the population. */
00150   double* fitness; /**< The fitnesses of the individuals. */
00151   double* fitnessSum; /**< The accumulated fitnesses of the individuals. */
00152   double overallFitness; /**< The sum of fitness in the current population. */
00153 
00154   /**
00155   * The function provides random values.
00156   * @return A random value in the range of [0 ... 1[.
00157   */
00158   static double random() {return rand() / (double(RAND_MAX) + 1);}
00159 
00160   /**
00161   * The function draws an indiviual from the previous population.
00162   * The probability of being drawn is based on the ratio of the individual
00163   * fitness in relation to the overall fitness of the population.
00164   * @return The individual that has been drawn.
00165   */
00166   const T& drawIndividual()
00167   {
00168     double randomValue = random() * overallFitness;
00169     int low = 0,
00170       up = size;
00171     while(low != up - 1)
00172     {
00173       int middle = (low + up) / 2;
00174       if(randomValue < fitnessSum[middle])
00175         up = middle;
00176       else
00177         low = middle;
00178     }
00179     statistics.add(low);
00180     return old[low];
00181   }
00182 
00183   /**
00184   * The function updates the fitness of the whole population.
00185   * It also updates the overall fitness.
00186   */
00187   void updateFitness()
00188   {
00189     overallFitness = 0;
00190     for(int i = 0; i < size; ++i)
00191     {
00192       fitnessSum[i] = overallFitness;
00193       fitness[i] = current[i].getFitness();
00194       overallFitness += fitness[i];
00195     }
00196   }
00197 
00198   /**
00199   * The function mutates the half of the population if a single individual was drawn too often.
00200   */
00201   void mutate()
00202   {
00203     int i;
00204     for(i = 0; i < size && statistics[i] <= size; ++i)
00205       ;
00206     if(i < size)
00207       for(i = 0; i < size; i += 2)
00208         current[i].mutate();
00209   }
00210 
00211 public:
00212   /**
00213   * Constructor.
00214   * @param size The number of individuals in the population.
00215   * @param initial The individual the population is initialized with.
00216   */
00217   BBPopulation(int size, const BBIndividual& initial)
00218   : statistics(size)
00219   {
00220     this->size = size;
00221     current = new T[size];
00222     old = new T[size];
00223     fitness = new double[size];
00224     fitnessSum = new double[size];
00225     for(int i = 0; i < size; ++i)
00226       current[i].init(initial);
00227   }
00228 
00229   /**
00230   * Destructor.
00231   */
00232   ~BBPopulation()
00233   {
00234     delete [] current;
00235     delete [] old;
00236     delete [] fitness;
00237     delete [] fitnessSum;
00238   }
00239 
00240   /**
00241    * The function returns the number of Individuals.
00242    * @return The number of individuals.
00243    */
00244   int getSize() const {return size;}
00245 
00246   /**
00247    * The operator provides access to the individuals.
00248    * @param index The index of the individual.
00249    * @return A reference to the individual with the index.
00250    */
00251   T& operator[](int index) {return current[index];}
00252 
00253   /**
00254    * The constant operator provides access to the individuals.
00255    * @param index The index of the individual.
00256    * @return A reference to the individual with the index.
00257    */
00258   const T& operator[](int index) const {return current[index];}
00259 
00260   /**
00261   * The function evolves the population.
00262   * @return The fittest individual.
00263   */
00264   void interpolate()
00265   {
00266     updateFitness();
00267 
00268     // current <-> old
00269     T* temp = old;
00270     old = current;
00271     current = temp;
00272 
00273     statistics.reset();
00274     for(int i = 0; i < size; ++i)
00275     {
00276       current[i] = drawIndividual();
00277       current[i].interpolate(drawIndividual());
00278     }
00279     mutate();    
00280   }
00281 
00282   void extrapolate()
00283   {
00284     updateFitness();
00285 
00286     // current <-> old
00287     T* temp = old;
00288     old = current;
00289     current = temp;
00290 
00291     statistics.reset();
00292     for(int i = 0; i < size; ++i)
00293     {
00294       current[i] = drawIndividual();
00295       current[i].extrapolate(drawIndividual());
00296     }
00297     mutate();
00298   }
00299 
00300   const BBIndividual& getFittest()
00301   {
00302     updateFitness();
00303 
00304     int fittest = 0;
00305     for(int i = 1; i < size; ++i)
00306       if(fitness[fittest] < fitness[i])
00307         fittest = i;
00308     return current[fittest];
00309   }
00310 
00311   Statistics& getStatistics() {return statistics;}
00312 };
00313 
00314 #endif // __BB2004Evo_h_
00315 
00316 /*
00317 * Change log :
00318 * 
00319 * $Log: BB2004Evo.h,v $
00320 * Revision 1.1.1.1  2004/05/22 17:36:13  cvsadm
00321 * created new repository GT2004_WM
00322 *
00323 * Revision 1.1  2004/03/03 21:17:11  roefer
00324 * For the sake of consistency, renamed BB* to BB2004*
00325 *
00326 * Revision 1.4  2004/03/03 08:02:24  roefer
00327 * Missing comments added
00328 *
00329 * Revision 1.3  2004/02/16 17:56:32  dueffert
00330 * InvKin engine and parameters separated
00331 *
00332 * Revision 1.2  2004/01/02 13:37:26  roefer
00333 * Handle if a single individual was drawn too often
00334 *
00335 * Revision 1.1  2003/12/29 15:48:54  roefer
00336 * Bremen Byters evo walking added
00337 *
00338 */

Generated on Thu Sep 23 19:57:37 2004 for GT2004 by doxygen 1.3.6