/*! * \brief Randomly select a node that takes arguments from a specific * tree in the individual. * \return Randomly selected tree */ unsigned int GP::Individual::chooseRandomNodeWithArgs(unsigned int inTree, GP::Context& ioContext) const { Beagle_StackTraceBeginM(); const GP::Tree& lTree = *(operator[](inTree)); unsigned int lSize = lTree.size(); if (lSize < 2) { std::ostringstream lOSS; lOSS << "In GP::Individual::chooseRandomNodeWithArgs(): "; lOSS << "Could not choose a node with arguments because the specified tree has fewer "; lOSS << "than two (" << lSize << ") nodes, hence there are no such nodes"; lOSS << " in the tree. This occurred while calling chooseRandomNodeWithArgs() with an "; lOSS << "inTree value of " << inTree; throw Beagle_RunTimeExceptionM(lOSS.str()); } // Loop through the tree adding appropriate nodes into the roulette RouletteT<unsigned int> lRoulette; for (unsigned int i=0; i<lSize; i++) { if(lTree[i].mSubTreeSize > 1) lRoulette.insert(i); } // Select node with roulette Beagle_AssertM(!lRoulette.empty()); return lRoulette.select(ioContext.getSystem().getRandomizer()); Beagle_StackTraceEndM(); }
/*! * \brief Apply the operation on a deme in the given context. * \param ioDeme Reference to the deme on which the operation takes place. * \param ioContext Evolutionary context of the operation. */ void GenerationalOp::operate(Deme& ioDeme, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_NonNullPointerAssertM(getRootNode()); Beagle_NonNullPointerAssertM(mElitismKeepSize); Beagle_ValidateParameterM(mElitismKeepSize->getWrappedValue() <= ioDeme.size(), "ec.elite.keepsize", "The elistism keepsize must be less than the deme size!"); Beagle_LogTraceM( ioContext.getSystem().getLogger(), "Processing using generational replacement strategy the " << uint2ordinal(ioContext.getDemeIndex()+1) << " deme" ); Beagle_LogTraceM(ioContext.getSystem().getLogger(), (*this)); RouletteT<unsigned int> lRoulette; buildRoulette(lRoulette, ioContext); Individual::Bag lOffsprings; const Factory& lFactory = ioContext.getSystem().getFactory(); if(mElitismKeepSize->getWrappedValue() > 0) { History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History")); std::make_heap(ioDeme.begin(), ioDeme.end(), IsLessPointerPredicate()); for(unsigned int i=0; i<mElitismKeepSize->getWrappedValue(); ++i) { std::string lIndividualType = ioDeme[0]->getType(); Individual::Alloc::Handle lIndividualAlloc = castHandleT<Individual::Alloc>(lFactory.getAllocator(lIndividualType)); Individual::Handle lEliteIndiv = castHandleT<Individual>(lIndividualAlloc->allocate()); lEliteIndiv->copy(*ioDeme[0], ioContext.getSystem()); lOffsprings.push_back(lEliteIndiv); if(lHistory != NULL) { HistoryID::Handle lHID = castHandleT<HistoryID>(ioDeme[0]->getMember("HistoryID")); std::vector<HistoryID> lParent; if(lHID != NULL) lParent.push_back(*lHID); lHistory->allocateNewID(*lEliteIndiv); lHistory->trace(ioContext, lParent, lEliteIndiv, getName(), "elitism"); } std::pop_heap(ioDeme.begin(), (ioDeme.end()-i), IsLessPointerPredicate()); } } for(unsigned int i=mElitismKeepSize->getWrappedValue(); i<ioDeme.size(); ++i) { unsigned int lIndexBreeder = lRoulette.select(ioContext.getSystem().getRandomizer()); BreederNode::Handle lSelectedBreeder=getRootNode(); for(unsigned int j=0; j<lIndexBreeder; ++j) lSelectedBreeder=lSelectedBreeder->getNextSibling(); Beagle_NonNullPointerAssertM(lSelectedBreeder); Beagle_NonNullPointerAssertM(lSelectedBreeder->getBreederOp()); Individual::Handle lBredIndiv = lSelectedBreeder->getBreederOp()->breed(ioDeme, lSelectedBreeder->getFirstChild(), ioContext); Beagle_NonNullPointerAssertM(lBredIndiv); lOffsprings.push_back(lBredIndiv); } for(unsigned int j=0; j<lOffsprings.size(); ++j) ioDeme[j] = lOffsprings[j]; Beagle_StackTraceEndM(); }
/*! * \brief Randomly select a node that takes no argument from a specific * tree in the individual. * \return Randomly selected tree */ unsigned int GP::Individual::chooseRandomNodeWithoutArgs(unsigned int inTree, GP::Context& ioContext) const { Beagle_StackTraceBeginM(); // Loop through the tree adding appropriate nodes into the roulette unsigned int lSize = operator[](inTree)->size(); RouletteT<unsigned int> lRoulette; for (unsigned int i=0; i<lSize; i++) { if (operator[](inTree)->operator[](i).mSubTreeSize == 1) { lRoulette.insert(i); } } // Select node with roulette Beagle_AssertM(!lRoulette.empty()); return lRoulette.select(ioContext.getSystem().getRandomizer()); Beagle_StackTraceEndM(); }
/*! * \brief Select a node for mating in the given individual, following the constraints penalties. * \param outSelectTreeIndex Tree index of the selected node. * \param outSelectNodeIndex Index of the selected node. * \param inSelectABranch True if node to select must be a branch, false if it must a leaf. * \param inNodeReturnType Desired return type for the nodes to be selected. * \param inPrimitSetIndex Primitive set index to which the tree must be associated. * \param inMaxSubTreeDepth Maximum sub tree depth allowed of the node to be selected. * \param inMaxSubTreeSize Maximum sub tree size allowed of the node to be selected. * \param inIndividual Individual to select the node from. * \param ioContext Evolutionary context. * \return True if there was node to select, false if no node respected all constraints. */ bool STGP::CrossoverConstrainedOp::selectNodeToMateWithType(unsigned int& outSelectTreeIndex, unsigned int& outSelectNodeIndex, bool inSelectABranch, const std::type_info* inNodeReturnType, unsigned int inPrimitSetIndex, unsigned int inMaxSubTreeDepth, unsigned int inMaxSubTreeSize, GP::Individual& inIndividual, GP::Context& ioContext) const { Beagle_StackTraceBeginM(); RouletteT< std::pair<unsigned int,unsigned int> > lRoulette; GP::Tree::Handle lOldTreeHandle = ioContext.getGenotypeHandle(); const unsigned int lOldTreeIndex = ioContext.getGenotypeIndex(); ioContext.emptyCallStack(); for(unsigned int i=0; i<inIndividual.size(); ++i) { if(inIndividual[i]->getPrimitiveSetIndex() != inPrimitSetIndex) continue; ioContext.setGenotypeHandle(inIndividual[i]); ioContext.setGenotypeIndex(i); buildRouletteWithType(lRoulette, inSelectABranch, inNodeReturnType, inMaxSubTreeDepth, inMaxSubTreeSize, 0, *inIndividual[i], ioContext); } ioContext.setGenotypeIndex(lOldTreeIndex); ioContext.setGenotypeHandle(lOldTreeHandle); if(lRoulette.size() == 0) return false; std::pair<unsigned int,unsigned int> lSelectedNode = lRoulette.select(ioContext.getSystem().getRandomizer()); outSelectTreeIndex = lSelectedNode.first; outSelectNodeIndex = lSelectedNode.second; return true; Beagle_StackTraceEndM(); }
/*! * \brief Build a roulette of nodes that can be selected following the constraints penalties. * \param ioRoulette Roulette of nodes that can be selected following the constraints given. * \param inSelectABranch True if node to select must be a branch, false if it must a leaf. * \param inNodeReturnType Desired return type for the nodes to be selected. * \param inMaxSubTreeDepth Maximum sub tree depth allowed of the node to be selected. * \param inMaxSubTreeSize Maximum sub tree size allowed of the node to be selected. * \param inActualIndex Index in actual tree of the node processed. * \param inTree Tree processed. * \param ioContext Evolutionary context. * \return Max depth of subtree processed. */ unsigned int STGP::CrossoverConstrainedOp::buildRouletteWithType( RouletteT< std::pair<unsigned int,unsigned int> >& ioRoulette, bool inSelectABranch, const std::type_info* inNodeReturnType, unsigned int inMaxSubTreeDepth, unsigned int inMaxSubTreeSize, unsigned int inActualIndex, GP::Tree& inTree, GP::Context& ioContext) const { Beagle_StackTraceBeginM(); const unsigned int lNbArgs = inTree[inActualIndex].mPrimitive->getNumberArguments(); const unsigned int lSubTreeSize = inTree[inActualIndex].mSubTreeSize; const bool lGoodArity = ((inTree.size()==1) || ((lNbArgs==0) != inSelectABranch)); ioContext.pushCallStack(inActualIndex); const std::type_info* lNodeType = inTree[inActualIndex].mPrimitive->getReturnType(ioContext); const bool lCompatibleTyping = ((inNodeReturnType==NULL) || (lNodeType==NULL) || (inNodeReturnType==lNodeType)); unsigned int lChildIndex = inActualIndex+1; unsigned int lMaxDepthDown = 0; for(unsigned int i=0; i<lNbArgs; ++i) { unsigned int lChildDepth = buildRouletteWithType(ioRoulette, inSelectABranch, inNodeReturnType, inMaxSubTreeDepth, inMaxSubTreeSize, lChildIndex, inTree, ioContext); lChildIndex += inTree[lChildIndex].mSubTreeSize; if(lChildDepth > lMaxDepthDown) lMaxDepthDown = lChildDepth; } ++lMaxDepthDown; const unsigned int lMaxDepthUp = ioContext.getCallStackSize(); ioContext.popCallStack(); if(lGoodArity && lCompatibleTyping && (lSubTreeSize<=inMaxSubTreeSize) && (lMaxDepthDown<=inMaxSubTreeDepth) && (lMaxDepthUp<=inMaxSubTreeDepth)) { std::pair<unsigned int,unsigned int> lPair(ioContext.getGenotypeIndex(), inActualIndex); ioRoulette.insert(lPair, 1.0); } return lMaxDepthDown; 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 Generate children from the breeder tree. * \param ioDeme Deme to generate children from. * \param ioContext Evolutionary context. * \param lNbChildren Number of children to generate. * \param inN Dimensionality of the problem. * \param ioCMAValues CMA values to use to generate new individual. * \param inSelectionWeights Selection weights used to generate children. */ void CMA::MuWCommaLambdaCMAFltVecOp::generateChildren(Deme& ioDeme, Context& ioContext, unsigned int inNbChildren, unsigned int inN, CMAValues& ioCMAValues, const Vector& inSelectionWeights) const { Beagle_StackTraceBeginM(); // Check parameters and log some information Beagle_NonNullPointerAssertM(mElitismKeepSize); Beagle_ValidateParameterM(mLMRatio->getWrappedValue() >= 1.0, mLMRatioName, "The LM ratio must be higher or equal to 1.0."); Beagle_ValidateParameterM(mElitismKeepSize->getWrappedValue() <= ioDeme.size(), "ec.elite.keepsize", "The elistism keepsize must be less than the deme size!"); Beagle_LogTraceM( ioContext.getSystem().getLogger(), std::string("Using CMA-ES (mu_w,lambda) replacement strategy to process the ")+ uint2ordinal(ioContext.getDemeIndex()+1)+" deme" ); Beagle_LogTraceM(ioContext.getSystem().getLogger(), (*this)); const Factory& lFactory = ioContext.getSystem().getFactory(); // Create weighted mean individual. std::sort(ioDeme.begin(), ioDeme.end(), IsMorePointerPredicate()); Individual::Alloc::Handle lIndividualAlloc = castHandleT<Individual::Alloc>(lFactory.getConceptAllocator("Individual")); Individual::Handle lMeanInd = castHandleT<Individual>(lIndividualAlloc->allocate()); Genotype::Alloc::Handle lGenotypeAlloc = castHandleT<Genotype::Alloc>(lFactory.getConceptAllocator("Genotype")); FltVec::FloatVector::Handle lMeanFloatVec = castHandleT<FltVec::FloatVector>(lGenotypeAlloc->allocate()); lMeanFloatVec->resize(inN); lMeanInd->push_back(lMeanFloatVec); for(unsigned int i=0; i<inN; ++i) (*lMeanFloatVec)[i] = 0.0; if(ioDeme.size()==1) { Beagle_AssertM(ioDeme[0]->size() == 1); FltVec::FloatVector::Handle lInd = castHandleT<FltVec::FloatVector>((*ioDeme[0])[0]); (*lMeanFloatVec) = *lInd; } else { for(unsigned int i=0; i<ioDeme.size(); ++i) { Beagle_AssertM(ioDeme[i]->size()==1); FltVec::FloatVector::Handle lVecI = castHandleT<FltVec::FloatVector>((*ioDeme[i])[0]); Beagle_AssertM(lVecI->size()==inN); for(unsigned int j=0; j<inN; ++j) (*lMeanFloatVec)[j] += (inSelectionWeights[i] * (*lVecI)[j]); } } ioCMAValues.mXmean.resize(inN); for(unsigned int i=0; i<inN; ++i) ioCMAValues.mXmean[i] = (*lMeanFloatVec)[i]; // Generate lambda children with breeder tree, first build breeder roulette RouletteT<unsigned int> lRoulette; buildRoulette(lRoulette, ioContext); // Keep best individuals if elitism is used const unsigned int lElitismKS=mElitismKeepSize->getWrappedValue(); if(lElitismKS > 0) { Individual::Bag lBestInd; History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History")); std::make_heap(ioDeme.begin(), ioDeme.end(), IsLessPointerPredicate()); for(unsigned int i=0; i<lElitismKS; ++i) { if(lHistory != NULL) { HistoryID::Handle lHID = castHandleT<HistoryID>(ioDeme[0]->getMember("HistoryID")); std::vector<HistoryID> lParent; if(lHID != NULL) lParent.push_back(*lHID); lHistory->allocateNewID(*ioDeme[0]); lHistory->trace(ioContext, lParent, ioDeme[0], getName(), "elitism"); } lBestInd.push_back(ioDeme[0]); std::pop_heap(ioDeme.begin(), ioDeme.end(), IsLessPointerPredicate()); ioDeme.pop_back(); } ioDeme.clear(); ioDeme.insert(ioDeme.end(), lBestInd.begin(), lBestInd.end()); } else ioDeme.clear(); // Generate the children Individual::Bag lBagWithMeanInd; lBagWithMeanInd.push_back(lMeanInd); for(unsigned int i=0; i<inNbChildren; ++i) { unsigned int lIndexBreeder = lRoulette.select(ioContext.getSystem().getRandomizer()); BreederNode::Handle lSelectedBreeder=getRootNode(); for(unsigned int j=0; j<lIndexBreeder; ++j) lSelectedBreeder=lSelectedBreeder->getNextSibling(); Beagle_NonNullPointerAssertM(lSelectedBreeder); Beagle_NonNullPointerAssertM(lSelectedBreeder->getBreederOp()); Individual::Handle lBredIndiv = lSelectedBreeder->getBreederOp()->breed(lBagWithMeanInd, lSelectedBreeder->getFirstChild(), ioContext); Beagle_NonNullPointerAssertM(lBredIndiv); ioDeme.push_back(lBredIndiv); } Beagle_StackTraceEndM(); }
/*! * \brief Standard mutate a constrained GP individual. * \param ioIndividual GP individual to standard mutate. * \param ioContext Context of the evolution. * \return True if the individual is effectively mutated, false if not. */ bool GP::MutationStandardSelectiveConstrainedOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext) { Beagle_StackTraceBeginM(); GP::Individual& lIndividual = castObjectT<GP::Individual&>(ioIndividual); GP::Context& lContext = castObjectT<GP::Context&>(ioContext); unsigned int lMaxTreeDepth = mMaxTreeDepth->getWrappedValue(); unsigned int lMaxRegenerationDepth = mMaxRegenerationDepth->getWrappedValue(); //Select node to mutate unsigned int lChoosenTree = 0; unsigned int lChoosenNode = 0; bool lDoParameterSearch = (lContext.getSystem().getRandomizer().rollUniform(0.0, 1.0) <= mMutParameterPb->getWrappedValue()); //Select primitive based on type for(unsigned int lTry = 0; lTry < 2; ++lTry) { //Do only twice std::vector<const std::type_info*> lDesiredTypes(1, ArgEph); RouletteT< std::pair<unsigned int,unsigned int> > lRoulette; SelectiveConstrainedSelectionOp::buildRoulette(lRoulette, lDesiredTypes, lIndividual, lContext,!lDoParameterSearch,lDoParameterSearch); if(lRoulette.size() == 0) { if(lDoParameterSearch) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", string("No EphemeralDouble node found.") ); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", string("No non EphemeralDouble node found.") ); } lDoParameterSearch = !lDoParameterSearch; if(lTry >= 1) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", "Unable to GP standard mutate the individual" ); return false; } } else { std::pair<unsigned int,unsigned int> lSelectedNode = lRoulette.select(ioContext.getSystem().getRandomizer()); lChoosenTree = lSelectedNode.first; lChoosenNode = lSelectedNode.second; break; } } if(lDoParameterSearch) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", string("Mutation applied only on EphemeralDouble node.") ); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", string("Mutation applied on node that are not EphemeralDouble.") ); } unsigned int lOldGenotypeIndex = lContext.getGenotypeIndex(); GP::Tree::Handle lOldGenotypeHandle = lContext.getGenotypeHandle(); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", std::string("Individual before GP standard mutation: ")+ ioIndividual.serialize() ); GP::Tree::Handle lActualTree = lIndividual[lChoosenTree]; GP::Tree::Handle lNewTree = castHandleT<GP::Tree>(lIndividual.getTypeAlloc()->allocate()); lNewTree->setPrimitiveSetIndex(lActualTree->getPrimitiveSetIndex()); lNewTree->setNumberArguments(lActualTree->getNumberArguments()); unsigned int lChoosenNodeSubTreeSize = (*lActualTree)[lChoosenNode].mSubTreeSize; lNewTree->insert(lNewTree->end(), lActualTree->begin(), lActualTree->begin()+lChoosenNode); lContext.setGenotypeIndex(lChoosenTree); lContext.setGenotypeHandle(lActualTree); lContext.emptyCallStack(); lActualTree->setContextToNode(lChoosenNode, lContext); lContext.popCallStack(); const unsigned int lMaxSubTreeDepth = minOf<unsigned int>(lMaxTreeDepth - lContext.getCallStackSize(), lMaxRegenerationDepth); lIndividual[lChoosenTree] = lNewTree; lContext.setGenotypeHandle(lNewTree); unsigned int lAttempt=0; if(lMaxSubTreeDepth >= 1) { for(; lAttempt < mNumberAttempts->getWrappedValue(); lAttempt++) { if(mInitOp->initTree(*lNewTree, 1, lMaxSubTreeDepth, lContext) != 0) break; } } else { lAttempt = mNumberAttempts->getWrappedValue(); } if(lAttempt == mNumberAttempts->getWrappedValue()) { lIndividual[lChoosenTree] = lActualTree; lContext.setGenotypeIndex(lOldGenotypeIndex); lContext.setGenotypeHandle(lOldGenotypeHandle); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", "Unable to GP standard mutate the individual" ); return false; } if( !lDoParameterSearch ) { //Set structure id invalid castHandleT<TreeSTag>((lIndividual)[0])->setStructureIDInvalid(); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", std::string("Set structure id invalid") ); } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", std::string("GP standard mutate the ")+uint2ordinal(lChoosenNode+1)+ std::string(" node, ")+ (*lActualTree)[lChoosenNode].mPrimitive->getName() +std::string(", of the ")+uint2ordinal(lChoosenTree+1)+ std::string(" tree with max depth ")+uint2str(lMaxSubTreeDepth) ); lNewTree->insert(lNewTree->end(), lActualTree->begin()+lChoosenNode+lChoosenNodeSubTreeSize, lActualTree->end()); unsigned int lDiffSize = (*lActualTree)[lChoosenNode].mSubTreeSize - (*lNewTree)[lChoosenNode].mSubTreeSize; for(unsigned int l=0; l<lContext.getCallStackSize(); l++) { (*lNewTree)[lContext.getCallStackElement(l)].mSubTreeSize -= lDiffSize; } lContext.setGenotypeIndex(lOldGenotypeIndex); lContext.setGenotypeHandle(lOldGenotypeHandle); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardSelectiveConstrainedOp", std::string("Individual after GP standard mutation: ")+ ioIndividual.serialize() ); return true; Beagle_StackTraceEndM("bool GP::MutationStandardSelectiveConstrainedOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext)"); }
/*! * \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(); }
/*! * \brief Swap mutate a constrained GP individual. * \param ioIndividual GP individual to swap mutate. * \param ioContext Context of the evolution. * \return True if the individual is effectively mutated, false if not. */ bool GP::MutationSwapDepthSelectiveConstrainedOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext) { Beagle_StackTraceBeginM(); GP::Individual& lIndividual = castObjectT<GP::Individual&>(ioIndividual); GP::Context& lContext = castObjectT<GP::Context&>(ioContext); double lDistrProba = mDistributionProba->getWrappedValue(); unsigned int lNumberAttempts = mNumberAttempts->getWrappedValue(); bool lMutationDone = false; //Select node to mutate unsigned int lChoosenTree = 0; unsigned int lChoosenNode = 0; bool lDoParameterSearch = (lContext.getSystem().getRandomizer().rollUniform(0.0, 1.0) <= mMutParameterPb->getWrappedValue()); RouletteT< std::pair<unsigned int,unsigned int> > lRoulette; //Select primitive based on type for(unsigned int lTry = 0; lTry < 2; ++lTry) { //Do only twice std::vector<const std::type_info*> lDesiredTypes(1, ArgEph); DepthDependentSelectionOp::buildRoulette(lRoulette, lDesiredTypes, lIndividual, lContext,!lDoParameterSearch,lDoParameterSearch); if(lRoulette.size() == 0) { if(lDoParameterSearch) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", string("No EphemeralDouble node found.") ); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", string("No non EphemeralDouble node found.") ); } lDoParameterSearch = !lDoParameterSearch; if(lTry >= 1) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", "Unable to GP standard mutate the individual" ); return false; } } else { std::pair<unsigned int,unsigned int> lSelectedNode = lRoulette.select(ioContext.getSystem().getRandomizer()); lChoosenTree = lSelectedNode.first; lChoosenNode = lSelectedNode.second; break; } } if(lDoParameterSearch) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", string("Mutation applied only on EphemeralDouble node.") ); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", string("Mutation applied on node that are not EphemeralDouble.") ); } GP::Tree& lTree = *lIndividual[lChoosenTree]; if(lTree.size() == 0) return false; GP::Tree::Handle lOldTreeHandle = lContext.getGenotypeHandle(); unsigned int lOldTreeIndex = lContext.getGenotypeIndex(); lContext.setGenotypeHandle(lIndividual[lChoosenTree]); lContext.setGenotypeIndex(lChoosenTree); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", std::string("Individual before constrained GP tree swap mutation: ")+ioIndividual.serialize() ); if(lTree.size() > 1) { bool lTypeNode = (lContext.getSystem().getRandomizer().rollUniform(0., 1.) < lDistrProba); //Clean the roulette to include only the choosen tree for(std::vector< std::pair<double, std::pair<unsigned int,unsigned int> > >::iterator lRouletteIter = lRoulette.begin(); lRouletteIter!=lRoulette.end();){ if(lRouletteIter->second.first != lChoosenTree || (lTree[lRouletteIter->second.second].mPrimitive->getNumberArguments() != 0) != lTypeNode ) { lRouletteIter = lRoulette.erase(lRouletteIter++); } else { ++lRouletteIter; } } if(lRoulette.size() > 0) lChoosenNode = lRoulette.select(ioContext.getSystem().getRandomizer()).second; } if( !lDoParameterSearch || lRoulette.size() > 0 ) { Primitive::Handle lOriginalPrimitive = lTree[lChoosenNode].mPrimitive; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", std::string("Trying to constrained GP tree swap mutate the ")+uint2ordinal(lChoosenNode+1)+ std::string(" node (primitive: \"")+lOriginalPrimitive->getName()+ std::string("\" nb args: ")+uint2str(lOriginalPrimitive->getNumberArguments())+ std::string(") of the ")+uint2ordinal(lChoosenTree+1)+std::string(" tree") ); GP::PrimitiveSet& lPrimitiveSet = lTree.getPrimitiveSet(lContext); unsigned int lNbArgsPrimit = lTree[lChoosenNode].mPrimitive->getNumberArguments(); lTree.setContextToNode(lChoosenNode, lContext); for(unsigned int lAttempt=0; lAttempt < lNumberAttempts; ++lAttempt) { Primitive::Handle lChoosenPrimitive = lPrimitiveSet.select(lNbArgsPrimit, lContext); if(lChoosenPrimitive==NULL) break; lTree[lChoosenNode].mPrimitive = lChoosenPrimitive->giveReference(lNbArgsPrimit, lContext); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", std::string("Trying the primitive \"")+lChoosenPrimitive->getName()+ std::string("\"") ); if(lTree.validateSubTree(lChoosenNode, lContext)) { lMutationDone = true; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", "Constrained GP tree swap mutation valid" ); break; } else { lTree[lChoosenNode].mPrimitive = lOriginalPrimitive; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", "Constrained GP tree swap mutation invalid" ); } } } lContext.setGenotypeHandle(lOldTreeHandle); lContext.setGenotypeIndex(lOldTreeIndex); if(lMutationDone) { if( !lDoParameterSearch ) { //Set structure id invalid castHandleT<TreeSTag>((lIndividual)[0])->setStructureIDInvalid(); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", std::string("Set structure id invalid") ); } Beagle_LogDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", std::string("Individual after constrained GP swap mutation: ")+ ioIndividual.serialize() ); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapDepthSelectiveConstrainedOp", "Unable to swap mutate the constrained individual" ); } return lMutationDone; Beagle_StackTraceEndM("bool GP::MutationSwapDepthSelectiveConstrainedOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext)"); }