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 // evocosm.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_EVOCOSM_H) 00036 #define LIBEVOCOSM_EVOCOSM_H 00037 00038 #if defined(_MSC_VER) 00039 #pragma warning (disable : 4786) 00040 #endif 00041 00042 #if defined(_OPENMP) 00043 #include <omp.h> 00044 #endif 00045 00046 // Standard C++ library 00047 #include <vector> 00048 00049 // libcoyotl 00050 #include "libcoyotl/validator.h" 00051 00052 // libevocosm 00053 #include "organism.h" 00054 #include "landscape.h" 00055 #include "mutator.h" 00056 #include "reproducer.h" 00057 #include "scaler.h" 00058 #include "migrator.h" 00059 #include "selector.h" 00060 #include "reporter.h" 00061 00063 00072 namespace libevocosm 00073 { 00074 using std::vector; 00075 00077 00081 template <class OrganismType> 00082 class organism_factory 00083 { 00084 public: 00086 00089 virtual OrganismType create() = 0; 00090 00092 00095 virtual void append(vector<OrganismType> & a_population, size_t a_size) = 0; 00096 }; 00097 00099 00103 template <class LandscapeType> 00104 class landscape_factory 00105 { 00106 public: 00108 00112 virtual LandscapeType generate() = 0; 00113 }; 00114 00116 00123 template <class OrganismType, class LandscapeType> 00124 class evocosm : protected globals 00125 { 00126 protected: 00128 listener & m_listener; 00129 00131 size_t m_population_size; 00132 00134 vector< vector<OrganismType> > m_populations; 00135 00137 size_t m_number_of_populations; 00138 00140 size_t m_number_of_unique_landscapes; 00141 00143 size_t m_number_of_common_landscapes; 00144 00146 vector< vector<LandscapeType> > m_unique_landscapes; 00147 00149 vector<LandscapeType> m_common_landscapes; 00150 00152 mutator<OrganismType> & m_mutator; 00153 00155 reproducer<OrganismType> & m_reproducer; 00156 00158 scaler<OrganismType> & m_scaler; 00159 00161 migrator<OrganismType> & m_migrator; 00162 00164 selector<OrganismType> & m_selector; 00165 00167 reporter<OrganismType,LandscapeType> & m_reporter; 00168 00170 size_t m_iteration; 00171 00173 bool m_minimizing; 00174 00176 bool m_running; 00177 00178 public: 00180 00201 evocosm(listener & a_listener, 00202 size_t a_population_size, 00203 size_t a_number_of_populations, 00204 size_t a_number_of_unique_landscapes, 00205 size_t a_number_of_common_landscapes, 00206 mutator<OrganismType> & a_mutator, 00207 reproducer<OrganismType> & a_reproducer, 00208 scaler<OrganismType> & a_scaler, 00209 migrator<OrganismType> & a_migrator, 00210 selector<OrganismType> & a_selector, 00211 reporter<OrganismType,LandscapeType> & a_reporter, 00212 organism_factory<OrganismType> & a_organism_factory, 00213 landscape_factory<LandscapeType> & a_landscape_factory, 00214 bool a_minimizing = false); 00215 00217 00221 evocosm(const evocosm<OrganismType, LandscapeType> & a_source); 00222 00224 00231 virtual ~evocosm(); 00232 00234 00239 evocosm & operator = (const evocosm<OrganismType, LandscapeType> & a_source); 00240 00242 00252 virtual bool run_generation(bool a_finished, double & a_fitness); 00253 00255 00261 vector<OrganismType, LandscapeType> & population(size_t a_index = 0) 00262 { 00263 return m_populations[a_index]; 00264 } 00265 00267 00270 void terminate() 00271 { 00272 m_running = false; 00273 } 00274 }; 00275 00276 // constructors 00277 template <class OrganismType, class LandscapeType> 00278 evocosm<OrganismType, LandscapeType>::evocosm(listener & a_listener, 00279 size_t a_population_size, 00280 size_t a_number_of_populations, 00281 size_t a_number_of_unique_landscapes, 00282 size_t a_number_of_common_landscapes, 00283 mutator<OrganismType> & a_mutator, 00284 reproducer<OrganismType> & a_reproducer, 00285 scaler<OrganismType> & a_scaler, 00286 migrator<OrganismType> & a_migrator, 00287 selector<OrganismType> & a_selector, 00288 reporter<OrganismType, LandscapeType> & a_reporter, 00289 organism_factory<OrganismType> & a_organism_factory, 00290 landscape_factory<LandscapeType> & a_landscape_factory, 00291 bool a_minimizing) 00292 : m_listener(a_listener), 00293 m_population_size(a_population_size), 00294 m_populations(), 00295 m_number_of_populations(a_number_of_populations), 00296 m_number_of_unique_landscapes(a_number_of_unique_landscapes), 00297 m_number_of_common_landscapes(a_number_of_common_landscapes), 00298 m_unique_landscapes(), 00299 m_common_landscapes(), 00300 m_mutator(a_mutator), 00301 m_reproducer(a_reproducer), 00302 m_scaler(a_scaler), 00303 m_migrator(a_migrator), 00304 m_selector(a_selector), 00305 m_reporter(a_reporter), 00306 m_iteration(0), 00307 m_minimizing(a_minimizing), 00308 m_running(true) 00309 { 00310 // adjust evocosm size if necessary 00311 libcoyotl::enforce_lower_limit(m_population_size,size_t(1)); 00312 libcoyotl::enforce_lower_limit(m_number_of_populations,size_t(1)); 00313 00314 // calculate number of common and unique landscapes 00315 if ((m_number_of_unique_landscapes < 1) && (m_number_of_common_landscapes == 0)) 00316 m_number_of_unique_landscapes = 1; 00317 00318 a_landscape_factory.generate(); 00319 00320 // allocate vectors of landscapes 00321 for (size_t n = 0; n < m_number_of_common_landscapes; ++n) 00322 m_common_landscapes.push_back(a_landscape_factory.generate()); 00323 00324 // create initial populations 00325 m_unique_landscapes.resize(m_number_of_populations); 00326 m_populations.resize(m_number_of_populations); 00327 00328 for (size_t p = 0; p < m_number_of_populations; ++p) 00329 { 00330 // add organisms to populations 00331 a_organism_factory.append(m_populations[p], m_population_size); 00332 00333 // create unique landscapes for this population 00334 for (size_t n = 0; n < m_number_of_unique_landscapes; ++n) 00335 m_unique_landscapes[p].push_back(a_landscape_factory.generate()); 00336 } 00337 } 00338 00339 // copy constructor 00340 template <class OrganismType, class LandscapeType> 00341 evocosm<OrganismType, LandscapeType>::evocosm(const evocosm<OrganismType, LandscapeType> & a_source) 00342 : m_population_size(a_source.m_population_size), 00343 m_populations(a_source.m_populations), 00344 m_number_of_populations(a_source.m_number_of_populations), 00345 m_number_of_common_landscapes(a_source.m_number_of_common_landscapes), 00346 m_number_of_unique_landscapes(a_source.m_number_of_unique_landscapes), 00347 m_common_landscapes(a_source.m_common_landscapes), 00348 m_unique_landscapes(a_source.m_unique_landscapes), 00349 m_mutator(a_source.m_mutator), 00350 m_reproducer(a_source.m_reproducer), 00351 m_scaler(a_source.m_scaler), 00352 m_migrator(a_source.m_migrator), 00353 m_selector(a_source.m_selector), 00354 m_iteration(a_source.m_iteration) 00355 { 00356 // nada 00357 } 00358 00359 // destructor 00360 template <class OrganismType, class LandscapeType> 00361 evocosm<OrganismType, LandscapeType>::~evocosm() 00362 { 00363 // nada 00364 } 00365 00366 // assignment operator 00367 template <class OrganismType, class LandscapeType> 00368 evocosm<OrganismType, LandscapeType> & evocosm<OrganismType, LandscapeType>::operator = (const evocosm<OrganismType, LandscapeType> & a_source) 00369 { 00370 m_population_size = a_source.m_population_size; 00371 m_populations = a_source.m_populations; 00372 m_number_of_populations = a_source.m_number_of_populations; 00373 00374 m_number_of_common_landscapes = a_source.m_number_of_common_landscapes; 00375 m_number_of_unique_landscapes = a_source.m_number_of_unique_landscapes; 00376 m_common_landscapes = a_source.m_common_landscapes; 00377 m_unique_landscapes = a_source.m_unique_landscapes; 00378 00379 m_mutator = a_source.m_mutator; 00380 m_reproducer = a_source.m_reproducer; 00381 m_scaler = a_source.m_scaler; 00382 m_migrator = a_source.m_migrator; 00383 m_selector = a_source.m_selector; 00384 00385 m_iteration = a_source.m_iteration; 00386 00387 return *this; 00388 } 00389 00390 // compute next generation 00391 template <class OrganismType, class LandscapeType> 00392 bool evocosm<OrganismType, LandscapeType>::run_generation(bool a_finished, double & a_fitness) 00393 { 00394 int n, p; 00395 00396 ++m_iteration; 00397 00398 // announce beginning of new generation 00399 m_listener.ping_generation_begin(m_iteration); 00400 00401 // test fitness for each chromosome 00402 for (p = 0; p < (int)m_number_of_populations; p++) 00403 { 00404 // announce beginning of population processing 00405 m_listener.ping_population_begin(p + 1); 00406 00407 // clear fitness 00408 // using an iterator here crashes MSVC++ 13.0 (.Net) with an internal error 00409 for (n = 0; n < (int)m_population_size; ++n) // vector<OrganismType>::iterator organism = m_populations[p].begin(); organism != m_populations[p].end; ++organism) 00410 m_populations[p][n].reset_all(); 00411 00412 // let other processes do something 00413 m_listener.yield(); 00414 00415 // accumulate fitness for each population common to all populations 00416 if (m_number_of_common_landscapes > 0) 00417 { 00418 #ifdef _OPENMP 00419 #pragma omp parallel for private(p,n) 00420 #endif 00421 for (n = 0; n < (int)m_number_of_common_landscapes; ++n) 00422 m_common_landscapes[n].test(m_populations[p]); 00423 } 00424 00425 // let other processes do something 00426 m_listener.yield(); 00427 00428 // accumulate fitness for each landscape unique to this population 00429 if (m_number_of_unique_landscapes > 0) 00430 { 00431 #ifdef _OPENMP 00432 #pragma omp parallel for private(p,n) 00433 #endif 00434 for (n = 0; n < (int)m_number_of_unique_landscapes; ++n) 00435 m_unique_landscapes[p][n].test(m_populations[p]); 00436 } 00437 00438 // announce completion of population processing 00439 m_listener.ping_population_end(p + 1); 00440 } 00441 00442 // report on new generation 00443 bool keep_going = m_reporter.report(m_populations,m_iteration,a_fitness,a_finished); 00444 00445 // let other processes do something 00446 m_listener.yield(); 00447 00448 if (keep_going && m_running) 00449 { 00450 // create next generation 00451 #ifdef _OPENMP 00452 #pragma omp parallel for private(p,n) 00453 #endif 00454 for (p = 0; p < (int)m_number_of_populations; ++p) 00455 { 00456 // reverse the sense of fitness when minimizing (i.e., best fitness is smallest value) 00457 if (m_minimizing) 00458 m_scaler.invert(m_populations[p]); 00459 00460 // let other processes do something 00461 m_listener.yield(); 00462 00463 // scale the population's fitness 00464 m_scaler.scale_fitness(m_populations[p]); 00465 00466 // let other processes do something 00467 m_listener.yield(); 00468 00469 // get survivors and number of chromosomes to add 00470 vector<OrganismType> survivors = m_selector.select_survivors(m_populations[p]); 00471 00472 // let other processes do something 00473 m_listener.yield(); 00474 00475 // give birth to new chromosomes 00476 vector<OrganismType> children = m_reproducer.breed(m_populations[p], m_population_size - survivors.size()); 00477 00478 // let other processes do something 00479 m_listener.yield(); 00480 00481 // mutate the child chromosomes 00482 m_mutator.mutate(children); 00483 00484 // let other processes do something 00485 m_listener.yield(); 00486 00487 // replace old evocosm with new one 00488 m_populations[p] = survivors; 00489 m_populations[p].insert(m_populations[p].end(),children.begin(),children.end()); 00490 } 00491 00492 if (m_number_of_populations > 1) 00493 m_migrator.migrate(m_populations); 00494 } 00495 00496 // we're done with this generation 00497 m_listener.ping_generation_end(m_iteration); 00498 00499 // let other processes do something 00500 m_listener.yield(); 00501 00502 return keep_going & m_running; 00503 } 00504 }; 00505 00506 #endif
© 1996-2005 Scott Robert Ladd. All rights reserved.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.