Пример #1
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 Test the fitness of a given individual.
 *  \param inIndividual Handle to the individual to test.
 *  \param ioSystem Handle to the system to use to test the individual.
 *  \par Note:
 *    This method is provided as a mean to test some individuals after an evolution.
 */
Fitness::Handle Beagle::MPI::EvaluationOp::test(Individual::Handle inIndividual, System::Handle ioSystem)
{
	Beagle_LogInfoM(
					ioSystem->getLogger(),
					"evaluation", "Beagle::MPIEvaluationOp",
					std::string("Testing the following individual: ")+inIndividual->serialize()
					);
    
	Context::Alloc::Handle lContextAlloc =
    castHandleT<Context::Alloc>(ioSystem->getContextAllocatorHandle());
	Context::Handle lContext = castHandleT<Context>(lContextAlloc->allocate());
	lContext->setSystemHandle(ioSystem);
	lContext->setIndividualHandle(inIndividual);
	Fitness::Handle lFitness = evaluate(*inIndividual, *lContext);
	
	Beagle_LogInfoM(
					ioSystem->getLogger(),
					"evaluation", "Beagle::MPIEvaluationOp",
					std::string("New fitness of the individual: ")+lFitness->serialize()
					);
    
	return lFitness;
}
Пример #3
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();
}
Пример #4
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();
}
void Beagle::MPI::EvaluationOp::evaluatorOperate(Deme& ioDeme, Context& ioContext) {
	try {
		//char lMessage[4096];
		int lMessageSize;
		MPI_Status lStatus;
		int lSource;

		bool lDone = false;
		while(!lDone) {
			//Receive an individual to evaluate
			MPI_Recv(&lMessageSize, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &lStatus);
			lSource = lStatus.MPI_SOURCE;
			if(lStatus.MPI_TAG == eEvolutionEnd) {
				Beagle_LogDetailedM(
								   ioContext.getSystem().getLogger(),
								   "evaluation", "Beagle::MPIEvaluationOp",
								   std::string("End of evolution received from process ") + int2str(lSource)
								   );
				lDone = true;
			} else {
				char *lMessage = new char[lMessageSize];
				unsigned int lGeneration;
				MPI_Recv(lMessage, lMessageSize, MPI_CHAR, lSource, MPI_ANY_TAG, MPI_COMM_WORLD, &lStatus);
				MPI_Recv(&lGeneration, 1, MPI_INT, lSource, MPI_ANY_TAG, MPI_COMM_WORLD, &lStatus);
				ioContext.setGeneration(lGeneration);
				Beagle_LogTraceM(
								   ioContext.getSystem().getLogger(),
								   "evaluation", "Beagle::MPIEvaluationOp",
								   std::string("Evaluating individual send from process ") + int2str(lSource)
								   );
				
				//Parse the received individual
				std::istringstream lStreamIn(lMessage);

				PACC::XML::Document lXMLParser;
				lXMLParser.parse(lStreamIn);

				PACC::XML::ConstIterator lIndividualRootNode = lXMLParser.getFirstRoot(); 

				
				//Read the received individual
				ioContext.getDeme().resize(0);
				Individual::Handle lIndividual = castHandleT<Individual>(ioContext.getDeme().getTypeAlloc()->allocate());
				lIndividual->readWithContext(lIndividualRootNode,ioContext);
				ioContext.setIndividualHandle(lIndividual);
				ioContext.setIndividualIndex(0);
				
//				Beagle_LogDebugM(
//								 ioContext.getSystem().getLogger(),
//								 "evaluation", "Beagle::MPIEvaluationOp",
//								 std::string("Individual received: ") + lIndividual->serialize()
//								 );
				
				//Free message string
				delete [] lMessage;
				
				//Evaluated the fitness of the received individual
				Fitness::Handle lFitness = evaluate(*lIndividual, ioContext);
			
				//Send back the fitness
				std::ostringstream lStreamOut;
				PACC::XML::Streamer lXMLStream(lStreamOut);

				lFitness->write(lXMLStream);
				//std::cout << "Sending fitness of size " << lStreamOut.str().size()+1 << ":" << std::endl << lStreamOut.str() << std::endl;
				lMessageSize = lStreamOut.str().size()+1;
				
				Beagle_LogTraceM(
									ioContext.getSystem().getLogger(),
									"evaluation", "Beagle::MPIEvaluationOp",
									std::string("Sending back fitness")
									);
				
				MPI_Send(&lMessageSize, 1, MPI_INT, lSource, eMessageSize, MPI_COMM_WORLD);
				MPI_Send(const_cast<char*>(lStreamOut.str().data()), lMessageSize, MPI_CHAR, lSource, eFitness, MPI_COMM_WORLD);
			}
		}
	} catch(Exception& inException) {
		std::cerr << "Exception catched in evaluator:" << std::endl << std::flush;
		std::cerr << inException.what() << std::endl << std::flush;
		exit(1);
	}
	catch(std::exception& inException) {
		std::cerr << "Standard exception catched in evaluator:" << std::endl << std::flush;
		std::cerr << inException.what() << std::endl << std::flush;
		exit(1);
	}
}
void Beagle::MPI::EvaluationOp::distributeDemeEvaluation(Deme& ioDeme, Context& ioContext) {
	try{
		std::vector<int> lProcess(mProcessSize, -1);
		lProcess[0] = -2; //Master should not be pick
		int lCurrentIndividual = 0;
		std::ostringstream lStreamOut;

		PACC::XML::Streamer lXMLStream(lStreamOut);

		//char lSizeMessage[256];
		int lMessageSize;
		MPI_Status lStatus;
		
		int lFlag;
		unsigned int lSource = 1;
		unsigned int lProcessIdx = 0;
		unsigned int lRecvIndividualIdx = 0;

		unsigned int lNbReceived = 0;		
		unsigned int lNbSent = 0;
		bool lAllSent = false;
		
		while( (lNbReceived < lNbSent) || !lAllSent ) {
			if(!lAllSent) {
				lProcessIdx = find(lProcess, -1, 0, lProcess.size());
				if( lProcessIdx != lProcess.size() ) {
					if((ioDeme[lCurrentIndividual]->getFitness() == NULL) ||
					   (ioDeme[lCurrentIndividual]->getFitness()->isValid() == false)) {
						
						//There is a process idle
						Beagle_LogVerboseM(   
										   ioContext.getSystem().getLogger(),
										   "evaluation", "Beagle::MPIEvaluationOp",
										   std::string("Evaluating the fitness of the ")+uint2ordinal(lCurrentIndividual+1)+
										   " individual"
										   );
						
						ioContext.setIndividualIndex(lCurrentIndividual);
						ioContext.setIndividualHandle(ioDeme[lCurrentIndividual]);
						
						//Send the individual to be evaluated
						Beagle_LogTraceM(
										   ioContext.getSystem().getLogger(),
										   "evaluation", "Beagle::MPIEvaluationOp",
										   std::string("Sending the ") + uint2ordinal(lCurrentIndividual+1) + std::string(" individual to ")+
										   uint2ordinal(lProcessIdx) + std::string(" evaluator")
										   );
						
						lStreamOut.str("");
						ioDeme[lCurrentIndividual]->write(lXMLStream);
						lMessageSize = lStreamOut.str().size()+1;
						MPI_Send(&lMessageSize, 1, MPI_INT, lProcessIdx, eMessageSize, MPI_COMM_WORLD);
						MPI_Send(const_cast<char*>(lStreamOut.str().data()), lMessageSize, MPI_CHAR, lProcessIdx, eIndividual, MPI_COMM_WORLD);
						//std::cout << "Sending individual : " << lStreamOut.str().data() << std::endl;
						unsigned int lGeneration = ioContext.getGeneration();
						MPI_Send(&lGeneration, 1, MPI_INT, lProcessIdx, eIndividual, MPI_COMM_WORLD);
						lProcess[lProcessIdx] = lCurrentIndividual;	
						++lNbSent;
					}
					++lCurrentIndividual;
					if(lCurrentIndividual >= ioDeme.size()) {
						lAllSent = true;
					}
				}
			}
			
			//Look if any cruncher sent a fitness back
			MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &lFlag, &lStatus);
			if (lFlag) {
				//Receive the evaluated fitness
				lSource = lStatus.MPI_SOURCE;
				MPI_Recv(&lMessageSize, 1, MPI_INT, lSource, eMessageSize, MPI_COMM_WORLD, &lStatus);
				char *lMessage = new char[lMessageSize];
				MPI_Recv(lMessage, lMessageSize, MPI_CHAR, lSource, eFitness, MPI_COMM_WORLD, &lStatus);
				lRecvIndividualIdx = lProcess[lSource];
				lProcess[lSource] = -1;
				++lNbReceived;
				
				Beagle_LogTraceM(
								   ioContext.getSystem().getLogger(),
								   "evaluation", "Beagle::MPIEvaluationOp",
								   std::string("Receiving the fitness of the ") + uint2ordinal(lRecvIndividualIdx+1) + 
								   std::string(" individual from ")+uint2ordinal(lSource) + std::string(" evaluator")
								   );
				
				//Read the received fitness
				std::istringstream lStreamIn(lMessage);
				PACC::XML::Document lXMLParser;

				lXMLParser.parse(lStreamIn);
				
				Fitness::Handle lFitness = castHandleT<Fitness>(ioDeme[lRecvIndividualIdx]->getFitnessAlloc()->allocate());
				PACC::XML::ConstIterator lFitnessRootNode = lXMLParser.getFirstRoot(); 

				lFitness->read(lFitnessRootNode);
				
				//Free message space
				delete [] lMessage;
				
				//Assign the fitness
				ioDeme[lRecvIndividualIdx]->setFitness(lFitness);
				ioDeme[lRecvIndividualIdx]->getFitness()->setValid();
				
				//Update stats
				ioContext.setProcessedDeme(ioContext.getProcessedDeme()+1);
				ioContext.setTotalProcessedDeme(ioContext.getTotalProcessedDeme()+1);
				ioContext.setProcessedVivarium(ioContext.getProcessedVivarium()+1);
				ioContext.setTotalProcessedVivarium(ioContext.getTotalProcessedVivarium()+1);  
				
				Beagle_LogDebugM(
								 ioContext.getSystem().getLogger(),
								 "evaluation", "Beagle::MPIEvaluationOp",
								 std::string("Received fitness of individual: ")+
								 ioDeme[lRecvIndividualIdx]->serialize()
								 );
				
				Beagle_LogDebugM(
								   ioContext.getSystem().getLogger(),
								   "evaluation", "Beagle::MPIEvaluationOp",
								   std::string("The individual\'s fitness is: ")+
								   ioDeme[lRecvIndividualIdx]->getFitness()->serialize()
								   );
			}
		}
	} catch(Exception& inException) {
		std::cerr << "Exception catched in evolver:" << std::endl << std::flush;
		std::cerr << inException.what() << std::endl << std::flush;
		exit(1);
	}
	catch(std::exception& inException) {
		std::cerr << "Standard exception catched in evolver:" << std::endl << std::flush;
		std::cerr << inException.what() << std::endl << std::flush;
		exit(1);
	}
}