mutationswapsubtreeop.cpp

来自「非常好的进化算法EC 实现平台 可以实现多种算法 GA GP」· C++ 代码 · 共 478 行 · 第 1/2 页

CPP
478
字号
/* *  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/MutationSwapSubtreeOp.cpp *  \brief  Source code of class GP::MutationSwapSubtreeOp. *  \author Christian Gagne <cgagne@gmail.com> *  \author Jianjun Hu <hujianju@msu.edu> *  \author Marc Parizeau <parizeau@gel.ulaval.ca> *  $Revision: 1.11 $ *  $Date: 2005/10/04 16:25:10 $ */#include "beagle/GP.hpp"#include <algorithm>#include <string>using namespace Beagle;/*! *  \brief Construct a GP swap subtree mutation operator. *  \param inMutationPbName Mutation probability parameter name used in register. *  \param inDistribPbName Swap mutation distribution probability parameter name. *  \param inName Name of the operator. */GP::MutationSwapSubtreeOp::MutationSwapSubtreeOp(Beagle::string inMutationPbName,                                                 Beagle::string inDistribPbName,                                                 Beagle::string inName) :  Beagle::MutationOp(inMutationPbName, inName),  mDistribPbName(inDistribPbName){ }/*! *  \brief Initialize the GP swap subtree mutation operator. *  \param ioSystem System of the evolution. */void GP::MutationSwapSubtreeOp::initialize(Beagle::System& ioSystem){  Beagle_StackTraceBeginM();  Beagle::MutationOp::initialize(ioSystem);  if(ioSystem.getRegister().isRegistered(mMutationPbName)) {    ioSystem.getRegister().deleteEntry(mMutationPbName);  }  if(ioSystem.getRegister().isRegistered(mMutationPbName)) {    mMutationProba = castHandleT<Float>(ioSystem.getRegister()[mMutationPbName]);  } else {    mMutationProba = new Float(float(0.0));    string lLongDescrip = "Swap subtree mutation probability for an individual. ";    lLongDescrip += "A swap subtree mutation consists to swap two subtrees of a tree in an ";    lLongDescrip += "individual.";    Register::Description lProbaDescription(      "Swap subtree mutation prob.",      "Float",      "0.0",      lLongDescrip    );    ioSystem.getRegister().addEntry(mMutationPbName, mMutationProba, lProbaDescription);  }  if(ioSystem.getRegister().isRegistered(mDistribPbName)) {    mDistributionProba = castHandleT<Float>(ioSystem.getRegister()[mDistribPbName]);  } else {    mDistributionProba = new Float(float(0.5));    string lLongDescrip = "Probability that a swap subtree is internal ";    lLongDescrip += "(the mutation occurs between three points, where the 2nd point is in the ";    lLongDescrip += "1st point's subtree, and the 3rd point is in the 2nd point's subtree) vs ";    lLongDescrip += "being external (the mutation occurs between two points, ";    lLongDescrip += "where both points are not within the other's subtree). ";    lLongDescrip += "Value of 1.0 means that the swap subtrees mutations are all internal ";    lLongDescrip += "while value of 0.0 means that swap subtrees mutations are all external.";    Register::Description lDescription(      "Swap subtree mut. distrib. prob.",      "Float",      "0.5",      lLongDescrip    );    ioSystem.getRegister().addEntry(mDistribPbName, mDistributionProba, lDescription);  }  if(ioSystem.getRegister().isRegistered("gp.tree.maxdepth")) {    mMaxTreeDepth = castHandleT<UInt>(ioSystem.getRegister()["gp.tree.maxdepth"]);  } else {    mMaxTreeDepth = new UInt(17);    Register::Description lDescription(      "Maximum tree depth",      "UInt",      "17",      "Maximum allowed depth for the trees."    );    ioSystem.getRegister().addEntry("gp.tree.maxdepth", mMaxTreeDepth, lDescription);  }  if(ioSystem.getRegister().isRegistered("gp.try")) {    mNumberAttempts = castHandleT<UInt>(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::MutationSwapSubtreeOp::initialize(Beagle::System& ioSystem)");}/*! *  \brief Swap subtree mutate a GP individual. *  \param ioIndividual GP individual to swap subtree mutate. *  \param ioContext Context of the evolution. */bool GP::MutationSwapSubtreeOp::mutate(Beagle::Individual& ioIndividual, Beagle::Context& ioContext){  Beagle_StackTraceBeginM();  // Initial parameters checks.  Beagle_AssertM(ioIndividual.size() > 0);  Beagle_ValidateParameterM(mNumberAttempts->getWrappedValue()>0, "gp.try", ">0");  // Cast method arguments.  GP::Individual&     lGPIndiv      = castObjectT<GP::Individual&>(ioIndividual);  GP::Context&        lContext1     = castObjectT<GP::Context&>(ioContext);  GP::Context::Alloc& lContextAlloc =    castObjectT<GP::Context::Alloc&>(ioContext.getSystem().getContextAllocator());  GP::Context::Handle lContextHdl2  = castHandleT<GP::Context>(lContextAlloc.clone(lContext1));  // Get parameters in local values, with the total number of nodes of the mutated individual.  bool             lMatingDone     = false;  float            lDistrProba     = mDistributionProba->getWrappedValue();  unsigned int     lMaxTreeDepth   = mMaxTreeDepth->getWrappedValue();  GP::Tree::Handle lOldTreeHandle1 = lContext1.getGenotypeHandle();  unsigned int     lOldTreeIndex1  = lContext1.getGenotypeIndex();  unsigned int     lSizeIndiv      = 0;  for(unsigned int i=0; i<lGPIndiv.size(); ++i) lSizeIndiv += lGPIndiv[i]->size();  // Some outputs.  Beagle_LogDebugM(    lContext1.getSystem().getLogger(),    "mutation", "Beagle::GP::MutationSwapSubtreeOp",    string("Individual tried for swap subtree mutation (before): ")+    lGPIndiv.serialize()  );  // Mutation loop. Try the given number of attempts to mutation the individual.  for(unsigned int lAttempt=0; lAttempt < mNumberAttempts->getWrappedValue(); lAttempt++) {    // Calculate the number of nodes in the individual    unsigned int lNbNodes = 0;    for(unsigned int i=0; i<lGPIndiv.size(); i++) lNbNodes += lGPIndiv[i]->size();    if(lNbNodes == 0) return false;    // Choose a node of the individual to mutate.    unsigned int lNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lNbNodes-1);          // Get the tree in which the choosen node is. Change the global node index to the tree's index.    unsigned int lChoosenTree = 0;    for(; lChoosenTree<lGPIndiv.size(); ++lChoosenTree) {      if(lNode1 < lGPIndiv[lChoosenTree]->size()) break;      Beagle_AssertM(lNode1 >= lGPIndiv[lChoosenTree]->size());      lNode1 -= lGPIndiv[lChoosenTree]->size();    }    Beagle_AssertM(lChoosenTree < lGPIndiv.size());    // Cannot do anything with an tree of size <= 1.    if(lGPIndiv[lChoosenTree]->size() <= 1) continue;    // Some outputs.    Beagle_LogVerboseM(      lContext1.getSystem().getLogger(),      "mutation", "Beagle::GP::MutationSwapSubtreeOp",      string("Trying a swap subtree mutation of the ")+uint2ordinal(lChoosenTree+1)+      string(" tree")    );    // Make two clones of the choosen tree.    GP::Tree::Alloc& lTreeAlloc  = castObjectT<GP::Tree::Alloc&>(*lGPIndiv.getTypeAlloc());    GP::Tree::Handle lTreeClone1 = castHandleT<GP::Tree>(lTreeAlloc.clone(*lGPIndiv[lChoosenTree]));    GP::Tree::Handle lTreeClone2 = castHandleT<GP::Tree>(lTreeAlloc.clone(*lGPIndiv[lChoosenTree]));    // Now we decide whether the swap subtree mutation is internal or external.    bool lMutationType = lContext1.getSystem().getRandomizer().rollUniform(0.0, 1.0) < lDistrProba;    // Cannot do an internal mutation when there is only one branch in the tree.    if(lTreeClone1->size() == (*lTreeClone1)[0].mPrimitive->getNumberArguments()+1)      lMutationType = false;    // This is special case, a linear tree. Cannot do an external mutation.    if(lTreeClone1->size() == (*lTreeClone1)[1].mSubTreeSize+1) {      if(lTreeClone1->size()==2) continue;   // Cannot do anything here with the tree.      lMutationType = true;    }    // lMutationType is true -> internal mutation    if(lMutationType)  {      // If the selected node is a terminal, or a branch with a subtree made only of terminals,      // choose another node in the same tree.      while((*lTreeClone1)[lNode1].mSubTreeSize ==            ((*lTreeClone1)[lNode1].mPrimitive->getNumberArguments()+1)) {        lNode1 = lContext1.getSystem().getRandomizer().rollInteger(0, lTreeClone1->size()-1);      }      // Choosing the second node, a branch in lNode1's subtree.      unsigned int lSubTreeSizeN1 = (*lTreeClone1)[lNode1].mSubTreeSize;      unsigned int lN2OffN1 =        lContext1.getSystem().getRandomizer().rollInteger(1, lSubTreeSizeN1-1);      unsigned int lNode2 = lNode1 + lN2OffN1;      while((*lTreeClone1)[lNode2].mPrimitive->getNumberArguments() == 0) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?