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