예제 #1
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 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 Swap mutate a constrained GP individual.
 *  \param ioIndividual GP individual to swap mutate.
 *  \param ioContext Context of the evolution.
 *  \return True if the individual is effectively mutated, false if not.
 */
bool STGP::MutationSwapConstrainedOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	GP::Individual& lIndividual  = castObjectT<GP::Individual&>(ioIndividual);
	GP::Context& lContext        = castObjectT<GP::Context&>(ioContext);
	double lDistrProba           = mDistributionProba->getWrappedValue();
	unsigned int lNumberAttempts = mNumberAttempts->getWrappedValue();
	bool lMutationDone           = false;

	unsigned int lNbNodes = 0;
	for(unsigned int i=0; i<lIndividual.size(); i++) lNbNodes += lIndividual[i]->size();
	if(lNbNodes == 0) return false;
	unsigned int lChoosenNode = lContext.getSystem().getRandomizer().rollInteger(0, lNbNodes-1);
	unsigned int lChoosenTree = 0;
	for(; (lChoosenTree+1)<lIndividual.size(); lChoosenTree++) {
		if(lChoosenNode < lIndividual[lChoosenTree]->size()) break;
		else lChoosenNode -= lIndividual[lChoosenTree]->size();
	}
	GP::Tree& lTree = *lIndividual[lChoosenTree];
	if(lTree.size() == 0) return false;

	GP::Tree::Handle lOldTreeHandle = lContext.getGenotypeHandle();
	unsigned int lOldTreeIndex = lContext.getGenotypeIndex();
	lContext.setGenotypeHandle(lIndividual[lChoosenTree]);
	lContext.setGenotypeIndex(lChoosenTree);

	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "Individual before constrained GP tree swap mutation"
	);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    ioIndividual
	);

	if(lTree.size() > 1) {
		bool lTypeNode = (lContext.getSystem().getRandomizer().rollUniform(0., 1.) < lDistrProba);
		while((lTree[lChoosenNode].mPrimitive->getNumberArguments() != 0) != lTypeNode) {
			lChoosenNode = lContext.getSystem().getRandomizer().rollInteger(0, lTree.size()-1);
		}
	}
	GP::Primitive::Handle lOriginalPrimitive = lTree[lChoosenNode].mPrimitive;

	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    std::string("Trying to constrained GP tree swap mutate the ")+uint2ordinal(lChoosenNode+1)+
	    std::string(" node (primitive: '")+lOriginalPrimitive->getName()+
	    std::string("' nb args: ")+uint2str(lOriginalPrimitive->getNumberArguments())+
	    std::string(") of the ")+uint2ordinal(lChoosenTree+1)+std::string(" tree")
	);

	GP::PrimitiveSet& lPrimitiveSet = lTree.getPrimitiveSet(lContext);
	unsigned int lNbArgsPrimit = lTree[lChoosenNode].mPrimitive->getNumberArguments();
	lTree.setContextToNode(lChoosenNode, lContext);
	for(unsigned int lAttempt=0; lAttempt < lNumberAttempts; ++lAttempt) {
		GP::Primitive::Handle lChoosenPrimitive = lPrimitiveSet.select(lNbArgsPrimit, lContext);
		if(lChoosenPrimitive==NULL) break;

		lTree[lChoosenNode].mPrimitive = lChoosenPrimitive->giveReference(lNbArgsPrimit, lContext);

		Beagle_LogVerboseM(
		    ioContext.getSystem().getLogger(),
		    std::string("Trying the primitive '")+lChoosenPrimitive->getName()+
		    std::string("'")
		);

		if(lTree.validateSubTree(lChoosenNode, lContext)) {
			lMutationDone = true;
			Beagle_LogVerboseM(
			    ioContext.getSystem().getLogger(),
			    "Constrained GP tree swap mutation valid"
			);
			break;
		} else {
			lTree[lChoosenNode].mPrimitive = lOriginalPrimitive;
			Beagle_LogVerboseM(
			    ioContext.getSystem().getLogger(),
			    "Constrained GP tree swap mutation invalid"
			);
		}
	}

	lContext.setGenotypeHandle(lOldTreeHandle);
	lContext.setGenotypeIndex(lOldTreeIndex);

	if(lMutationDone) {
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "Individual after constrained GP swap mutation"
		);
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    ioIndividual
		);
	} else {
		Beagle_LogVerboseM(
		    ioContext.getSystem().getLogger(),
		    "Unable to swap mutate the constrained individual"
		);
	}

	return lMutationDone;
	Beagle_StackTraceEndM();
}
bool Beagle::GP::MutationEphemeralOpT<T>::mutate(Beagle::Individual& ioIndividual,
        Beagle::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	Beagle_LogDetailedM(
	    ioContext.getSystem().getLogger(),
	    "mutation", "Beagle::GP::MutationEphemeralOpT",
	    std::string("Mutating ")+uint2ordinal(ioContext.getGenotypeIndex()+1)+
	    std::string(" individual with GP::MutationEphemeralOpT")
	);

	GP::Individual& lIndividual = castObjectT<GP::Individual&>(ioIndividual);
	GP::Context& lContext = castObjectT<GP::Context&>(ioContext);

	// Get index of potential primitives with parameters that can be selected for mutation.
	std::vector< std::pair<unsigned int,unsigned int> > lPotentialParam;
	for(unsigned int i=0; i<lIndividual.size(); ++i) {
		GP::Tree& lTree = *lIndividual[i];
		for(unsigned int j=0; j<lTree.size(); ++j) {
			if(lTree[j].mPrimitive->getName() == *mEphemeralName) {
				lPotentialParam.push_back(std::make_pair(i,j));
			}
		}
	}

	// Return if there is not potential parameters.
	if(lPotentialParam.empty()) return false;

	// Mutating a primitive
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "mutation",
	    "Beagle::GP::MutationEphemeralOpT",
	    "Individual before GP parameters mutation"
	);
	Beagle_LogObjectDebugM(
	    ioContext.getSystem().getLogger(),
	    "mutation",
	    "Beagle::GP::MutationEphemeralOpT",
	    ioIndividual
	);

	// Store original context values
	unsigned int lOldGenotypeIndex = lContext.getGenotypeIndex();
	GP::Tree::Handle lOldGenotypeHandle = lContext.getGenotypeHandle();

	// Get reference to primitive to mutate and other objects.
	const unsigned int lSelectedParam =
	    lContext.getSystem().getRandomizer().rollInteger(0,lPotentialParam.size()-1);
	GP::Tree::Handle lSelectedTree = lIndividual[lPotentialParam[lSelectedParam].first];
	lContext.setGenotypeIndex(lPotentialParam[lSelectedParam].first);
	lContext.setGenotypeHandle(lSelectedTree);
	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    "mutation", "Beagle::GP::MutationEphemeralOpT",
	    std::string("Mutating the parameter of the ")+
	    uint2ordinal(lPotentialParam[lSelectedParam].second+1)+
	    std::string(" node in the ")+uint2ordinal(lPotentialParam[lSelectedParam].first+1)+
	    std::string(" tree")
	);

	// Mutate parameter value.
	GP::Primitive::Handle lSelectedPrimit =
	    (*lSelectedTree)[lPotentialParam[lSelectedParam].second].mPrimitive;
	typename GP::EphemeralT<T>::Handle lSelectedEphemeral =
	    castHandleT<typename GP::EphemeralT<T> >(lSelectedPrimit);
	GP::Primitive::Handle lGeneratedPrimit =
	    lSelectedEphemeral->generate(mEphemeralName->getWrappedValue(), lContext);
	(*lSelectedTree)[lPotentialParam[lSelectedParam].second].mPrimitive = lGeneratedPrimit;

	Beagle_LogVerboseM(
	    ioContext.getSystem().getLogger(),
	    "mutation", "Beagle::GP::MutationEphemeralOpT",
	    std::string("Changing the ephemeral from ")+lSelectedPrimit->serialize()+
	    std::string(" to ")+lGeneratedPrimit->serialize()
	);

	// Restore original context values
	lContext.setGenotypeIndex(lOldGenotypeIndex);
	lContext.setGenotypeHandle(lOldGenotypeHandle);

	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "mutation",
	    "Beagle::GP::MutationEphemeralOpT",
	    "Individual after GP parameters mutation"
	);
	Beagle_LogObjectDebugM(
	    ioContext.getSystem().getLogger(),
	    "mutation",
	    "Beagle::GP::MutationEphemeralOpT",
	    ioIndividual
	);

	return true;
	Beagle_StackTraceEndM("bool GP::MutationEphemeralOpT<T>::mutate(Individual& ioIndividual, Context& ioContext)");
}
/*!
 *  \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");
}