Created by Scott Robert Ladd at Coyote Gulch Productions.
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 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.