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 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.