Differential Evolution C++ library
|
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