/*! * \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; }
/*! * \brief Do fast non-dominated sort and evaluate Pareto fronts of data up to given size. * \param outParetoFronts Pareto fronts from the fast ND sort. * \param inSortStop Number of individuals on the Pareto fronts needed to stop the sort. * \param inIndividualPool Pool of individuals to get next Pareto front of. * \param ioContext Evolutionary context. */ void EMO::NSGA2Op::sortFastND(NSGA2Op::Fronts& outParetoFronts, unsigned int inSortStop, const Individual::Bag& inIndividualPool, Context& ioContext) const { Beagle_StackTraceBeginM(); outParetoFronts.clear(); if(inSortStop == 0) return; outParetoFronts.resize(1); unsigned int lParetoSorted = 0; // N: Number of dominating individuals std::vector<unsigned int> lN(inIndividualPool.size(), 0); // S: Set of dominated individuals Fronts lS(inIndividualPool.size()); // First pass to get first Pareto front and domination sets for(unsigned int i=0; i<inIndividualPool.size(); ++i) { Fitness::Handle lFitI = inIndividualPool[i]->getFitness(); for(unsigned int j=(i+1); j<inIndividualPool.size(); ++j) { Fitness::Handle lFitJ = inIndividualPool[j]->getFitness(); if(lFitJ->isDominated(*lFitI)) { lS[i].push_back(j); // Add index j to dominated set of i ++lN[j]; // Increment domination counter of j } else if(lFitI->isDominated(*lFitJ)) { lS[j].push_back(i); // Add index i to dominated set of j ++lN[i]; // Increment domination counter of i } } if(lN[i] == 0) { // If i is non-dominated outParetoFronts.back().push_back(i); ++lParetoSorted; } } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(1)+std::string(" Pareto front consists of ")+ uint2str(outParetoFronts.back().size())+" individuals" ); // Continue ranking until individual pool is empty or stop criterion reach while((lParetoSorted < inIndividualPool.size()) && (lParetoSorted < inSortStop)) { unsigned int lIndexLastFront = outParetoFronts.size() - 1; outParetoFronts.resize(outParetoFronts.size() + 1); for(unsigned int k=0; k<outParetoFronts[lIndexLastFront].size(); ++k) { unsigned int lIndexPk = outParetoFronts[lIndexLastFront][k]; for(unsigned int l=0; l<lS[lIndexPk].size(); ++l) { unsigned int lIndexSl = lS[lIndexPk][l]; if(--lN[lIndexSl] == 0) { outParetoFronts.back().push_back(lIndexSl); ++lParetoSorted; } } } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(outParetoFronts.size())+std::string(" Pareto front consists of ")+ uint2str(outParetoFronts.back().size())+" individuals" ); } Beagle_StackTraceEndM(); }
/*! * \brief Apply NPGA2 multiobjective selection operator. * \param ioDeme Deme on which selection operator is applied. * \param ioContext Evolutionary context. */ void NPGA2Op::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); if(ioDeme.size() == 0) return; Beagle_LogTraceM( ioContext.getSystem().getLogger(), std::string("Applying NPGA2 multiobjective selection on the ")+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); std::vector<bool> lAlreadySelectedIndiv(ioDeme.size(), false); Individual::Bag lSelectedIndividual; const Factory& lFactory = ioContext.getSystem().getFactory(); // Generate new generation by selection for(unsigned int i=0; i<ioDeme.size(); ++i) { // First participant unsigned int lFirstParticipant = ioContext.getSystem().getRandomizer().rollInteger(0, ioDeme.size()-1); std::vector<unsigned int> lNDParticipants(1, lFirstParticipant); // Following participants to tournament for(unsigned int j=1; j<mNumberParticipants->getWrappedValue(); ++j) { unsigned int lParticipant = ioContext.getSystem().getRandomizer().rollInteger(0, ioDeme.size()-1); // Test if participant is dominated or dominate other participants bool lIsDominated = false; Fitness::Handle lPartFitness = ioDeme[lParticipant]->getFitness(); for(unsigned int k=0; k<lNDParticipants.size(); ++k) { Fitness::Handle lFitnessNDk = ioDeme[lNDParticipants[k]]->getFitness(); if(lPartFitness->isDominated(*lFitnessNDk)) { lIsDominated = true; } else if(lFitnessNDk->isDominated(*lPartFitness)) { lNDParticipants.erase(lNDParticipants.begin()+k); } } if(lIsDominated==false) lNDParticipants.push_back(lParticipant); } // Test if there is a tie. If so evaluate niche count. Beagle_AssertM(lNDParticipants.size() != 0); unsigned int lWinner = lNDParticipants[0]; if(lNDParticipants.size() > 1) { float lLowestNicheCount = evalNicheCount(*ioDeme[lNDParticipants[0]], lSelectedIndividual); for(unsigned int j=1; j<lNDParticipants.size(); ++j) { float lNicheCount = evalNicheCount(*ioDeme[lNDParticipants[j]], lSelectedIndividual); if(lNicheCount < lLowestNicheCount) { lLowestNicheCount = lNicheCount; lWinner = lNDParticipants[j]; } } } // Put winner in selected individual bag if(lAlreadySelectedIndiv[lWinner]) { std::string lIndividualType = ioDeme[lWinner]->getType(); Individual::Alloc::Handle lIndividualAlloc = castHandleT<Individual::Alloc>(lFactory.getAllocator(lIndividualType)); Individual::Handle lIndividual = castHandleT<Individual>(lIndividualAlloc->allocate()); lIndividual->copy(*ioDeme[lWinner], ioContext.getSystem()); lSelectedIndividual.push_back(lIndividual); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(lWinner+1)+" individual selected again in NPGA2 selection process" ); } else { lSelectedIndividual.push_back(ioDeme[lWinner]); lAlreadySelectedIndiv[lWinner] = true; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), uint2ordinal(lWinner+1)+" individual selected in NPGA2 selection process" ); } } // Copy selected individuals into deme for(unsigned int j=0; j<ioDeme.size(); ++j) ioDeme[j] = lSelectedIndividual[j]; Beagle_StackTraceEndM(); }
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); } }