/*! * \brief Mutate an ES individual. * \param ioIndividual ES individual to mutate. * \param ioContext Context of the evolution. * \return True as individual are always mutated. */ bool GA::MutationESVecOp::mutate(Beagle::Individual& ioIndividual, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_ValidateParameterM(mMinStrategy->getWrappedValue()>=0.0,mMinStrategyName,"<0"); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationESVecOp", std::string("Applying evolution strategy mutation to an individual") ); for(unsigned int i=0; i<ioIndividual.size(); i++) { GA::ESVector::Handle lVector = castHandleT<GA::ESVector>(ioIndividual[i]); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationESVecOp", std::string("Mutating the ")+uint2ordinal(i+1)+" ES vector" ); Beagle_LogObjectDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationESVecOp", *lVector ); const double lT = 1.0 / std::sqrt(2.0 * std::sqrt(double(lVector->size()))); const double lTPrime = 1.0 / std::sqrt(2.0 * lVector->size()); const double lN = ioContext.getSystem().getRandomizer().rollGaussian(0.0, 1.0); const double lMinStrategy = mMinStrategy->getWrappedValue(); for(unsigned int j=0; j<lVector->size(); j++) { const double lMaxVal = j<mMaxValue->size() ? (*mMaxValue)[j] : mMaxValue->back(); const double lMinVal = j<mMinValue->size() ? (*mMinValue)[j] : mMinValue->back(); const double lNi = ioContext.getSystem().getRandomizer().rollGaussian(0.0, 1.0); (*lVector)[j].mStrategy *= std::exp((lTPrime * lN) + (lT * lNi)); if((*lVector)[j].mStrategy < lMinStrategy) (*lVector)[j].mStrategy = lMinStrategy; (*lVector)[j].mValue += (*lVector)[j].mStrategy * lNi; if((*lVector)[j].mValue > lMaxVal) (*lVector)[j].mValue = lMaxVal; if((*lVector)[j].mValue < lMinVal) (*lVector)[j].mValue = lMinVal; Beagle_LogDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationESVecOp", std::string("ES mutating by adding ")+dbl2str((*lVector)[j].mStrategy * lNi)+ std::string(" to the value and multiplying the strategy by ")+ dbl2str(std::exp((lTPrime * lN) + (lT * lNi)))+ std::string(" to mutate the pair ")+uint2str(j)+ std::string(" of the ES vector") ); } Beagle_LogObjectDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationESVecOp", *lVector ); } return true; Beagle_StackTraceEndM("bool GA::MutationESVecOp::mutate(Beagle::Individual& ioIndividual, Context& ioContext)"); }
/*! * \brief Uniformly mutate an integer vector GA individual. * \param ioIndividual GA individual to mutate. * \param ioContext Context of the evolution. * \return True if the individual is effectively mutated, false if not. */ bool GA::MutationUniformIntVecOp::mutate(Beagle::Individual& ioIndividual, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_ValidateParameterM(mIntMutateProba->getWrappedValue()>=0.0, mIntMutatePbName, "<0"); bool lMutated = false; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationUniformIntVecOp", std::string("Integer uniform mutation probability is: ")+ dbl2str(mIntMutateProba->getWrappedValue()) ); for(unsigned int i=0; i<ioIndividual.size(); i++) { GA::IntegerVector::Handle lIV = castHandleT<GA::IntegerVector>(ioIndividual[i]); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationUniformIntVecOp", std::string("Uniformly mutating the ")+uint2ordinal(i+1)+" integer vector" ); Beagle_LogObjectDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationUniformIntVecOp", *lIV ); for(unsigned int j=0; j<lIV->size(); j++) { double lRolledPb = ioContext.getSystem().getRandomizer().rollUniform(); if(lRolledPb <= mIntMutateProba->getWrappedValue()) { const int lMaxVal = j<mMaxValue->size() ? (*mMaxValue)[j] : mMaxValue->back(); const int lMinVal = j<mMinValue->size() ? (*mMinValue)[j] : mMinValue->back(); Beagle_AssertM(lMaxVal >= lMinVal); const int lRandVal = (int)ioContext.getSystem().getRandomizer().rollInteger(0,lMaxVal-lMinVal); (*lIV)[j] = (lRandVal+lMinVal); lMutated = true; } } if(lMutated) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationUniformIntVecOp", std::string("The integer vector has been uniformly mutated") ); Beagle_LogObjectDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationUniformIntVecOp", *lIV ); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GA::MutationUniformIntVecOp", std::string("The integer vector has not been mutated") ); } } return lMutated; Beagle_StackTraceEndM("bool GA::MutationUniformIntVecOp::mutate(Beagle::Individual& ioIndividual, Context& ioContext)"); }
/*! * \brief Mutate a linear GP individual. * \param ioIndividual Linear GP individual to mutate. * \param ioContext Context of the evolution. * \return True if the individual is effectively mutated, false if not. */ bool LinGP::MutationOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext) { Beagle_ValidateParameterM(mInstructMutateProba->getWrappedValue()>=0.0, mInstructMutatePbName, "<0"); bool lMutated = false; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Linear GP mutation probability is: ")+ dbl2str(mInstructMutateProba->getWrappedValue()) ); LinGP::Context& lLinGPContext = castObjectT<LinGP::Context&>(ioContext); LinGP::InstructionSuperSet::Handle lInsSS = castHandleT<LinGP::InstructionSuperSet>(lLinGPContext.getSystem().getComponent("LinGP-InstructionSuperSet")); for(unsigned int i=0; i<ioIndividual.size(); i++) { LinGP::Program::Handle lProgram = castHandleT<LinGP::Program>(ioIndividual[i]); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Mutating the ")+uint2ordinal(i+1)+" program" ); Beagle_LogDebugM( ioContext.getSystem().getLogger(), *lProgram ); for(unsigned int j=0; j<lProgram->size(); j++) { double lRolledPb = ioContext.getSystem().getRandomizer().rollUniform(); if(lRolledPb <= mInstructMutateProba->getWrappedValue()) { (*lProgram)[j] = lInsSS->getInstructionSets()[i]->selectRandomInstruction(lLinGPContext.getSystem())->giveReference(lLinGPContext); lMutated = true; } } if(lMutated) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("The program has been mutated") ); Beagle_LogDebugM( ioContext.getSystem().getLogger(), *lProgram ); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("The program has not been mutated") ); } } return lMutated; }
/*! * \brief Bit flip mutate a bit string individual. * \param ioIndividual Individual to mutate. * \param ioContext Context of the evolution. * \return True if the individual is effectively mutated, false if not. */ bool BitStr::MutationFlipBitOp::mutate(Beagle::Individual& ioIndividual, Context& ioContext) { Beagle_StackTraceBeginM(); Beagle_ValidateParameterM(mBitMutateProba->getWrappedValue()>=0.0, mBitMutatePbName, "<0"); bool lMutated = false; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Bit flip mutation probability is: ")+dbl2str(mBitMutateProba->getWrappedValue()) ); for(unsigned int i=0; i<ioIndividual.size(); i++) { BitStr::BitString::Handle lBS = castHandleT<BitStr::BitString>(ioIndividual[i]); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Flip mutating the ")+uint2ordinal(i+1)+" bitstring" ); Beagle_LogDebugM(ioContext.getSystem().getLogger(), *lBS); for(unsigned int j=0; j<lBS->size(); j++) { double lRolledPb = ioContext.getSystem().getRandomizer().rollUniform(); if(lRolledPb <= mBitMutateProba->getWrappedValue()) { (*lBS)[j] = !(*lBS)[j]; lMutated = true; } } if(lMutated) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("The bitstring has been flip mutated") ); Beagle_LogDebugM(ioContext.getSystem().getLogger(), *lBS); } else { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("The bitstring has not been mutated") ); } } return lMutated; Beagle_StackTraceEndM(); }
/*! * \brief Gaussian mutate a real-valued GA individual. * \param ioIndividual Real-valued GA individual to mutate. * \param ioContext Context of the evolution. * \return True if the individual is effectively mutated, false if not. */ bool FltVec::MutationGaussianOp::mutate(Beagle::Individual& ioIndividual, Context& ioContext) { Beagle_StackTraceBeginM(); bool lMutated = false; Beagle_LogVerboseM( ioContext.getSystem().getLogger(), string("Gaussian mutations with mean of ")+ mMutateGaussMu->serialize()+ string(", and standard deviation of ")+ mMutateGaussSigma->serialize() ); for(unsigned int i=0; i<ioIndividual.size(); i++) { FltVec::FloatVector::Handle lVector = castHandleT<FltVec::FloatVector>(ioIndividual[i]); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), string("Gaussian mutation the ")+uint2ordinal(i+1)+" float vector" ); Beagle_LogDebugM(ioContext.getSystem().getLogger(), *lVector); for(unsigned int j=0; j<lVector->size(); j++) { const float lRolledPb = ioContext.getSystem().getRandomizer().rollUniform(); if(lRolledPb <= mMutateFloatPb->getWrappedValue()) { const double lMaxVal = j<mMaxValue->size() ? (*mMaxValue)[j] : mMaxValue->back(); const double lMinVal = j<mMinValue->size() ? (*mMinValue)[j] : mMinValue->back(); const double lIncVal = j<mIncValue->size() ? (*mIncValue)[j] : mIncValue->back(); const double lMu = j<mMutateGaussMu->size() ? (*mMutateGaussMu)[j] : mMutateGaussMu->back(); const double lSigma = j<mMutateGaussSigma->size() ? (*mMutateGaussSigma)[j] : mMutateGaussSigma->back(); Beagle_AssertM(lSigma>=0.0); const double lMValue = ioContext.getSystem().getRandomizer().rollGaussian(lMu,lSigma); (*lVector)[j] += lMValue; if((*lVector)[j] > lMaxVal) (*lVector)[j] = lMaxVal; if((*lVector)[j] < lMinVal) (*lVector)[j] = lMinVal; if(std::fabs(lIncVal)>1e-12) { (*lVector)[j] = lIncVal * round((*lVector)[j] / lIncVal); if((*lVector)[j] > lMaxVal) (*lVector)[j] -= lIncVal; if((*lVector)[j] < lMinVal) (*lVector)[j] += lIncVal; } lMutated = true; Beagle_LogDebugM( ioContext.getSystem().getLogger(), string("Gaussian mutating by adding ")+dbl2str(lMValue)+ string(" to the value at the index ")+uint2str(j)+ string(" of the float vector") ); } } if(lMutated) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "The float vector has been mutated" ); Beagle_LogDebugM(ioContext.getSystem().getLogger(), *lVector); } else { Beagle_LogVerboseM(ioContext.getSystem().getLogger(), "The float vector has not been mutated"); } } return lMutated; Beagle_StackTraceEndM(); }
/*! * \brief Mate two indice integer vector GA individuals for partialy matched crossover. * \param ioIndiv1 First individual to mate. * \param ioContext1 Evolutionary context of the first individual. * \param ioIndiv2 Second individual to mate. * \param ioContext2 Evolutionary context of the second individual. * \return True if the individuals are effectively mated, false if not. */ bool Beagle::GA::CrossoverPMXOp::mate(Beagle::Individual& ioIndiv1, Beagle::Context& ioContext1, Beagle::Individual& ioIndiv2, Beagle::Context& ioContext2) { Beagle_StackTraceBeginM(); unsigned int lNbGenotypes = minOf<unsigned int>(ioIndiv1.size(), ioIndiv2.size()); if(lNbGenotypes == 0) return false; Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverPMXOp", "Individuals mated (before GA partily matched crossover)" ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverPMXOp", ioIndiv1 ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverPMXOp", ioIndiv2 ); for(unsigned int i=0; i<lNbGenotypes; ++i) { GA::IntegerVector::Handle lIndividual1 = castHandleT<IntegerVector>(ioIndiv1[i]); GA::IntegerVector::Handle lIndividual2 = castHandleT<IntegerVector>(ioIndiv2[i]); std::deque<int> lIndividual1Copy(lIndividual1->begin(), lIndividual1->end()); std::deque<int> lIndividual2Copy(lIndividual2->begin(), lIndividual2->end()); unsigned int lSize = minOf<unsigned int>(lIndividual1->size(), lIndividual2->size()); unsigned int a = ioContext1.getSystem().getRandomizer().rollInteger(0, lSize-1); unsigned int b = ioContext1.getSystem().getRandomizer().rollInteger(0, lSize-1); if(a > b){std::swap(a, b);} for(unsigned int j = a; j <= b; ++j){ for(unsigned int k = 0; k < lSize; ++k){ if((*lIndividual1)[k] == lIndividual1Copy[j]) (*lIndividual1)[k] = lIndividual2Copy[j]; else if((*lIndividual1)[k] == lIndividual2Copy[j]) (*lIndividual1)[k] = lIndividual1Copy[j]; if((*lIndividual2)[k] == lIndividual1Copy[j]) (*lIndividual2)[k] = lIndividual2Copy[j]; else if((*lIndividual2)[k] == lIndividual2Copy[j]) (*lIndividual2)[k] = lIndividual1Copy[j]; } } } Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverPMXOp", "Individuals mated (after GA partialy matched crossover)" ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverPMXOp", ioIndiv1 ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverPMXOp", ioIndiv2 ); return true; Beagle_StackTraceEndM("bool GA::CrossoverPMXOp::mate(Individual& ioIndiv1, Context& ioContext1, Individual& ioIndiv2, Context& ioContext2)"); }
/*! * \brief Swap subtree mutate a GP individual. * \param ioIndividual GP individual to swap subtree mutate. * \param ioContext Context of the evolution. */ bool GP::MutationSwapSubtreeOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext) { Beagle_StackTraceBeginM(); // Initial parameters checks. Beagle_AssertM(ioIndividual.size() > 0); Beagle_ValidateParameterM(mNumberAttempts->getWrappedValue()>0, "gp.try", ">0"); // Cast method arguments. GP::Individual& lGPIndiv = castObjectT<GP::Individual&>(ioIndividual); GP::Context& lContext1 = castObjectT<GP::Context&>(ioContext); Context::Alloc::Handle lContextAlloc = castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context")); GP::Context::Handle lContextHdl2 = castHandleT<GP::Context>(lContextAlloc->clone(lContext1)); const Factory& lFactory = ioContext.getSystem().getFactory(); GP::Tree::Alloc::Handle lTreeAlloc = castHandleT<GP::Tree::Alloc>(lFactory.getConceptAllocator("Genotype")); // Get parameters in local values, with the total number of nodes of the mutated individual. bool lMatingDone = false; float lDistrProba = mDistributionProba->getWrappedValue(); unsigned int lMaxTreeDepth = mMaxTreeDepth->getWrappedValue(); GP::Tree::Handle lOldTreeHandle1 = lContext1.getGenotypeHandle(); unsigned int lOldTreeIndex1 = lContext1.getGenotypeIndex(); unsigned int lSizeIndiv = 0; for(unsigned int i=0; i<lGPIndiv.size(); ++i) lSizeIndiv += lGPIndiv[i]->size(); // Some outputs. Beagle_LogDebugM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", "Individual tried for swap subtree mutation (before)" ); Beagle_LogObjectDebugM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", lGPIndiv ); // Mutation loop. Try the given number of attempts to mutation the individual. for(unsigned int lAttempt=0; lAttempt < mNumberAttempts->getWrappedValue(); lAttempt++) { // Calculate the number of nodes in the individual unsigned int lNbNodes = 0; for(unsigned int i=0; i<lGPIndiv.size(); i++) lNbNodes += lGPIndiv[i]->size(); if(lNbNodes == 0) return false; // Choose a node of the individual to mutate. unsigned int lNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lNbNodes-1); // Get the tree in which the choosen node is. Change the global node index to the tree's index. unsigned int lChoosenTree = 0; for(; lChoosenTree<lGPIndiv.size(); ++lChoosenTree) { if(lNode1 < lGPIndiv[lChoosenTree]->size()) break; Beagle_AssertM(lNode1 >= lGPIndiv[lChoosenTree]->size()); lNode1 -= lGPIndiv[lChoosenTree]->size(); } Beagle_AssertM(lChoosenTree < lGPIndiv.size()); // Cannot do anything with an tree of size <= 1. if(lGPIndiv[lChoosenTree]->size() <= 1) continue; // Some outputs. Beagle_LogVerboseM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", std::string("Trying a swap subtree mutation of the ")+uint2ordinal(lChoosenTree+1)+ std::string(" tree") ); // Make two clones of the choosen tree. GP::Tree::Handle lTreeClone1 = castHandleT<GP::Tree>(lTreeAlloc->clone(*lGPIndiv[lChoosenTree])); GP::Tree::Handle lTreeClone2 = castHandleT<GP::Tree>(lTreeAlloc->clone(*lGPIndiv[lChoosenTree])); // Now we decide whether the swap subtree mutation is internal or external. bool lMutationType = lContext1.getSystem().getRandomizer().rollUniform(0.0, 1.0) < lDistrProba; // Cannot do an internal mutation when there is only one branch in the tree. if(lTreeClone1->size() == (*lTreeClone1)[0].mPrimitive->getNumberArguments()+1) lMutationType = false; // This is special case, a linear tree. Cannot do an external mutation. if(lTreeClone1->size() == (*lTreeClone1)[1].mSubTreeSize+1) { if(lTreeClone1->size()==2) continue; // Cannot do anything here with the tree. lMutationType = true; } // lMutationType is true -> internal mutation if(lMutationType) { // If the selected node is a terminal, or a branch with a subtree made only of terminals, // choose another node in the same tree. while((*lTreeClone1)[lNode1].mSubTreeSize == ((*lTreeClone1)[lNode1].mPrimitive->getNumberArguments()+1)) { lNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lTreeClone1->size()-1); } // Choosing the second node, a branch in lNode1's subtree. unsigned int lSubTreeSizeN1 = (*lTreeClone1)[lNode1].mSubTreeSize; unsigned int lN2OffN1 = lContext1.getSystem().getRandomizer().rollInteger(1, lSubTreeSizeN1-1); unsigned int lNode2 = lNode1 + lN2OffN1; while((*lTreeClone1)[lNode2].mPrimitive->getNumberArguments() == 0) { lN2OffN1 = lContext1.getSystem().getRandomizer().rollInteger(1, lSubTreeSizeN1-1); lNode2 = lNode1 + lN2OffN1; } // Choosing the third node, any node in lNode2's subtree. unsigned int lSubTreeSizeN2 = (*lTreeClone1)[lNode2].mSubTreeSize; unsigned int lN3OffN2 = lContext1.getSystem().getRandomizer().rollInteger(1, lSubTreeSizeN2-1); // Ok, now we can exchange the subtrees. // New value of lNode1 and lNode2 for the second exchange. unsigned int lNode3Exch2 = lNode1 + lN3OffN2; unsigned int lNode1Exch2 = lNode2; // New value of lNode1 and lNode2 for the third exchange. unsigned int lNode2Exch3 = lNode1 + lN3OffN2 + lN2OffN1; unsigned int lNode3Exch3 = lNode2; // First exchange. lTreeClone1->setContextToNode(lNode1, lContext1); lTreeClone2->setContextToNode(lNode2, *lContextHdl2); exchangeSubTrees(*lTreeClone1, lNode1, lContext1, *lTreeClone2, lNode2, *lContextHdl2); // Second exchange. lTreeClone1->setContextToNode(lNode3Exch2, lContext1); lTreeClone2->setContextToNode(lNode1Exch2, *lContextHdl2); exchangeSubTrees(*lTreeClone1, lNode3Exch2, lContext1, *lTreeClone2, lNode1Exch2, *lContextHdl2); // Third exchange. lTreeClone1->setContextToNode(lNode2Exch3, lContext1); lTreeClone2->setContextToNode(lNode3Exch3, *lContextHdl2); exchangeSubTrees(*lTreeClone1, lNode2Exch3, lContext1, *lTreeClone2, lNode3Exch3, *lContextHdl2); // Checking if the tree depth is respected. If not, start again. if(lTreeClone1->getTreeDepth() > lMaxTreeDepth) { Beagle_LogVerboseM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", "Tree maximum depth exceeded. GP swap subtree mutation invalid." ); continue; } lGPIndiv[lChoosenTree] = lTreeClone1; Beagle_LogVerboseM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", "GP swap subtree mutation valid" ); lMatingDone = true; break; // The swap subtree mutation is valid. } // lMutationType is false -> external mutation else { // Deterniming the minimal node index to use. unsigned int lMinNodeIndex = 0; for(; lTreeClone1->size() == ((*lTreeClone1)[lMinNodeIndex].mSubTreeSize+lMinNodeIndex); ++lMinNodeIndex) { if(lMinNodeIndex == (lTreeClone1->size()-1)) continue; // Can't do anything with linear tree. } // Change lNode1 if less than minimum node index. if(lNode1 < lMinNodeIndex) lNode1 = lContext1.getSystem().getRandomizer().rollInteger(lMinNodeIndex, lTreeClone1->size()-1); // Choosing second swap subtree mutation point. std::vector<unsigned int> lValidN2; for(unsigned int i=lMinNodeIndex; i<lTreeClone1->size(); ++i) { if((i>=lNode1) && (i<lNode1+(*lTreeClone1)[lNode1].mSubTreeSize)) continue; else if((lNode1>=i) && (lNode1<(i+(*lTreeClone1)[i].mSubTreeSize))) continue; else lValidN2.push_back(i); } unsigned int lNode2 = lValidN2[lContext1.getSystem().getRandomizer().rollInteger(0, lValidN2.size()-1)]; Beagle_LogVerboseM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", std::string("Trying an external swap subtree mutation of the ")+uint2ordinal(lNode1+1)+ std::string(" node with the subtree to the ")+uint2ordinal(lNode2+1)+ std::string(" node") ); // Ok, now we can exchange the subtrees. // New value of lNode1 and lNode2 for the second exchange. unsigned int lNode1Exch2 = lNode1; unsigned int lNode2Exch2 = lNode2; if(lNode1 < lNode2) { lNode2Exch2 += (*lTreeClone1)[lNode2].mSubTreeSize; lNode2Exch2 -= (*lTreeClone1)[lNode1].mSubTreeSize; } else { lNode1Exch2 += (*lTreeClone1)[lNode1].mSubTreeSize; lNode1Exch2 -= (*lTreeClone1)[lNode2].mSubTreeSize; } // First exchange. lTreeClone1->setContextToNode(lNode1, lContext1); lTreeClone2->setContextToNode(lNode2, *lContextHdl2); exchangeSubTrees(*lTreeClone1, lNode1, lContext1, *lTreeClone2, lNode2, *lContextHdl2); // Second exchange. lTreeClone1->setContextToNode(lNode2Exch2, lContext1); lTreeClone2->setContextToNode(lNode1Exch2, *lContextHdl2); exchangeSubTrees(*lTreeClone1, lNode2Exch2, lContext1, *lTreeClone2, lNode1Exch2, *lContextHdl2); // Checking if the tree depth is respected. If not, start again. if(lTreeClone1->getTreeDepth() > lMaxTreeDepth) { Beagle_LogVerboseM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", "Tree maximum depth exceeded. GP swap subtree mutation invalid." ); continue; } lGPIndiv[lChoosenTree] = lTreeClone1; Beagle_LogVerboseM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", "GP swap subtree mutation valid" ); lMatingDone = true; break; // The swap subtree mutation is valid. } } // Replace the contexts. lContext1.setGenotypeHandle(lOldTreeHandle1); lContext1.setGenotypeIndex(lOldTreeIndex1); if(lMatingDone) { Beagle_LogDebugM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", "Individual after swap subtree mutation" ); Beagle_LogObjectDebugM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", lGPIndiv ); } else { Beagle_LogVerboseM( lContext1.getSystem().getLogger(), "mutation", "Beagle::GP::MutationSwapSubtreeOp", "No GP swap subtree mutation done" ); } return lMatingDone; Beagle_StackTraceEndM(); }
/*! * \brief Mate two GP individuals for a crossover. * \param ioIndiv1 First individual to mate. * \param ioContext1 Evolutionary context of the first individual. * \param ioIndiv2 Second individual to mate. * \param ioContext2 Evolutionary context of the second individual. * \return True if the individuals are effectively mated, false if not. */ bool GP::CrossoverOp::mate(Beagle::Individual& ioIndiv1, Beagle::Context& ioContext1, Beagle::Individual& ioIndiv2, Beagle::Context& ioContext2) { Beagle_StackTraceBeginM(); // Initial parameters checks Beagle_AssertM(&ioIndiv1 != &ioIndiv2); Beagle_AssertM(ioIndiv1.size() > 0); Beagle_AssertM(ioIndiv1.size() == ioIndiv2.size()); Beagle_ValidateParameterM(mNumberAttempts->getWrappedValue()>0,"gp.try",">0"); // Cast method arguments. GP::Individual& lIndiv1 = castObjectT<GP::Individual&>(ioIndiv1); GP::Individual& lIndiv2 = castObjectT<GP::Individual&>(ioIndiv2); GP::Context& lContext1 = castObjectT<GP::Context&>(ioContext1); GP::Context& lContext2 = castObjectT<GP::Context&>(ioContext2); // Get parameters in local values, with the total number of nodes of an individual. bool lMatingDone = false; float lDistrProba = mDistributionProba->getWrappedValue(); unsigned int lMaxTreeDepth = mMaxTreeDepth->getWrappedValue(); GP::Tree::Handle lOldTreeHandle1 = lContext1.getGenotypeHandle(); unsigned int lOldTreeIndex1 = lContext1.getGenotypeIndex(); GP::Tree::Handle lOldTreeHandle2 = lContext2.getGenotypeHandle(); unsigned int lOldTreeIndex2 = lContext2.getGenotypeIndex(); unsigned int lSizeIndiv1 = 0; for(unsigned int i=0; i<lIndiv1.size(); i++) lSizeIndiv1 += lIndiv1[i]->size(); Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", "Individuals to mate (before GP crossover)" ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", lIndiv1 ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", lIndiv2 ); // Crossover loop. Try the given number of attempts to mate two individuals. for(unsigned int lAttempt=0; lAttempt<mNumberAttempts->getWrappedValue(); lAttempt++) { // Choose a node in all the individual node. unsigned int lChoosenNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lSizeIndiv1-1); // Get the tree in which the choosen node is. Change the global // node index to the tree's index. unsigned int lChoosenTree1 = 0; for(; lChoosenTree1<lIndiv1.size(); lChoosenTree1++) { if(lChoosenNode1 < lIndiv1[lChoosenTree1]->size()) break; Beagle_AssertM(lChoosenNode1 >= lIndiv1[lChoosenTree1]->size()); lChoosenNode1 -= lIndiv1[lChoosenTree1]->size(); } Beagle_AssertM(lChoosenTree1 < lIndiv1.size()); // Choose a type of node (branch or leaf) following the // distribution probability and change the node for another node // of the same tree if the types mismatch. GP::Tree& lTree1 = *lIndiv1[lChoosenTree1]; const unsigned int lPrimitiveSetIndex1 = lTree1.getPrimitiveSetIndex(); if(lTree1.size() > 1) { bool lTypeNode1 = (lContext1.getSystem().getRandomizer().rollUniform(0.0, 1.0) < lDistrProba); while((lTree1[lChoosenNode1].mPrimitive->getNumberArguments() != 0) != lTypeNode1) { lChoosenNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lTree1.size()-1); } } // Choose a node in the second individual from a tree with the same primitive set index. unsigned int lSizeIndiv2 = 0; for(unsigned int i=0; i<lIndiv2.size(); i++) { if(lIndiv2[i]->getPrimitiveSetIndex() == lPrimitiveSetIndex1) { lSizeIndiv2 += lIndiv2[i]->size(); } } // Check to see that there is at least one node that can be selected if(lSizeIndiv2==0) { Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverConstrainedOp", std::string("Crossover attempt failed: The tree chosen from the first individual has")+ " a primitive set index of "+uint2str(lPrimitiveSetIndex1)+ " and there are no trees in the second individual with that primitive set index" ); continue; } // Choose a node in the second individual unsigned int lChoosenNode2 = lContext2.getSystem().getRandomizer().rollInteger(0, lSizeIndiv2-1); // Find which tree the choosen node is in. unsigned int lChoosenTree2 = 0; for(; lChoosenTree2<lIndiv2.size(); lChoosenTree2++) { if(lIndiv2[lChoosenTree2]->getPrimitiveSetIndex() == lPrimitiveSetIndex1) { if(lChoosenNode2 < lIndiv2[lChoosenTree2]->size()) break; Beagle_AssertM(lChoosenNode2 >= lIndiv2[lChoosenTree2]->size()); lChoosenNode2 -= lIndiv2[lChoosenTree2]->size(); } } Beagle_AssertM(lChoosenTree2 < lIndiv2.size()); GP::Tree& lTree2 = *lIndiv2[lChoosenTree2]; // Choose a type of node (branch or leaf) following the // distribution probability and change the node for another node // of the same tree if the types mismatch. if(lTree2.size() > 1) { bool lTypeNode2 = (lContext2.getSystem().getRandomizer().rollUniform(0.0, 1.0) < lDistrProba); while((lTree2[lChoosenNode2].mPrimitive->getNumberArguments() != 0) != lTypeNode2) { lChoosenNode2 = lContext2.getSystem().getRandomizer().rollInteger(0, lTree2.size()-1); } } // Set the first context to the node of the first tree. // Check if depth is ok. Do a new crossover attempt if not. lTree1.setContextToNode(lChoosenNode1, lContext1); unsigned int lNewDepthTree1 = lContext1.getCallStackSize() + lTree2.getTreeDepth(lChoosenNode2) - 1; if(lNewDepthTree1 > lMaxTreeDepth) { Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverConstrainedOp", std::string("Crossover attempt failed because the depth of the resulting tree in the ")+ std::string("first individual would exceed the depth constraint") ); continue; } // Set the first context to the node of the second tree. // Check if depth is ok. Do a new crossover attempt if not. lTree2.setContextToNode(lChoosenNode2, lContext2); unsigned int lNewDepthTree2 = lContext2.getCallStackSize() + lTree1.getTreeDepth(lChoosenNode1) - 1; if(lNewDepthTree2 > lMaxTreeDepth) { Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverConstrainedOp", std::string("Crossover attempt failed because the depth of the resulting tree in the ")+ std::string("second individual would exceed the depth constraint") ); continue; } // Mate the trees. Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", std::string("Trying to mate the ")+uint2ordinal(lChoosenTree1+1)+ std::string(" tree of the first individual with the ")+uint2ordinal(lChoosenTree2+1)+ std::string(" tree of the second individual") ); Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", std::string("Trying to exchange the ")+uint2ordinal(lChoosenNode1+1)+ std::string(" node of the first tree with the ")+uint2ordinal(lChoosenNode2+1)+ std::string(" node of the second tree") ); mateTrees(lTree1, lChoosenNode1, lContext1, lTree2, lChoosenNode2, lContext2); lMatingDone = true; Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", "GP crossover valid" ); break; // The crossover is valid. } // Replace the contexts. lContext1.setGenotypeHandle(lOldTreeHandle1); lContext1.setGenotypeIndex(lOldTreeIndex1); lContext2.setGenotypeHandle(lOldTreeHandle2); lContext2.setGenotypeIndex(lOldTreeIndex2); if(lMatingDone) { Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", "Individuals mated (after GP crossover)" ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", lIndiv1 ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", lIndiv2 ); } else { Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GP::CrossoverOp", "No GP crossover done" ); } return lMatingDone; Beagle_StackTraceEndM("bool GP::CrossoverOp::mate(Beagle::Individual& ioIndiv1, Beagle::Context& ioContext1, Beagle::Individual& ioIndiv2, Beagle::Context& ioContext2)"); }
/*! * \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. */ Beagle::Fitness::Handle AnalogFilterParameterEvalOp::evaluate(Beagle::Individual& inIndividual, Beagle::Context& ioContext) { Beagle_AssertM(inIndividual.size() == 1); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "evaluation", "AnalogFilterParameterEvalOp", std::string("Evaluating individual: ")+ inIndividual.serialize() ); BGFitness *lFitness = new BGFitness(0); GrowingBondGraph::Handle lBondGraph; GA::FloatVector::Handle lParametersVector = castHandleT<GA::FloatVector>(inIndividual[0]); BGContext& lBGContext = castObjectT<BGContext&>(ioContext); SpeciesGA& lSpecies = castObjectT<SpeciesGA&>(ioContext.getDeme()); RepresentantGP::Handle lIndividual = castHandleT<RepresentantGP>(lSpecies.getRepresentant()); TreeSTag::Handle lTree = castHandleT<TreeSTag>((*lIndividual)[0]); // lTree->assignNewParameterVector(lParametersVector, lBGContext); lBondGraph = lTree->getBondGraph(); lBondGraph->assignParameters(*lParametersVector); lIndividual->getFitness()->setInvalid(); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "evaluation", "AnalogFilterParameterEvalOp", std::string("Individual after parameter assignment: ")+ lIndividual->serialize() ); try { vector<double> lInitial; //Run the individual to create the bond graph. // RootReturn lResult; // // lBGContext.setIndividualHandle(lIndividual); // lIndividual->run(lResult, lBGContext); // lBondGraph = lBGContext.getBondGraph(); // lTree->setBondGraph(lBondGraph); // // //Set output bond // Bond* lOutputBond = lBondGraph->getComponents()[lResult.getValue()-1]->getPorts()[0]->getBond(); // lBondGraph->setOutputBonds(lOutputBond, 0); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "evaluation", "AnalogFilterParameterEvalOp", std::string("Evaluating bondgrap: ")+ lBondGraph->BondGraph::serialize() ); //lBondGraph->simplify(); //Get state equations lBondGraph->assignCausality(); lBondGraph->computeStateEquation(); PACC::Matrix lA,lB,lB2,lC,lD,lD2; lBondGraph->getStateMatrix(lA,lB,lB2); lBondGraph->getOutputMatrix(lC,lD,lD2); lFitness->addStateMatrix(lA); lFitness->addStateMatrix(lB); lFitness->addStateMatrix(lC); lFitness->addStateMatrix(lD); //Check to see if the system is LTI if(lBondGraph->hasDeferentialCausality()) { //lFitness->setValue(ioContext.getSystem().getRandomizer().getFloat()); lFitness->setValue(0); //delete lBondGraph; return lFitness; } else { #ifndef DEBUG_NOMATLAB //Evalute the response in Matlab. // Cast the state matrix as input data // The mwArray::SetData is copying in column major order and the PACC::Matrix is a row major order // Therefore, the matrix need to be transposed. PACC::Matrix lAt,lBt,lCt,lDt; if(!lA.empty()) lAt = lA.transpose(); if(!lB.empty()) lBt = lB.transpose(); if(!lC.empty()) lCt = lC.transpose(); if(!lD.empty()) lDt = lD.transpose(); double *lValueA = new double[lAt.size()]; std::copy(lAt.begin(), lAt.end(), lValueA); mwArray lArrayA(lAt.getCols(),lAt.getRows(), mxDOUBLE_CLASS, mxREAL); lArrayA.SetData(lValueA,lAt.size()); double *lValueB = new double[lBt.size()]; std::copy(lBt.begin(), lBt.end(), lValueB); mwArray lArrayB(lBt.getCols(),lBt.getRows(), mxDOUBLE_CLASS, mxREAL); lArrayB.SetData(lValueB,lBt.size()); double *lValueC = new double[lCt.size()]; std::copy(lCt.begin(), lCt.end(), lValueC); mwArray lArrayC(lCt.getCols(),lCt.getRows(), mxDOUBLE_CLASS, mxREAL); lArrayC.SetData(lValueC,lCt.size()); double *lValueD = new double[lDt.size()]; std::copy(lDt.begin(), lDt.end(), lValueD); mwArray lArrayD(lDt.getCols(),lDt.getRows(), mxDOUBLE_CLASS, mxREAL); lArrayD.SetData(lValueD,lDt.size()); // Create output array mwArray loutArray; // Call the library function AnalogFilterEval(1, loutArray, lArrayA, lArrayB, lArrayC,lArrayD); // Extract the output int lNbOutput = loutArray.NumberOfElements(); double* loutValues = new double[lNbOutput]; loutArray.GetData(loutValues, lNbOutput); // Bundle the fitness lFitness->setValue(loutValues[0]); delete [] lValueA; delete [] lValueB; delete [] lValueC; delete [] lValueD; delete [] loutValues; #else lFitness->setValue(ioContext.getSystem().getRandomizer().getFloat()); #endif } } catch (const mwException& inException) { std::cerr << inException.what() << std::endl; PACC::Matrix lA,lB,lB2,lC,lD,lD2; lBondGraph->getStateMatrix(lA,lB,lB2); lBondGraph->getOutputMatrix(lC,lD,lD2); PACC::XML::Streamer lStream(cerr); lA.write(lStream); cerr << endl; lB.write(lStream); cerr << endl; lC.write(lStream); cerr << endl; lD.write(lStream); cerr << endl; //Save bond graph for debuging std::ostringstream lFilename; lFilename << "bug/bondgraph_bug_" << ioContext.getGeneration() << "_" << ioContext.getIndividualIndex(); #ifndef WITHOUT_GRAPHVIZ lBondGraph->plotGraph(lFilename.str()+std::string(".svg")); #endif ofstream lFileStream((lFilename.str()+std::string(".xml")).c_str()); PACC::XML::Streamer lStreamer(lFileStream); lBondGraph->write(lStreamer); #ifdef STOP_ON_ERROR exit(EXIT_FAILURE); #endif } catch(std::runtime_error inError) { std::cerr << "Error catched while evaluating the bond graph: " << inError.what() << std::endl; //Save bond graph for debuging std::ostringstream lFilename; lFilename << "bug/bondgraph_bug_" << ioContext.getGeneration() << "_" << ioContext.getIndividualIndex(); #ifndef WITHOUT_GRAPHVIZ lBondGraph->plotGraph(lFilename.str()+std::string(".svg")); #endif ofstream lFileStream((lFilename.str()+std::string(".xml")).c_str()); PACC::XML::Streamer lStreamer(lFileStream); lBondGraph->write(lStreamer); //Assign null fitness lFitness->setValue(0); #ifdef XMLBEAGLE XMLStreamer lStreamer2(std::cout); inIndividual.write(lStreamer2); #else inIndividual.write(lStreamer); #endif #ifdef STOP_ON_ERROR exit(EXIT_FAILURE); #endif } //delete lBondGraph; return lFitness; }
/*! * \brief Mate two GP individuals for a constrained tree crossover. * \param ioIndiv1 First individual to mate. * \param ioContext1 Evolutionary context of the first individual. * \param ioIndiv2 Second individual to mate. * \param ioContext2 Evolutionary context of the second individual. * \return True if the individuals are effectively mated, false if not. */ bool STGP::CrossoverConstrainedOp::mate(Beagle::Individual& ioIndiv1, Beagle::Context& ioContext1, Beagle::Individual& ioIndiv2, Beagle::Context& ioContext2) { Beagle_StackTraceBeginM(); // Initial parameters checks Beagle_AssertM(ioIndiv1.size() > 0); //Beagle_AssertM(ioIndiv1.size() == ioIndiv2.size()); Beagle_ValidateParameterM(mNumberAttempts->getWrappedValue()>0,"gp.try",">0"); // Cast method arguments. GP::Individual& lIndiv1 = castObjectT<GP::Individual&>(ioIndiv1); GP::Individual& lIndiv2 = castObjectT<GP::Individual&>(ioIndiv2); GP::Context& lContext1 = castObjectT<GP::Context&>(ioContext1); GP::Context& lContext2 = castObjectT<GP::Context&>(ioContext2); // Get parameters in local values, with the total number of nodes of an individual. bool lMatingDone = false; float lDistrProba = mDistributionProba->getWrappedValue(); unsigned int lMaxTreeDepth = mMaxTreeDepth->getWrappedValue(); GP::Tree::Handle lOldTreeHandle1 = lContext1.getGenotypeHandle(); unsigned int lOldTreeIndex1 = lContext1.getGenotypeIndex(); GP::Tree::Handle lOldTreeHandle2 = lContext2.getGenotypeHandle(); unsigned int lOldTreeIndex2 = lContext2.getGenotypeIndex(); unsigned int lSizeIndiv1 = 0; for(unsigned int i=0; i<lIndiv1.size(); i++) lSizeIndiv1 += lIndiv1[i]->size(); Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "Individuals to mate (before constrained GP crossover)" ); Beagle_LogDebugM( ioContext1.getSystem().getLogger(), lIndiv1 ); Beagle_LogDebugM( ioContext1.getSystem().getLogger(), lIndiv2 ); // Crossover loop. Try the given number of attempts to mate two individuals. for(unsigned int lAttempt=0; lAttempt < mNumberAttempts->getWrappedValue(); ++lAttempt) { // Choose a node in all the individual node. unsigned int lChoosenNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lSizeIndiv1-1); // Get the tree in which the choosen node is. Change the global node index to the tree's index. unsigned int lChoosenTree1 = 0; for(; lChoosenTree1<lIndiv1.size(); lChoosenTree1++) { if(lChoosenNode1 < lIndiv1[lChoosenTree1]->size()) break; Beagle_AssertM(lChoosenNode1 >= lIndiv1[lChoosenTree1]->size()); lChoosenNode1 -= lIndiv1[lChoosenTree1]->size(); } Beagle_AssertM(lChoosenTree1 < lIndiv1.size()); // Choose a type of node (branch or leaf) following the distribution probability and change the // node for another node of the same tree if the types mismatch. GP::Tree& lTree1 = *lIndiv1[lChoosenTree1]; const unsigned int lPrimitiveSetIndex1 = lTree1.getPrimitiveSetIndex(); if(lTree1.size() > 1) { bool lTypeNode1 = (lContext1.getSystem().getRandomizer().rollUniform(0.0, 1.0) < lDistrProba); while((lTree1[lChoosenNode1].mPrimitive->getNumberArguments() != 0) != lTypeNode1) { lChoosenNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lTree1.size()-1); } } // Choose type of node (branch or leaf) for the second node. const bool lTypeNode2 = (lContext2.getSystem().getRandomizer().rollUniform(0.0, 1.0) < lDistrProba); // Compute max depth allowable. lTree1.setContextToNode(lChoosenNode1, lContext1); const unsigned int lTmpMaxDepth1 = lMaxTreeDepth - lContext1.getCallStackSize(); const unsigned int lTmpMaxDepth2 = lMaxTreeDepth - lTree1.getTreeDepth(lChoosenNode1); const unsigned int lMaxDepthTree2 = minOf(lTmpMaxDepth1, lTmpMaxDepth2); // Select a node in second individual for the crossover. unsigned int lChoosenTree2=0; unsigned int lChoosenNode2=0; #ifdef BEAGLE_HAVE_RTTI const std::type_info* lDesiredType = lTree1[lChoosenNode1].mPrimitive->getReturnType(lContext1); bool lGoodSelect = selectNodeToMateWithType(lChoosenTree2, lChoosenNode2, lTypeNode2, lDesiredType, lPrimitiveSetIndex1, lMaxDepthTree2, UINT_MAX, lIndiv2, lContext2); #else // BEAGLE_HAVE_RTTI bool lGoodSelect = selectNodeToMate(lChoosenTree2, lChoosenNode2, lTypeNode2, lPrimitiveSetIndex1, lMaxDepthTree2, UINT_MAX, lIndiv2, lContext2); #endif // BEAGLE_HAVE_RTTI // Check to see that there is at least one node that can be selected if(lGoodSelect==false) { Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), std::string("Crossover attempt failed: it seems there is no corresponding nodes in second ")+ std::string("individual that would meet all the constraints") ); continue; } // Get reference to the tree the choosen node is in. Beagle_AssertM(lChoosenTree2 < lIndiv2.size()); GP::Tree& lTree2 = *lIndiv2[lChoosenTree2]; lTree2.setContextToNode(lChoosenNode2, lContext2); // Mate the trees. Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), std::string("Trying to exchange the ")+uint2ordinal(lChoosenNode1+1)+ std::string(" node of the ")+uint2ordinal(lChoosenTree1+1)+ std::string(" tree of the first individual with the ")+uint2ordinal(lChoosenNode2+1)+ std::string(" node of the ")+uint2ordinal(lChoosenTree2+1)+ std::string(" tree of the second individual") ); mateTrees(lTree1, lChoosenNode1, lContext1, lTree2, lChoosenNode2, lContext2); // If one tree is not valid, undo the crossover and do a new crossover attempt. lContext1.setGenotypeHandle(lIndiv1[lChoosenTree1]); lContext1.setGenotypeIndex(lChoosenTree1); lContext2.setGenotypeHandle(lIndiv2[lChoosenTree2]); lContext2.setGenotypeIndex(lChoosenTree2); if(lTree1.validateSubTree(lChoosenNode1,lContext1) && lTree2.validateSubTree(lChoosenNode2,lContext2)) { lMatingDone = true; Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "Constrained tree GP crossover valid" ); break; // The crossover is valid. } else { // Undo crossover. Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "Crossover attempt failed because one of the resulting trees was invalid" ); mateTrees(lTree1, lChoosenNode1, lContext1, lTree2, lChoosenNode2, lContext2); continue; } } // Replace the contexts. lContext1.setGenotypeHandle(lOldTreeHandle1); lContext1.setGenotypeIndex(lOldTreeIndex1); lContext2.setGenotypeHandle(lOldTreeHandle2); lContext2.setGenotypeIndex(lOldTreeIndex2); if(lMatingDone) { Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "Individuals mated (after constrained tree GP crossover)" ); Beagle_LogDebugM( ioContext1.getSystem().getLogger(), lIndiv1 ); Beagle_LogDebugM( ioContext1.getSystem().getLogger(), lIndiv2 ); } else { Beagle_LogVerboseM( ioContext1.getSystem().getLogger(), "No constrained tree GP crossover done" ); } return lMatingDone; Beagle_StackTraceEndM(); }
/*! * \brief Mate two indice integer vector GA individuals for non-wrapping ordered crossover. * \param ioIndiv1 First individual to mate. * \param ioContext1 Evolutionary context of the first individual. * \param ioIndiv2 Second individual to mate. * \param ioContext2 Evolutionary context of the second individual. * \return True if the individuals are effectively mated, false if not. */ bool Beagle::GA::CrossoverNWOXOp::mate(Beagle::Individual& ioIndiv1, Beagle::Context& ioContext1, Beagle::Individual& ioIndiv2, Beagle::Context& ioContext2) { Beagle_StackTraceBeginM(); unsigned int lNbGenotypes = minOf<unsigned int>(ioIndiv1.size(), ioIndiv2.size()); if(lNbGenotypes == 0) return false; Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverNWOXOp", "Individuals mated (before GA non-wrapping ordered crossover)" ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverNWOXOp", ioIndiv1 ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverNWOXOp", ioIndiv2 ); for(unsigned int i=0; i<lNbGenotypes; ++i) { GA::IntegerVector::Handle lIndividual1 = castHandleT<IntegerVector>(ioIndiv1[i]); GA::IntegerVector::Handle lIndividual2 = castHandleT<IntegerVector>(ioIndiv2[i]); unsigned int lSize = minOf<unsigned int>(lIndividual1->size(), lIndividual2->size()); unsigned int a = ioContext1.getSystem().getRandomizer().rollInteger(0, lSize-1); unsigned int b = ioContext1.getSystem().getRandomizer().rollInteger(0, lSize-1); if(a > b){std::swap(a, b);} bool* lHoleSet1 = new bool[lSize]; bool* lHoleSet2 = new bool[lSize]; for(unsigned int j = 0; j < lSize; ++j){ if(j < a || j > b){ lHoleSet1[(*lIndividual2)[j]] = false; lHoleSet2[(*lIndividual1)[j]] = false; }else{ lHoleSet1[(*lIndividual2)[j]] = true; lHoleSet2[(*lIndividual1)[j]] = true; } } std::vector<unsigned int> lChild1; std::vector<unsigned int> lChild2; for(unsigned int j = 0; j < lSize; ++j){ if(!lHoleSet1[(*lIndividual1)[j]]) lChild1.push_back((*lIndividual1)[j]); if(!lHoleSet2[(*lIndividual2)[j]]) lChild2.push_back((*lIndividual2)[j]); } lChild1.insert(lChild1.begin() + a, lIndividual2->begin() + a, lIndividual2->begin() + (b + 1)); lChild2.insert(lChild2.begin() + a, lIndividual1->begin() + a, lIndividual1->begin() + (b + 1)); // Transfer the child in the ouput individuals for(unsigned int j = 0; j < lSize; ++j){ (*lIndividual1)[j] = lChild1[j]; (*lIndividual2)[j] = lChild2[j]; } delete[] lHoleSet1; delete[] lHoleSet2; } Beagle_LogDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverNWOXOp", "Individuals mated (after GA non-wrapping ordered crossover)" ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverNWOXOp", ioIndiv1 ); Beagle_LogObjectDebugM( ioContext1.getSystem().getLogger(), "crossover", "Beagle::GA::CrossoverNWOXOp", ioIndiv2 ); return true; Beagle_StackTraceEndM("bool GA::CrossoverNWOXOp::mate(Individual& ioIndiv1, Context& ioContext1, Individual& ioIndiv2, Context& ioContext2)"); }