Evocosm - A C++ Framework for Evolutionary Computing

Main Index

Created by Scott Robert Ladd at Coyote Gulch Productions.


evocosm.h

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.