/*! * \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 the characteristic operation. * \param ioDeme Deme to use to write the milestone. * \param ioContext Context of the evolution. */ void RandomShuffleDemeOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); std::random_shuffle(ioDeme.begin(), ioDeme.end(), ioContext.getSystem().getRandomizer()); Beagle_StackTraceEndM("void RandomShuffleDemeOp::operate(Deme& ioDeme, Context& ioContext)"); }
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 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 the CMA-ES (Mu_W+Lambda) 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. * \throw Beagle::ValidationException If a parameter is missing or have a bad value. * \throw Beagle::AssertException If an invalid condition appears. */ void CMA::MuWCommaLambdaCMAFltVecOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); // Get real popsize and size of float vectors from register. UIntArray::Handle lPopSize; if(ioContext.getSystem().getRegister().isRegistered("ec.pop.size")) { lPopSize = castHandleT<UIntArray>(ioContext.getSystem().getRegister()["ec.pop.size"]); } else { std::ostringstream lOSS; lOSS << "Population size parameter 'ec.pop.size' is not found in register!"; throw ValidationException(lOSS.str()); } const unsigned int lDemeSize = (*lPopSize)[ioContext.getDemeIndex()]; UInt::Handle lFloatVectorSize; if(ioContext.getSystem().getRegister().isRegistered("ga.init.vectorsize")) { lFloatVectorSize = castHandleT<UInt>(ioContext.getSystem().getRegister()["ga.init.vectorsize"]); } else { std::ostringstream lOSS; lOSS << "GA::MuWCommaLambdaCMAFltVecOp must be used in fixed-lenght float vector "; lOSS << "individuals. Parameter 'ga.init.vectorsize' is not in register, "; lOSS << "while it is needed to set initial size of the different CMA-ES matrices "; lOSS << "and vectors."; throw ValidationException(lOSS.str()); } const unsigned int lN=lFloatVectorSize->getWrappedValue(); // Get the appropriate CMA values from the CMA holder component. CMA::CMAValues& lValues = getCMAValues(ioContext.getDemeIndex(),lN,ioContext); // Compute weights and effective mu Vector lWeight; double lMuEff = 0.0; lMuEff = generateSelectionWeights(lDemeSize, lWeight); if(ioDeme.size() == 1) lMuEff = 1.; // If the replacement strategy possess a breeder tree if(getRootNode()!=NULL) { // Generate new children. const unsigned int lLambda = (unsigned int)std::ceil(mLMRatio->getWrappedValue()*double(lDemeSize)); generateChildren(ioDeme, ioContext, lLambda, lN, lValues, lWeight); // Check if all individuals have known fitness. for(unsigned int i=0; i<ioDeme.size(); ++i) { // If there is one invalid fitness, we should exit. // Evaluation will be taken elsewhere (we hope), and actual operator will be recalled. if((ioDeme[i]->getFitness()==NULL) || (ioDeme[i]->getFitness()->isValid()==false)) return; } } // Keep mu best children Beagle_AssertM(ioDeme.size() > lDemeSize); std::sort(ioDeme.begin(), ioDeme.end(), IsMorePointerPredicate()); ioDeme.resize(lDemeSize); // Update CMA-ES values. updateValues(ioDeme, ioContext, lN, lMuEff, lWeight, lValues); Beagle_StackTraceEndM(); }