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