Example #1
0
/*!
 *  \brief Read an individual bag from a XML file.
 *  \param inFileName Filename to read individual bag from.
 *  \param ioSystem Evolutionary system used to read individual.
 *  \param inBagTag Name of the XML tag containing the list of individuals to read.
 *  \return True if an individual of the given name was found and read from file.
 *    false if nothing was found.
 */
bool IndividualBag::readFromFile(std::string inFileName,
                                 System& ioSystem,
                                 std::string inBagTag)
{
	Beagle_StackTraceBeginM();
	std::ifstream lIFS(inFileName.c_str());
	PACC::XML::Document lParser(lIFS, inFileName);
	lIFS.close();
	PACC::XML::ConstFinder lBagFinder(lParser.getFirstDataTag());
	PACC::XML::ConstIterator lIndivTag = lBagFinder.find(std::string("//IndividualBag")+inBagTag);
	if(!lIndivTag) return false;

	Context::Alloc::Handle lContextAlloc =
	    castHandleT<Context::Alloc>(ioSystem.getFactory().getConceptAllocator("Concept"));
	Context::Handle lContext =
	    castHandleT<Context>(lContextAlloc->allocate());
	lContext->setSystemHandle(&ioSystem);

	Beagle_LogInfoM(
	    ioSystem.getLogger(),
	    std::string("Reading an individual bag from file '")+inFileName+
	    std::string("' that is in-between the XML tags '")+inBagTag+std::string("'")
	);

	readIndividuals(lIndivTag, *lContext);

	return true;
	Beagle_StackTraceEndM();
}
Example #2
0
/*!
 *  \brief Apply the crossover operation on a breeding pool, returning a mated individual.
 *  \param inBreedingPool Breeding pool to use for the crossover operation.
 *  \param inChild Node handle associated to child node in the breeder tree.
 *  \param ioContext Evolutionary context of the crossover operation.
 *  \return Mated individual.
 */
Individual::Handle CrossoverOp::breed(Individual::Bag& inBreedingPool,
                                      BreederNode::Handle inChild,
                                      Context& ioContext)
{
	Beagle_StackTraceBeginM();

	Context::Alloc::Handle lContextAlloc =
	    castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context"));
	Context::Handle lContext2 = castHandleT<Context>(lContextAlloc->clone(ioContext));

	Beagle_NonNullPointerAssertM(inChild);
	Beagle_NonNullPointerAssertM(inChild->getBreederOp());
	Individual::Handle lIndiv1 = inChild->getBreederOp()->breed(inBreedingPool,
	                             inChild->getFirstChild(),
	                             ioContext);

	Beagle_NonNullPointerAssertM(inChild->getNextSibling());
	Beagle_NonNullPointerAssertM(inChild->getNextSibling()->getBreederOp());
	Individual::Handle lIndiv2 =
	    inChild->getNextSibling()->getBreederOp()->breed(inBreedingPool,
	            inChild->getNextSibling()->getFirstChild(),
	            *lContext2);
	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    std::string("Mating the ")+uint2ordinal(ioContext.getIndividualIndex()+1)+
	    std::string(" individual with the ")+uint2ordinal(lContext2->getIndividualIndex()+1)+
	    " individual"
	);

	if((lIndiv1 != NULL) && (lIndiv2 != NULL)) {
		bool lMated = mate(*lIndiv1, ioContext, *lIndiv2, *lContext2);
		if(lMated) {
			if(lIndiv1->getFitness() != NULL) lIndiv1->getFitness()->setInvalid();
			if(lIndiv2->getFitness() != NULL) lIndiv2->getFitness()->setInvalid();
			History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History"));
			if(lHistory != NULL) {
				std::vector<HistoryID> lParents;
				HistoryID::Handle lHID1 = castHandleT<HistoryID>(lIndiv1->getMember("HistoryID"));
				if(lHID1 != NULL) lParents.push_back(*lHID1);
				HistoryID::Handle lHID2 = castHandleT<HistoryID>(lIndiv2->getMember("HistoryID"));
				if(lHID2 != NULL) lParents.push_back(*lHID2);
				lHistory->incrementHistoryVar(*lIndiv1);
				lHistory->trace(ioContext, lParents, lIndiv1, getName(), "crossover");
			}
		}
	}

	return lIndiv1;
	Beagle_StackTraceEndM();
}
Example #3
0
/*!
 *  \brief Push execution context to prepare the execution of the argument.
 *  \param inNumberArguments Number of arguments of called tree.
 *  \param ioContext Evolutionary context.
 */
void GP::Argument::pushExecutionContext(unsigned int inNumberArguments, GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	switch(mSharedData->mEvalMode) {
	case eCaching: {
		Object::Bag::Handle lNewCache = new Object::Bag(inNumberArguments, NULL);
		mSharedData->mCaches.push_back(lNewCache);
		Context::Alloc::Handle lContextAlloc =
			castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context"));
		GP::Context::Handle lNewEvalContext =
			castHandleT<GP::Context>(lContextAlloc->clone(ioContext));
		mSharedData->mEvalContext.push_back(lNewEvalContext);
		break;
	}
	case eJustInTime: {
		Context::Alloc::Handle lContextAlloc =
		    castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context"));
		GP::Context::Handle lNewEvalContext =
		    castHandleT<GP::Context>(lContextAlloc->clone(ioContext));
		mSharedData->mEvalContext.push_back(lNewEvalContext);
		break;
	}
	case ePreCompute: {
		Object::Bag::Handle lNewCache = new Object::Bag(inNumberArguments, NULL);
		lNewCache->resize(inNumberArguments);
		for(unsigned int i=0; i<inNumberArguments; ++i) {
			Object::Handle lArgI = mSharedData->mTypeAllocator->allocate();
			getArgument(i, *lArgI, ioContext);
			(*lNewCache)[i] = lArgI;
		}
		mSharedData->mCaches.push_back(lNewCache);
	}
	default: {
		throw Beagle_InternalExceptionM(std::string("Undefined evaluation mode (")+
		                                uint2str(mSharedData->mEvalMode)+std::string(") for the arguments!"));
	}
	}
	Beagle_StackTraceEndM();
}
Example #4
0
/*!
 *  \brief Read individual from a XML file. If several individuals are in file, read
 *    first tagged occurence of individual.
 *  \param inFileName Filename to read individual from.
 *  \param ioSystem Evolutionary system to read individual.
 *  \return True if an individual was found and read from file, false if nothing was found.
 */
bool Individual::readFromFile(std::string inFileName, System& ioSystem)
{
	Beagle_StackTraceBeginM();
	std::ifstream lIFS(inFileName.c_str());
	PACC::XML::Document lParser(lIFS, inFileName);
	lIFS.close();
	PACC::XML::ConstFinder lIndivFinder(lParser.getFirstDataTag());
	PACC::XML::ConstIterator lIndivTag = lIndivFinder.find("//Individual");
	if(!lIndivTag) return false;

	Context::Alloc::Handle lContextAlloc =
	    castHandleT<Context::Alloc>(ioSystem.getFactory().getConceptAllocator("Context"));
	Context::Handle lContext = castHandleT<Context>(lContextAlloc->allocate());
	lContext->setSystemHandle(&ioSystem);
	lContext->setIndividualHandle(this);
	lContext->setIndividualIndex(0);

	readWithContext(lIndivTag, *lContext);

	return true;
	Beagle_StackTraceEndM();
}
/*!
 *  \brief Test the fitness of a given individual.
 *  \param inIndividual Handle to the individual to test.
 *  \param ioSystem Handle to the system to use to test the individual.
 *  \par Note:
 *    This method is provided as a mean to test some individuals after an evolution.
 */
Fitness::Handle Beagle::MPI::EvaluationOp::test(Individual::Handle inIndividual, System::Handle ioSystem)
{
	Beagle_LogInfoM(
					ioSystem->getLogger(),
					"evaluation", "Beagle::MPIEvaluationOp",
					std::string("Testing the following individual: ")+inIndividual->serialize()
					);
    
	Context::Alloc::Handle lContextAlloc =
    castHandleT<Context::Alloc>(ioSystem->getContextAllocatorHandle());
	Context::Handle lContext = castHandleT<Context>(lContextAlloc->allocate());
	lContext->setSystemHandle(ioSystem);
	lContext->setIndividualHandle(inIndividual);
	Fitness::Handle lFitness = evaluate(*inIndividual, *lContext);
	
	Beagle_LogInfoM(
					ioSystem->getLogger(),
					"evaluation", "Beagle::MPIEvaluationOp",
					std::string("New fitness of the individual: ")+lFitness->serialize()
					);
    
	return lFitness;
}
/*!
 *  \brief Evaluate the fitness of the given individual.
 *  \param inIndividual Current individual to evaluate.
 *  \param ioContext Evolutionary context.
 *  \return Handle to the fitness value of the individual.
 *
 *  This method evaluates only a single individual.  For this
 *  operator, it is much better to group individuals into a bag and
 *  pass the bag to evaluate(Individual::Bag& ioIndividuals, Context::Bag& ioContexts).
 */
Fitness::Handle EvaluationMultipleOp::evaluate(Individual& inIndividual, Context& ioContext)
{
	Beagle_StackTraceBeginM();
	// Create a bag for the individual
	Individual::Bag lIndividuals;
	lIndividuals.resize(1);
	Beagle_AssertM(inIndividual == ioContext.getIndividual());
	lIndividuals[0] = ioContext.getIndividualHandle();

	// Create a context for the individual
	Context::Bag lContexts;
	lContexts.resize(1);
	Context::Alloc::Handle lContextAlloc =
	    castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context"));
	lContexts[0] = castHandleT<Context>(lContextAlloc->clone(ioContext));

	// Call evalutate()
	Fitness::Bag::Handle lFitnessBag = evaluateIndividuals(lIndividuals,lContexts);

	// Return fitness
	Beagle_AssertM( !lFitnessBag->empty() );
	return lFitnessBag->at(0);
	Beagle_StackTraceEndM();
}
/*!
 *  \brief Read a primitive super set from a XML subtree.
 *  \param inIter XML iterator used to read the super set from.
 *  \param ioSystem Evolutionary system.
 *  \throw Beagle::IOException If size atribute not present.
 */
void GP::PrimitiveSuperSet::readWithSystem(PACC::XML::ConstIterator inIter, Beagle::System& ioSystem)
{
	Beagle_StackTraceBeginM();
	if((inIter->getType()!=PACC::XML::eData) || (inIter->getValue()!="GP-PrimitiveSuperSet"))
		throw Beagle_IOExceptionNodeM(*inIter, "tag <GP-PrimitiveSuperSet> expected!");
	const Factory& lFactory = ioSystem.getFactory();
	Context::Alloc::Handle lContextAlloc =
	    castHandleT<Context::Alloc>(lFactory.getConceptAllocator("Context"));
	GP::Context::Handle lGPContext =
	    castHandleT<GP::Context>(lContextAlloc->allocate());
	lGPContext->setSystemHandle(System::Handle(&ioSystem));
	GP::PrimitiveSet::Alloc::Handle lPrimitSetsAlloc =
		castHandleT<GP::PrimitiveSet::Alloc>(lFactory.getConceptAllocator("GP-PrimitiveSet"));
	mPrimitSets.clear();
	for(PACC::XML::ConstIterator lChild=inIter->getFirstChild(); lChild; ++lChild) {
		if((lChild->getType()==PACC::XML::eData) && (lChild->getValue()=="GP-PrimitiveSet")) {
			GP::PrimitiveSet::Handle lPrimitSet =
				castHandleT<GP::PrimitiveSet>(lPrimitSetsAlloc->allocate());
			lPrimitSet->readWithContext(lChild, *lGPContext);
			mPrimitSets.push_back(lPrimitSet);
		}
	}
	Beagle_StackTraceEndM("void GP::PrimitiveSuperSet::readWithSystem(PACC::XML::ConstIterator inIter, Beagle::System& ioSystem)");
}
/*!
 *  \brief Add individuals to the bag such that the total equals getIndisPerGroup().
 *  \param ioIndividuals Bag of individuals to evaluate.
 *  \param ioContexts Bag of evolutionary context.
 *  \return The number of individuals added to the bag.
 *
 *  The new individuals are chosen from the current deme.
 */
unsigned int EvaluationMultipleOp::enlargeGroup(Individual::Bag& ioIndividuals,
        Context::Bag& ioContexts)
{
	Beagle_StackTraceBeginM();
	Context& lContext = castObjectT<Context&>(*(ioContexts[0]));

	// Calculate the number of individuals to add
	unsigned int lNumToAdd = mIndisPerGroup - ioIndividuals.size();
	Beagle_LogVerboseM(
	    lContext.getSystem().getLogger(),
	    std::string("Adding ")+uint2str(lNumToAdd)+std::string(" individuals to the group (for padding)")
	);

	// Resize the bags
	unsigned int lIndisCounter = ioIndividuals.size();
	ioIndividuals.resize(mIndisPerGroup);
	ioContexts.resize(mIndisPerGroup);

	// Loop through all the individuals in the deme
	Deme& lDeme = lContext.getDeme();
	std::vector<unsigned int> lSelectableIndis;
	lSelectableIndis.resize(lDeme.size());
	unsigned int lSelectableIndisCounter = 0;
	for (unsigned int i=0; i<lDeme.size(); i++) {
		// Loop through all the individuals in the bag
		bool lAdd = true;
		for(unsigned int j=0; j<ioIndividuals.size(); j++) {
			if(lDeme[i] == ioIndividuals[j]) {
				lAdd = false;
				break;
			}
		}
		// If the individual is not already in the bag, add it as an option
		if(lAdd) {
			lSelectableIndis[lSelectableIndisCounter] = i;
			lSelectableIndisCounter++;
		}
	}

	// Check there are sufficient individuals to choose
	if(lSelectableIndis.size() < lNumToAdd) {
		throw Beagle_RunTimeExceptionM("There are insufficient individuals in the deme to perform evaluation");
	}

	// Add individuals
	for(unsigned int i=0; i<lNumToAdd; i++) {
		unsigned int lIndex =
		    lContext.getSystem().getRandomizer().rollInteger(0,lSelectableIndisCounter-1);
		unsigned int lIndiIndex = lSelectableIndis[lIndex];
		Beagle_LogVerboseM(
		    lContext.getSystem().getLogger(),
		    std::string("Adding ")+uint2ordinal(lIndiIndex+1)+
		    std::string(" individual to the group (for padding)")
		);
		Beagle_AssertM(lIndiIndex < lDeme.size());
		ioIndividuals[lIndisCounter] = lDeme[ lIndiIndex ];
		Context::Alloc::Handle lContextAlloc =
		    castHandleT<Context::Alloc>(lContext.getSystem().getFactory().getConceptAllocator("Context"));
		ioContexts[lIndisCounter] = castHandleT<Context>(lContextAlloc->clone(*(ioContexts[0])));
		ioContexts[lIndisCounter]->setIndividualHandle( ioIndividuals[lIndisCounter] );
		ioContexts[lIndisCounter]->setIndividualIndex( lIndiIndex );
		lIndisCounter++;
	}
	Beagle_AssertM( lIndisCounter==ioIndividuals.size() );

	return lNumToAdd;
	Beagle_StackTraceEndM();
}
/*!
 *  \brief Apply the evaluation process on the invalid individuals of the deme.
 *  \param ioDeme Deme to process.
 *  \param ioContext Context of the evolution.
 */
void EvaluationMultipleOp::operate(Deme& ioDeme, Context& ioContext)
{
	Beagle_StackTraceBeginM();
	Beagle_LogTraceM(
	    ioContext.getSystem().getLogger(),
	    "Evaluating the fitness of the individuals in the " << 
	    uint2ordinal(ioContext.getDemeIndex()+1) << " deme"
	);

	Beagle_AssertM( ioDeme.size()!=0 );

	// Prepare stats
	prepareStats(ioDeme,ioContext);

	// Generate a vector of indicies into the population
	std::vector<unsigned int> lEvalVector;
	for(unsigned int i=0; i<ioDeme.size(); i++) {
		if((ioDeme[i]->getFitness() == NULL) ||
		        (ioDeme[i]->getFitness()->isValid() == false)) {
			lEvalVector.push_back(i);
			Beagle_LogDebugM(
			    ioContext.getSystem().getLogger(),
			    "Added " << uint2ordinal(i+1) << " individual for evaluation."
			);
		}
	}
	std::random_shuffle(lEvalVector.begin(), lEvalVector.end(),
	                    ioContext.getSystem().getRandomizer());

	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "There are " << lEvalVector.size() << " individuals to be evaluated."
	);

	History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History"));

	while ( !lEvalVector.empty() ) {
		// Put individuals and context into bags.
		Individual::Bag lIndividuals;
		Context::Bag lContexts;
		lIndividuals.resize( mIndisPerGroup );
		lContexts.resize( mIndisPerGroup );
		unsigned int lIndiCounter =0;

		for (unsigned int i=0; i<mIndisPerGroup; i++) {
			// Set individual
			lIndividuals[i] = ioDeme[lEvalVector.back()];
			lIndiCounter++;
			// Set context
			Context::Alloc::Handle lContextAlloc =
			    castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context"));
			Context::Handle lContext = castHandleT<Context>(lContextAlloc->clone(ioContext));
			lContext->setIndividualIndex( lEvalVector.back() );
			lContext->setIndividualHandle( ioDeme[lEvalVector.back()] );
			lContexts[i] = lContext;
			// Remove this index from the evaluation vector
			lEvalVector.pop_back();
			if(lEvalVector.empty()) {
				lIndividuals.resize( lIndiCounter );
				lContexts.resize( lIndiCounter );
				break;
			}
		}

		// Evaluate individuals
		std::ostringstream lOSS;
		lOSS << "Evaluating the fitness of the ";
		for(unsigned int i=0; i<lIndiCounter; i++) {
			// Add to message
			if (i==lIndiCounter-1) lOSS << " and ";
			lOSS << uint2ordinal(lContexts[i]->getIndividualIndex()+1);
			if (i<lIndiCounter-2) lOSS << ", ";
		}
		lOSS << " individuals";
		Beagle_LogVerboseM(
		    ioContext.getSystem().getLogger(),
		    lOSS.str()
		);
		Fitness::Bag::Handle lFitnessBag = evaluateIndividuals(lIndividuals, lContexts);

		// Assign fitnesses
		for (unsigned int i=0; i<lIndiCounter; i++) {
			Beagle_LogDebugM(
			    ioContext.getSystem().getLogger(),
			    "Considering fitness of the " << uint2ordinal(lContexts[i]->getIndividualIndex()+1) << " individual"
			);
			Beagle_AssertM( i < lFitnessBag->size() );
			Fitness::Handle lFitness = lFitnessBag->at(i);
			Beagle_NonNullPointerAssertM( lFitness );
			lIndividuals[i]->setFitness( lFitness );
			lIndividuals[i]->getFitness()->setValid();
			if(lHistory != NULL) {
				lHistory->allocateID(*lIndividuals[i]);
				lHistory->trace(ioContext, std::vector<HistoryID>(), lIndividuals[i], getName(), "evaluation");
			}

			Beagle_LogVerboseM(
			    ioContext.getSystem().getLogger(),
			    *lIndividuals[i]->getFitness()
			);
		}

		// Update stats
		updateStats(lIndividuals.size(),ioContext);
	}

	updateHallOfFameWithDeme(ioDeme,ioContext);
	Beagle_StackTraceEndM();
}
/*!
 *  \brief 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();
}
Example #11
0
/*!
 *  \brief Apply the crossover operation on the deme.
 *  \param ioDeme Current deme of individuals to mate.
 *  \param ioContext Context of the evolution.
 */
void CrossoverOp::operate(Deme& ioDeme, Context& ioContext)
{
	Beagle_StackTraceBeginM();

	Beagle_ValidateParameterM(mMatingProba->getWrappedValue()>=0.0, mMatingProbaName, "<0");

	Beagle_LogTraceM(
	    ioContext.getSystem().getLogger(),
	    std::string("Mating individuals of the ")+
	    uint2ordinal(ioContext.getDemeIndex()+1)+" deme"
	);
	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    std::string("Mating individuals with probability ")+
	    dbl2str(mMatingProba->getWrappedValue())
	);

	History::Handle lHistory = castHandleT<History>(ioContext.getSystem().haveComponent("History"));

	Individual::Handle lOldIndividualHandle = ioContext.getIndividualHandle();
	unsigned int lOldIndividualIndex = ioContext.getIndividualIndex();

	std::vector<unsigned int> lMateVector;
	for(unsigned int i=0; i<ioDeme.size(); i++) {
		if(ioContext.getSystem().getRandomizer().rollUniform() <= mMatingProba->getWrappedValue()) {
			lMateVector.push_back(i);
		}
	}

	std::random_shuffle(lMateVector.begin(), lMateVector.end(),
	                    ioContext.getSystem().getRandomizer());
	if((lMateVector.size() % 2) != 0) lMateVector.pop_back();

	int j = 0;
	int lSize = lMateVector.size();

#if defined(BEAGLE_USE_OMP_NR) || defined(BEAGLE_USE_OMP_R)
	static OpenMP::Handle lOpenMP = castHandleT<OpenMP>(ioContext.getSystem().getComponent("OpenMP"));
	const Factory& lFactory = ioContext.getSystem().getFactory();
	const std::string& lContextName = lFactory.getConceptTypeName("Context");
	Context::Alloc::Handle lContextAlloc = castHandleT<Context::Alloc>(lFactory.getAllocator(lContextName));
	Context::Bag lContexts(lOpenMP->getMaxNumThreads());
	Context::Bag lContexts2(lOpenMP->getMaxNumThreads());
	for(unsigned int i = 0; i < lOpenMP->getMaxNumThreads(); ++i) {
		lContexts[i] = castHandleT<Context>(lContextAlloc->clone(ioContext));
		lContexts2[i] = castHandleT<Context>(lContextAlloc->clone(ioContext));
	}
#if defined(BEAGLE_USE_OMP_NR)
#pragma omp parallel for shared(lSize, lMateVector, lHistory, lContexts, lContexts2) private(j) schedule(dynamic)
#elif defined(BEAGLE_USE_OMP_R)
	const int lChunkSize = std::max((int)(lSize / lOpenMP->getMaxNumThreads()), 1);
#pragma omp parallel for shared(lSize, lMateVector, lHistory, lContexts, lContexts2) private(j) schedule(static, lChunkSize)
#endif
#else
	Context::Alloc::Handle lContextAlloc =
	    castHandleT<Context::Alloc>(ioContext.getSystem().getFactory().getConceptAllocator("Context"));
	Context::Handle lContext2 = castHandleT<Context>(lContextAlloc->clone(ioContext));
#endif
	for(j=0; j<lSize; j+=2) {
		unsigned int lFirstMate  = lMateVector[j];
		unsigned int lSecondMate = lMateVector[j+1];

#if defined(BEAGLE_USE_OMP_NR) || defined(BEAGLE_USE_OMP_R)
		lContexts[lOpenMP->getThreadNum()]->setIndividualIndex(lFirstMate);
		lContexts[lOpenMP->getThreadNum()]->setIndividualHandle(ioDeme[lFirstMate]);
		lContexts2[lOpenMP->getThreadNum()]->setIndividualIndex(lSecondMate);
		lContexts2[lOpenMP->getThreadNum()]->setIndividualHandle(ioDeme[lSecondMate]);
#else
		ioContext.setIndividualIndex(lFirstMate);
		ioContext.setIndividualHandle(ioDeme[lFirstMate]);
		lContext2->setIndividualIndex(lSecondMate);
		lContext2->setIndividualHandle(ioDeme[lSecondMate]);
#endif

		Beagle_LogVerboseM(
		    ioContext.getSystem().getLogger(),
		    std::string("Mating the ")+uint2ordinal(lFirstMate+1)+
		    std::string(" individual with the ")+uint2ordinal(lSecondMate+1)+" individual"
		);

		std::vector<HistoryID> lParents;
		if(lHistory != NULL) {
#pragma omp critical (Beagle_History)
			{
				HistoryID::Handle lHID1 = castHandleT<HistoryID>(ioDeme[lFirstMate]->getMember("HistoryID"));
				if(lHID1 != NULL) lParents.push_back(*lHID1);
				HistoryID::Handle lHID2 = castHandleT<HistoryID>(ioDeme[lSecondMate]->getMember("HistoryID"));
				if(lHID2 != NULL) lParents.push_back(*lHID2);
			}
		}

#if defined(BEAGLE_USE_OMP_NR) || defined(BEAGLE_USE_OMP_R)
		bool lMated = mate(*ioDeme[lFirstMate], *(lContexts[lOpenMP->getThreadNum()]), *ioDeme[lSecondMate], *(lContexts2[lOpenMP->getThreadNum()]));
#else
		bool lMated = mate(*ioDeme[lFirstMate], ioContext, *ioDeme[lSecondMate], *lContext2);
#endif
		if(lMated) {
			if(ioDeme[lFirstMate]->getFitness() != NULL) {
				ioDeme[lFirstMate]->getFitness()->setInvalid();
			}
			if(ioDeme[lSecondMate]->getFitness() != NULL) {
				ioDeme[lSecondMate]->getFitness()->setInvalid();
			}
			if(lHistory != NULL) {
#pragma omp critical (Beagle_History)
				{
					lHistory->incrementHistoryVar(*ioDeme[lFirstMate]);
#if defined(BEAGLE_USE_OMP_R) || defined(BEAGLE_USE_OMP_NR)
					lHistory->trace(*lContexts[lOpenMP->getThreadNum()], lParents, ioDeme[lFirstMate], getName(), "crossover");
#else
					lHistory->trace(ioContext, lParents, ioDeme[lFirstMate], getName(), "crossover");
#endif
					lHistory->incrementHistoryVar(*ioDeme[lSecondMate]);
#if defined(BEAGLE_USE_OMP_R) || defined(BEAGLE_USE_OMP_NR)
					lHistory->trace(*lContexts[lOpenMP->getThreadNum()], lParents, ioDeme[lSecondMate], getName(), "crossover");
#else
					lHistory->trace(ioContext, lParents, ioDeme[lSecondMate], getName(), "crossover");
#endif
				}
			}
		}
	}

	ioContext.setIndividualIndex(lOldIndividualIndex);
	ioContext.setIndividualHandle(lOldIndividualHandle);

	Beagle_StackTraceEndM();
}