Exemple #1
0
/*!
 *  \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();
}
Exemple #4
0
/*!
 *  \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&)");
}
Exemple #9
0
/*!
 *  \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();
}
Exemple #10
0
/*!
 *  \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)");
}
Exemple #17
0
/*!
 *  \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>&)");
}
Exemple #20
0
/*!
 *  \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();
}
Exemple #22
0
/*!
 *  \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();
}
Exemple #23
0
/*!
 *  \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();
}