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