# ifndef __EO_MULTISTART_H__ # define __EO_MULTISTART_H__ # include # include "eoMpi.h" namespace eo { namespace mpi { template< class EOT > struct MultiStartData { typedef eoUF< eoPop&, void> ResetAlgo; MultiStartData( bmpi::communicator& _comm, eoAlgo& _algo, int _masterRank, ResetAlgo & _resetAlgo ) : runs( 0 ), pop(), bests(), comm( _comm ), algo( _algo ), masterRank( _masterRank ), resetAlgo( _resetAlgo ) { // empty } // dynamic parameters int runs; eoPop< EOT > bests; eoPop< EOT > pop; // static parameters bmpi::communicator& comm; eoAlgo& algo; ResetAlgo& resetAlgo; int masterRank; }; template< class EOT > class SendTaskMultiStart : public SendTaskFunction< MultiStartData< EOT > > { public: using SendTaskFunction< MultiStartData< EOT > >::_data; void operator()( int wrkRank ) { --(_data->runs); } }; template< class EOT > class HandleResponseMultiStart : public HandleResponseFunction< MultiStartData< EOT > > { public: using HandleResponseFunction< MultiStartData< EOT > >::_data; void operator()( int wrkRank ) { EOT individual; MultiStartData< EOT >& d = *_data; d.comm.recv( wrkRank, 1, individual ); d.bests.push_back( individual ); } }; template< class EOT > class ProcessTaskMultiStart : public ProcessTaskFunction< MultiStartData< EOT > > { public: using ProcessTaskFunction< MultiStartData >::_data; void operator()() { _data->resetAlgo( _data->pop ); _data->algo( _data->pop ); _data->comm.send( _data->masterRank, 1, _data->pop.best_element() ); } }; template< class EOT > class IsFinishedMultiStart : public IsFinishedFunction< MultiStartData< EOT > > { public: using IsFinishedFunction< MultiStartData< EOT > >::_data; bool operator()() { return _data->runs <= 0; } }; template< class EOT > class MultiStartStore : public JobStore< MultiStartData< EOT > > { public: typedef typename MultiStartData::ResetAlgo ResetAlgo; typedef eoUF< int, std::vector > GetSeeds; MultiStartStore( eoAlgo & algo, int masterRank, ResetAlgo & resetAlgo, GetSeeds & getSeeds ) : _data( eo::mpi::Node::comm(), algo, masterRank, resetAlgo ), _getSeeds( getSeeds ), _masterRank( masterRank ) { this->_iff = new IsFinishedMultiStart< EOT >; this->_iff->needDelete(true); this->_stf = new SendTaskMultiStart< EOT >; this->_stf->needDelete(true); this->_hrf = new HandleResponseMultiStart< EOT >; this->_hrf->needDelete(true); this->_ptf = new ProcessTaskMultiStart< EOT >; this->_ptf->needDelete(true); } void init( const std::vector& workers, int runs ) { _data.runs = runs; int nbWorkers = workers.size(); std::vector< int > seeds = _getSeeds( nbWorkers ); if( eo::mpi::Node::comm().rank() == _masterRank ) { if( seeds.size() < nbWorkers ) { // Random seeds for( int i = seeds.size(); i < nbWorkers; ++i ) { seeds.push_back( eo::rng.rand() ); } } for( int i = 0 ; i < nbWorkers ; ++i ) { int wrkRank = workers[i]; eo::mpi::Node::comm().send( wrkRank, 1, seeds[ i ] ); } } else { int seed; eo::mpi::Node::comm().recv( _masterRank, 1, seed ); eo::log << eo::debug << eo::mpi::Node::comm().rank() << "- Seed: " << seed << std::endl; eo::rng.reseed( seed ); } } MultiStartData* data() { return &_data; } private: MultiStartData< EOT > _data; GetSeeds & _getSeeds; int _masterRank; }; template // No seeds! Use default generator struct DummyGetSeeds : public MultiStartStore::GetSeeds { std::vector operator()( int n ) { return std::vector(); } }; template // Multiple of a seed struct MultiplesOfNumber : public MultiStartStore::GetSeeds { MultiplesOfNumber ( int n = 0 ) { while( n == 0 ) { n = eo::rng.rand(); } _seed = n; _i = 0; } std::vector operator()( int n ) { std::vector ret; for( unsigned int i = 0; i < n; ++i ) { ret.push_back( (++_i) * _seed ); } return ret; } private: unsigned int _seed; unsigned int _i; }; template struct GetRandomSeeds : public MultiStartStore::GetSeeds { GetRandomSeeds( int seed ) { eo::rng.reseed( seed ); } std::vector operator()( int n ) { std::vector ret; for(int i = 0; i < n; ++i) { ret.push_back( eo::rng.rand() ); } return ret; } }; template struct ReuseOriginalPopEA: public MultiStartStore::ResetAlgo { ReuseOriginalPopEA( eoGenContinue & continuator, const eoPop& originalPop, eoEvalFunc& eval) : _initial( continuator.totalGenerations() ), _continuator( continuator ), _originalPop( originalPop ), _eval( eval ) { // empty } void operator()( eoPop& pop ) { pop = _originalPop; for(unsigned i = 0, size = pop.size(); i < size; ++i) { _eval( pop[i] ); } _continuator.totalGenerations( _initial ); } private: unsigned int _initial; eoGenContinue & _continuator; const eoPop& _originalPop; eoEvalFunc& _eval; }; template< class EOT > struct ReuseSamePopEA : public MultiStartStore::ResetAlgo { ReuseSamePopEA( eoGenContinue& continuator, const eoPop& originalPop, eoEvalFunc& eval ) : _continuator( continuator ), _originalPop( originalPop ), _firstTime( true ), _initial( continuator.totalGenerations() ) { for( unsigned i = 0, size = originalPop.size(); i < size; ++i ) { eval(_originalPop[i]); } } void operator()( eoPop& pop ) { if( _firstTime ) { pop = _originalPop; _firstTime = false; } _continuator.totalGenerations( _initial ); } protected: eoGenContinue& _continuator; eoPop _originalPop; bool _firstTime; int _initial; }; template< class EOT > class MultiStart : public OneShotJob< MultiStartData< EOT > > { public: MultiStart( AssignmentAlgorithm & algo, int masterRank, MultiStartStore< EOT > & store, // dynamic parameters int runs, const std::vector& seeds = std::vector() ) : OneShotJob< MultiStartData< EOT > >( algo, masterRank, store ) { store.init( algo.idles(), runs ); } eoPop& best_individuals() { return this->store.data()->bests; } }; } // namespace mpi } // namespace eo # endif // __EO_MULTISTART_H__