コード例 #1
0
/*!
 *  \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)");
}
コード例 #2
0
/*!
 *  \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)");
}
コード例 #3
0
ファイル: MutationOp.cpp プロジェクト: GhostGambler/beagle
/*!
 *  \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;
}
コード例 #4
0
/*!
 *  \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();
}
コード例 #5
0
/*!
 *  \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();
}
コード例 #6
0
/*!
 *  \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)");
}
コード例 #7
0
/*!
 *  \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();
}
コード例 #8
0
/*!
 *  \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;
}
コード例 #10
0
/*!
 *  \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();
}
コード例 #11
0
/*!
 *  \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)");
}