Evocosm - A C++ Framework for Evolutionary Computing

Main Index

Created by Scott Robert Ladd at Coyote Gulch Productions.


scaler.h

00001 //---------------------------------------------------------------------
00002 //  Algorithmic Conjurings @ http://www.coyotegulch.com
00003 //  Evocosm -- An Object-Oriented Framework for Evolutionary Algorithms
00004 //
00005 //  scaler.h
00006 //---------------------------------------------------------------------
00007 //
00008 //  Copyright 1996, 1999, 2002, 2003, 2004, 2005, 2007 Scott Robert Ladd
00009 //
00010 //  This program is free software; you can redistribute it and/or modify
00011 //  it under the terms of the GNU General Public License as published by
00012 //  the Free Software Foundation; either version 2 of the License, or
00013 //  (at your option) any later version.
00014 //  
00015 //  This program is distributed in the hope that it will be useful,
00016 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 //  GNU General Public License for more details.
00019 //  
00020 //  You should have received a copy of the GNU General Public License
00021 //  along with this program; if not, write to the
00022 //      Free Software Foundation, Inc.
00023 //      59 Temple Place - Suite 330
00024 //      Boston, MA 02111-1307, USA.
00025 //
00026 //-----------------------------------------------------------------------
00027 //
00028 //  For more information on this software package, please visit
00029 //  Scott's web site, Coyote Gulch Productions, at:
00030 //
00031 //      http://www.coyotegulch.com
00032 //  
00033 //-----------------------------------------------------------------------
00034 
00035 #if !defined(LIBEVOCOSM_SCALER_H)
00036 #define LIBEVOCOSM_SCALER_H
00037 
00038 // Standard C Library
00039 #include <cmath>
00040 
00041 // Standard C++
00042 #include <limits>
00043 #include <algorithm>
00044 
00045 // libevocosm
00046 #include "organism.h"
00047 
00048 namespace libevocosm
00049 {
00051 
00059     template <class OrganismType>
00060     class scaler : protected globals
00061     {
00062     public:
00064 
00071         virtual ~scaler()
00072         {
00073             // nada
00074         }
00075 
00077 
00083         virtual void scale_fitness(vector<OrganismType> & a_population) = 0;
00084         
00086 
00089         void invert(vector<OrganismType> & a_population)
00090         {
00091             double base = min_element(a_population.begin(), a_population.end())->fitness()
00092                         + max_element(a_population.begin(), a_population.end())->fitness();
00093             
00094             for (typename vector<OrganismType>::iterator organism = a_population.begin(); organism != a_population.end(); ++organism)
00095                organism->fitness() = base - organism->fitness();
00096         }                
00097     };
00098 
00100 
00105     template <class OrganismType>
00106     class null_scaler : public scaler<OrganismType>
00107     {
00108     public:
00110 
00114         virtual void scale_fitness(vector<OrganismType> & a_population)
00115         {
00116             // nada
00117         }
00118     };
00119 
00121 
00126     template <class OrganismType>
00127     class linear_norm_scaler : public scaler<OrganismType>
00128     {
00129     public:
00131 
00134         linear_norm_scaler(double a_fitness_multiple = 2.0)
00135             : m_fitness_multiple(a_fitness_multiple)
00136         {
00137             // nada
00138         }
00139 
00141 
00145         virtual void scale_fitness(vector<OrganismType> & a_population)
00146         {
00147             // calculate max, average, and minimum fitness for the population
00148             double max_fitness = std::numeric_limits<double>::min();
00149             double min_fitness = std::numeric_limits<double>::max();
00150             double avg_fitness = 0.0;
00151             
00152             for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00153             {
00154                 // do we have a new maximum?
00155                 if (org->fitness() > max_fitness)
00156                     max_fitness = org->fitness();
00157                 
00158                 // do we have a new minimum?
00159                 if (org->fitness() < min_fitness)
00160                     min_fitness = org->fitness();
00161                 
00162                 // accumulate for average
00163                 avg_fitness += org->fitness();
00164             }
00165             
00166             avg_fitness /= double(a_population.size());
00167             
00168             // calculate coefficients for fitness scaling
00169             double slope;
00170             double intercept;
00171             double delta;
00172             
00173             if (min_fitness > ((m_fitness_multiple * avg_fitness - max_fitness) / (m_fitness_multiple - 1.0)))
00174             {
00175                 // normal scaling
00176                 delta = max_fitness - avg_fitness;
00177                 slope = (m_fitness_multiple - 1.0) * avg_fitness / delta;
00178                 intercept = avg_fitness * (max_fitness - m_fitness_multiple * avg_fitness) / delta;
00179             }
00180             else
00181             {
00182                 // extreme scaling
00183                 delta = avg_fitness - min_fitness;
00184                 slope = avg_fitness / delta;
00185                 intercept = -min_fitness * avg_fitness / delta;
00186             }
00187             
00188             // adjust fitness values
00189             for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00190                 org->fitness() = slope * org->fitness() + intercept;
00191         }
00192         
00193     private:
00194         double m_fitness_multiple;
00195     };
00196 
00198 
00203     template <class OrganismType>
00204     class windowed_scaler : public scaler<OrganismType>
00205     {
00206     public:
00208 
00211         windowed_scaler()
00212         {
00213             // nada
00214         }
00215 
00217 
00221         virtual void scale_fitness(vector<OrganismType> & a_population)
00222         {
00223             // Find minimum fitness
00224             // Note that organisms sort in reverse order of fitness, such that
00225             // the "maximum" value has the smallest fitness.
00226             double min_fitness = min_element(a_population.begin(), a_population.end())->fitness();
00227             
00228             // assign new fitness values
00229             for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00230                 org->fitness() -= min_fitness;
00231         }
00232     };
00233     
00235 
00240     template <class OrganismType>
00241     class exponential_scaler : public scaler<OrganismType>
00242     {
00243     public:
00245 
00252         exponential_scaler(double a_a = 1.0, double a_b = 1.0, double a_power = 2.0)
00253           : m_a(a_a),
00254             m_b(a_b),
00255             m_power(a_power)
00256         {
00257             // nada
00258         }
00259 
00261 
00265         virtual void scale_fitness(vector<OrganismType> & a_population)
00266         {
00267             // assign new fitness values
00268             for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00269                 org->fitness() = pow((m_a * org->fitness() + m_b),m_power);
00270         }
00271 
00272     private:
00273         double m_a;
00274         double m_b;
00275         double m_power;
00276     };
00277     
00279 
00283     template <class OrganismType>
00284     class quadratic_scaler : public scaler<OrganismType>
00285     {
00286     public:
00288 
00291         quadratic_scaler(double a_a, double a_b, double a_c)
00292             : m_a(a_a), m_b(a_b), m_c(a_c)
00293         {
00294             // nada
00295         }
00296 
00298 
00302         virtual void scale_fitness(vector<OrganismType> & a_population)
00303         {
00304             // adjust fitness values
00305             for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00306             {
00307                 double f = org->fitness();
00308                 org->fitness() = m_a * pow(f,2.0) + m_b * f + m_c;
00309             }
00310         }
00311         
00312     private:
00313         double m_a;
00314         double m_b;
00315         double m_c;
00316     };
00317 
00319 
00323     template <class OrganismType>
00324     class sigma_scaler : public scaler<OrganismType>
00325     {
00326     public:
00328 
00331         sigma_scaler()
00332         {
00333         }
00334 
00336 
00343         virtual void scale_fitness(vector<OrganismType> & a_population)
00344         {
00345             // calculate the mean
00346             double mean = 0.0;
00347             for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00348                 mean += org->fitness();
00349             
00350             mean /= static_cast<double>(a_population.size());
00351             
00352             // calculate variance
00353             double variance = 0.0;
00354             for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00355             {
00356                 double diff = org->fitness() - mean;
00357                 variance += (diff * diff);
00358             }
00359             
00360             variance /= static_cast<double>(a_population.size() - 1);
00361 
00362             // calculate 2 times the std. deviation (sigma)
00363             double sigma2 = 2.0 * sqrt(variance);
00364             
00365             // now assign new fitness values
00366             if (sigma2 == 0.0)
00367             {
00368                 for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00369                     org->fitness() = 1.0;
00370             }
00371             else   
00372             {
00373                 for (typename vector<OrganismType>::iterator org = a_population.begin(); org != a_population.end(); ++org)
00374                 {
00375                     // change fitness
00376                     org->fitness() = (1.0 + org->fitness() / mean) / sigma2;
00377                     
00378                     // avoid tiny or zero fitness value; everyone gets to reproduce
00379                     if (org->fitness() < 0.1)
00380                         org->fitness() = 0.1;
00381                 }
00382             }
00383         }
00384     };
00385 
00386 };
00387 
00388 #endif

© 1996-2005 Scott Robert Ladd. All rights reserved.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.