/*! * \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 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(); }