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, 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_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 // libevocosm 00050 #include "validator.h" 00051 #include "organism.h" 00052 #include "landscape.h" 00053 #include "mutator.h" 00054 #include "reproducer.h" 00055 #include "scaler.h" 00056 #include "migrator.h" 00057 #include "selector.h" 00058 #include "reporter.h" 00059 00061 00070 namespace libevocosm 00071 { 00072 using std::vector; 00073 00075 00079 template <class OrganismType> 00080 class organism_factory 00081 { 00082 public: 00084 00087 virtual OrganismType create() = 0; 00088 00090 00093 virtual void append(vector<OrganismType> & a_population, size_t a_size) = 0; 00094 }; 00095 00097 00101 template <class LandscapeType> 00102 class landscape_factory 00103 { 00104 public: 00106 00110 virtual LandscapeType generate() = 0; 00111 }; 00112 00114 00121 template <class OrganismType, class LandscapeType> 00122 class evocosm : protected globals 00123 { 00124 protected: 00126 listener & m_listener; 00127 00129 size_t m_population_size; 00130 00132 vector< vector<OrganismType> > m_populations; 00133 00135 size_t m_number_of_populations; 00136 00138 size_t m_number_of_unique_landscapes; 00139 00141 size_t m_number_of_common_landscapes; 00142 00144 vector< vector<LandscapeType> > m_unique_landscapes; 00145 00147 vector<LandscapeType> m_common_landscapes; 00148 00150 mutator<OrganismType> & m_mutator; 00151 00153 reproducer<OrganismType> & m_reproducer; 00154 00156 scaler<OrganismType> & m_scaler; 00157 00159 migrator<OrganismType> & m_migrator; 00160 00162 selector<OrganismType> & m_selector; 00163 00165 reporter<OrganismType,LandscapeType> & m_reporter; 00166 00168 size_t m_iteration; 00169 00171 bool m_minimizing; 00172 00174 bool m_running; 00175 00176 public: 00178 00199 evocosm(listener & a_listener, 00200 size_t a_population_size, 00201 size_t a_number_of_populations, 00202 size_t a_number_of_unique_landscapes, 00203 size_t a_number_of_common_landscapes, 00204 mutator<OrganismType> & a_mutator, 00205 reproducer<OrganismType> & a_reproducer, 00206 scaler<OrganismType> & a_scaler, 00207 migrator<OrganismType> & a_migrator, 00208 selector<OrganismType> & a_selector, 00209 reporter<OrganismType,LandscapeType> & a_reporter, 00210 organism_factory<OrganismType> & a_organism_factory, 00211 landscape_factory<LandscapeType> & a_landscape_factory, 00212 bool a_minimizing = false); 00213 00215 00219 evocosm(const evocosm<OrganismType, LandscapeType> & a_source); 00220 00222 00229 virtual ~evocosm(); 00230 00232 00237 evocosm & operator = (const evocosm<OrganismType, LandscapeType> & a_source); 00238 00240 00250 virtual bool run_generation(bool a_finished, double & a_fitness); 00251 00253 00259 vector<OrganismType, LandscapeType> & population(size_t a_index = 0) 00260 { 00261 return m_populations[a_index]; 00262 } 00263 00265 00268 void terminate() 00269 { 00270 m_running = false; 00271 } 00272 }; 00273 00274 // constructors 00275 template <class OrganismType, class LandscapeType> 00276 evocosm<OrganismType, LandscapeType>::evocosm(listener & a_listener, 00277 size_t a_population_size, 00278 size_t a_number_of_populations, 00279 size_t a_number_of_unique_landscapes, 00280 size_t a_number_of_common_landscapes, 00281 mutator<OrganismType> & a_mutator, 00282 reproducer<OrganismType> & a_reproducer, 00283 scaler<OrganismType> & a_scaler, 00284 migrator<OrganismType> & a_migrator, 00285 selector<OrganismType> & a_selector, 00286 reporter<OrganismType, LandscapeType> & a_reporter, 00287 organism_factory<OrganismType> & a_organism_factory, 00288 landscape_factory<LandscapeType> & a_landscape_factory, 00289 bool a_minimizing) 00290 : m_listener(a_listener), 00291 m_population_size(a_population_size), 00292 m_populations(), 00293 m_number_of_populations(a_number_of_populations), 00294 m_number_of_unique_landscapes(a_number_of_unique_landscapes), 00295 m_number_of_common_landscapes(a_number_of_common_landscapes), 00296 m_unique_landscapes(), 00297 m_common_landscapes(), 00298 m_mutator(a_mutator), 00299 m_reproducer(a_reproducer), 00300 m_scaler(a_scaler), 00301 m_migrator(a_migrator), 00302 m_selector(a_selector), 00303 m_reporter(a_reporter), 00304 m_iteration(0), 00305 m_minimizing(a_minimizing), 00306 m_running(true) 00307 { 00308 // adjust evocosm size if necessary 00309 libevocosm::enforce_lower_limit(m_population_size,size_t(1)); 00310 libevocosm::enforce_lower_limit(m_number_of_populations,size_t(1)); 00311 00312 // calculate number of common and unique landscapes 00313 if ((m_number_of_unique_landscapes < 1) && (m_number_of_common_landscapes == 0)) 00314 m_number_of_unique_landscapes = 1; 00315 00316 a_landscape_factory.generate(); 00317 00318 // allocate vectors of landscapes 00319 for (size_t n = 0; n < m_number_of_common_landscapes; ++n) 00320 m_common_landscapes.push_back(a_landscape_factory.generate()); 00321 00322 // create initial populations 00323 m_unique_landscapes.resize(m_number_of_populations); 00324 m_populations.resize(m_number_of_populations); 00325 00326 for (size_t p = 0; p < m_number_of_populations; ++p) 00327 { 00328 // add organisms to populations 00329 a_organism_factory.append(m_populations[p], m_population_size); 00330 00331 // create unique landscapes for this population 00332 for (size_t n = 0; n < m_number_of_unique_landscapes; ++n) 00333 m_unique_landscapes[p].push_back(a_landscape_factory.generate()); 00334 } 00335 } 00336 00337 // copy constructor 00338 template <class OrganismType, class LandscapeType> 00339 evocosm<OrganismType, LandscapeType>::evocosm(const evocosm<OrganismType, LandscapeType> & a_source) 00340 : m_population_size(a_source.m_population_size), 00341 m_populations(a_source.m_populations), 00342 m_number_of_populations(a_source.m_number_of_populations), 00343 m_number_of_common_landscapes(a_source.m_number_of_common_landscapes), 00344 m_number_of_unique_landscapes(a_source.m_number_of_unique_landscapes), 00345 m_common_landscapes(a_source.m_common_landscapes), 00346 m_unique_landscapes(a_source.m_unique_landscapes), 00347 m_mutator(a_source.m_mutator), 00348 m_reproducer(a_source.m_reproducer), 00349 m_scaler(a_source.m_scaler), 00350 m_migrator(a_source.m_migrator), 00351 m_selector(a_source.m_selector), 00352 m_iteration(a_source.m_iteration) 00353 { 00354 // nada 00355 } 00356 00357 // destructor 00358 template <class OrganismType, class LandscapeType> 00359 evocosm<OrganismType, LandscapeType>::~evocosm() 00360 { 00361 // nada 00362 } 00363 00364 // assignment operator 00365 template <class OrganismType, class LandscapeType> 00366 evocosm<OrganismType, LandscapeType> & evocosm<OrganismType, LandscapeType>::operator = (const evocosm<OrganismType, LandscapeType> & a_source) 00367 { 00368 m_population_size = a_source.m_population_size; 00369 m_populations = a_source.m_populations; 00370 m_number_of_populations = a_source.m_number_of_populations; 00371 00372 m_number_of_common_landscapes = a_source.m_number_of_common_landscapes; 00373 m_number_of_unique_landscapes = a_source.m_number_of_unique_landscapes; 00374 m_common_landscapes = a_source.m_common_landscapes; 00375 m_unique_landscapes = a_source.m_unique_landscapes; 00376 00377 m_mutator = a_source.m_mutator; 00378 m_reproducer = a_source.m_reproducer; 00379 m_scaler = a_source.m_scaler; 00380 m_migrator = a_source.m_migrator; 00381 m_selector = a_source.m_selector; 00382 00383 m_iteration = a_source.m_iteration; 00384 00385 return *this; 00386 } 00387 00388 // compute next generation 00389 template <class OrganismType, class LandscapeType> 00390 bool evocosm<OrganismType, LandscapeType>::run_generation(bool a_finished, double & a_fitness) 00391 { 00392 int n, p; 00393 00394 ++m_iteration; 00395 00396 // announce beginning of new generation 00397 m_listener.ping_generation_begin(m_iteration); 00398 00399 // test fitness for each chromosome 00400 for (p = 0; p < (int)m_number_of_populations; p++) 00401 { 00402 // announce beginning of population processing 00403 m_listener.ping_population_begin(p + 1); 00404 00405 // clear fitness 00406 // using an iterator here crashes MSVC++ 13.0 (.Net) with an internal error 00407 for (n = 0; n < (int)m_population_size; ++n) // vector<OrganismType>::iterator organism = m_populations[p].begin(); organism != m_populations[p].end; ++organism) 00408 m_populations[p][n].reset_all(); 00409 00410 // let other processes do something 00411 m_listener.yield(); 00412 00413 // accumulate fitness for each population common to all populations 00414 if (m_number_of_common_landscapes > 0) 00415 { 00416 for (n = 0; n < (int)m_number_of_common_landscapes; ++n) 00417 m_common_landscapes[n].test_pop(m_populations[p]); 00418 } 00419 00420 // let other processes do something 00421 m_listener.yield(); 00422 00423 // accumulate fitness for each landscape unique to this population 00424 if (m_number_of_unique_landscapes > 0) 00425 { 00426 for (n = 0; n < (int)m_number_of_unique_landscapes; ++n) 00427 m_unique_landscapes[p][n].test_pop(m_populations[p]); 00428 } 00429 00430 // announce completion of population processing 00431 m_listener.ping_population_end(p + 1); 00432 } 00433 00434 // report on new generation 00435 bool keep_going = m_reporter.report(m_populations,m_iteration,a_fitness,a_finished); 00436 00437 // let other processes do something 00438 m_listener.yield(); 00439 00440 if (keep_going && m_running) 00441 { 00442 // create next generation 00443 for (p = 0; p < (int)m_number_of_populations; ++p) 00444 { 00445 // reverse the sense of fitness when minimizing (i.e., best fitness is smallest value) 00446 if (m_minimizing) 00447 m_scaler.invert(m_populations[p]); 00448 00449 // let other processes do something 00450 m_listener.yield(); 00451 00452 // scale the population's fitness 00453 m_scaler.scale_fitness(m_populations[p]); 00454 00455 // let other processes do something 00456 m_listener.yield(); 00457 00458 // get survivors and number of chromosomes to add 00459 vector<OrganismType> survivors = m_selector.select_survivors(m_populations[p]); 00460 00461 // let other processes do something 00462 m_listener.yield(); 00463 00464 // give birth to new chromosomes 00465 vector<OrganismType> children = m_reproducer.breed(m_populations[p], m_population_size - survivors.size()); 00466 00467 // let other processes do something 00468 m_listener.yield(); 00469 00470 // mutate the child chromosomes 00471 m_mutator.mutate(children); 00472 00473 // let other processes do something 00474 m_listener.yield(); 00475 00476 // replace old evocosm with new one 00477 m_populations[p] = survivors; 00478 m_populations[p].insert(m_populations[p].end(),children.begin(),children.end()); 00479 } 00480 00481 if (m_number_of_populations > 1) 00482 m_migrator.migrate(m_populations); 00483 } 00484 00485 // we're done with this generation 00486 m_listener.ping_generation_end(m_iteration); 00487 00488 // let other processes do something 00489 m_listener.yield(); 00490 00491 return keep_going & m_running; 00492 } 00493 }; 00494 00495 #endif
© 1996-2005 Scott Robert Ladd. All rights reserved.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.