/*! * \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(); }
/*! * \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"); }