// "peoSyncIslandMig.h" // (c) OPAC Team, LIFL, August 2005 /* Contact: paradiseo-help@lists.gforge.inria.fr */ #ifndef __peoSyncIslandMig_h #define __peoSyncIslandMig_h #include #include #include #include #include #include #include #include #include "core/topology.h" #include "core/thread.h" #include "core/eoPop_comm.h" #include "core/peo_debug.h" //! Class providing the basis for the synchronous island migration model. //! The peoSyncIslandMig class offers the elementary basis for implementating a //! synchronous island migration model - requires the specification of several basic //! parameters, i.e. frequency of the migrations, selection and replacement strategies, //! a topological model and the source and destination population for the migrating individuals. //! The main difference as opposed to the asynchronous migration model is the synchronization step //! performed after selecting and sending the emigrant individuals. //! //! The migration operator is called at the end of each generation of an evolutionary algorithms //! as a checkpoint object - the following code exposes the structure of a classic evolutionary algorithm: //! //! //! //! //! //! //! //! //!
do {    
         select( population, offsprings );   // select the offsprings from the current population
         transform( offsprings );   // crossover and mutation operators are applied on the selected offsprings
         evaluate( offsprings );   // evaluation step of the resulting offspring
         replace( population, offsprings );   // replace the individuals in the current population whith individuals from the offspring population, according to a specified replacement strategy
} while ( eaCheckpointContinue( population ) );   // checkpoint operators are applied on the current population, including the migration operator, if any specified
//! //! Constructing a synchronous island migration model requires having defined (1) a topological migration model, //! (2) the control parameters of the migration process, (3) a checkpoint object associated with an evolutionary algorithm, //! and (4) an owner object must be set. The owner object must be derived from the Runner class (for example //! a peoEA object represents a possible owner). //! A simple example is offered bellow: //! //!
    //!
  1. topological model to be followed when performing migrations:
    //!
    //! //! //!
    RingTopology migTopology;   // a simple ring topological model - each island communicates with two other islands
    //!
  2. //! //!
  3. the continuation criterion, selection and replacement strategy etc. are defined:
    //!
    //! //! //! //! //! //! //! //! //! //!
    eoPop< EOT > population( POP_SIZE, popInitializer );   // population of individuals to be used for the evolutionary algorithm
       
    eoRandomSelect< EOT > migSelectStrategy;   // selection strategy - in this case a random selection is applied
    eoSelectNumber< EOT > migSelect( migSelectStrategy, MIG_SIZE );   // number of individuals to be selected using the specified strategy
    eoPlusReplacement< EOT > migReplace;   // immigration strategy - the worse individuals in the destination population are replaced by the immigrant individuals
       
    peoSyncIslandMig< EOT > syncMigration( //!
             MIG_FREQ, migSelect, migReplace, migTopology, //!
             population, population //!
    );  
    // synchronous migration object - the emigrant individuals are selected from the same from population in which the immigrant individuals are being integrated
    //!
  4. //! //!
  5. creation of a checkpoint object as part of the definition of an evolutionary algoritm (details of th EA not given as being out of scope):
    //!
    //! //! //! //! //! //! //! //!
    ...    
    eoGenContinue< EOT > eaCont( NUM_GEN );   // the evolutionary algorithm will stop after NUM_GEN generations
    eoCheckPoint< EOT > eaCheckpointContinue( eaCont );   // number of individuals to be selected using the specified strategy
    ...    
    eaCheckpointContinue.add( syncMigration );   // adding the migration operator as checkpoint element
    ...    
    //!
  6. //! //!
  7. definition of an owner evolutionary algorithm (an object inheriting the Runner class):
    //!
    //! //! //! //! //!
    peoEA< EOT > eaAlg( eaCheckpointContinue, eaPopEval, eaSelect, eaTransform, eaReplace);   // evolutionary algorithm having as checkpoint the eaCheckpointContinue object defined above
    syncMigration.setOwner( eaAlg );   // setting the evolutionary algorithm as owner of the migration object
    eaAlg( population );   // applying the evolutionary algorithm on a given population
    //!
  8. //!
//! //! The source and the destination population for the migration object were specified as being the same, in step no. 2, //! as we are usually interested in selecting the emigrants and integrating the immigrant individuals from and in, respectively, one unique //! population, iteratively evolved by an evolutionary algorithm. There is no restriction in having two distinct populations //! as source and destination for the emigrant and immigrant individuals respectively. //! //! The above steps only create a synchronous migration object associated to an evolutionary algorithm. The creation of several //! islands requires the reiteration of the steps 2 through 4 for creating distinct algorithms, with distinct populations and //! the associated distinctly parametrized migration objects. The interconnecting element is the underlying topology, defined at step 1 //! (the same C++ migTopology object has to be passed as parameter for all the migration objects, in order to interconnect them). template< class EOT > class peoSyncIslandMig : public Cooperative, public eoUpdater { public: //! Constructor for the peoSyncIslandMig class; the characteristics of the migration model are defined //! through the specified parameters - out of the box objects provided in EO, etc., or custom, derived objects may be passed as parameters. //! //! @param unsigned __frequency - frequency of the migrations - the migrations occur periodically; //! @param eoSelect< EOT >& __select - selection strategy to be applied for constructing a list of emigrant individuals out of the source population; //! @param eoReplacement< EOT >& __replace - replacement strategy used for integrating the immigrant individuals in the destination population; //! @param Topology& __topology - topological model to be followed when performing migrations; //! @param eoPop< EOT >& __source - source population from which the emigrant individuals are selected; //! @param eoPop< EOT >& __destination - destination population in which the immigrant population are integrated. peoSyncIslandMig( unsigned __frequency, eoSelect< EOT >& __select, eoReplacement< EOT >& __replace, Topology& __topology, eoPop< EOT >& __source, eoPop< EOT >& __destination ); //! Function operator to be called as checkpoint for performing the migration step. The emigrant individuals are selected //! from the source population and sent to the next island (defined by the topology object) while the immigrant //! individuals are integrated in the destination population. There is no need to explicitly call the function - the //! wrapper checkpoint object (please refer to the above example) will perform the call when required. void operator()(); //! Auxiliary function dealing with sending the emigrant individuals. There is no need to explicitly call the function. void pack(); //! Auxiliary function dealing with receiving immigrant individuals. There is no need to explicitly call the function. void unpack(); //! Auxiliary function dealing with migration notifications. There is no need to explicitly call the function. void notifySending(); private: void emigrate(); void immigrate(); private: eoPeriodicContinue< EOT > cont; eoSelect< EOT >& select; // selection strategy eoReplacement< EOT >& replace; // replacement strategy Topology& topology; // neighboring topology // source and target populations eoPop< EOT >& source; eoPop< EOT >& destination; // immigrants & emigrants in the queue std :: queue< eoPop< EOT > > imm; std :: queue< eoPop< EOT > > em; std :: queue< Cooperative* > coop_em; sem_t sync; }; template< class EOT > peoSyncIslandMig< EOT > :: peoSyncIslandMig( unsigned __frequency, eoSelect< EOT >& __select, eoReplacement< EOT >& __replace, Topology& __topology, eoPop< EOT >& __source, eoPop< EOT >& __destination ) : cont( __frequency ), select( __select ), replace( __replace ), topology( __topology ), source( __source ), destination( __destination ) { __topology.add( *this ); sem_init( &sync, 0, 0 ); } template< class EOT > void peoSyncIslandMig< EOT > :: pack() { lock(); { :: pack( coop_em.front()->getKey() ); :: pack( em.front() ); coop_em.pop(); em.pop(); } unlock(); } template< class EOT > void peoSyncIslandMig< EOT > :: unpack() { lock(); { eoPop< EOT > mig; :: unpack( mig ); imm.push( mig ); } unlock(); sem_post( &sync ); } template< class EOT > void peoSyncIslandMig< EOT > :: emigrate() { std :: vector< Cooperative* > in, out; topology.setNeighbors( this, in, out ); for ( unsigned i = 0; i < out.size(); i ++ ) { eoPop< EOT > mig; select( source, mig ); em.push( mig ); coop_em.push( out[ i ] ); send( out[ i ] ); printDebugMessage( "sending some emigrants." ); } } template< class EOT > void peoSyncIslandMig< EOT > :: immigrate() { lock(); { assert( imm.size() ); replace( destination, imm.front() ) ; imm.pop(); printDebugMessage( "receiving some immigrants." ); } unlock(); } template< class EOT > void peoSyncIslandMig< EOT > :: operator()() { if ( !cont( source ) ) { // sending emigrants emigrate(); stop(); // synchronizing sem_wait( &sync ); getOwner()->setActive(); // receiving immigrants immigrate(); } } template< class EOT > void peoSyncIslandMig< EOT > :: notifySending() { lock(); { if ( imm.empty() ) { printDebugMessage( "entering pasive mode\n" ); getOwner()->setPassive(); } } unlock(); resume(); } #endif