Evocosm - A C++ Framework for Evolutionary Computing

Main Index

Created by Scott Robert Ladd at Coyote Gulch Productions.


function_optimizer.h
00001 /*
00002     Evocosm is a C++ framework for implementing evolutionary algorithms.
00003 
00004     Copyright 2011 Scott Robert Ladd. All rights reserved.
00005 
00006     Evocosm is user-supported open source software. Its continued development is dependent
00007     on financial support from the community. You can provide funding by visiting the Evocosm
00008     website at:
00009 
00010         http://www.coyotegulch.com
00011 
00012     You may license Evocosm in one of two fashions:
00013 
00014     1) Simplified BSD License (FreeBSD License)
00015 
00016     Redistribution and use in source and binary forms, with or without modification, are
00017     permitted provided that the following conditions are met:
00018 
00019     1.  Redistributions of source code must retain the above copyright notice, this list of
00020         conditions and the following disclaimer.
00021 
00022     2.  Redistributions in binary form must reproduce the above copyright notice, this list
00023         of conditions and the following disclaimer in the documentation and/or other materials
00024         provided with the distribution.
00025 
00026     THIS SOFTWARE IS PROVIDED BY SCOTT ROBERT LADD ``AS IS'' AND ANY EXPRESS OR IMPLIED
00027     WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00028     FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SCOTT ROBERT LADD OR
00029     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00030     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00031     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00032     ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00033     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00034     ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035 
00036     The views and conclusions contained in the software and documentation are those of the
00037     authors and should not be interpreted as representing official policies, either expressed
00038     or implied, of Scott Robert Ladd.
00039 
00040     2) Closed-Source Proprietary License
00041 
00042     If your project is a closed-source or proprietary project, the Simplified BSD License may
00043     not be appropriate or desirable. In such cases, contact the Evocosm copyright holder to
00044     arrange your purchase of an appropriate license.
00045 
00046     The author can be contacted at:
00047 
00048           scott.ladd@coyotegulch.com
00049           scott.ladd@gmail.com
00050           http:www.coyotegulch.com
00051 */
00052 
00053 #if !defined(EVOCOSM_FUNCTION_OPTIMIZER_H)
00054 #define EVOCOSM_FUNCTION_OPTIMIZER_H
00055 
00056 #include <vector>
00057 #include <stdexcept>
00058 #include <limits>
00059 
00060 // other elements of Evocosm
00061 #include "evocosm.h"
00062 #include "evoreal.h"
00063 
00064 // OpenMP support, if requested
00065 #if defined(_OPENMP)
00066 #include <omp.h>
00067 #endif
00068 
00069 namespace libevocosm
00070 {
00072 
00077     class fopt_global
00078     {
00079     protected:
00081 
00089         typedef vector<double> t_function(vector<double> a_args);
00090 
00092         static evoreal g_evoreal;
00093     };
00094 
00096 
00105     class function_solution : public organism< vector<double> >, protected fopt_global
00106     {
00107     public:
00114         double value;
00115 
00116     protected:
00118         virtual void child_copy(const organism & a_source)
00119         {
00120             value = dynamic_cast<const function_solution &>(a_source).value;
00121         }
00122 
00123     private:
00124         double m_minarg;
00125         double m_maxarg;
00126         double m_extent;
00127 
00128     public:
00130 
00133         function_solution()
00134           : organism< vector<double> >(),
00135             value(0.0),
00136             m_minarg(-1.0),
00137             m_maxarg(1.0),
00138             m_extent(2.0)
00139         {
00140             // nada
00141         }
00142 
00144 
00147         function_solution(int a_nargs, double a_minarg, double a_maxarg)
00148           : organism< vector<double> >(), value(0.0)
00149         {
00150             double base;
00151             double extent;
00152 
00153             if (a_maxarg < a_minarg)
00154             {
00155                 double temp = a_maxarg;
00156                 a_maxarg = a_minarg;
00157                 a_minarg = a_maxarg;
00158             }
00159 
00160             m_minarg = a_minarg;
00161             m_maxarg = a_maxarg;
00162             m_extent = a_maxarg - a_minarg;
00163 
00164             // values fall in the range [-1,1]
00165             for (size_t n = 0; n < a_nargs; ++n)
00166                 genes.push_back(g_random.get_real() * m_extent + a_minarg);
00167         }
00168 
00170 
00173         function_solution(const vector<double> & a_source)
00174           : organism< vector<double> >(a_source), value(0.0)
00175         {
00176             // nada
00177         }
00178 
00180 
00184         function_solution(const organism< vector<double> > & a_source)
00185           : organism< vector<double> >(a_source), value(0.0)
00186         {
00187             // nada
00188         }
00189 
00191 
00195         function_solution(const function_solution & a_source)
00196           : organism< vector<double> >(a_source),
00197             value(a_source.value),
00198             m_minarg(a_source.m_minarg),
00199             m_maxarg(a_source.m_maxarg),
00200             m_extent(a_source.m_extent)
00201         {
00202             // nada
00203         }
00204 
00206 
00209         virtual ~function_solution()
00210         {
00211             // nada
00212         }
00213 
00215 
00220         function_solution & operator = (const function_solution & a_source)
00221         {
00222             organism< vector<double> >::operator = (a_source);
00223             value = a_source.value;
00224             m_minarg = a_source.m_minarg;
00225             m_maxarg = a_source.m_maxarg;
00226             m_extent = a_source.m_extent;
00227             return *this;
00228         }
00229 
00231 
00238         virtual bool operator < (const organism< vector<double> > & a_right) const
00239         {
00240             return (fitness > a_right.fitness);
00241         }
00242     };
00243 
00245 
00248     class function_mutator : public mutator<function_solution>, protected fopt_global
00249     {
00250     public:
00252 
00255         function_mutator(double a_mutation_rate)
00256           : m_mutation_rate(a_mutation_rate)
00257         {
00258             // adjust mutation rate if necessary
00259             if (m_mutation_rate > 1.0)
00260                 m_mutation_rate = 1.0;
00261             else if (m_mutation_rate < 0.0)
00262                 m_mutation_rate = 0.0;
00263         }
00264 
00266 
00270         function_mutator(const function_mutator & a_source)
00271             : m_mutation_rate(a_source.m_mutation_rate)
00272         {
00273             // nada
00274         }
00275 
00277 
00280         virtual ~function_mutator()
00281         {
00282             // nada
00283         }
00284 
00286 
00291         function_mutator & operator = (const function_mutator & a_source)
00292         {
00293             m_mutation_rate = a_source.m_mutation_rate;
00294             return *this;
00295         }
00296 
00298 
00302         double mutation_rate() const
00303         {
00304             return m_mutation_rate;
00305         }
00306 
00308 
00312         void mutate(vector<function_solution> & a_population);
00313 
00314     private:
00315         // rate of mutation
00316         double m_mutation_rate;
00317     };
00318 
00320 
00323     class function_reproducer : public reproducer<function_solution>, protected fopt_global
00324     {
00325     public:
00327 
00330         function_reproducer(double p_crossover_rate = 1.0)
00331             : m_crossover_rate(p_crossover_rate)
00332         {
00333             // adjust crossover rate if necessary
00334             if (m_crossover_rate > 1.0)
00335                 m_crossover_rate = 1.0;
00336             else if (m_crossover_rate < 0.0)
00337                 m_crossover_rate = 0.0;
00338         }
00339 
00341 
00345         function_reproducer(const function_reproducer & a_source)
00346             : m_crossover_rate(a_source.m_crossover_rate)
00347         {
00348             // nada
00349         }
00350 
00352 
00355         virtual ~function_reproducer()
00356         {
00357             // nada
00358         }
00359 
00361 
00366         function_reproducer & operator = (const function_reproducer & a_source)
00367         {
00368             m_crossover_rate = a_source.m_crossover_rate;
00369             return *this;
00370         }
00371 
00373 
00377         double crossover_rate() const
00378         {
00379             return m_crossover_rate;
00380         }
00381 
00383 
00392         virtual vector<function_solution> breed(const vector<function_solution> & a_population, size_t p_limit);
00393 
00394     private:
00395         // crossover chance
00396         double m_crossover_rate;
00397     };
00398 
00400 
00405     class function_landscape : public landscape<function_solution>, protected fopt_global
00406     {
00407     public:
00409 
00414         function_landscape(t_function * a_function, listener<function_solution> & a_listener)
00415           : landscape<function_solution>(a_listener),
00416             m_function(a_function)
00417         {
00418             // nada
00419         }
00420 
00422         function_landscape(const function_landscape & a_source)
00423           : landscape<function_solution>(a_source),
00424             m_function(a_source.m_function)
00425         {
00426             // nada
00427         }
00428 
00430         function_landscape & operator = (const function_landscape & a_source)
00431         {
00432             landscape<function_solution>::operator = (a_source);
00433             m_function = a_source.m_function;
00434             return *this;
00435         }
00436 
00438 
00441         ~function_landscape()
00442         {
00443             // nada
00444         }
00445 
00447 
00454         virtual double test(function_solution & a_organism, bool a_verbose = false) const
00455         {
00456             vector<double> z = m_function(a_organism.genes);
00457             a_organism.value   = z[0];
00458             a_organism.fitness = z[1];
00459             return a_organism.fitness;
00460         }
00461 
00462     private:
00463         // fitness function pointer
00464         t_function * m_function;
00465     };
00466 
00468 
00472     class function_analyzer : public analyzer<function_solution>
00473     {
00474     private:
00475         function_solution m_prev_best;
00476         size_t m_count;
00477 
00478     public:
00480 
00484         function_analyzer(listener<function_solution> & a_listener, size_t max_iterations)
00485             : analyzer<function_solution>(a_listener, max_iterations),
00486               m_prev_best(function_solution()),
00487               m_count(0)
00488         {
00489             // nada
00490         }
00491 
00493 
00503         virtual bool analyze(const vector<function_solution> & a_population,
00504                              size_t a_iteration,
00505                              double & a_fitness);
00506     };
00507 
00509 
00513     class function_listener : public null_listener<function_solution>
00514     {
00515     public:
00517 
00521         virtual void ping_generation_begin(size_t a_iteration);
00522 
00524 
00529         virtual void ping_generation_end(const vector<function_solution> & a_population, size_t a_iteration);
00530     };
00531 
00533 
00538     class function_optimizer : protected fopt_global, protected function_listener
00539     {
00540     private:
00541         // objects that define the characteristics of the genetic algorithm
00542         vector<function_solution>             m_population;
00543         function_landscape                    m_landscape;
00544         function_mutator                      m_mutator;
00545         function_reproducer                   m_reproducer;
00546         linear_norm_scaler<function_solution> m_scaler;
00547         elitism_selector<function_solution>   m_selector;
00548         function_analyzer                     m_analyzer;
00549 
00550         // the evocosm binds it all together
00551         evocosm<function_solution> * m_evocosm;
00552 
00553         // number of iterations to run
00554         const size_t m_iterations;
00555 
00556     public:
00558 
00568         function_optimizer(t_function * a_function,
00569                            size_t       a_nargs,
00570                            double       a_minarg,
00571                            double       a_maxarg,
00572                            size_t       a_norgs,
00573                            double       a_mutation_rate,
00574                            size_t       a_iterations);
00575 
00577 
00580         virtual ~function_optimizer();
00581 
00583 
00588         void run();
00589     };
00590 
00591 };
00592 
00593 #endif

© 1996-2005 Scott Robert Ladd. All rights reserved.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.