/* * Open BEAGLE * Copyright (C) 2001-2005 by Christian Gagne and Marc Parizeau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: * Laboratoire de Vision et Systemes Numeriques * Departement de genie electrique et de genie informatique * Universite Laval, Quebec, Canada, G1K 7P4 * http://vision.gel.ulaval.ca * */ /*! * \file beagle/GP/src/MutationStandardConstrainedOp.cpp * \brief Source code of class GP::MutationStandardConstrainedOp. * \author Christian Gagne * \author Marc Parizeau * $Revision: 1.13 $ * $Date: 2005/10/04 16:25:10 $ */ #include "beagle/GP.hpp" #include #include using namespace Beagle; /*! * \brief Construct a constrained GP tree standard mutation operator. * \param inInitOp Initialization operator used to mutate the GP subtree. * \param inMutationPbName Mutation probability parameter name used in register. * \param inMaxRegenDepthName Maximum regeneration depth in mutation parameter name. * \param inName Name of the operator. */ GP::MutationStandardConstrainedOp::MutationStandardConstrainedOp(GP::InitializationOp::Handle inInitOp, Beagle::string inMutationPbName, Beagle::string inMaxRegenDepthName, Beagle::string inName) : MutationStandardOp(inInitOp, inMutationPbName, inMaxRegenDepthName, inName) { } /*! * \brief Initialize the constrained GP tree standard mutation operator. * \param ioSystem System of the evolution. */ void GP::MutationStandardConstrainedOp::initialize(Beagle::System& ioSystem) { Beagle_StackTraceBeginM(); MutationStandardOp::initialize(ioSystem); if(ioSystem.getRegister().isRegistered("gp.try")) { mNumberAttempts = castHandleT(ioSystem.getRegister()["gp.try"]); } else { mNumberAttempts = new UInt(2); string lLongDescrip = "Maximum number of attempts to modify a GP tree in a genetic "; lLongDescrip += "operation. As there is topological constraints on GP trees (i.e. tree "; lLongDescrip += "depth limit), it is often necessary to try a genetic operation several times."; Register::Description lDescription( "Max number of attempts", "UInt", "2", lLongDescrip ); ioSystem.getRegister().addEntry("gp.try", mNumberAttempts, lDescription); } Beagle_StackTraceEndM("void GP::MutationStandardConstrainedOp::initialize(Beagle::System& ioSystem)"); } /*! * \brief Standard mutate a constrained GP individual. * \param ioIndividual GP individual to standard mutate. * \param ioContext Context of the evolution. * \return True if the individual is effectively mutated, false if not. */ bool GP::MutationStandardConstrainedOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext) { Beagle_StackTraceBeginM(); GP::Individual& lIndividual = castObjectT(ioIndividual); GP::Context& lContext = castObjectT(ioContext); unsigned int lMaxTreeDepth = mMaxTreeDepth->getWrappedValue(); unsigned int lMaxRegenerationDepth = mMaxRegenerationDepth->getWrappedValue(); unsigned int lNbNodes = 0; for(unsigned int i=0; isize(); if(lNbNodes == 0) return false; unsigned int lChoosenNode = lContext.getSystem().getRandomizer().rollInteger(0, lNbNodes-1); unsigned int lChoosenTree = 0; for(; (lChoosenTree+1)size()) break; else lChoosenNode -= lIndividual[lChoosenTree]->size(); } unsigned int lOldGenotypeIndex = lContext.getGenotypeIndex(); GP::Tree::Handle lOldGenotypeHandle = lContext.getGenotypeHandle(); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardConstrainedOp", string("Individual before GP standard mutation: ")+ ioIndividual.serialize() ); GP::Tree::Handle lActualTree = lIndividual[lChoosenTree]; GP::Tree::Handle lNewTree = castHandleT(lIndividual.getTypeAlloc()->allocate()); lNewTree->setPrimitiveSetIndex(lActualTree->getPrimitiveSetIndex()); lNewTree->setNumberArguments(lActualTree->getNumberArguments()); unsigned int lChoosenNodeSubTreeSize = (*lActualTree)[lChoosenNode].mSubTreeSize; lNewTree->insert(lNewTree->end(), lActualTree->begin(), lActualTree->begin()+lChoosenNode); lContext.setGenotypeIndex(lChoosenTree); lContext.setGenotypeHandle(lActualTree); lContext.emptyCallStack(); lActualTree->setContextToNode(lChoosenNode, lContext); lContext.popCallStack(); const unsigned int lMaxSubTreeDepth = minOf(lMaxTreeDepth - lContext.getCallStackSize(), lMaxRegenerationDepth); lIndividual[lChoosenTree] = lNewTree; lContext.setGenotypeHandle(lNewTree); unsigned int lAttempt=0; for(; lAttempt < mNumberAttempts->getWrappedValue(); lAttempt++) { if(mInitOp->initTree(*lNewTree, 1, lMaxSubTreeDepth, lContext) != 0) break; } if(lAttempt == mNumberAttempts->getWrappedValue()) { lIndividual[lChoosenTree] = lActualTree; lContext.setGenotypeIndex(lOldGenotypeIndex); lContext.setGenotypeHandle(lOldGenotypeHandle); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardConstrainedOp", "Unable to GP standard mutate the individual" ); return false; } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), "mutation", "Beagle::GP::MutationStandardConstrainedOp", string("GP standard mutate the ")+uint2ordinal(lChoosenNode+1)+ string(" node of the ")+uint2ordinal(lChoosenTree+1)+ string(" tree with max depth ")+uint2str(lMaxSubTreeDepth) ); lNewTree->insert(lNewTree->end(), lActualTree->begin()+lChoosenNode+lChoosenNodeSubTreeSize, lActualTree->end()); unsigned int lDiffSize = (*lActualTree)[lChoosenNode].mSubTreeSize - (*lNewTree)[lChoosenNode].mSubTreeSize; for(unsigned int l=0; l