Differential Evolution C++ library
C:/dev/de/differentialevolution/differential_evolution.hpp
00001 /*
00002  * Copyright (c) 2011 Adrian Michel
00003  * http://www.amichel.com
00004  *
00005  * Permission to use, copy, modify, distribute and sell this 
00006  * software and its documentation for any purpose is hereby 
00007  * granted without fee, provided that both the above copyright 
00008  * notice and this permission notice appear in all copies and in 
00009  * the supporting documentation. 
00010  *  
00011  * This library is distributed in the hope that it will be 
00012  * useful. However, Adrian Michel makes no representations about
00013  * the suitability of this software for any purpose.  It is 
00014  * provided "as is" without any express or implied warranty. 
00015  * 
00016  * Should you find this library useful, please email 
00017  * info@amichel.com with a link or other reference 
00018  * to your work. 
00019 */
00020 
00021 #ifndef DE_DIFFERENTIAL_EVOLUTION_HPP_INCLUDED
00022 #define DE_DIFFERENTIAL_EVOLUTION_HPP_INCLUDED
00023 
00024 // MS compatible compilers support #pragma once
00025 
00026 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
00027 #pragma once
00028 #endif
00029 
00030 #include <boost/shared_ptr.hpp>
00031 #include <boost/make_shared.hpp>
00032 #include <boost/enable_shared_from_this.hpp>
00033 #include <boost/shared_array.hpp>
00034 #include <boost/scope_exit.hpp>
00035 
00036 #include "random_generator.hpp"
00037 #include "multithread.hpp"
00038 #include "individual.hpp"
00039 #include "processors.hpp"
00040 #include "mutation_strategy.hpp"
00041 #include "population.hpp"
00042 #include "selection_strategy.hpp"
00043 #include "termination_strategy.hpp"
00044 #include "listener.hpp"
00045 
00046 namespace de
00047 {
00048 
00055 class differential_evolution_exception
00056 {
00057 };
00058 
00067 template< typename T > class differential_evolution
00068 {
00069 private:
00070         const size_t m_varCount;
00071         const size_t m_popSize;
00072 
00073         population_ptr m_pop1;
00074         population_ptr m_pop2;
00075         individual_ptr m_bestInd;
00076 
00077         constraints_ptr m_constraints;
00078         typename processors< T >::processors_ptr m_processors;
00079         termination_strategy_ptr m_terminationStrategy;
00080         selection_strategy_ptr m_selectionStrategy;
00081         mutation_strategy_ptr m_mutationStrategy;
00082         listener_ptr m_listener;
00083 
00084         const bool m_minimize;
00085 public:
00110         differential_evolution( size_t varCount, size_t popSize, typename processors< T >::processors_ptr processors, constraints_ptr constraints, bool minimize, 
00111                                                    termination_strategy_ptr terminationStrategy, selection_strategy_ptr selectionStrategy, 
00112                                                         mutation_strategy_ptr mutationStrategy, de::listener_ptr listener )
00113         try
00114 
00115                 : m_varCount( varCount ), m_popSize( popSize ), m_pop1( boost::make_shared< population >( popSize, varCount, constraints ) ), 
00116                 m_pop2( boost::make_shared< population >( popSize, varCount ) ), m_bestInd( m_pop1->best( minimize ) ),
00117                 m_constraints( constraints ), m_processors( processors ), m_minimize( minimize ), m_terminationStrategy( terminationStrategy ),
00118                 m_listener( listener ), m_selectionStrategy( selectionStrategy ), m_mutationStrategy( mutationStrategy )
00119         {
00120                 assert( processors );
00121                 assert( constraints );
00122                 assert( terminationStrategy );
00123                 assert( selectionStrategy );
00124                 assert( listener );
00125                 assert( mutationStrategy );
00126 
00127                 assert( popSize > 0 );
00128                 assert( varCount > 0 );
00129 
00130                 // initializing population 1 by running all objective functions with
00131                 // the initial random arguments
00132                 processors->push( m_pop1 );
00133                 processors->start();
00134                 processors->wait();
00135 
00136         }
00137         catch( const processors_exception&)
00138         {
00139                 throw differential_evolution_exception();
00140         }
00141 
00142         virtual ~differential_evolution(void)
00143         {
00144         }
00145 
00155         void run()
00156         {
00157                 try
00158                 {
00159                         m_listener->start();
00160                         individual_ptr bestIndIteration( m_bestInd );
00161 
00162                         for( size_t genCount = 0 ; m_terminationStrategy->event( m_bestInd, genCount ); ++genCount ) 
00163                         {
00164                                 m_listener->startGeneration( genCount );
00165                                 for( size_t i = 0; i < m_popSize; ++i) 
00166                                 {
00167                                         mutation_strategy::mutation_info mutationInfo( ( *m_mutationStrategy)( *m_pop1, bestIndIteration, i ) );
00168 
00169                                         individual_ptr tmpInd( boost::tuples::get< 0 >( mutationInfo ) );
00170 
00171                                         tmpInd->ensureConstraints( m_constraints, boost::tuples::get< 1 >( mutationInfo ) );
00172 
00173                                         // populate the queue
00174                                         m_processors->push( tmpInd );
00175 
00176                                         // put temps in a temp vector for now (they are empty until processed), will be moved to the right place
00177                                         // after processed
00178                                         (*m_pop2)[ i ] = tmpInd;
00179                                 }
00180 
00181                                 m_listener->startProcessors( genCount );
00182                                 m_processors->start();
00183                                 m_processors->wait();
00184                                 m_listener->endProcessors( genCount );
00185 
00186                                 //BestParentChildSelectionStrategy()( m_pop1, m_pop2, m_bestInd, m_minimize );
00187                                 m_listener->startSelection( genCount );
00188                                 (*m_selectionStrategy)( m_pop1, m_pop2, m_bestInd, m_minimize );
00189                                 bestIndIteration = m_bestInd;
00190 
00191                                 m_listener->endSelection( genCount );
00192 
00193                                 m_listener->endGeneration( genCount, bestIndIteration, m_bestInd );
00194 
00195                         }
00196 
00197                         BOOST_SCOPE_EXIT_TPL( (m_listener) )
00198                         {
00199                                 m_listener->end();
00200                         } 
00201                         BOOST_SCOPE_EXIT_END
00202                 }
00203                 catch( const processors_exception& )
00204                 {
00205                         m_listener->error();
00206                         throw differential_evolution_exception();
00207                 }
00208 
00209         }
00210 
00219         individual_ptr best() const { return m_bestInd; }
00220 };
00221 
00222 }
00223 
00224 #endif //DE_DIFFERENTIAL_EVOLUTION_HPP_INCLUDED