/*!
 *  \brief Invoke GP tree to execute as ADF.
 *  \param outResult Result of GP tree invocation
 *  \param ioTree Tree to invoke.
 *  \param ioContext Evolutionary context.
 */
void GP::Module::invoke(GP::Datum& outResult, GP::Tree::Handle ioTree, GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	GP::Tree::Handle lOldGenotypeHandle = ioContext.getGenotypeHandle();
	unsigned int lOldGenotypeIndex = ioContext.getGenotypeIndex();
	ioContext.setGenotypeHandle(ioTree);
	ioContext.setGenotypeIndex(mIndex);
	ioContext.incrementNodesExecuted();
	ioContext.pushCallStack(0);
	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    "EMA", "Beagle::GP::Module",
	    std::string("Interpreting the ")+uint2ordinal(mIndex+1)+std::string(" module")
	);
	Beagle_LogObjectDebugM(
	    ioContext.getSystem().getLogger(),
	    "EMA", "Beagle::GP::Module",
	    *ioTree
	);
	(*ioTree)[0].mPrimitive->execute(outResult, ioContext);
	ioContext.popCallStack();
	ioContext.checkExecutionTime();
	ioContext.setGenotypeHandle(lOldGenotypeHandle);
	ioContext.setGenotypeIndex(lOldGenotypeIndex);
	Beagle_StackTraceEndM("void GP::Module::invoke(GP::Datum& outResult, GP::Tree::Handle ioTree, GP::Context& ioContext)");
}
/*!
 *  \brief Initialize a tree.
 *  \param outTree Tree to initialize.
 *  \param inMinDepth Minimum depth of to make tree.
 *  \param inMaxDepth Maximum depth of to make tree.
 *  \param ioContext Evolution context.
 *  \return Size of newly initialized tree.
 */
unsigned int GP::InitGrowOp::initTree(GP::Tree& outTree,
                                      unsigned int inMinDepth,
                                      unsigned int inMaxDepth,
                                      GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();

	if (mKozaGrow->getWrappedValue()) {
		Beagle_LogVerboseM(
		    ioContext.getSystem().getLogger(),
		    "initialization", "Beagle::GP::InitGrowConstrainedOp",
		    "Setting the minimum depth to 2 (as per 'gp.init.kozagrow')"
		);
		inMinDepth=2;
	}

	Beagle_AssertM(inMaxDepth >= inMinDepth);
	Beagle_AssertM(inMinDepth>0);

	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    "initialization", "Beagle::GP::InitGrowOp",
	    std::string("Using the \'grow\' method (with maximum depth ")+uint2str(inMaxDepth)+
	    std::string(" and minimum depth ")+uint2str(inMinDepth)+std::string(") to initialize the ")+
	    uint2ordinal(ioContext.getGenotypeIndex()+1)+std::string(" tree")
	);

	return initSubTreeGrow(outTree, inMinDepth, inMaxDepth, ioContext);
	Beagle_StackTraceEndM("unsigned int GP::InitGrowOp::initTree(GP::Tree &outTree, unsigned int inMinDepth, unsigned int inMaxDepth, GP::Context& ioContext) const");
}
/*!
 *  \brief Generate a new ADF primitive from the given specifications.
 *  \param inIndex Tree index for which the primitive is created.
 *  \param inName Name of the primitive generated.
 *  \param inArgsName Name of the arguments associated to the invoker created.
 *  \param ioContext Evolutionary context.
 */
GP::Invoker::Handle GP::ADF::generateInvoker(unsigned int inIndex,
        std::string inName,
        std::string inArgsName,
        GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	if(inIndex == UINT_MAX) {
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "primitive selection","Beagle::GP::ADF::generateInvoker",
		    "Generated ADF with UINT_MAX"
		);

		return new GP::ADF(UINT_MAX, UINT_MAX, inName, inArgsName);
	} else {
		GP::Tree::Handle lTree = ioContext.getIndividual()[inIndex];

		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "primitive selection","Beagle::GP::ADF::generateInvoker",
		    std::string("Generated ADF with index ")+uint2str(inIndex)+" ("+uint2str(lTree->getNumberArguments())+" args)"
		);

		return new GP::ADF(inIndex, lTree->getNumberArguments(), inName, inArgsName);
	}
	Beagle_StackTraceEndM("GP::Invoker::Handle GP::ADF::generateInvoker(unsigned int inIndex, string inName, string inArgsName, GP::Context& ioContext) const");
}
Beispiel #4
0
/*!
 *  \brief Evaluate the individual fitness for the spambase problem.
 *  \param inIndividual Individual to evaluate.
 *  \param ioContext Evolutionary context.
 *  \return Handle to the fitness measure,
 */
Fitness::Handle SpambaseEvalOp::evaluate(GP::Individual& inIndividual, GP::Context& ioContext)
{
	// Get reference to data set
	DataSetClassification::Handle lDataSet =
	    castHandleT<DataSetClassification>(ioContext.getSystem().getComponent("DataSet"));
	if(lDataSet == NULL) {
		throw Beagle_RunTimeExceptionM("Data set is not present in the system, could not proceed further!");
	}

	// Generate indices used as data subset for fitness evaluation
	std::vector<unsigned int> lSubSet(lDataSet->size());
	for(unsigned int i=0; i<lSubSet.size(); ++i) lSubSet[i] = i;
	std::random_shuffle(lSubSet.begin(), lSubSet.end(),
	                    ioContext.getSystem().getRandomizer());
	if(Spambase_TestSize < lSubSet.size()) {
		lSubSet.resize(Spambase_TestSize);
	}

	// Evaluate sampled test cases
	unsigned int lCorrectCount = 0;
	for(unsigned int i=0; i<Spambase_TestSize; ++i) {
		const bool lPositiveID = ((*lDataSet)[lSubSet[i]].first == 1);
		const Beagle::Vector& lData = (*lDataSet)[lSubSet[i]].second;
		for(unsigned int j=0; j<lData.size(); ++j) {
			std::ostringstream lOSS;
			lOSS << "IN" << j;
			setValue(lOSS.str(), Double(lData[j]), ioContext);
		}
		Bool lResult;
		inIndividual.run(lResult, ioContext);
		if(lResult.getWrappedValue() == lPositiveID) ++lCorrectCount;
	}
	double lFitness = double(lCorrectCount) / Spambase_TestSize;
	return new EC::FitnessSimple(lFitness);
}
Beispiel #5
0
/*!
 *  \brief Validate the GP individual.
 *  \param ioContext Evolutionary context.
 *  \return True if the GP individual is valid, false if not.
 */
bool GP::Individual::validate(GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	bool lResult = true;

	Beagle_LogDetailedM(
	    ioContext.getSystem().getLogger(),
	    std::string("Validating ")+uint2ordinal(ioContext.getIndividualIndex()+1)+
	    std::string(" individual")
	);

	// Store original values.
	GP::Tree::Handle lOldTreeHandle = ioContext.getGenotypeHandle();
	unsigned int lOldTreeIndex = ioContext.getGenotypeIndex();

	// Loop through each of the trees in the individual
	for (unsigned int i=0; i<size(); i++) {
		GP::Tree::Handle lTree = (*this)[i];
		if (lTree == NULL) {
			Beagle_LogVerboseM(
			    ioContext.getSystem().getLogger(),
			    std::string("Skipping ")+uint2ordinal(i+1)+std::string(" tree because it's NULL-valued")
			);
			continue;
		}

		Beagle_LogVerboseM(
		    ioContext.getSystem().getLogger(),
		    std::string("Validating ")+uint2ordinal(i+1)+std::string(" tree")
		);

		// Store the new values
		ioContext.setGenotypeHandle(lTree);
		ioContext.setGenotypeIndex(i);

		lTree->setContextToNode(0, ioContext);
		if(!lTree->validateSubTree(0, ioContext)) {
			Beagle_LogVerboseM(
			    ioContext.getSystem().getLogger(),
			    std::string("Validation of ")+uint2ordinal(i+1)+std::string(" tree failed.")
			);
			lResult = false;
			break;
		}
	}

	if(lResult) {
		Beagle_LogVerboseM(
		    ioContext.getSystem().getLogger(),
		    std::string("Individual passed validation testing.")
		);
	}

	// Restore the original values.
	ioContext.setGenotypeHandle(lOldTreeHandle);
	ioContext.setGenotypeIndex(lOldTreeIndex);

	return lResult;
	Beagle_StackTraceEndM();
}
Beispiel #6
0
/*!
 *  \brief Set the value of the named GP primitive of the primitive sets.
 *  \param inName Name of the variable to set.
 *  \param inValue Value of the primitive.
 *  \param ioContext Context of the evaluation.
 *  \throw Beagle::RunTimeException If the named primitive is not found in any sets.
 */
void Coev::GPEvaluationOp::setValue(std::string inName,
                                    const Object& inValue,
                                    GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	GP::PrimitiveSuperSet::Handle lSuperSet =
	    castHandleT<GP::PrimitiveSuperSet>(ioContext.getSystem().getComponent("GP-PrimitiveSuperSet"));
	if(lSuperSet == NULL) {
		throw Beagle_RunTimeExceptionM("There should be a GP::PrimitiveSuperSet component in the system");
	}
	bool lValueFound = false;
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    std::string("Setting the primitives named '")+inName+
	    std::string("' to the value: ")+inValue.serialize()
	);
	for(unsigned int i=0; i<lSuperSet->size(); i++) {
		GP::Primitive::Handle lPrimitive = (*lSuperSet)[i]->getPrimitiveByName(inName);
		if(!lPrimitive) continue;
		lValueFound = true;
		lPrimitive->setValue(inValue);
	}
	if(lValueFound == false) {
		std::string lMessage = "The primitive named '";
		lMessage += inName;
		lMessage += "' was not found in any ";
		lMessage += "of the primitive sets. Maybe the primitive was not properly inserted ";
		lMessage += "or the name is mispelled.";
		throw Beagle_RunTimeExceptionM(lMessage);
	}
	Beagle_StackTraceEndM();
}
/*!
 *  \brief  Generate a new random ephemeral Double constant between [-1,1].
 *  \param  inName Name of the constant.
 *  \param  ioContext Context to use to generate the value.
 *  \return Handle to the ephemeral Double constant generated.
 */
GP::Primitive::Handle EphemeralDoubleWide::generate(Beagle::string inName, GP::Context& ioContext)
{
  Beagle_StackTraceBeginM();
  double factor = ioContext.getSystem().getRandomizer().rollUniform(-1.,1.);
  double exp = ioContext.getSystem().getRandomizer().rollUniform(-4.,3.);
  Double::Handle lValue = new Double(factor*pow(10, exp));
  return new EphemeralDoubleWide(lValue, inName);
  Beagle_StackTraceEndM("GP::Primitive::Handle SinsGP::EphemeralDoubleWide::generate(string inName, GP::Context& ioContext)");
}
Beispiel #8
0
/*!
 *  \brief Interpret the GP individual.
 *  \param outResult Datum containing the result of the interpretation.
 *  \param ioContext GP evolutionary context.
 *  \throw Beagle::ObjectException When individual or tree are empty.
 *  \throw Beagle::AssertException When context is not correctly set.
 *  \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed.
 *  \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed.
 */
void GP::Individual::run(GP::Datum& outResult, GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	if(&ioContext.getIndividual() != this) {
		std::ostringstream lOSS;
		lOSS << "In GP::Individual::run():  For the given context, ";
		lOSS << "getIndividual() did not return the same individual as was passed to this (run) ";
		lOSS << "method. Consider setting the context's individual to be the same by using the ";
		lOSS << "method Context::setIndividualHandle().";
		throw Beagle_RunTimeExceptionM(lOSS.str());
	}
	if(empty()) throw Beagle_ObjectExceptionM("Could not interpret, individual has no trees!");
	if((*this)[0]->empty()) throw Beagle_ObjectExceptionM("Could not interpret, 1st tree is empty!");
	Tree::Handle lOldTreeHandle = ioContext.getGenotypeHandle();
	unsigned int lOldTreeIndex  = ioContext.getGenotypeIndex();
	ioContext.setGenotypeIndex(0);
	ioContext.setGenotypeHandle((*this)[0]);
	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    std::string("Running the ")+uint2ordinal(ioContext.getIndividualIndex()+1)+
	    std::string(" individual")
	);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    std::string("The individual is: ")
	);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    (*this)
	);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    std::string("Executing the first tree root node '")+
	    (*(*this)[0])[0].mPrimitive->getName()+"'"
	);
	ioContext.setNodesExecutionCount(0);
	ioContext.incrementNodesExecuted();
	ioContext.getExecutionTimer().reset();
	ioContext.pushCallStack(0);
	(*(*this)[0])[0].mPrimitive->execute(outResult, ioContext);
	ioContext.popCallStack();
	ioContext.checkExecutionTime();
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    std::string("Result of executing the ")+uint2ordinal(ioContext.getIndividualIndex()+1)+
	    std::string(" individual: ")+outResult.serialize()
	);
	ioContext.setGenotypeIndex(lOldTreeIndex);
	ioContext.setGenotypeHandle(lOldTreeHandle);
	Beagle_StackTraceEndM();
}
Beispiel #9
0
/*!
 *  \brief Execute argument primitive.
 *  \param outResult Result containing value of argument.
 *  \param ioContext Evolutionary context.
 */
void GP::Argument::execute(GP::Datum& outResult, GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "evaluation", "Beagle::GP::Argument",
	    std::string("Executing the ")+uint2ordinal(mIndex+1)+" argument"
	);
	switch (mSharedData->mEvalMode) {
	case ePreCompute:
		// The result of evaluating the argument has already been calculated.
		Beagle_AssertM(mIndex < mSharedData->mCaches.back()->size());
		mSharedData->mTypeAllocator->copy(outResult, *(*mSharedData->mCaches.back())[mIndex]);
		break;
	case eJustInTime:
		// Evaluate the argument because we're not caching them.
		forceEvaluation(outResult, ioContext);
		break;
	case eCaching:
		// Check first if the argument has been evaluated (i.e. is it in the cache?)
		// If it has been evaluated then get it from the cache; otherwise evaluate it.
		Beagle_AssertM(mIndex < mSharedData->mCaches.back()->size());
		if((*mSharedData->mCaches.back())[mIndex]!=NULL) {
			Beagle_LogDebugM(
			    ioContext.getSystem().getLogger(),
			    "evaluation", "Beagle::GP::Argument",
			    "Getting result from the cache"
			);
			mSharedData->mTypeAllocator->copy(outResult, *(*mSharedData->mCaches.back())[mIndex]);
		} else {
			Object::Bag::Handle lCurrentCache = mSharedData->mCaches.back();
			mSharedData->mCaches.pop_back();
			forceEvaluation(outResult, ioContext);
			mSharedData->mCaches.push_back(lCurrentCache);
			(*lCurrentCache)[mIndex] = mSharedData->mTypeAllocator->clone(outResult);
			Beagle_LogDebugM(
			    ioContext.getSystem().getLogger(),
			    "evaluation", "Beagle::GP::Argument",
			    "Result added to cache"
			);
		}
		break;
	default:
		throw Beagle_InternalExceptionM(std::string("Undefined evaluation mode (")+
		                                uint2str(mSharedData->mEvalMode)+std::string(") for arguments!"));
	}

	Beagle_StackTraceEndM();
}
/*!
 *  \brief Initialize a constrained GP tree of a specified depth using the "full" approach.
 *  \param outTree Tree to initialize.
 *  \param inMinDepth Minimum depth to make tree.
 *  \param inMaxDepth Maximum depth to make tree.
 *  \param ioContext Evolutionary context.
 */
unsigned int GP::InitFullConstrainedOp::initTree(GP::Tree& outTree,
        unsigned int inMinDepth,
        unsigned int inMaxDepth,
        GP::Context &ioContext) const
{
	Beagle_StackTraceBeginM();

	const unsigned int lDepth = inMaxDepth;
	Beagle_AssertM(lDepth>0);

	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    "initialization", "Beagle::GP::InitFullConstrainedOp",
	    std::string("Using the constrained \'full\' method (with depth ")+
	    uint2str(lDepth)+std::string(") to initialize the ")+
	    uint2ordinal(ioContext.getGenotypeIndex()+1)+std::string(" tree.")
	);

	unsigned int lSubTreeSize;
	do {
		lSubTreeSize = initConstrainedSubTreeFull(outTree, lDepth, ioContext);
	} while (lSubTreeSize == 0);
	return lSubTreeSize;
	Beagle_StackTraceEndM("unsigned int GP::InitFullConstrainedOp::initTree(GP::Tree& outTree, unsigned int inMinDepth, unsigned int inMaxDepth, GP::Context &ioContext) const");
}
Beispiel #11
0
/*!
 *  \brief Return indices of the trees that can be invoked by the module.
 *  \param outCandidates Indices of tree that can be selected as invokable in the actual context.
 *  \param inNumberArguments Number of arguments for which the selection is desired.
 *  \param ioContext Evolutionary context.
 */
void GP::Module::getCandidatesToInvoke(std::vector<unsigned int>& outCandidates,
                                       unsigned int inNumberArguments,
                                       GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	outCandidates.clear();
	for(unsigned int i=0; i<ioContext.getCallStackSize(); ++i) {
		if(ioContext.getGenotype()[ioContext.getCallStackElement(i)].mPrimitive->getName() == getName())
			return;
	}
	Component::Handle lComponent = ioContext.getSystem().getComponent("ModuleVector");
	GP::ModuleVectorComponent::Handle lModVector =
	    castHandleT<GP::ModuleVectorComponent>(lComponent);
	if(lModVector==NULL) {
		throw Beagle_RunTimeExceptionM(std::string("GP system is not configured with a module vector. ")+
		                               std::string("Consider adding a GP::ModuleVectorComponent object to the system."));
	}
	for(unsigned int i=0; i<lModVector->size(); ++i) {
		if((*lModVector)[i]==NULL) continue;
		const unsigned int lNbArgsTree = (*lModVector)[i]->getNumberArguments();
		if(inNumberArguments == GP::Primitive::eAny) outCandidates.push_back(i);
		else if((inNumberArguments==GP::Primitive::eBranch) && (lNbArgsTree>0))
			outCandidates.push_back(i);
		else if(inNumberArguments == lNbArgsTree) outCandidates.push_back(i);
	}
	Beagle_StackTraceEndM();
}
Beispiel #12
0
/*!
 *  \brief Randomly select a node from a specific tree in the individual.
 *  \return Randomly selected tree
 *
 *  Each node has an equal probability of being selected.
 */
unsigned int GP::Individual::chooseRandomNode(unsigned int inTree, GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	Beagle_AssertM(operator[](inTree)->size()!=0);
	return ioContext.getSystem().getRandomizer().rollInteger(0, operator[](inTree)->size()-1);
	Beagle_StackTraceEndM();
}
Beispiel #13
0
/*!
 *  \brief Randomly select a node that takes arguments from a specific
 *    tree in the individual.
 *  \return Randomly selected tree
 */
unsigned int GP::Individual::chooseRandomNodeWithArgs(unsigned int inTree,
        GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	const GP::Tree& lTree = *(operator[](inTree));
	unsigned int lSize = lTree.size();
	if (lSize < 2) {
		std::ostringstream lOSS;
		lOSS << "In GP::Individual::chooseRandomNodeWithArgs(): ";
		lOSS << "Could not choose a node with arguments because the specified tree has fewer ";
		lOSS << "than two (" << lSize << ") nodes, hence there are no such nodes";
		lOSS << " in the tree. This occurred while calling chooseRandomNodeWithArgs() with an ";
		lOSS << "inTree value of " << inTree;
		throw Beagle_RunTimeExceptionM(lOSS.str());
	}

	// Loop through the tree adding appropriate nodes into the roulette
	RouletteT<unsigned int> lRoulette;
	for (unsigned int i=0; i<lSize; i++) {
		if(lTree[i].mSubTreeSize > 1) lRoulette.insert(i);
	}

	// Select node with roulette
	Beagle_AssertM(!lRoulette.empty());
	return lRoulette.select(ioContext.getSystem().getRandomizer());
	Beagle_StackTraceEndM();
}
Beispiel #14
0
/*!
 *  \brief Return a reference to the actual argument.
 *  \param inNumberArguments
 *  \param ioContext Evolutionary context.
 *  \return Handle to argument.
 */
GP::Primitive::Handle GP::Argument::giveReference(unsigned int inNumberArguments, GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	if(mIndex!=eGenerator) return this;
	const unsigned int lTreeNbArgs = ioContext.getGenotype().getNumberArguments();
	Beagle_AssertM(lTreeNbArgs > 0);
	const unsigned int lGenIndex =
	    ioContext.getSystem().getRandomizer().rollInteger(0,(lTreeNbArgs-1));
	return generateArgument(lGenIndex);
	Beagle_StackTraceEndM();
}
Beispiel #15
0
/*!
 *  \brief Initialize a tree.
 *  \param outTree Tree to initialize.
 *  \param inMinDepth Minimum depth to make tree.
 *  \param inMaxDepth Maximum depth to make tree.
 *  \param ioContext Evolution context.
 *  \return Size of newly initialized tree.
 */
unsigned int GP::InitHalfOp::initTree(GP::Tree &outTree,
                                      unsigned int inMinDepth,
                                      unsigned int inMaxDepth,
                                      GP::Context &ioContext) const
{
	Beagle_StackTraceBeginM();
	if(ioContext.getSystem().getRandomizer().rollUniform(0.0, 1.0) < 0.5)
		return mInitFullOp.initTree(outTree, inMinDepth, inMaxDepth, ioContext);
	return mInitGrowOp.initTree(outTree, inMinDepth, inMaxDepth, ioContext);
	Beagle_StackTraceEndM();
}
Beispiel #16
0
/*!
 *  \brief Randomly select a tree from the individual.
 *  \return Randomly selected tree
 *
 *  The selection is biased towards trees with a greater number of nodes
 *  (i.e. each node has an equal probability of being selected).
 */
unsigned int GP::Individual::chooseRandomTree(GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	unsigned int lChosenNode = ioContext.getSystem().getRandomizer().rollInteger(0, getTotalNodes()-1);
	unsigned int lChosenTree = 0;
	for(; (lChosenTree+1)<size(); lChosenTree++) {
		if(lChosenNode < (*this)[lChosenTree]->size()) break;
		else lChosenNode -= (*this)[lChosenTree]->size();
	}
	return lChosenTree;
	Beagle_StackTraceEndM();
}
Beispiel #17
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();
}
Beispiel #18
0
/*!
 *  \brief Validate the ADF position in the tree.
 *  \param ioContext Evolutionary context.
 *  \return True if the ADF is correctly positioned, false if not.
 *  \throw Beagle::AssertException If the context is in a bad state.
 */
bool GP::ADF::validate(GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	if(mIndex <= ioContext.getGenotypeIndex()) {
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "validation","Beagle::GP::ADF::validate",
		    std::string("Validation failed because the ADF's index (")+uint2str(mIndex)+
		    ") is less than or equal to the genotype index ("+uint2str(ioContext.getGenotypeIndex())+")"
		);
		return false;
	}
	if(mIndex >= ioContext.getIndividual().size()) {
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "validation","Beagle::GP::ADF::validate",
		    std::string("Validation failed because the ADF's index (")+uint2str(mIndex)+
		    ") is greater than or equal to the individual's size ("+
		    uint2str(ioContext.getIndividual().size())+")"
		);
		return false;
	}
	if(ioContext.getIndividual()[mIndex]->getNumberArguments() != getNumberArguments()) {
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "validation","Beagle::GP::ADF::validate",
		    std::string("Validation failed because the number of arguments for the tree (")+
		    uint2str(ioContext.getIndividual()[mIndex]->getNumberArguments())+
		    ") differed from the number of arguments for the primitive ("+
		    uint2str(getNumberArguments())+")"
		);
		return false;
	}
	return GP::Primitive::validate(ioContext);
	Beagle_StackTraceEndM("bool GP::ADF::validate(GP::Context& ioContext) const");
}
Beispiel #19
0
/*!
 *  \brief Get reference the tree to invoke.
 *  \param ioContext Evolutionary context.
 *  \return Handle to the invoked tree.
 */
GP::Tree::Handle GP::Module::getInvokedTree(GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	Component::Handle lComponent = ioContext.getSystem().getComponent("ModuleVector");
	GP::ModuleVectorComponent::Handle lModVector =
	    castHandleT<GP::ModuleVectorComponent>(lComponent);
	if(lModVector==NULL) {
		throw Beagle_RunTimeExceptionM(std::string("GP system is not configured with a module vector. ")+
		                               std::string("Consider adding a GP::ModuleVectorComponent object to the system."));
	}
	Beagle_AssertM(mIndex < lModVector->size());
	Beagle_AssertM((*lModVector)[mIndex] != NULL);
	return (*lModVector)[mIndex];
	Beagle_StackTraceEndM();
}
Beispiel #20
0
/*!
 *  \brief Randomly select a node that takes no argument from a specific
 *    tree in the individual.
 *  \return Randomly selected tree
 */
unsigned int GP::Individual::chooseRandomNodeWithoutArgs(unsigned int inTree,
        GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	// Loop through the tree adding appropriate nodes into the roulette
	unsigned int lSize = operator[](inTree)->size();
	RouletteT<unsigned int> lRoulette;
	for (unsigned int i=0; i<lSize; i++) {
		if (operator[](inTree)->operator[](i).mSubTreeSize == 1) {
			lRoulette.insert(i);
		}
	}
	// Select node with roulette
	Beagle_AssertM(!lRoulette.empty());
	return lRoulette.select(ioContext.getSystem().getRandomizer());
	Beagle_StackTraceEndM();
}
Beispiel #21
0
/*!
 *  \brief Generate a new Module primitive from the given specifications.
 *  \param inIndex Tree index for which the primitive is created.
 *  \param inName Name of the primitive generated.
 *  \param inArgsName Name of the arguments associated to the invoker created.
 *  \param ioContext Evolutionary context.
 */
GP::Invoker::Handle GP::Module::generateInvoker(unsigned int inIndex,
        std::string inName,
        std::string inArgsName,
        GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	Component::Handle lComponent = ioContext.getSystem().getComponent("ModuleVector");
	GP::ModuleVectorComponent::Handle lModVector =
	    castHandleT<GP::ModuleVectorComponent>(lComponent);
	if(lModVector==NULL) {
		throw Beagle_RunTimeExceptionM(std::string("GP system is not configured with a module vector. ")+
		                               std::string("Consider adding a GP::ModuleVectorComponent object to the system."));
	}
	GP::Tree::Handle lTree = (*lModVector)[inIndex];
	Beagle_AssertM(lTree != NULL);
	return new GP::Module(inIndex, lTree->getNumberArguments(), inName, inArgsName);
	Beagle_StackTraceEndM();
}
Beispiel #22
0
/*!
 *  \brief Validate the module position in the tree.
 *  \param ioContext Evolutionary context.
 *  \return True if the module is correctly positioned, false if not.
 *  \throw Beagle::AssertException If the context is in a bad state.
 */
bool GP::Module::validate(GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	for(unsigned int i=0; i<ioContext.getCallStackSize(); ++i) {
		if(ioContext.getGenotype()[ioContext.getCallStackElement(i)].mPrimitive->getName() == getName())
			return false;
	}
	Component::Handle lComponent = ioContext.getSystem().getComponent("ModuleVector");
	GP::ModuleVectorComponent::Handle lModVector =
	    castHandleT<GP::ModuleVectorComponent>(lComponent);
	if(lModVector==NULL) {
		throw Beagle_RunTimeExceptionM(std::string("GP system is not configured with a module vector. ")+
		                               std::string("Consider adding a GP::ModuleVectorComponent object to the system."));
	}
	Beagle_AssertM((*lModVector)[mIndex]!=NULL);
	if((*lModVector)[mIndex]->getNumberArguments() != getNumberArguments()) return false;
	return GP::Primitive::validate(ioContext);
	Beagle_StackTraceEndM();
}
/*!
 *  \brief Return a reference of the ADF primitive.
 *  \param inNumberArguments Number of arguments asked for the reference.
 *  \param ioContext Evolutionary context.
 *  \return Handle to the reference generated.
 */
GP::Primitive::Handle GP::Invoker::giveReference(unsigned int inNumberArguments,
        GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	// If not an invoker, return this directly.
	if(mIndex!=eGenerator) return this;

	// Generate new invoker.
	std::vector<unsigned int> lCandidates;
	getCandidatesToInvoke(lCandidates, inNumberArguments, ioContext);

	unsigned int lIndex = UINT_MAX;
	if(lCandidates.size() > 0) {
		lIndex = lCandidates[ioContext.getSystem().getRandomizer().rollInteger(0,lCandidates.size()-1)];
	}
	Handle lGeneratedInvoker = generateInvoker(lIndex, getName(), mArgsName, ioContext);

	// Return newly generated invoker.
	return lGeneratedInvoker;
	Beagle_StackTraceEndM("GP::Primitive::Handle GP::Invoker::giveReference(unsigned int inNumberArguments, GP::Context& ioContext)");
}
Beispiel #24
0
void GP::Argument::forceEvaluation(GP::Datum& outResult, GP::Context& ioContext)
{
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "evaluation", "Beagle::GP::Argument",
	    std::string("Evaluating the ")+uint2ordinal(mIndex+1)+" argument"
	);

	GP::Context::Handle lActualContext = mSharedData->mEvalContext.back();
	mSharedData->mEvalContext.pop_back();
	lActualContext->setAllowedNodesExecution(ioContext.getAllowedNodesExecution());
	lActualContext->setAllowedExecutionTime(ioContext.getAllowedExecutionTime());
	lActualContext->setNodesExecutionCount(ioContext.getNodesExecutionCount());
	lActualContext->getExecutionTimer() = ioContext.getExecutionTimer();
	getArgument(mIndex, outResult, *lActualContext);
	ioContext.getExecutionTimer() = lActualContext->getExecutionTimer();
	ioContext.setNodesExecutionCount(lActualContext->getNodesExecutionCount());
	ioContext.setAllowedExecutionTime(lActualContext->getAllowedExecutionTime());
	ioContext.setAllowedNodesExecution(lActualContext->getAllowedNodesExecution());
	mSharedData->mEvalContext.push_back(lActualContext);
}
/*!
 *  \brief Select a node for mating in the given individual, following the constraints penalties.
 *  \param outSelectTreeIndex Tree index of the selected node.
 *  \param outSelectNodeIndex Index of the selected node.
 *  \param inSelectABranch True if node to select must be a branch, false if it must a leaf.
 *  \param inNodeReturnType Desired return type for the nodes to be selected.
 *  \param inPrimitSetIndex Primitive set index to which the tree must be associated.
 *  \param inMaxSubTreeDepth Maximum sub tree depth allowed of the node to be selected.
 *  \param inMaxSubTreeSize Maximum sub tree size allowed of the node to be selected.
 *  \param inIndividual Individual to select the node from.
 *  \param ioContext Evolutionary context.
 *  \return True if there was node to select, false if no node respected all constraints.
 */
bool STGP::CrossoverConstrainedOp::selectNodeToMateWithType(unsigned int& outSelectTreeIndex,
        unsigned int& outSelectNodeIndex,
        bool inSelectABranch,
        const std::type_info* inNodeReturnType,
        unsigned int inPrimitSetIndex,
        unsigned int inMaxSubTreeDepth,
        unsigned int inMaxSubTreeSize,
        GP::Individual& inIndividual,
        GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	RouletteT< std::pair<unsigned int,unsigned int> > lRoulette;
	GP::Tree::Handle lOldTreeHandle = ioContext.getGenotypeHandle();
	const unsigned int lOldTreeIndex = ioContext.getGenotypeIndex();
	ioContext.emptyCallStack();
	for(unsigned int i=0; i<inIndividual.size(); ++i) {
		if(inIndividual[i]->getPrimitiveSetIndex() != inPrimitSetIndex) continue;
		ioContext.setGenotypeHandle(inIndividual[i]);
		ioContext.setGenotypeIndex(i);
		buildRouletteWithType(lRoulette,
		                      inSelectABranch,
		                      inNodeReturnType,
		                      inMaxSubTreeDepth,
		                      inMaxSubTreeSize,
		                      0,
		                      *inIndividual[i],
		                      ioContext);
	}
	ioContext.setGenotypeIndex(lOldTreeIndex);
	ioContext.setGenotypeHandle(lOldTreeHandle);
	if(lRoulette.size() == 0) return false;
	std::pair<unsigned int,unsigned int> lSelectedNode =
	    lRoulette.select(ioContext.getSystem().getRandomizer());
	outSelectTreeIndex = lSelectedNode.first;
	outSelectNodeIndex = lSelectedNode.second;
	return true;
	Beagle_StackTraceEndM();
}
/*!
 *  \brief Evaluate the individual fitness.
 *  \param inIndividual Individual to evaluate.
 *  \param ioContext Evolutionary context.
 *  \return Handle to the fitness measure.
 */
Fitness::Handle SharedLibEvalOp::evaluate(GP::Individual& inIndividual, GP::Context& ioContext)
{
    Beagle_StackTraceBeginM();

    std::ostringstream lOSS;
    lOSS << "Evaluating individual " << ioContext.getIndividualIndex() << ", deme ";
    lOSS << ioContext.getDemeIndex() << ", generation " << ioContext.getGeneration(); 
    Beagle_LogDebugM(ioContext.getSystem().getLogger(), "evaluate", "Beagle::GP::SpamebaseEvalOp", lOSS.str());

    GP::PrimitiveSuperSet::Handle lPrimitiveSuperSet= 
        castHandleT<GP::PrimitiveSuperSet>(ioContext.getSystem().getComponent("GP-PrimitiveSuperSet"));
    GP::PrimitiveSet::Handle lPrimitiveSet= (*lPrimitiveSuperSet)[0];

    // Get a handle on the shared library used for evaluation.
    // TODO: Open shared lib only once per generation!
    this->mTimer.reset();
    if (this->mSharedLibHandle)
    {
        dlclose(this->mSharedLibHandle);
        Beagle_LogDebugM(
            ioContext.getSystem().getLogger(), "evaluate", "Beagle::GP::SpamebaseEvalOp", 
            "Closed previously opened shared lib.");
    }
    if (!ioContext.getSystem().getRegister().isRegistered("icu.compiler.lib-path"))
    {
        throw Beagle_RunTimeExceptionM("Parameter icu.compiler.lib-path not found in registry; make sure to apply SharedLibCompilerOp before applying SharedLibEvalOp.");    
    }
    std::string lLibName= castHandleT<String>(ioContext.getSystem().getRegister()["icu.compiler.lib-path"])->getWrappedValue();
    this->mSharedLibHandle= dlopen((const char*)lLibName.c_str(), RTLD_LAZY);
    if (!this->mSharedLibHandle) 
    {
        throw Beagle_RunTimeExceptionM("Cannot open shared library "+ lLibName+ ": "+ dlerror()+ ".");
    }
    dlerror();

    // Draw a sample from the data set to construct the training set.
    
    this->mTimer.reset();
	// Get a handle on D, S, and L.
    DataSetBinaryClassification::Handle lDataSet= castHandleT<DataSetBinaryClassification>(ioContext.getSystem().getComponent("DataSet"));
    std::vector<unsigned int>* lIndexesPositives= lDataSet->getIndexesPositives();
    std::vector<unsigned int>* lIndexesNegatives= lDataSet->getIndexesNegatives();
    int lNrSamplesPositive= castHandleT<Int>(ioContext.getSystem().getRegister()["icu.trainingset.size-pos"])->getWrappedValue();
    int lNrSamplesNegative= castHandleT<Int>(ioContext.getSystem().getRegister()["icu.trainingset.size-neg"])->getWrappedValue();
    
    // Shuffle both negative and positive indexes.
    std::random_shuffle(lIndexesPositives->begin(), lIndexesPositives->end(), ioContext.getSystem().getRandomizer());
    std::random_shuffle(lIndexesNegatives->begin(), lIndexesNegatives->end(), ioContext.getSystem().getRandomizer());
    
    // Nr of columns in each row in the dataset.
    int lNrColumns= castHandleT<Int>(ioContext.getSystem().getRegister()["icu.dataset.columns"])->getWrappedValue();
    
    double lTimeInit= this->mTimer.getValue();
    this->mTimer.reset();

    // Evaluate sampled test cases
    unsigned int lTruePositives = 0;
    unsigned int lTrueNegatives = 0;
    unsigned int lFalsePositives= 0;
    unsigned int lFalseNegatives= 0;
    int (*apply_individual)(float[])= 0;
    float lValues[lNrColumns];
    std::vector<unsigned int>::iterator lLastIndex= lIndexesPositives->begin()+ lNrSamplesPositive;


    // Positives.
    for(std::vector<unsigned int>::const_iterator lIndex=lIndexesPositives->begin(); lIndex!=lLastIndex; ++lIndex)
    {
        const Beagle::Vector& lData = (*lDataSet)[*lIndex].second;
        std::ostringstream lFunctionName;
        lFunctionName << "apply_individual_";
        lFunctionName << ioContext.getGeneration() << "_" << ioContext.getDemeIndex() << "_" << ioContext.getIndividualIndex();
        apply_individual= (int(*)(float*))dlsym(this->mSharedLibHandle, lFunctionName.str().c_str());
        char* lError= 0;
        if ((lError = dlerror()) != NULL) {
            throw Beagle_RunTimeExceptionM("Error loading function "+ lFunctionName.str()+ ": "+ lError+ ".");
        }
        for(unsigned int j=0; j<lData.size(); ++j) {
            lValues[j]= Float(lData[j]);
        }		
        bool lResult= apply_individual(lValues);
        (lResult == 1) ? lTruePositives++ : lFalseNegatives++;
    }
    // Negatives.
    lLastIndex= lIndexesNegatives->begin()+ lNrSamplesNegative;
    for(std::vector<unsigned int>::const_iterator lIndex=lIndexesNegatives->begin(); lIndex!=lLastIndex; ++lIndex)
    {
        const Beagle::Vector& lData = (*lDataSet)[*lIndex].second;
        std::ostringstream lFunctionName;
        lFunctionName << "apply_individual_";
        lFunctionName << ioContext.getGeneration() << "_" << ioContext.getDemeIndex() << "_" << ioContext.getIndividualIndex();
        apply_individual= (int(*)(float*))dlsym(this->mSharedLibHandle, lFunctionName.str().c_str());
        char* lError= 0;
        if ((lError = dlerror()) != NULL) {
            throw Beagle_RunTimeExceptionM("Error loading function "+ lFunctionName.str()+ ": "+ lError+ ".");
        }
        for(unsigned int j=0; j<lData.size(); ++j) {
            lValues[j]= Float(lData[j]);
        }		
        bool lResult= apply_individual(lValues);
        (lResult == 0) ? lTrueNegatives++ : lFalsePositives++;
    }


    double lTimeEvaluate= this->mTimer.getValue();

    {
        using namespace std;
        ostringstream lOSS;
        lOSS << "g" << ioContext.getGeneration();
        lOSS << " d" << ioContext.getDemeIndex();
        lOSS << " i" << ioContext.getIndividualIndex() << ", ";
        lOSS << "TP|FP|FN|TN = ";
        lOSS.width(7);
        lOSS << right << lTruePositives << "|";
        lOSS.width(7);
        lOSS << right << lFalsePositives << "|";
        lOSS.width(7);
        lOSS << right << lFalseNegatives << "|";
        lOSS.width(7);
        lOSS << right << lTrueNegatives;
        Beagle_LogDetailedM(ioContext.getSystem().getLogger(), "evaluate", "Beagle::GP::SharedLibEvalOp", lOSS.str());
    }

    GP::FitnessMCC* fitness= new GP::FitnessMCC(lTruePositives, lFalsePositives, lTrueNegatives, lFalseNegatives);

    return fitness;

    Beagle_StackTraceEndM("SharedLibEvalOp::evaluate(GP::Individual& inIndividual, GP::Context& ioContext)");
}
Beispiel #27
0
/*!
 *  \brief Expand given module of a GP tree.
 *  \param inNodeToExpand Index of node to expand in GP tree.
 *  \param ioTree Tree from which module will be expanded.
 *  \param ioContext Evolutionary context.
 */
void GP::ModuleExpandOp::expand(unsigned int inNodeToExpand,
                                GP::Tree& ioTree,
                                GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	// Log tree before expansion.
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "Tree before expansion"
	);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    ioTree
	);

	// Get the module index and reference.
	Module::Handle lModuleInstance = castHandleT<Module>(ioTree[inNodeToExpand].mPrimitive);
	unsigned int lModuleIndex = lModuleInstance->getIndex();
	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    std::string("Expanding ")+uint2ordinal(lModuleIndex+1)+
	    std::string(" module (called from ")+uint2ordinal(inNodeToExpand+1)+
	    std::string(" node of the tree)")
	);
	ModuleVectorComponent::Handle lModuleVectorComponent =
	    castHandleT<ModuleVectorComponent>(ioContext.getSystem().getComponent("ModuleVector"));
	if(lModuleVectorComponent==NULL) {
		throw Beagle_RunTimeExceptionM(std::string("GP system is not configured with a module vector. ")+
		                               std::string("Consider adding a GP::ModuleVectorComponent object to the system."));
	}
	Beagle::GP::Tree::Handle lModule = (*lModuleVectorComponent)[lModuleIndex];
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    *lModule
	);

	// Generate new tree.
	const Factory& lFactory = ioContext.getSystem().getFactory();
	GP::Tree::Alloc::Handle lTreeAlloc =
		castHandleT<GP::Tree::Alloc>(lFactory.getConceptAllocator("Genotype"));
	GP::Tree::Handle lNewTree = castHandleT<GP::Tree>(lTreeAlloc->allocate());
	std::string lArgName = lModuleInstance->getArgsName();
	ioTree.setContextToNode(inNodeToExpand, ioContext);
	for(unsigned int i=0; i<lModule->size(); ++i) {
		if((*lModule)[i].mPrimitive->getName() != lArgName) {
			lNewTree->push_back(GP::Node((*lModule)[i].mPrimitive));
		} else {
			GP::Argument::Handle lArg = castHandleT<GP::Argument>((*lModule)[i].mPrimitive);
			const unsigned int lChildIndex =
			    ioTree[inNodeToExpand].mPrimitive->getChildrenNodeIndex(lArg->getIndex(), ioContext);
			lNewTree->insert(lNewTree->end(), ioTree.begin()+lChildIndex,
			                 ioTree.begin()+lChildIndex+ioTree[lChildIndex].mSubTreeSize);
		}
	}
	ioTree.erase(ioTree.begin()+inNodeToExpand,
	             ioTree.begin()+inNodeToExpand+ioTree[inNodeToExpand].mSubTreeSize);
	ioTree.insert(ioTree.begin()+inNodeToExpand, lNewTree->begin(), lNewTree->end());
	ioTree.fixSubTreeSize();

	// Log results.
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "Tree after expansion"
	);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    ioTree
	);
	
	Beagle_StackTraceEndM();
}
/*!
 *  \brief Initialize a GP constrained sub-tree of a specified depth using the "full" approach.
 *  \param ioTree Tree containing the sub-tree to initialize.
 *  \param inSubTreeDepth Depth of the sub-tree to initialize.
 *  \param ioContext Evolutionary context.
 *  \return Generated sub-tree size.
 */
unsigned int GP::InitFullConstrainedOp::initConstrainedSubTreeFull(GP::Tree& ioTree,
        unsigned int inSubTreeDepth,
        GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	Beagle_AssertM(inSubTreeDepth>0);

	GP::PrimitiveSet& lPrimitSet = ioTree.getPrimitiveSet(ioContext);
	GP::Primitive::Handle lPrimit = NULL;
	const unsigned int lNodeIndex = ioTree.size();
	for(unsigned int lAttempt=0; lAttempt < mNumberAttempts->getWrappedValue(); ++lAttempt) {
#ifdef BEAGLE_HAVE_RTTI
		const std::type_info* lDesiredType = NULL;
		if(ioTree.size()==0) lDesiredType = ioTree.getRootType(ioContext);
		else {
			const unsigned int lParentIndex = ioContext.getCallStackTop();
			unsigned int lArgsIndexChild = 0;
			for(unsigned int lChildIndex=(lParentIndex+1);
			        lChildIndex!=lNodeIndex; lChildIndex += ioTree[lChildIndex].mSubTreeSize) {
				Beagle_AssertM(lChildIndex <= ioTree.size());
				++lArgsIndexChild;
				Beagle_AssertM(lArgsIndexChild < ioTree[lParentIndex].mPrimitive->getNumberArguments());
			}
			lDesiredType = ioTree[lParentIndex].mPrimitive->getArgType(lArgsIndexChild, ioContext);
		}
		if(inSubTreeDepth == 1) {
			lPrimit = lPrimitSet.selectWithType(GP::Primitive::eTerminal, lDesiredType, ioContext);
			if(!lPrimit) return 0;
			lPrimit = lPrimit->giveReference(GP::Primitive::eTerminal, ioContext);
		} else {
			lPrimit = lPrimitSet.selectWithType(GP::Primitive::eBranch, lDesiredType, ioContext);
			if(!lPrimit) return 0;
			lPrimit = lPrimit->giveReference(GP::Primitive::eBranch, ioContext);
		}
#else // BEAGLE_HAVE_RTTI
		if(inSubTreeDepth == 1) {
			lPrimit = lPrimitSet.select(GP::Primitive::eTerminal, ioContext);
			if(!lPrimit) {
				string lMessage = "There is no leaf (primitive without argument) in the ";
				lMessage += uint2ordinal(ioContext.getGenotypeIndex());
				lMessage += " primitive set!";
				throw Beagle_RunTimeExceptionM(lMessage);
			}
			lPrimit = lPrimit->giveReference(GP::Primitive::eTerminal, ioContext);
		} else {
			lPrimit = lPrimitSet.select(GP::Primitive::eBranch, ioContext);
			if(!lPrimit) {
				string lMessage = "There is no branch (primitive with arguments) in the ";
				lMessage += uint2ordinal(ioContext.getGenotypeIndex());
				lMessage += " primitive set!";
				throw Beagle_RunTimeExceptionM(lMessage);
			}
			lPrimit = lPrimit->giveReference(GP::Primitive::eBranch, ioContext);
		}
#endif // BEAGLE_HAVE_RTTI
		ioTree.push_back(GP::Node(lPrimit, 0));
		ioContext.pushCallStack(lNodeIndex);
		if(lPrimit->validate(ioContext)) {
			unsigned int lSubTreeSize = 1;
			bool lGoodInit = true;
			for(unsigned int i=0; i<lPrimit->getNumberArguments(); i++) {
				unsigned int lArgSubTreeSize =
				    initConstrainedSubTreeFull(ioTree, inSubTreeDepth-1, ioContext);
				if(lArgSubTreeSize == 0) {
					for(unsigned int j=1; j<lSubTreeSize; j++) ioTree.pop_back();
					lGoodInit = false;
					break;
				}
				lSubTreeSize += lArgSubTreeSize;
			}
			if(lGoodInit) {
				ioContext.popCallStack();
				ioTree[lNodeIndex].mSubTreeSize = lSubTreeSize;
				return lSubTreeSize;
			}
		} else {
			Beagle_LogDebugM(
			    ioContext.getSystem().getLogger(),
			    "initialization", "Beagle::GP::InitFullConstrainedOp",
			    "Primitive failed validation testing"
			);
		}
		ioContext.popCallStack();
		ioTree.pop_back();
	}
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "initialization", "Beagle::GP::InitFullConstrainedOp",
	    "Could not correctly initialize this node; backtracking instead."
	);
	return 0; // Could not initialize this node correctly, backtracking instead.
	Beagle_StackTraceEndM("unsigned int GP::InitFullConstrainedOp::initConstrainedSubTreeFull(GP::Tree& ioTree, unsigned int inSubTreeDepth, GP::Context& ioContext) const");
}
/*!
 *  \brief  Generate a new random ephemeral Double constant in [0,100].
 *  \param  inName Name of the constant.
 *  \param  ioContext Context to use to generate the value.
 *  \return Handle to the ephemeral Double constant generated.
 */
GP::Primitive::Handle EphemeralPercent::generate(std::string inName, GP::Context& ioContext)
{
	Double::Handle lValue = new Double(ioContext.getSystem().getRandomizer().rollUniform(0.,100.));
	return new EphemeralPercent(lValue);
}