/*!
 *  \brief Initialize a GP sub-tree of a specified depth using the "grow" approach.
 *  \param ioTree Tree containing the sub-tree to initialize.
 *  \param inMinDepth Minimal depth of the sub-tree to initialize.
 *  \param inMaxDepth Maximal depth of the sub-tree to initialize.
 *  \param ioContext Evolutionary context.
 *  \return Generated sub-tree size.
 */
unsigned int GP::InitGrowOp::initSubTreeGrow(GP::Tree& ioTree,
        unsigned int inMinDepth,
        unsigned int inMaxDepth,
        GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	Beagle_AssertM(inMaxDepth >= inMinDepth);
	Beagle_AssertM(inMinDepth>0);
	GP::PrimitiveSet& lPrimitSet = ioTree.getPrimitiveSet(ioContext);
	GP::Primitive::Handle lPrimit = NULL;
	if(inMinDepth > 1) {
		lPrimit = lPrimitSet.select(GP::Primitive::eBranch, ioContext);
		if(!lPrimit) {
			std::string lMessage = "There is no branch (primitive with arguments) in the ";
			lMessage += uint2ordinal(ioContext.getGenotypeIndex()+1);
			lMessage += " primitive set!";
			throw Beagle_RunTimeExceptionM(lMessage);
		}
		lPrimit = lPrimit->giveReference(GP::Primitive::eBranch, ioContext);
	} else if(inMaxDepth == 1) {
		lPrimit = lPrimitSet.select(GP::Primitive::eTerminal, ioContext);
		if(!lPrimit) {
			std::string lMessage = "There is no leaf (primitive without argument) in the ";
			lMessage += uint2ordinal(ioContext.getGenotypeIndex()+1);
			lMessage += " primitive set!";
			throw Beagle_RunTimeExceptionM(lMessage);
		}
		lPrimit = lPrimit->giveReference(GP::Primitive::eTerminal, ioContext);
	} else {
		lPrimit = lPrimitSet.select(GP::Primitive::eAny, ioContext);
		if(!lPrimit) {
			std::string lMessage = "There is no primitive in the ";
			lMessage += uint2ordinal(ioContext.getGenotypeIndex()+1);
			lMessage += " primitive set!";
			throw Beagle_RunTimeExceptionM(lMessage);
		}
		lPrimit = lPrimit->giveReference(GP::Primitive::eAny, ioContext);
	}
	unsigned int lNodeIndex = ioTree.size();
	ioTree.push_back(GP::Node(lPrimit, 1));
	unsigned int lSubTreeSize = 1;
	unsigned int lMinDepth = (inMinDepth > 1) ? (inMinDepth-1) : 1;
	for(unsigned int i=0; i<ioTree[lNodeIndex].mPrimitive->getNumberArguments(); i++) {
		lSubTreeSize += initSubTreeGrow(ioTree, lMinDepth, inMaxDepth-1, ioContext);
	}
	ioTree[lNodeIndex].mSubTreeSize = lSubTreeSize;
	return lSubTreeSize;
	Beagle_StackTraceEndM("unsigned int GP::InitGrowOp::initSubTreeGrow(GP::Tree& ioTree, unsigned int inMinDepth, unsigned int inMaxDepth, GP::Context& ioContext) const");
}
/*!
 *  \brief Build a roulette of nodes that can be selected following the constraints penalties.
 *  \param ioRoulette Roulette of nodes that can be selected following the constraints given.
 *  \param inSelectABranch True if node to select must be a branch, false if it must a leaf.
 *  \param inNodeReturnType Desired return type for the nodes to be selected.
 *  \param inMaxSubTreeDepth Maximum sub tree depth allowed of the node to be selected.
 *  \param inMaxSubTreeSize Maximum sub tree size allowed of the node to be selected.
 *  \param inActualIndex Index in actual tree of the node processed.
 *  \param inTree Tree processed.
 *  \param ioContext Evolutionary context.
 *  \return Max depth of subtree processed.
 */
unsigned int STGP::CrossoverConstrainedOp::buildRouletteWithType(
    RouletteT< std::pair<unsigned int,unsigned int> >& ioRoulette,
    bool inSelectABranch,
    const std::type_info* inNodeReturnType,
    unsigned int inMaxSubTreeDepth,
    unsigned int inMaxSubTreeSize,
    unsigned int inActualIndex,
    GP::Tree& inTree,
    GP::Context& ioContext) const
{
	Beagle_StackTraceBeginM();
	const unsigned int lNbArgs = inTree[inActualIndex].mPrimitive->getNumberArguments();
	const unsigned int lSubTreeSize = inTree[inActualIndex].mSubTreeSize;
	const bool lGoodArity = ((inTree.size()==1) || ((lNbArgs==0) != inSelectABranch));
	ioContext.pushCallStack(inActualIndex);
	const std::type_info* lNodeType = inTree[inActualIndex].mPrimitive->getReturnType(ioContext);
	const bool lCompatibleTyping = ((inNodeReturnType==NULL) || (lNodeType==NULL) ||
	                                (inNodeReturnType==lNodeType));
	unsigned int lChildIndex = inActualIndex+1;
	unsigned int lMaxDepthDown = 0;
	for(unsigned int i=0; i<lNbArgs; ++i) {
		unsigned int lChildDepth = buildRouletteWithType(ioRoulette,
		                           inSelectABranch,
		                           inNodeReturnType,
		                           inMaxSubTreeDepth,
		                           inMaxSubTreeSize,
		                           lChildIndex,
		                           inTree,
		                           ioContext);
		lChildIndex += inTree[lChildIndex].mSubTreeSize;
		if(lChildDepth > lMaxDepthDown) lMaxDepthDown = lChildDepth;
	}
	++lMaxDepthDown;
	const unsigned int lMaxDepthUp = ioContext.getCallStackSize();
	ioContext.popCallStack();
	if(lGoodArity && lCompatibleTyping && (lSubTreeSize<=inMaxSubTreeSize) &&
	        (lMaxDepthDown<=inMaxSubTreeDepth) && (lMaxDepthUp<=inMaxSubTreeDepth)) {
		std::pair<unsigned int,unsigned int> lPair(ioContext.getGenotypeIndex(), inActualIndex);
		ioRoulette.insert(lPair, 1.0);
	}
	return lMaxDepthDown;
	Beagle_StackTraceEndM();
}
Example #3
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  Exchange two GP trees on given points.
 *  \param  ioTree1 First tree to mate.
 *  \param  inNode1 Node index of the swap subtree first point.
 *  \param  ioContext1 Evolutionary context relatively to the first tree.
 *  \param  ioTree2 Second tree to mate.
 *  \param  inNode2 Node index of the swap subtree second point.
 *  \param  ioContext2 Evolutionary context relatively to the second tree.
 */
void GP::MutationSwapSubtreeOp::exchangeSubTrees(GP::Tree& ioTree1,
        unsigned int inNode1,
        GP::Context& ioContext1,
        GP::Tree& ioTree2,
        unsigned int inNode2,
        GP::Context& ioContext2)
{
	Beagle_StackTraceBeginM();
	Beagle_AssertM(&ioTree1 != &ioTree2);
	unsigned int lSwapSize1 = ioTree1[inNode1].mSubTreeSize;
	unsigned int lSwapSize2 = ioTree2[inNode2].mSubTreeSize;
	if(lSwapSize1 <= lSwapSize2) {
		std::swap_ranges(ioTree1.begin()+inNode1, ioTree1.begin()+inNode1+lSwapSize1, ioTree2.begin()+inNode2);
		ioTree1.insert(ioTree1.begin()+inNode1+lSwapSize1,
		               ioTree2.begin()+inNode2+lSwapSize1,
		               ioTree2.begin()+inNode2+lSwapSize2);
		ioTree2.erase(ioTree2.begin()+inNode2+lSwapSize1, ioTree2.begin()+inNode2+lSwapSize2);
	} else {
		std::swap_ranges(ioTree1.begin()+inNode1, ioTree1.begin()+inNode1+lSwapSize2, ioTree2.begin()+inNode2);
		ioTree2.insert(ioTree2.begin()+inNode2+lSwapSize2,
		               ioTree1.begin()+inNode1+lSwapSize2,
		               ioTree1.begin()+inNode1+lSwapSize1);
		ioTree1.erase(ioTree1.begin()+inNode1+lSwapSize2, ioTree1.begin()+inNode1+lSwapSize1);
	}
	int lDiffSize = lSwapSize1 - lSwapSize2;
	for(unsigned int i=0; i<(ioContext1.getCallStackSize()-1); i++)
		ioTree1[ioContext1.getCallStackElement(i)].mSubTreeSize -= lDiffSize;
	for(unsigned int j=0; j<(ioContext2.getCallStackSize()-1); j++)
		ioTree2[ioContext2.getCallStackElement(j)].mSubTreeSize += lDiffSize;
	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");
}