Listing 1: The GASolver class template

//
//  gasolver.h - GASolver is a class template.
//  The template typename T must  be derived
//  from GAGenome.
//////////////////////////////////////////////
#ifndef GASOLVER_H
#define GASOLVER_H
#include "math.h"

////////////////////////////////////////
template<typename T>
class GASolver
{
protected :
   int           m_popSize ; // The genome
   T*            m_pop     ; // population.  
   T             m_bestEver; // The best ever genome.
   // GA paramenters.
   int           m_nGenerations;// # of generations
   bool          m_maximize; // min/max flag
   double        m_mutation; // mutation probability
   double        m_cross   ; // crossover probability
   double        m_sigma   ; // sigma trucation
   double        m_trunc  ;  // truncation constant

public :
   //--------------------------------
   int Solve(T &bestSolution)
   {
      Initialize();
      Evaluate();
      for (int i=0;i<m_nGenerations;i++)
      {
         Select();
         CrossOver();
         Mutate();
         Evaluate();
      }
      bestSolution = m_bestEver;
      return 0;
   }

   //--------------------------------
   int Maximize( T &bestSolution)
   {
      //  Solve for maximum
      m_maximize = true;
      return Solve( bestSolution);
   }

   //--------------------------------
   int Minimize( T &bestSolution)
   {
      //  Solve for minimimum
      m_maximize = false;
      return Solve( bestSolution);
   }

   //
   //  constructor,destructor.
   //--------------------------------
   GASolver()
   {
      m_popSize = 0;
      m_pop = NULL;
      m_nGenerations = 100;
      m_mutation = 0.01;
      m_cross = 0.50;
      m_sigma = 1.5;
      m_trunc =0;
      m_maximize = true;
   };

   ~GASolver()
   {
      if (m_pop)
         delete [] m_pop;
   }

   //--------------------------------
   void   SetPopSize( int popSize)
   {
      //  Population size.
      if (m_pop)
         delete [] m_pop;
      m_popSize = popSize;
      m_pop = NULL;
      if (m_popSize)
         m_pop = new T[popSize];
   }
   
   //--------------------------------
   void SetNumGenerations( int numGenerations)
   {
      m_nGenerations = numGenerations;
   }

   //--------------------------------
   void SetMutationFactor( double mutationFactor)
   {
      //  Probability of mutation.
      m_mutation = mutationFactor;
   }
   
   //--------------------------------
   void SetCrossOverFactor( double crossOverFactor)
   {
      //  Probability of crossover.
      m_cross = crossOverFactor;
   }

   //--------------------------------
   void SetFitnessSigma( double fitnessSigma)
   {
      //  Sigma trunctation parameter
      //  used for cacluating fitness.
      m_sigma = fitnessSigma;
   }


protected:
   //--------------------------------
   void Initialize()
   {
      // Initialize each genome in population.
      RandomSeed( 15);
      for (int j=0;j<m_popSize;j++)
      {
         m_pop[j].Initialize();
      }
      m_bestEver.Initialize();
      m_bestEver.m_obj = m_bestEver.Evaluate();
   }

   //
   //--------------------------------
   void Select()
   {
      // This routine selects the next generation.
      // First, get the fitness function total for
      // the entier population.
      double sumFit = 0;
      for (int j=0;j<m_popSize;j++)
         sumFit += m_pop[j].m_fitness;
      //
      //  Weight each individual against total to
      //  to determine probability of selection
      double sumProb = 0;
      for (j=0;j<m_popSize;j++)
      {
         double prob;
         prob = sumProb + m_pop[j].m_fitness/sumFit;
         m_pop[j].m_selProb = prob;
         sumProb = prob;
         m_pop[j].m_selected = 0; 
      }
      //
      //  Spin the roullete wheel popSize 
      //  times to select
      //  the most fit individuals.
      for (j=0;j<m_popSize;j++)
      {
         double r = RandomNum(10000)/10000.;
         int k=0;
         while ((m_pop[k].m_selProb < r)
             && (k < (m_popSize-1)))
         {
            k++;
         }
         m_pop[k].m_selected++; 
      }
      //
      //  Kill off the unselected individuals
      //  and make copies of multiply 
      //  selected individuals.
      for (j=0;j<m_popSize;j++)
      {
         while (m_pop[j].m_selected > 1)
         {
            for (int k=0;k<m_popSize;k++)
            {
               if (m_pop[k].m_selected == 0)
               {
                  m_pop[k] = m_pop[j];
                  m_pop[k].m_selected = 1;
                  m_pop[j].m_selected--;
                  break;
               }
            }
         }
      }
   }

   //--------------------------------
   void CrossOver()
   {
       //
      //  Mate selected chromosomes in 
      //  the new population randomly.
      int first = -1;
      for (int j=0;j<m_popSize;j++)
      {
         // generate a probability
         double r = RandomNum(10000)/10000.;
         //  
         //  The probability of crossover
         //  is m_cross.
         if (r < m_cross)
         {
            // found 1st partner
            if (first == -1) 
               first = j;
            else
            {
               // we have 2 parnters
               // crossover
               m_pop[j].CrossOver( &m_pop[first]);
               first = -1;
            }
         }
      }
   }

   //
   //--------------------------------
   void Mutate()
   {
      // Mutation
      for (int j=0;j<m_popSize;j++)
      {
         //
         // mutate the genome according
         // to the m_mutation probability
         // factor.
         m_pop[j].Mutate(m_mutation);
      }
   }
   
   //--------------------------------
   void Evaluate()
   {
      //
      // Evaluates the  fitness of each genome.
      // Keep track of best ever genome.
      //
      // First step is to caculate objective
      // value for each genome and determine
      // the best ever genome.
      double totalObjVal=0;
      for (int j=0;j<m_popSize;j++)
      {
         double objVal = m_pop[j].Evaluate();
         m_pop[j].m_obj = objVal;
         if (m_maximize)
         {
            if (m_pop[j].m_obj > m_bestEver.m_obj)
               m_bestEver = m_pop[j];
         }
         else
         {
            if (m_pop[j].m_obj < m_bestEver.m_obj)
               m_bestEver = m_pop[j];
         }
         totalObjVal += objVal;
      }
      //
      //  Sigma truncation constant (m_trunc) 
      //  is calculated here. Used for fitness 
      //  calculation further below.
      m_trunc = 0;
      if (m_sigma != 0)
      {
         // calulate fitness constant using avg, std dev.
         double avg = totalObjVal/m_popSize;
         double stdDev = 0;
         for (int j=0;j<m_popSize;j++)
         {
            double delta = m_pop[j].m_obj - avg;
            delta = delta*delta;
            stdDev += delta;
         }
         //
         //  sigma truncation constant is some
         //  number of standard deviations from
         //  the average obj function value.
         stdDev = sqrt( stdDev/(m_popSize-1.0));
         if (m_maximize)
            m_trunc=avg - m_sigma*stdDev;
         else
            m_trunc=avg + m_sigma*stdDev;
      }
      //
      // Calcuate the fitness.
      for (j=0;j<m_popSize;j++)
      {
         //
         // Fitness for maximum and minimum optimization.
         if (m_maximize)
            m_pop[j].m_fitness = m_pop[j].m_obj-m_trunc;
         else
            m_pop[j].m_fitness = m_trunc - m_pop[j].m_obj;
         //
         // If the object value is too many
         // standard deviations away from
         // the average then it has zero fitness
         // and it will be killed off in the
         // selection process.
         if (m_pop[j].m_fitness < 0)
         {
            m_pop[j].m_fitness = 0;
         }
      }

   }

};

#endif
— End of Listing —