/*! * \brief Evaluate crowding distance of a pool of individuals. * \param outDistances Evaluated crowding distance and associated indexes. * \param inIndividualPool Pool of individuals to evaluate distance on. */ void EMO::NSGA2Op::evalCrowdingDistance(NSGA2Op::Distances& outDistances, const Individual::Bag& inIndividualPool) const { Beagle_StackTraceBeginM(); outDistances.clear(); if(inIndividualPool.size() == 0) return; outDistances.resize(inIndividualPool.size()); std::vector<CrowdingPair> lCrowdingSet(inIndividualPool.size()); for(unsigned int i=0; i<inIndividualPool.size(); ++i) { outDistances[i].first = 0.; outDistances[i].second = i; lCrowdingSet[i].first = i; lCrowdingSet[i].second = inIndividualPool[i]->getFitness(); } const unsigned int lNumberObjectives = lCrowdingSet.back().second->getNumberOfObjectives(); for(unsigned int j=0; j<lNumberObjectives; ++j) { std::sort(lCrowdingSet.begin(), lCrowdingSet.end(), IsLessCrowdingPairPredicate(j)); outDistances[lCrowdingSet.front().first].first = DBL_MAX; outDistances[lCrowdingSet.back().first].first = DBL_MAX; for(unsigned int k=1; k<(lCrowdingSet.size()-1); ++k) { if(outDistances[lCrowdingSet[k].first].first < DBL_MAX) { const double lObjDiff = lCrowdingSet[k+1].second->getObjective(j) - lCrowdingSet[k-1].second->getObjective(j); outDistances[lCrowdingSet[k].first].first += lObjDiff; } } } std::sort(outDistances.begin(), outDistances.end(), std::greater< std::pair<double,unsigned int> >()); Beagle_StackTraceEndM(); }
/*! * \brief Select an individual in a population randomly (using an uniform distribution). * \param ioPool Pool of individuals to use for selection. * \param ioContext Evolutionary context. */ unsigned int SelectRandomOp::selectIndividual(Individual::Bag& ioPool, Context& ioContext) { Beagle_StackTraceBeginM(); if(ioPool.size() < 2) return 0; return ioContext.getSystem().getRandomizer().rollInteger(0, ioPool.size()-1); Beagle_StackTraceEndM("unsigned int SelectRandomOp::selectIndividual(Individual::Bag& ioPool, Context& ioContext)"); }
/*! * \brief Recombine individuals by weighted mean to generate a new individual. * \param inIndivPool Parents being recombined. * \param ioContext Evolutionary context. * \return Children generated by recombination. */ Individual::Handle SAES::RecombinationWeightedOp::recombine(Individual::Bag& inIndivPool, Context& ioContext) { Beagle_StackTraceBeginM(); // Compute recombination weights. std::vector<double> lWeights(inIndivPool.size()); for(unsigned int i=0; i<lWeights.size(); ++i) { lWeights[i] = std::log(double(lWeights.size()+1)); lWeights[i] -= std::log(double(i+1)); } // Recombine parents to generate new individual. const Factory& lFactory = ioContext.getSystem().getFactory(); Individual::Alloc::Handle lIndivAlloc = castHandleT<Individual::Alloc>(lFactory.getConceptAllocator("Individual")); Genotype::Alloc::Handle lGenotypeAlloc = castHandleT<Genotype::Alloc>(lFactory.getConceptAllocator("Genotype")); Individual::Handle lChildIndiv = castHandleT<Individual>(lIndivAlloc->allocate()); std::vector< std::vector<double> > lCountGenoSum; for(unsigned int i=0; i<inIndivPool.size(); ++i) { const unsigned int lPoolISize = inIndivPool[i]->size(); const unsigned int lChildSize = lChildIndiv->size(); if(lPoolISize > lChildSize) { lCountGenoSum.resize(lPoolISize); lChildIndiv->resize(lPoolISize); for(unsigned int j=lChildSize; j<lPoolISize; ++j) { (*lChildIndiv)[j] = castHandleT<Genotype>(lGenotypeAlloc->allocate()); } } for(unsigned int j=0; j<lPoolISize; ++j) { SAES::PairVector::Handle lChildGenoJ = castHandleT<SAES::PairVector>((*lChildIndiv)[j]); SAES::PairVector::Handle lPoolIGenoJ = castHandleT<SAES::PairVector>((*inIndivPool[i])[j]); const unsigned int lPoolIGenoJSize = lPoolIGenoJ->size(); if(lPoolIGenoJSize > lChildGenoJ->size()) { lChildGenoJ->resize(lPoolIGenoJSize,0.0); lCountGenoSum[j].resize(lPoolIGenoJSize,0); } for(unsigned int k=0; k<lPoolIGenoJSize; ++k) { (*lChildGenoJ)[k].mValue += (lWeights[i] * (*lPoolIGenoJ)[k].mValue); (*lChildGenoJ)[k].mStrategy += (lWeights[i] * (*lPoolIGenoJ)[k].mStrategy); lCountGenoSum[j][k] += lWeights[i]; } } } for(unsigned int i=0; i<lChildIndiv->size(); ++i) { SAES::PairVector::Handle lChildGenoI = castHandleT<SAES::PairVector>((*lChildIndiv)[i]); for(unsigned int j=0; j<lChildGenoI->size(); ++j) { (*lChildGenoI)[j].mValue /= lCountGenoSum[i][j]; (*lChildGenoI)[j].mStrategy /= lCountGenoSum[i][j]; } } Beagle_LogDebugM(ioContext.getSystem().getLogger(), *lChildIndiv); return lChildIndiv; Beagle_StackTraceEndM(); }
/*! * \brief Apply the operation on a deme in the given context. * \param ioDeme Reference to the deme on which the operation takes place. * \param ioContext Evolutionary context of the operation. */ void GenerationalOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_NonNullPointerAssertM(getRootNode()); Beagle_NonNullPointerAssertM(mElitismKeepSize); Beagle_ValidateParameterM(mElitismKeepSize->getWrappedValue() <= ioDeme.size(), "ec.elite.keepsize", "The elistism keepsize must be less than the deme size!"); Beagle_LogTraceM( ioContext.getSystem().getLogger(), "Processing using generational replacement strategy the " << uint2ordinal(ioContext.getDemeIndex()+1) << " deme" ); Beagle_LogTraceM(ioContext.getSystem().getLogger(), (*this)); RouletteT<unsigned int> lRoulette; buildRoulette(lRoulette, ioContext); Individual::Bag lOffsprings; const Factory& lFactory = ioContext.getSystem().getFactory(); if(mElitismKeepSize->getWrappedValue() > 0) { History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History")); std::make_heap(ioDeme.begin(), ioDeme.end(), IsLessPointerPredicate()); for(unsigned int i=0; i<mElitismKeepSize->getWrappedValue(); ++i) { std::string lIndividualType = ioDeme[0]->getType(); Individual::Alloc::Handle lIndividualAlloc = castHandleT<Individual::Alloc>(lFactory.getAllocator(lIndividualType)); Individual::Handle lEliteIndiv = castHandleT<Individual>(lIndividualAlloc->allocate()); lEliteIndiv->copy(*ioDeme[0], ioContext.getSystem()); lOffsprings.push_back(lEliteIndiv); if(lHistory != NULL) { HistoryID::Handle lHID = castHandleT<HistoryID>(ioDeme[0]->getMember("HistoryID")); std::vector<HistoryID> lParent; if(lHID != NULL) lParent.push_back(*lHID); lHistory->allocateNewID(*lEliteIndiv); lHistory->trace(ioContext, lParent, lEliteIndiv, getName(), "elitism"); } std::pop_heap(ioDeme.begin(), (ioDeme.end()-i), IsLessPointerPredicate()); } } for(unsigned int i=mElitismKeepSize->getWrappedValue(); i<ioDeme.size(); ++i) { unsigned int lIndexBreeder = lRoulette.select(ioContext.getSystem().getRandomizer()); BreederNode::Handle lSelectedBreeder=getRootNode(); for(unsigned int j=0; j<lIndexBreeder; ++j) lSelectedBreeder=lSelectedBreeder->getNextSibling(); Beagle_NonNullPointerAssertM(lSelectedBreeder); Beagle_NonNullPointerAssertM(lSelectedBreeder->getBreederOp()); Individual::Handle lBredIndiv = lSelectedBreeder->getBreederOp()->breed(ioDeme, lSelectedBreeder->getFirstChild(), ioContext); Beagle_NonNullPointerAssertM(lBredIndiv); lOffsprings.push_back(lBredIndiv); } for(unsigned int j=0; j<lOffsprings.size(); ++j) ioDeme[j] = lOffsprings[j]; Beagle_StackTraceEndM(); }
void LogIndividualDataOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); if(mNumberIndividualPerDem->getWrappedValue() <= 0) { return; } // Temporary buffer of individuals. Individual::Bag lTempPop; if(ioContext.getGeneration() != mGenerationCalculated) { mGenerationCalculated = ioContext.getGeneration(); mNbDemesCalculated = 0; } if(++mNbDemesCalculated == mPopSize->size() && mOnlyVivarium->getWrappedValue()) { //Make heap of all individual in the vivarium for( unsigned int i = 0; i < ioContext.getVivarium().size(); ++i) { lTempPop.insert(lTempPop.end(), ioContext.getVivarium()[i]->begin(), ioContext.getVivarium()[i]->end()); } } else if(mOnlyVivarium->getWrappedValue()){ return; } else { //Process only this deme // Insert pointer of all the individuals of the deme in the buffer. lTempPop.insert(lTempPop.end(), ioDeme.begin(), ioDeme.end()); } // Make the buffer a STL heap with the fittest individual on the top. std::make_heap(lTempPop.begin(), lTempPop.end(), IsLessPointerPredicate()); for(unsigned int i = 0; i < mNumberIndividualPerDem->getWrappedValue(); ++i) { Individual::Handle lIndividual = NULL; if( !mKeepData->getWrappedValue() ) { //Strip the simulation data of the individual lIndividual = castHandleT<Individual>(ioDeme.getTypeAlloc()->cloneData(*lTempPop[0])); LogFitness::Handle lFitness = castHandleT<LogFitness>(lIndividual->getFitness()); lFitness->clearData(); } else { lIndividual = lTempPop[0]; } Beagle_LogObjectM( ioContext.getSystem().getLogger(), Logger::eStats, "history", "Beagle::LogIndividualDataOp", *lIndividual ); // STL heap pop of the best individual of the temporary buffer. std::pop_heap(lTempPop.begin(), lTempPop.end(), IsLessPointerPredicate()); lTempPop.pop_back(); } Beagle_StackTraceEndM("void LogIndividualDataOp::operate(Deme& ioDeme, Context& ioContext)"); }
/*! * \brief Select inN first individuals. * \param inN Number of individuals to select. * \param ioPool Pool from which the individuals are choosen. * \param ioContext Evolutionary context. * \param outSelections Vector of unsigned ints that say how often an individual was selected. * * The output of this method is via outSelection. It produces a * vector the same size as ioPool, where each index says how many * times an individual was selected. If this is not the desired * output, consider using the method convertToList(). */ void SelectFirstOp::selectNIndividuals(unsigned int inN, Individual::Bag& ioPool, Context& ioContext, std::vector<unsigned int>& outSelections) { Beagle_StackTraceBeginM(); const unsigned int lDivNP = inN / ioPool.size(); const unsigned int lModNP = inN % ioPool.size(); outSelections.resize(ioPool.size()); for(unsigned int i=0; i<ioPool.size(); ++i) { outSelections[i] = (i<lModNP) ? lDivNP+1 : lDivNP; } Beagle_StackTraceEndM("void SelectFirstOp::selectNIndividuals(unsigned int,Individual::Bag&,Context&,std::vector<unsigned int>&)"); }
/*! * \brief Select an individual using the tournament selection method. * \param ioPool Individual pool to use for selection. * \param ioContext Context of the evolution. * \return Index of the choosen individual in the pool. */ unsigned int SelectTournamentOp::selectOneIndividual(Individual::Bag& ioPool, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_ValidateParameterM(mNumberParticipants->getWrappedValue() > 0, "ec.sel.tournsize", ">0"); unsigned int lChoosenIndividual = ioContext.getSystem().getRandomizer().rollInteger(0,((unsigned int)ioPool.size())-1); Beagle_LogDebugM( ioContext.getSystem().getLogger(), std::string("Starting by choosing the ")+ uint2ordinal(lChoosenIndividual+1)+" individual" ); for(unsigned int j=1; j<mNumberParticipants->getWrappedValue(); j++) { unsigned int lTriedIndividual = ioContext.getSystem().getRandomizer().rollInteger(0,((unsigned int)ioPool.size())-1); if(ioPool[lChoosenIndividual]->isLess(*ioPool[lTriedIndividual])) { lChoosenIndividual = lTriedIndividual; Beagle_LogDebugM( ioContext.getSystem().getLogger(), std::string("Trying the ")+uint2ordinal(lTriedIndividual+1)+ " individual -> choosing it" ); } else { Beagle_LogDebugM( ioContext.getSystem().getLogger(), std::string("Trying the ")+uint2ordinal(lTriedIndividual+1)+ " individual -> the previously choosen one is better" ); } } Beagle_LogDebugM( ioContext.getSystem().getLogger(), "Selecting the " << uint2ordinal(lChoosenIndividual+1) << " individual" ); Beagle_LogDebugM(ioContext.getSystem().getLogger(), *ioPool[lChoosenIndividual]); return lChoosenIndividual; Beagle_StackTraceEndM(); }
/*! * \brief Select best individual of a pool of individuals. * \param ioPool Pool of individuals to use for selection. * \param ioContext Evolutionary context. */ unsigned int SelectBestOp::selectIndividual(Individual::Bag& ioPool, Context& ioContext) { Beagle_StackTraceBeginM(); unsigned int lBestIndex = 0; for(unsigned int i=1; i<ioPool.size(); ++i) { if(ioPool[lBestIndex]->isLess(*ioPool[i])) { lBestIndex = i; } } return lBestIndex; Beagle_StackTraceEndM("unsigned int SelectBestOp::selectIndividual(Individual::Bag&,Context&)"); }
/*! * \brief Apply NSGA2 multiobjective selection operator as a standard operator. * \param ioDeme Deme on which selection operator is applied. * \param ioContext Evolutionary context. */ void EMO::NSGA2Op::applyAsStandardOperator(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); // Fast non-dominated sorting, followed by insertion of the first Pareto fronts. Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "Applying fast non-dominated sorting on the whole population" ); NSGA2Op::Fronts lParetoFronts; const unsigned int lDesiredPopSize = (*mPopSize)[ioContext.getDemeIndex()]; Individual::Bag lSortedPop(ioDeme); sortFastND(lParetoFronts, lDesiredPopSize, lSortedPop, ioContext); unsigned int lIndexDeme=0; for(unsigned int j=0; j<(lParetoFronts.size()-1); ++j) { for(unsigned int k=0; k<lParetoFronts[j].size(); ++k) { ioDeme[lIndexDeme++] = lSortedPop[lParetoFronts[j][k]]; } } // Insertion of the last Pareto front, using crowding distance Individual::Bag lLastFrontIndiv; for(unsigned int l=0; l<lParetoFronts.back().size(); ++l) { lLastFrontIndiv.push_back(lSortedPop[lParetoFronts.back()[l]]); } NSGA2Op::Distances lDistances; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "Computing crowding distance on the " << uint2ordinal(lParetoFronts.size()) << " Pareto front, which is made of " << uint2ordinal(lParetoFronts.back().size()) << " individuals" ); evalCrowdingDistance(lDistances, lLastFrontIndiv); for(unsigned int m=0; lIndexDeme<lDesiredPopSize; ++m) { ioDeme[lIndexDeme++] = lLastFrontIndiv[lDistances[m].second]; } ioDeme.resize(lDesiredPopSize); Beagle_StackTraceEndM(); }
/*! * \brief Evaluate niche count of an individual over a pool of individuals. * \param inEvalIndividual Individual for which we need to evaluate crowding distance. * \param inIndividualPool Pool of individuals to evaluate distance on. * \return Niche count value. */ float NPGA2Op::evalNicheCount(const Individual& inEvalIndividual, const Individual::Bag& inIndividualPool) const { Beagle_StackTraceBeginM(); double lNicheCount = 0.; const Fitness::Handle lEvalFitness = inEvalIndividual.getFitness(); for(unsigned int i=0; i<inIndividualPool.size(); ++i) { float lDistance = lEvalFitness->getDistance(*inIndividualPool[i]->getFitness()); if(lDistance < mNicheRadius->getWrappedValue()) { lNicheCount += (1.0 - (lDistance / mNicheRadius->getWrappedValue())); } } return lNicheCount; Beagle_StackTraceEndM(); }
/*! * \brief Evaluate the fitness of the given individual. * \param inIndividual Current individual to evaluate. * \param ioContext Evolutionary context. * \return Handle to the fitness value of the individual. * * This method evaluates only a single individual. For this * operator, it is much better to group individuals into a bag and * pass the bag to evaluate(Individual::Bag& ioIndividuals, Context::Bag& ioContexts). */ Fitness::Handle EvaluationMultipleOp::evaluate(Individual& inIndividual, Context& ioContext) { Beagle_StackTraceBeginM(); // Create a bag for the individual Individual::Bag lIndividuals; lIndividuals.resize(1); Beagle_AssertM(inIndividual == ioContext.getIndividual()); lIndividuals[0] = ioContext.getIndividualHandle(); // Create a context for the individual Context::Bag lContexts; lContexts.resize(1); Context::Alloc::Handle lContextAlloc = castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context")); lContexts[0] = castHandleT<Context>(lContextAlloc->clone(ioContext)); // Call evalutate() Fitness::Bag::Handle lFitnessBag = evaluateIndividuals(lIndividuals,lContexts); // Return fitness Beagle_AssertM( !lFitnessBag->empty() ); return lFitnessBag->at(0); Beagle_StackTraceEndM(); }
/*! * \brief Recombine individuals by averaging to generate a new individual. * \param inIndivPool Parents being recombined. * \param ioContext Evolutionary context. * \return Children generated by recombination. */ Individual::Handle Beagle::GA::RecombinationESVecOp::recombine(Individual::Bag& inIndivPool, Context& ioContext) { Beagle_StackTraceBeginM(); // Recombine parents to generate new individual. const Factory& lFactory = ioContext.getSystem().getFactory(); Individual::Alloc::Handle lIndivAlloc = castHandleT<Individual::Alloc>(lFactory.getConceptAllocator("Individual")); Genotype::Alloc::Handle lGenotypeAlloc = castHandleT<Genotype::Alloc>(lFactory.getConceptAllocator("Genotype")); Individual::Handle lChildIndiv = castHandleT<Individual>(lIndivAlloc->allocate()); std::vector< std::vector<unsigned int> > lCountGenoSum; for(unsigned int i=0; i<inIndivPool.size(); ++i) { const unsigned int lPoolISize = inIndivPool[i]->size(); const unsigned int lChildSize = lChildIndiv->size(); if(lPoolISize > lChildSize) { lCountGenoSum.resize(lPoolISize); lChildIndiv->resize(lPoolISize); for(unsigned int j=lChildSize; j<lPoolISize; ++j) { (*lChildIndiv)[j] = castHandleT<Genotype>(lGenotypeAlloc->allocate()); } } for(unsigned int j=0; j<lPoolISize; ++j) { GA::ESVector::Handle lChildGenoJ = castHandleT<GA::ESVector>((*lChildIndiv)[j]); GA::ESVector::Handle lPoolIGenoJ = castHandleT<GA::ESVector>((*inIndivPool[i])[j]); const unsigned int lPoolIGenoJSize = lPoolIGenoJ->size(); if(lPoolIGenoJSize > lChildGenoJ->size()) { lChildGenoJ->resize(lPoolIGenoJSize,0.0); lCountGenoSum[j].resize(lPoolIGenoJSize,0); } for(unsigned int k=0; k<lPoolIGenoJSize; ++k) { (*lChildGenoJ)[k].mValue += (*lPoolIGenoJ)[k].mValue; (*lChildGenoJ)[k].mStrategy += (*lPoolIGenoJ)[k].mStrategy; ++lCountGenoSum[j][k]; } } } for(unsigned int i=0; i<lChildIndiv->size(); ++i) { GA::ESVector::Handle lChildGenoI = castHandleT<GA::ESVector>((*lChildIndiv)[i]); for(unsigned int j=0; j<lChildGenoI->size(); ++j) { (*lChildGenoI)[j].mValue /= double(lCountGenoSum[i][j]); (*lChildGenoI)[j].mStrategy /= double(lCountGenoSum[i][j]); } } Beagle_LogDebugM( ioContext.getSystem().getLogger(), "crossover", "Beagle::GA::RecombinationESVecOp", "Individual generated by recombination" ); Beagle_LogObjectDebugM( ioContext.getSystem().getLogger(), "crossover", "Beagle::GA::RecombinationESVecOp", *lChildIndiv ); return lChildIndiv; Beagle_StackTraceEndM("Individual::Handle Beagle::GA::RecombinationESVecOp::recombine(Individual::Bag& inIndivPool,Context& ioContext)"); }
/*! * \brief Add individuals to the bag such that the total equals getIndisPerGroup(). * \param ioIndividuals Bag of individuals to evaluate. * \param ioContexts Bag of evolutionary context. * \return The number of individuals added to the bag. * * The new individuals are chosen from the current deme. */ unsigned int EvaluationMultipleOp::enlargeGroup(Individual::Bag& ioIndividuals, Context::Bag& ioContexts) { Beagle_StackTraceBeginM(); Context& lContext = castObjectT<Context&>(*(ioContexts[0])); // Calculate the number of individuals to add unsigned int lNumToAdd = mIndisPerGroup - ioIndividuals.size(); Beagle_LogVerboseM( lContext.getSystem().getLogger(), std::string("Adding ")+uint2str(lNumToAdd)+std::string(" individuals to the group (for padding)") ); // Resize the bags unsigned int lIndisCounter = ioIndividuals.size(); ioIndividuals.resize(mIndisPerGroup); ioContexts.resize(mIndisPerGroup); // Loop through all the individuals in the deme Deme& lDeme = lContext.getDeme(); std::vector<unsigned int> lSelectableIndis; lSelectableIndis.resize(lDeme.size()); unsigned int lSelectableIndisCounter = 0; for (unsigned int i=0; i<lDeme.size(); i++) { // Loop through all the individuals in the bag bool lAdd = true; for(unsigned int j=0; j<ioIndividuals.size(); j++) { if(lDeme[i] == ioIndividuals[j]) { lAdd = false; break; } } // If the individual is not already in the bag, add it as an option if(lAdd) { lSelectableIndis[lSelectableIndisCounter] = i; lSelectableIndisCounter++; } } // Check there are sufficient individuals to choose if(lSelectableIndis.size() < lNumToAdd) { throw Beagle_RunTimeExceptionM("There are insufficient individuals in the deme to perform evaluation"); } // Add individuals for(unsigned int i=0; i<lNumToAdd; i++) { unsigned int lIndex = lContext.getSystem().getRandomizer().rollInteger(0,lSelectableIndisCounter-1); unsigned int lIndiIndex = lSelectableIndis[lIndex]; Beagle_LogVerboseM( lContext.getSystem().getLogger(), std::string("Adding ")+uint2ordinal(lIndiIndex+1)+ std::string(" individual to the group (for padding)") ); Beagle_AssertM(lIndiIndex < lDeme.size()); ioIndividuals[lIndisCounter] = lDeme[ lIndiIndex ]; Context::Alloc::Handle lContextAlloc = castHandleT<Context::Alloc>(lContext.getSystem().getFactory().getConceptAllocator("Context")); ioContexts[lIndisCounter] = castHandleT<Context>(lContextAlloc->clone(*(ioContexts[0]))); ioContexts[lIndisCounter]->setIndividualHandle( ioIndividuals[lIndisCounter] ); ioContexts[lIndisCounter]->setIndividualIndex( lIndiIndex ); lIndisCounter++; } Beagle_AssertM( lIndisCounter==ioIndividuals.size() ); return lNumToAdd; Beagle_StackTraceEndM(); }
/*! * \brief Apply the evaluation process on the invalid individuals of the deme. * \param ioDeme Deme to process. * \param ioContext Context of the evolution. */ void EvaluationMultipleOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_LogTraceM( ioContext.getSystem().getLogger(), "Evaluating the fitness of the individuals in the " << uint2ordinal(ioContext.getDemeIndex()+1) << " deme" ); Beagle_AssertM( ioDeme.size()!=0 ); // Prepare stats prepareStats(ioDeme,ioContext); // Generate a vector of indicies into the population std::vector<unsigned int> lEvalVector; for(unsigned int i=0; i<ioDeme.size(); i++) { if((ioDeme[i]->getFitness() == NULL) || (ioDeme[i]->getFitness()->isValid() == false)) { lEvalVector.push_back(i); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "Added " << uint2ordinal(i+1) << " individual for evaluation." ); } } std::random_shuffle(lEvalVector.begin(), lEvalVector.end(), ioContext.getSystem().getRandomizer()); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "There are " << lEvalVector.size() << " individuals to be evaluated." ); History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History")); while ( !lEvalVector.empty() ) { // Put individuals and context into bags. Individual::Bag lIndividuals; Context::Bag lContexts; lIndividuals.resize( mIndisPerGroup ); lContexts.resize( mIndisPerGroup ); unsigned int lIndiCounter =0; for (unsigned int i=0; i<mIndisPerGroup; i++) { // Set individual lIndividuals[i] = ioDeme[lEvalVector.back()]; lIndiCounter++; // Set context Context::Alloc::Handle lContextAlloc = castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context")); Context::Handle lContext = castHandleT<Context>(lContextAlloc->clone(ioContext)); lContext->setIndividualIndex( lEvalVector.back() ); lContext->setIndividualHandle( ioDeme[lEvalVector.back()] ); lContexts[i] = lContext; // Remove this index from the evaluation vector lEvalVector.pop_back(); if(lEvalVector.empty()) { lIndividuals.resize( lIndiCounter ); lContexts.resize( lIndiCounter ); break; } } // Evaluate individuals std::ostringstream lOSS; lOSS << "Evaluating the fitness of the "; for(unsigned int i=0; i<lIndiCounter; i++) { // Add to message if (i==lIndiCounter-1) lOSS << " and "; lOSS << uint2ordinal(lContexts[i]->getIndividualIndex()+1); if (i<lIndiCounter-2) lOSS << ", "; } lOSS << " individuals"; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), lOSS.str() ); Fitness::Bag::Handle lFitnessBag = evaluateIndividuals(lIndividuals, lContexts); // Assign fitnesses for (unsigned int i=0; i<lIndiCounter; i++) { Beagle_LogDebugM( ioContext.getSystem().getLogger(), "Considering fitness of the " << uint2ordinal(lContexts[i]->getIndividualIndex()+1) << " individual" ); Beagle_AssertM( i < lFitnessBag->size() ); Fitness::Handle lFitness = lFitnessBag->at(i); Beagle_NonNullPointerAssertM( lFitness ); lIndividuals[i]->setFitness( lFitness ); lIndividuals[i]->getFitness()->setValid(); if(lHistory != NULL) { lHistory->allocateID(*lIndividuals[i]); lHistory->trace(ioContext, std::vector<HistoryID>(), lIndividuals[i], getName(), "evaluation"); } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), *lIndividuals[i]->getFitness() ); } // Update stats updateStats(lIndividuals.size(),ioContext); } updateHallOfFameWithDeme(ioDeme,ioContext); Beagle_StackTraceEndM(); }
/*! * \brief Evaluate the fitness of the given bag of individuals. * \param ioIndividuals Bag of individuals to evaluate. * \param ioContexts Bag of evolutionary context. * \return Handle to a bag of fitness values, one for each individual. */ Fitness::Bag::Handle EvaluationMultipleOp::evaluateIndividuals(Individual::Bag& ioIndividuals, Context::Bag& ioContexts) { Beagle_StackTraceBeginM(); Beagle_AssertM(ioIndividuals.size()==ioContexts.size()); Beagle_AssertM(ioIndividuals.size()!=0); Context& lContext = castObjectT<Context&>(*(ioContexts[0])); // Check if sufficient individuals are in the bag Beagle_AssertM( ioIndividuals.size() <= mIndisPerGroup ); unsigned int lNumToIgnore = 0; if (ioIndividuals.size() != mIndisPerGroup) { lNumToIgnore = enlargeGroup(ioIndividuals, ioContexts); } // Create bag of null-fitnesses Fitness::Bag::Handle lFitnessBagAll = new Fitness::Bag; lFitnessBagAll->resize( ioIndividuals.size() ); Beagle_NonNullPointerAssertM( lFitnessBagAll ); // Set up cases if (mCases == NULL) setupCases(ioIndividuals.size(),lContext); Case::Bag::Handle lCases = pruneIgnorableCases(lNumToIgnore); // Call evaluateCase for each case for (unsigned int i=0; i<lCases->size(); i++) { Beagle_LogVerboseM( lContext.getSystem().getLogger(), std::string("Evaluating the ")+uint2ordinal(i+1)+std::string(" case") ); Case& lCase = *(lCases->at(i)); Beagle_AssertM( lCase.mIndices.size() == mIndisPerCase ); // Setup bags of individuals and contexts Individual::Bag lIndividuals; Context::Bag lContexts; lIndividuals.resize( mIndisPerCase ); lContexts.resize( mIndisPerCase ); for (unsigned int j=0; j<mIndisPerCase; j++) { unsigned int lIndex = lCase.mIndices[j]; lIndividuals[j] = ioIndividuals[ lIndex ]; lContexts[j] = ioContexts[ lIndex ]; } // Log individual's details std::ostringstream lOSS; for (unsigned int j=0; j<lIndividuals.size(); j++) { if (j!=0) lOSS << ", "; lOSS << uint2ordinal(lContexts[j]->getIndividualIndex()+1); } Beagle_LogDebugM( lContext.getSystem().getLogger(), uint2ordinal(i+1) << " case: " << lOSS.str() ); // Call evalutateCase() Fitness::Bag::Handle lFitnessBagCase = evaluateCase(lIndividuals, lContexts); // Log resulting fitnesses Beagle_NonNullPointerAssertM( lFitnessBagCase ); Beagle_LogDebugM( lContext.getSystem().getLogger(), "Evaluation of the case is complete. The fitnesses are as follows:" ); for (unsigned int j=0; j<mIndisPerCase; j++) { Beagle_NonNullPointerAssertM( lFitnessBagCase->at(j) ); Beagle_LogDebugM( lContext.getSystem().getLogger(), std::string("Fitness of the ")+ uint2ordinal(ioContexts[lCase.mIndices[j]]->getIndividualIndex()+1)+ std::string(" individual") ); Beagle_LogDebugM(lContext.getSystem().getLogger(), *(*lFitnessBagCase)[j]); // Need to assign fitness values from case to lFitnessBagAll unsigned int lIndex = lCase.mIndices[j]; Beagle_LogDebugM( lContext.getSystem().getLogger(), "Setting fitness for lFitnessBagAll at index " << uint2str(lIndex) ); Beagle_AssertM(lIndex < lFitnessBagAll->size()); if (lFitnessBagAll->at(lIndex)==NULL) { (*lFitnessBagAll)[lIndex] = lFitnessBagCase->at(j); } else { combineFitnesses(lFitnessBagAll->at(lIndex), lFitnessBagCase->at(j) ); Beagle_LogDebugM( lContext.getSystem().getLogger(), "Fitness of the " << uint2ordinal(ioContexts[lIndex]->getIndividualIndex()+1) << " individual has been combined to" ); Beagle_LogDebugM(lContext.getSystem().getLogger(), *(*lFitnessBagAll)[lIndex]); } } } Beagle_LogDebugM( lContext.getSystem().getLogger(), "Evaluation of all cases is complete. Fitnesses are as follows:" ); for (unsigned int i=0; i<ioIndividuals.size(); i++) { if (i>=mIndisPerGroup-lNumToIgnore) { // Nullify ignorable individuals' fitness scores Beagle_LogDebugM( lContext.getSystem().getLogger(), "Ignoring fitness of the " << uint2ordinal(ioContexts[i]->getIndividualIndex()+1) << " individual" ); (*lFitnessBagAll)[i] = NULL; continue; } Beagle_NonNullPointerAssertM( lFitnessBagAll->at(i) ); Beagle_LogDebugM( lContext.getSystem().getLogger(), "Fitness of the " << uint2ordinal(ioContexts[i]->getIndividualIndex()+1) << " individual" ); Beagle_LogDebugM(lContext.getSystem().getLogger(), *(*lFitnessBagAll)[i]); } return lFitnessBagAll; Beagle_StackTraceEndM(); }
/*! * \brief Apply the decimation operation on the deme. * \param ioDeme Current deme of individuals to decimate. * \param ioContext Context of the evolution. */ void DecimateOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_ValidateParameterM((mDecimationRatio->getWrappedValue()<=1.0), mDecimationRatioName, "The decimation ratio must be less than or equal to 1.0."); Beagle_LogTraceM( ioContext.getSystem().getLogger(), "decimation", "Beagle::DecimateOp", std::string("Applying decimation operation on the ")+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); // Calculate the number of individuals to keep from the deme unsigned int lMu = 0; if(mDecimationRatio->getWrappedValue() == -1.0) { Beagle_AssertM(ioContext.getDemeIndex() < mPopSize->size()); lMu = (*mPopSize)[ioContext.getDemeIndex()]; } else { lMu = (unsigned int)std::ceil(mDecimationRatio->getWrappedValue()*float(ioDeme.size())); Beagle_AssertM(ioContext.getDemeIndex() < mPopSize->size()); int lDiffSize = (*mPopSize)[ioContext.getDemeIndex()] - lMu; if((lDiffSize >= -1) && (lDiffSize <= 1)) lMu = (*mPopSize)[ioContext.getDemeIndex()]; } Beagle_LogTraceM( ioContext.getSystem().getLogger(), "decimation", "Beagle::DecimateOp", std::string("Keeping ")+uint2str(lMu)+" of the "+uint2str(ioDeme.size())+ " individuals from the "+uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); // Check that the number of individuals to keep (mu) isn't greater than the deme size if(lMu > ioDeme.size()) { std::ostringstream lOSS; lOSS << "Warning: the actual population size (" << ioDeme.size(); lOSS << ") is less than the desired decimation size (" << lMu; lOSS << "). Decimation is thus not applied."; Beagle_LogBasicM( ioContext.getSystem().getLogger(), "decimation", "Beagle::DecimateOp", lOSS.str() ); return; } // Copy the individuals to be kept into the deme std::make_heap(ioDeme.begin(), ioDeme.end(), IsLessPointerPredicate()); Individual::Bag lSurvivors; for(unsigned int i=0; i<lMu; ++i) { lSurvivors.push_back(ioDeme.front()); std::pop_heap(ioDeme.begin(), (ioDeme.end()-i), IsLessPointerPredicate()); } ioDeme.clear(); ioDeme.insert(ioDeme.begin(), lSurvivors.begin(), lSurvivors.end()); Beagle_LogDetailedM( ioContext.getSystem().getLogger(), "decimation", "Beagle::DecimateOp", std::string("There are now ")+uint2str(ioDeme.size())+" individuals in the "+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); Beagle_StackTraceEndM("void DecimateOp::operate(Deme& ioDeme, Context& ioContext)"); }
/*! * \brief Apply the recombination operation on a breeding pool, returning a recombined individual. * \param inBreedingPool Breeding pool to use for the recombination operation. * \param inChild Node handle associated to child node in the breeder tree. * \param ioContext Evolutionary context of the recombination operation. * \return Recombined individual. */ Individual::Handle RecombinationOp::breed(Individual::Bag& inBreedingPool, BreederNode::Handle inChild, Context& ioContext) { Beagle_StackTraceBeginM(); // Generate parents for recombination. Individual::Bag::Handle lParents = new Individual::Bag; if(inChild == NULL) { const unsigned int lNbGenerated = (mNumberRecomb->getWrappedValue()==0) ? inBreedingPool.size() : minOf<unsigned int>(inBreedingPool.size(), mNumberRecomb->getWrappedValue()); if(lNbGenerated == inBreedingPool.size()) (*lParents) = inBreedingPool; else { std::vector<unsigned int> lIndices(inBreedingPool.size()); for(unsigned int i=0; i<lIndices.size(); ++i) lIndices[i] = i; std::random_shuffle(lIndices.begin(), lIndices.end(), ioContext.getSystem().getRandomizer()); for(unsigned int i=0; i<lNbGenerated; ++i) { lParents->push_back(inBreedingPool[lIndices[i]]); } } } else { Beagle_NonNullPointerAssertM(inChild->getBreederOp()); const unsigned int lNbGenerated = (mNumberRecomb->getWrappedValue()==0) ? inBreedingPool.size() : minOf<unsigned int>(inBreedingPool.size(), mNumberRecomb->getWrappedValue()); for(unsigned int i=0; i<lNbGenerated; ++i) { Individual::Handle lIndiv = inChild->getBreederOp()->breed(inBreedingPool, inChild->getFirstChild(), ioContext); lParents->push_back(lIndiv); } } // Log parents selected for recombination. Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Recombining ")+uint2str(lParents->size())+std::string(" individuals together") ); // Do recombination operation on parent and get the resulting child. Individual::Handle lChildIndiv = recombine(*lParents, ioContext); if(lChildIndiv->getFitness() != NULL) { lChildIndiv->getFitness()->setInvalid(); } // Log information to history, if it is used. History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History")); if(lHistory != NULL) { std::vector<HistoryID> lParentNames; for(unsigned int i=0; i<lParents->size(); ++i) { HistoryID::Handle lHID = castHandleT<HistoryID>(lParents->at(i)->getMember("HistoryID")); if(lHID != NULL) lParentNames.push_back(*lHID); } lHistory->incrementHistoryVar(*lChildIndiv); lHistory->trace(ioContext, lParentNames, lChildIndiv, getName(), "recombination"); } return lChildIndiv; Beagle_StackTraceEndM(); }
/*! * \brief Apply the oversize replacement strategy operation on a deme. * \param ioDeme Reference to the deme on which the operation takes place. * \param ioContext Evolutionary context of the operation. */ void OversizeOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_NonNullPointerAssertM(getRootNode()); Beagle_ValidateParameterM (mOversizeRatio->getWrappedValue() >= 1.0 || mOversizeRatio->getWrappedValue() == -1.0, mOversizeRatioName, "The oversize ratio must be greater than or equal to 1.0, or equal to -1.0."); Beagle_LogTraceM( ioContext.getSystem().getLogger(), "replacement-strategy", "Beagle::OversizeOp", string("Using oversize replacement strategy to process the ")+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); Beagle_LogObjectM( ioContext.getSystem().getLogger(), Logger::eTrace, "replacement-strategy", "Beagle::OversizeOp", (*this) ); RouletteT<unsigned int> lRoulette; buildRoulette(lRoulette, ioContext); // Calculate the increase in size (lambda) float lRatio = mOversizeRatio->getWrappedValue(); unsigned int lLambda; if (lRatio == -1.0) { // Using special ratio of -1.0 ensures deme grows to size specified in 'ec.pop.size' if (!ioContext.getSystem().getRegister().isRegistered("ec.pop.size")) { throw Beagle_RunTimeExceptionM(getName()+" requires register variable 'ec.pop.size'"); } UIntArray::Handle lPopSize = castHandleT<UIntArray> (ioContext.getSystem().getRegister().getEntry("ec.pop.size")); unsigned int lSpecifiedDemeSize = (*lPopSize)[ioContext.getDemeIndex()]; unsigned int lCurrentDemeSize = ioDeme.size(); if (lSpecifiedDemeSize < lCurrentDemeSize) { throw Beagle_RunTimeExceptionM (std::string("For the ")+uint2ordinal(ioContext.getDemeIndex()+1)+ " deme, the size specified in 'ec.pop.size' ("+uint2str(lSpecifiedDemeSize)+ ") is less than the current deme size ("+uint2str(lCurrentDemeSize)+ "). "+getName()+" can only increase the size of the deme. Consider using DecimateOp "+ "if you wish to decrease the size of the deme"); } lLambda = lSpecifiedDemeSize - lCurrentDemeSize; } else { // Using ratio to scale the deme's population lLambda = (unsigned int)ceil((lRatio-1.0)*float(ioDeme.size())); } Beagle_LogTraceM( ioContext.getSystem().getLogger(), "replacement-strategy", "Beagle::OversizeOp", string("Population will be increased in size by ")+uint2str(lLambda)+" individuals" ); // Create the new individuals. Individual::Bag lOffsprings; for(unsigned int i=0; i<lLambda; ++i) { unsigned int lIndexBreeder = lRoulette.select(ioContext.getSystem().getRandomizer()); BreederNode::Handle lSelectedBreeder=getRootNode(); for(unsigned int j=0; j<lIndexBreeder; ++j) lSelectedBreeder=lSelectedBreeder->getNextSibling(); Beagle_NonNullPointerAssertM(lSelectedBreeder); Beagle_NonNullPointerAssertM(lSelectedBreeder->getBreederOp()); Individual::Handle lBredIndiv = lSelectedBreeder->getBreederOp()->breed(ioDeme, lSelectedBreeder->getFirstChild(), ioContext); Beagle_NonNullPointerAssertM(lBredIndiv); lOffsprings.push_back(lBredIndiv); } // Add the new individuals into the deme. ioDeme.insert(ioDeme.end(), lOffsprings.begin(), lOffsprings.end()); Beagle_LogDetailedM( ioContext.getSystem().getLogger(), "replacement-strategy", "Beagle::OversizeOp", string("There are now ")+uint2str(ioDeme.size())+" individuals in the "+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); Beagle_StackTraceEndM("void OversizeOp::operate(Deme& ioDeme, Context& ioContext)"); }
/*! * \brief Select inN best individuals. * \param inN Number of individuals to select. * \param ioPool Pool from which the individuals are choosen. * \param ioContext Evolutionary context. * \param outSelections Vector of unsigned ints that say how often an individual was selected. * * The output of this method is via outSelection. It produces a * vector the same size as ioPool, where each index says how many * times an individual was selected. If this is not the desired * output, consider using the method convertToList(). */ void SelectBestOp::selectNIndividuals(unsigned int inN, Individual::Bag& ioPool, Context& ioContext, std::vector<unsigned int>& outSelections) { Beagle_StackTraceBeginM(); // Check that we're not selecting all the individuals if((inN%ioPool.size()) == 0) { Beagle_LogBasicM( ioContext.getSystem().getLogger(), "selection", "Beagle::SelectBestOp", std::string("Warning! Selecting the best ")+uint2str(inN)+" individuals from a pool size of "+ uint2str(ioPool.size())+" (during SelectBestOp) means that every individual will be selected "+ uint2str(inN/ioPool.size())+" times, thus applying no selective pressure." ); } // Copy the pool, pairing indices and handles to individuals Beagle_LogDebugM( ioContext.getSystem().getLogger(), "selection", "Beagle::SelectBestOp", "Copying pool's individuals and pairing them to their indices" ); typedef std::vector< std::pair< unsigned int, Individual::Handle > > lTempPoolType; lTempPoolType lTempPool; lTempPool.resize(ioPool.size()); unsigned int lIndex = 0; for(lTempPoolType::iterator lItr=lTempPool.begin(); lItr!=lTempPool.end(); ++lItr) { lItr->first = lIndex; lItr->second = ioPool[lIndex++]; } Beagle_AssertM(ioPool.size() == lTempPool.size()); // Sort population if(inN > ioPool.size()) { Beagle_LogBasicM( ioContext.getSystem().getLogger(), "selection", "Beagle::SelectBestOp", std::string("Warning sorting entire copy of pool because number to select (")+uint2str(inN)+ ") is greater than size of pool ("+uint2str(ioPool.size())+")" ); std::sort(lTempPool.begin(),lTempPool.end(), TempPoolPredicate()); } else { Beagle_LogDebugM( ioContext.getSystem().getLogger(), "selection", "Beagle::SelectBestOp", std::string("Partial sorting top ")+uint2str(inN)+" individuals in copy of pool" ); std::partial_sort(lTempPool.begin(), lTempPool.begin()+inN, lTempPool.end(), TempPoolPredicate()); } // Write to the selection table Beagle_LogDebugM( ioContext.getSystem().getLogger(), "selection", "Beagle::SelectBestOp", "Writing selection table" ); outSelections.clear(); outSelections.resize(lTempPool.size()); for (unsigned int i=0; i<inN; i++) { unsigned int lSelection = lTempPool[i%lTempPool.size()].first; Beagle_LogDebugM( ioContext.getSystem().getLogger(), "selection", "Beagle::SelectBestOp", std::string("Selecting ")+uint2ordinal(i+1)+" best ("+uint2ordinal(lSelection+1)+" individual)" ); ++(outSelections[lSelection]); } Beagle_StackTraceEndM("void SelectBestOp::selectNIndividuals(unsigned int,Individual::Bag&,Context&,std::vector<unsigned int>&)"); }
/*! * \brief Apply NPGA2 multiobjective selection operator. * \param ioDeme Deme on which selection operator is applied. * \param ioContext Evolutionary context. */ void NPGA2Op::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); if(ioDeme.size() == 0) return; Beagle_LogTraceM( ioContext.getSystem().getLogger(), std::string("Applying NPGA2 multiobjective selection on the ")+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); std::vector<bool> lAlreadySelectedIndiv(ioDeme.size(), false); Individual::Bag lSelectedIndividual; const Factory& lFactory = ioContext.getSystem().getFactory(); // Generate new generation by selection for(unsigned int i=0; i<ioDeme.size(); ++i) { // First participant unsigned int lFirstParticipant = ioContext.getSystem().getRandomizer().rollInteger(0, ioDeme.size()-1); std::vector<unsigned int> lNDParticipants(1, lFirstParticipant); // Following participants to tournament for(unsigned int j=1; j<mNumberParticipants->getWrappedValue(); ++j) { unsigned int lParticipant = ioContext.getSystem().getRandomizer().rollInteger(0, ioDeme.size()-1); // Test if participant is dominated or dominate other participants bool lIsDominated = false; Fitness::Handle lPartFitness = ioDeme[lParticipant]->getFitness(); for(unsigned int k=0; k<lNDParticipants.size(); ++k) { Fitness::Handle lFitnessNDk = ioDeme[lNDParticipants[k]]->getFitness(); if(lPartFitness->isDominated(*lFitnessNDk)) { lIsDominated = true; } else if(lFitnessNDk->isDominated(*lPartFitness)) { lNDParticipants.erase(lNDParticipants.begin()+k); } } if(lIsDominated==false) lNDParticipants.push_back(lParticipant); } // Test if there is a tie. If so evaluate niche count. Beagle_AssertM(lNDParticipants.size() != 0); unsigned int lWinner = lNDParticipants[0]; if(lNDParticipants.size() > 1) { float lLowestNicheCount = evalNicheCount(*ioDeme[lNDParticipants[0]], lSelectedIndividual); for(unsigned int j=1; j<lNDParticipants.size(); ++j) { float lNicheCount = evalNicheCount(*ioDeme[lNDParticipants[j]], lSelectedIndividual); if(lNicheCount < lLowestNicheCount) { lLowestNicheCount = lNicheCount; lWinner = lNDParticipants[j]; } } } // Put winner in selected individual bag if(lAlreadySelectedIndiv[lWinner]) { std::string lIndividualType = ioDeme[lWinner]->getType(); Individual::Alloc::Handle lIndividualAlloc = castHandleT<Individual::Alloc>(lFactory.getAllocator(lIndividualType)); Individual::Handle lIndividual = castHandleT<Individual>(lIndividualAlloc->allocate()); lIndividual->copy(*ioDeme[lWinner], ioContext.getSystem()); lSelectedIndividual.push_back(lIndividual); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(lWinner+1)+" individual selected again in NPGA2 selection process" ); } else { lSelectedIndividual.push_back(ioDeme[lWinner]); lAlreadySelectedIndiv[lWinner] = true; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(lWinner+1)+" individual selected in NPGA2 selection process" ); } } // Copy selected individuals into deme for(unsigned int j=0; j<ioDeme.size(); ++j) ioDeme[j] = lSelectedIndividual[j]; Beagle_StackTraceEndM(); }
/*! * \brief Generate children from the breeder tree. * \param ioDeme Deme to generate children from. * \param ioContext Evolutionary context. * \param lNbChildren Number of children to generate. * \param inN Dimensionality of the problem. * \param ioCMAValues CMA values to use to generate new individual. * \param inSelectionWeights Selection weights used to generate children. */ void CMA::MuWCommaLambdaCMAFltVecOp::generateChildren(Deme& ioDeme, Context& ioContext, unsigned int inNbChildren, unsigned int inN, CMAValues& ioCMAValues, const Vector& inSelectionWeights) const { Beagle_StackTraceBeginM(); // Check parameters and log some information Beagle_NonNullPointerAssertM(mElitismKeepSize); Beagle_ValidateParameterM(mLMRatio->getWrappedValue() >= 1.0, mLMRatioName, "The LM ratio must be higher or equal to 1.0."); Beagle_ValidateParameterM(mElitismKeepSize->getWrappedValue() <= ioDeme.size(), "ec.elite.keepsize", "The elistism keepsize must be less than the deme size!"); Beagle_LogTraceM( ioContext.getSystem().getLogger(), std::string("Using CMA-ES (mu_w,lambda) replacement strategy to process the ")+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); Beagle_LogTraceM(ioContext.getSystem().getLogger(), (*this)); const Factory& lFactory = ioContext.getSystem().getFactory(); // Create weighted mean individual. std::sort(ioDeme.begin(), ioDeme.end(), IsMorePointerPredicate()); Individual::Alloc::Handle lIndividualAlloc = castHandleT<Individual::Alloc>(lFactory.getConceptAllocator("Individual")); Individual::Handle lMeanInd = castHandleT<Individual>(lIndividualAlloc->allocate()); Genotype::Alloc::Handle lGenotypeAlloc = castHandleT<Genotype::Alloc>(lFactory.getConceptAllocator("Genotype")); FltVec::FloatVector::Handle lMeanFloatVec = castHandleT<FltVec::FloatVector>(lGenotypeAlloc->allocate()); lMeanFloatVec->resize(inN); lMeanInd->push_back(lMeanFloatVec); for(unsigned int i=0; i<inN; ++i) (*lMeanFloatVec)[i] = 0.0; if(ioDeme.size()==1) { Beagle_AssertM(ioDeme[0]->size() == 1); FltVec::FloatVector::Handle lInd = castHandleT<FltVec::FloatVector>((*ioDeme[0])[0]); (*lMeanFloatVec) = *lInd; } else { for(unsigned int i=0; i<ioDeme.size(); ++i) { Beagle_AssertM(ioDeme[i]->size()==1); FltVec::FloatVector::Handle lVecI = castHandleT<FltVec::FloatVector>((*ioDeme[i])[0]); Beagle_AssertM(lVecI->size()==inN); for(unsigned int j=0; j<inN; ++j) (*lMeanFloatVec)[j] += (inSelectionWeights[i] * (*lVecI)[j]); } } ioCMAValues.mXmean.resize(inN); for(unsigned int i=0; i<inN; ++i) ioCMAValues.mXmean[i] = (*lMeanFloatVec)[i]; // Generate lambda children with breeder tree, first build breeder roulette RouletteT<unsigned int> lRoulette; buildRoulette(lRoulette, ioContext); // Keep best individuals if elitism is used const unsigned int lElitismKS=mElitismKeepSize->getWrappedValue(); if(lElitismKS > 0) { Individual::Bag lBestInd; History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History")); std::make_heap(ioDeme.begin(), ioDeme.end(), IsLessPointerPredicate()); for(unsigned int i=0; i<lElitismKS; ++i) { if(lHistory != NULL) { HistoryID::Handle lHID = castHandleT<HistoryID>(ioDeme[0]->getMember("HistoryID")); std::vector<HistoryID> lParent; if(lHID != NULL) lParent.push_back(*lHID); lHistory->allocateNewID(*ioDeme[0]); lHistory->trace(ioContext, lParent, ioDeme[0], getName(), "elitism"); } lBestInd.push_back(ioDeme[0]); std::pop_heap(ioDeme.begin(), ioDeme.end(), IsLessPointerPredicate()); ioDeme.pop_back(); } ioDeme.clear(); ioDeme.insert(ioDeme.end(), lBestInd.begin(), lBestInd.end()); } else ioDeme.clear(); // Generate the children Individual::Bag lBagWithMeanInd; lBagWithMeanInd.push_back(lMeanInd); for(unsigned int i=0; i<inNbChildren; ++i) { unsigned int lIndexBreeder = lRoulette.select(ioContext.getSystem().getRandomizer()); BreederNode::Handle lSelectedBreeder=getRootNode(); for(unsigned int j=0; j<lIndexBreeder; ++j) lSelectedBreeder=lSelectedBreeder->getNextSibling(); Beagle_NonNullPointerAssertM(lSelectedBreeder); Beagle_NonNullPointerAssertM(lSelectedBreeder->getBreederOp()); Individual::Handle lBredIndiv = lSelectedBreeder->getBreederOp()->breed(lBagWithMeanInd, lSelectedBreeder->getFirstChild(), ioContext); Beagle_NonNullPointerAssertM(lBredIndiv); ioDeme.push_back(lBredIndiv); } Beagle_StackTraceEndM(); }
/*! * \brief Do fast non-dominated sort and evaluate Pareto fronts of data up to given size. * \param outParetoFronts Pareto fronts from the fast ND sort. * \param inSortStop Number of individuals on the Pareto fronts needed to stop the sort. * \param inIndividualPool Pool of individuals to get next Pareto front of. * \param ioContext Evolutionary context. */ void EMO::NSGA2Op::sortFastND(NSGA2Op::Fronts& outParetoFronts, unsigned int inSortStop, const Individual::Bag& inIndividualPool, Context& ioContext) const { Beagle_StackTraceBeginM(); outParetoFronts.clear(); if(inSortStop == 0) return; outParetoFronts.resize(1); unsigned int lParetoSorted = 0; // N: Number of dominating individuals std::vector<unsigned int> lN(inIndividualPool.size(), 0); // S: Set of dominated individuals Fronts lS(inIndividualPool.size()); // First pass to get first Pareto front and domination sets for(unsigned int i=0; i<inIndividualPool.size(); ++i) { Fitness::Handle lFitI = inIndividualPool[i]->getFitness(); for(unsigned int j=(i+1); j<inIndividualPool.size(); ++j) { Fitness::Handle lFitJ = inIndividualPool[j]->getFitness(); if(lFitJ->isDominated(*lFitI)) { lS[i].push_back(j); // Add index j to dominated set of i ++lN[j]; // Increment domination counter of j } else if(lFitI->isDominated(*lFitJ)) { lS[j].push_back(i); // Add index i to dominated set of j ++lN[i]; // Increment domination counter of i } } if(lN[i] == 0) { // If i is non-dominated outParetoFronts.back().push_back(i); ++lParetoSorted; } } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(1)+std::string(" Pareto front consists of ")+ uint2str(outParetoFronts.back().size())+" individuals" ); // Continue ranking until individual pool is empty or stop criterion reach while((lParetoSorted < inIndividualPool.size()) && (lParetoSorted < inSortStop)) { unsigned int lIndexLastFront = outParetoFronts.size() - 1; outParetoFronts.resize(outParetoFronts.size() + 1); for(unsigned int k=0; k<outParetoFronts[lIndexLastFront].size(); ++k) { unsigned int lIndexPk = outParetoFronts[lIndexLastFront][k]; for(unsigned int l=0; l<lS[lIndexPk].size(); ++l) { unsigned int lIndexSl = lS[lIndexPk][l]; if(--lN[lIndexSl] == 0) { outParetoFronts.back().push_back(lIndexSl); ++lParetoSorted; } } } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(outParetoFronts.size())+std::string(" Pareto front consists of ")+ uint2str(outParetoFronts.back().size())+" individuals" ); } Beagle_StackTraceEndM(); }
/*! * \brief Apply NSGA2 multiobjective selection operator as a replacement strategy. * \param ioDeme Deme on which selection operator is applied. * \param ioContext Evolutionary context. */ void EMO::NSGA2Op::applyAsReplacementStrategy(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_LogTraceM( ioContext.getSystem().getLogger(), std::string("Processing using NSGA2 replacement strategy the ")+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); Beagle_LogTraceM(ioContext.getSystem().getLogger(), (*this)); // Generate a new generation of individuals, merged with the actual one. const unsigned int lLambda = (unsigned int)std::ceil(mLMRatio->getWrappedValue()*float(ioDeme.size())); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "Generating " << lLambda << " offsprings using breeder tree" ); RouletteT<unsigned int> lRoulette; buildRoulette(lRoulette, ioContext); Individual::Bag lOffsprings(ioDeme); for(unsigned int i=0; i<lLambda; ++i) { unsigned int lIndexBreeder = lRoulette.select(ioContext.getSystem().getRandomizer()); BreederNode::Handle lSelectedBreeder=getRootNode(); for(unsigned int j=0; j<lIndexBreeder; ++j) lSelectedBreeder=lSelectedBreeder->getNextSibling(); Beagle_NonNullPointerAssertM(lSelectedBreeder); Beagle_NonNullPointerAssertM(lSelectedBreeder->getBreederOp()); Individual::Handle lBredIndiv = lSelectedBreeder->getBreederOp()->breed(ioDeme, lSelectedBreeder->getFirstChild(), ioContext); Beagle_NonNullPointerAssertM(lBredIndiv); lOffsprings.push_back(lBredIndiv); } // Fast non-dominated sorting, followed by insertion of the first Pareto fronts. Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "Applying fast non-dominated sorting on the union of parents and offsprings individual" ); NSGA2Op::Fronts lParetoFronts; sortFastND(lParetoFronts, ioDeme.size(), lOffsprings, ioContext); unsigned int lIndexDeme=0; for(unsigned int j=0; j<(lParetoFronts.size()-1); ++j) { for(unsigned int k=0; k<lParetoFronts[j].size(); ++k) { ioDeme[lIndexDeme++] = lOffsprings[lParetoFronts[j][k]]; } } // Insertion of the last Pareto front, using crowding distance Individual::Bag lLastFrontIndiv; for(unsigned int l=0; l<lParetoFronts.back().size(); ++l) { lLastFrontIndiv.push_back(lOffsprings[lParetoFronts.back()[l]]); } NSGA2Op::Distances lDistances; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "Computing crowding distance on the " << uint2ordinal(lParetoFronts.size()) << " Pareto front, which is made of " << lParetoFronts.back().size() << " individuals" ); evalCrowdingDistance(lDistances, lLastFrontIndiv); for(unsigned int m=0; lIndexDeme<ioDeme.size(); ++m) { ioDeme[lIndexDeme++] = lLastFrontIndiv[lDistances[m].second]; } Beagle_StackTraceEndM(); }