# make_op_real.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // make_op.h - the real-valued version
    00005 // (c) Maarten Keijzer, Marc Schoenauer and GeNeura Team, 2001
    00006 /*
    00007     This library is free software; you can redistribute it and/or
    00008     modify it under the terms of the GNU Lesser General Public
    00009     License as published by the Free Software Foundation; either
    00010     version 2 of the License, or (at your option) any later version.
    00011
    00012     This library is distributed in the hope that it will be useful,
    00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015     Lesser General Public License for more details.
    00016
    00017     You should have received a copy of the GNU Lesser General Public
    00018     License along with this library; if not, write to the Free Software
    00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00020
    00021     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
    00022              Marc.Schoenauer@polytechnique.fr
    00023              mkeijzer@dhi.dk
    00024  */
    00025 //-----------------------------------------------------------------------------
    00026
    00027 #ifndef _make_op_h
    00028 #define _make_op_h
    00029
    00030 // the operators
    00031 #include <eoOp.h>
    00032 #include <eoGenOp.h>
    00033 #include <eoCloneOps.h>
    00034 #include <eoOpContainer.h>
    00035 // combinations of simple eoOps (eoMonOp and eoQuadOp)
    00036 #include <eoProportionalCombinedOp.h>
    00037
    00038 // the specialized Real stuff
    00039 #include <es/eoReal.h>
    00040 #include <es/eoEsChromInit.h>
    00041 #include <es/eoRealOp.h>
    00042 #include <es/eoNormalMutation.h>
    00043   // also need the parser and param includes
    00044 #include <utils/eoParser.h>
    00045 #include <utils/eoState.h>
    00046
    00047
    00048 /*
    00049  * This function builds the operators that will be applied to the eoReal
    00050  *
    00051  * It uses a parser (to get user parameters) and a state (to store the memory)
    00052  * the last argument is an individual, needed for 2 reasons
    00053  *     it disambiguates the call after instanciations
    00054  *     some operator might need some private information about the indis
    00055  *
    00056  * This is why the template is the complete EOT even though only the fitness
    00057  * is actually templatized here: the following only applies to bitstrings
    00058  *
    00059  * Note : the last parameter is an eoInit: if some operator needs some info
    00060  *        about the gneotypes, the init has it all (e.g. bounds, ...)
    00061  *        Simply do
    00062  *        EOT myEO;
    00063  *        _init(myEO);
    00064  *        and myEO is then an ACTUAL object
    00065 */
    00066
    00067 template <class EOT>
    00068 eoGenOp<EOT> & do_make_op(eoParser& _parser, eoState& _state, eoRealInitBounded<EOT>& _init)
    00069 {
    00070   // get std::vector size
    00071   unsigned vecSize = _init.size();
    00072
    00073   // First, decide whether the objective variables are bounded
    00074   eoValueParam<eoRealVectorBounds>& boundsParam
    00075       = _parser.getORcreateParam(eoRealVectorBounds(vecSize,eoDummyRealNoBounds), "objectBounds",
    00076                                  "Bounds for variables", 'B', "Variation Operators");
    00077
    00078   // this is a temporary version(!),
    00079   // while Maarten codes the full tree-structured general operator input
    00080   // BTW we must leave that simple version available somehow, as it is the one
    00081   // that 90% people use!
    00082   eoValueParam<std::string>& operatorParam
    00083       = _parser.getORcreateParam(std::string("SGA"), "operator",
    00084                                  "Description of the operator (SGA only now)",
    00085                                  'o', "Variation Operators");
    00086
    00087   if (operatorParam.value() != std::string("SGA"))
    00088     throw std::runtime_error("Sorry, only SGA-like operator available right now\n");
    00089
    00090     // now we read Pcross and Pmut,
    00091     // the relative weights for all crossovers -> proportional choice
    00092     // the relative weights for all mutations -> proportional choice
    00093     // and create the eoGenOp that is exactly
    00094     // crossover with pcross + mutation with pmut
    00095
    00096   eoValueParam<double>& pCrossParam
    00097       = _parser.getORcreateParam(0.6, "pCross",
    00098                                  "Probability of Crossover",
    00099                                  'C', "Variation Operators" );
    00100   // minimum check
    00101   if ( (pCrossParam.value() < 0) || (pCrossParam.value() > 1) )
    00102     throw std::runtime_error("Invalid pCross");
    00103
    00104   eoValueParam<double>& pMutParam
    00105       = _parser.getORcreateParam(0.1, "pMut",
    00106                                  "Probability of Mutation",
    00107                                  'M', "Variation Operators" );
    00108   // minimum check
    00109   if ( (pMutParam.value() < 0) || (pMutParam.value() > 1) )
    00110     throw std::runtime_error("Invalid pMut");
    00111
    00112     // the crossovers
    00114     // the parameters
    00115   eoValueParam<double>& alphaParam
    00116       = _parser.getORcreateParam(double(0.0), "alpha",
    00117                                  "Bound for factor of linear recombinations",
    00118                                  'a', "Variation Operators" );
    00119   // minimum check
    00120   if ( (alphaParam.value() < 0) )
    00121     throw std::runtime_error("Invalid BLX coefficient alpha");
    00122
    00123
    00124   eoValueParam<double>& segmentRateParam
    00125       = _parser.getORcreateParam(double(1.0), "segmentRate",
    00126                                  "Relative rate for segment crossover",
    00127                                  's', "Variation Operators" );
    00128   // minimum check
    00129   if ( (segmentRateParam.value() < 0) )
    00130     throw std::runtime_error("Invalid segmentRate");
    00131
    00132   eoValueParam<double>& hypercubeRateParam
    00133       = _parser.getORcreateParam(double(1.0), "hypercubeRate",
    00134                                  "Relative rate for hypercube crossover",
    00135                                  'A', "Variation Operators" );
    00136   // minimum check
    00137   if ( (hypercubeRateParam.value() < 0) )
    00138     throw std::runtime_error("Invalid hypercubeRate");
    00139
    00140   eoValueParam<double>& uxoverRateParam
    00141       = _parser.getORcreateParam(double(1.0), "uxoverRate",
    00142                                  "Relative rate for uniform crossover",
    00143                                  'A', "Variation Operators" );
    00144   // minimum check
    00145   if ( (uxoverRateParam.value() < 0) )
    00146     throw std::runtime_error("Invalid uxoverRate");
    00147
    00148     // minimum check
    00149   bool bCross = true;
    00150   if (segmentRateParam.value()+hypercubeRateParam.value()+uxoverRateParam.value()==0)
    00151     {
    00152       std::cerr << "Warning: no crossover" << std::endl;
    00153       bCross = false;
    00154     }
    00155
    00156   // Create the CombinedQuadOp
    00157   eoPropCombinedQuadOp<EOT> *ptCombinedQuadOp = NULL;
    00158   eoQuadOp<EOT> *ptQuad = NULL;
    00159
    00160   if (bCross)
    00161     {
    00162       // segment crossover for bitstring - pass it the bounds
    00163       ptQuad = new eoSegmentCrossover<EOT>(boundsParam.value(), alphaParam.value());
    00164       _state.storeFunctor(ptQuad);
    00165       ptCombinedQuadOp = new eoPropCombinedQuadOp<EOT>(*ptQuad, segmentRateParam.value());
    00166
    00167         // hypercube crossover
    00168       ptQuad = new eoHypercubeCrossover<EOT>(boundsParam.value(), alphaParam.value());
    00169       _state.storeFunctor(ptQuad);
    00170       ptCombinedQuadOp->add(*ptQuad, hypercubeRateParam.value());
    00171
    00172         // uniform crossover
    00173       ptQuad = new eoRealUXover<EOT>();
    00174       _state.storeFunctor(ptQuad);
    00175       ptCombinedQuadOp->add(*ptQuad, uxoverRateParam.value());
    00176
    00177       // don't forget to store the CombinedQuadOp
    00178       _state.storeFunctor(ptCombinedQuadOp);
    00179     }
    00180
    00181   // the mutations
    00183   // the parameters
    00184   eoValueParam<double> & epsilonParam
    00185       = _parser.getORcreateParam(0.01, "epsilon",
    00186                                  "Half-size of interval for Uniform Mutation",
    00187                                  'e', "Variation Operators" );
    00188   // minimum check
    00189   if ( (epsilonParam.value() < 0) )
    00190     throw std::runtime_error("Invalid epsilon");
    00191
    00192   eoValueParam<double> & uniformMutRateParam
    00193       = _parser.getORcreateParam(1.0, "uniformMutRate",
    00194                                  "Relative rate for uniform mutation",
    00195                                  'u', "Variation Operators" );
    00196   // minimum check
    00197   if ( (uniformMutRateParam.value() < 0) )
    00198     throw std::runtime_error("Invalid uniformMutRate");
    00199
    00200   eoValueParam<double> & detMutRateParam
    00201       = _parser.getORcreateParam(1.0, "detMutRate",
    00202                                  "Relative rate for deterministic uniform mutation",
    00203                                  'd', "Variation Operators" );
    00204   // minimum check
    00205   if ( (detMutRateParam.value() < 0) )
    00206     throw std::runtime_error("Invalid detMutRate");
    00207
    00208   eoValueParam<double> & normalMutRateParam
    00209       = _parser.getORcreateParam(1.0, "normalMutRate",
    00210                                  "Relative rate for Gaussian mutation", 'd', "Variation Operators" );
    00211   // minimum check
    00212   if ( (normalMutRateParam.value() < 0) )
    00213     throw std::runtime_error("Invalid normalMutRate");
    00214
    00215   eoValueParam<double> & sigmaParam
    00216       = _parser.getORcreateParam(0.3, "sigma",
    00217                                  "Sigma (fixed) for Gaussian mutation",
    00218                                  's', "Variation Operators" );
    00219
    00220   eoValueParam<double> & pNormalParam
    00221       = _parser.getORcreateParam(1.0, "pNormal",
    00222                                  "Proba. to change each variable for Gaussian mutation",
    00223                                  's', "Variation Operators" );
    00224
    00225     // minimum check
    00226   bool bMut = true;
    00227   if (uniformMutRateParam.value()+detMutRateParam.value()+normalMutRateParam.value()==0)
    00228     {
    00229       std::cerr << "Warning: no mutation" << std::endl;
    00230       bMut = false;
    00231     }
    00232   if (!bCross && !bMut)
    00233     throw std::runtime_error("No operator called in SGA operator definition!!!");
    00234
    00235     // Create the CombinedMonOp
    00236   eoPropCombinedMonOp<EOT> *ptCombinedMonOp = NULL;
    00237   eoMonOp<EOT> *ptMon = NULL;
    00238
    00239   if (bMut)
    00240     {
    00241       // uniform mutation on all components:
    00242       // offspring(i) uniformly chosen in [parent(i)-epsilon, parent(i)+epsilon]
    00243       ptMon = new eoUniformMutation<EOT>(boundsParam.value(), epsilonParam.value());
    00244       _state.storeFunctor(ptMon);
    00245       // create the CombinedMonOp
    00246       ptCombinedMonOp = new eoPropCombinedMonOp<EOT>(*ptMon, uniformMutRateParam.value());
    00247
    00248         // mutate exactly 1 component (uniformly) per individual
    00249       ptMon = new eoDetUniformMutation<EOT>(boundsParam.value(), epsilonParam.value());
    00250       _state.storeFunctor(ptMon);
    00251       ptCombinedMonOp->add(*ptMon, detMutRateParam.value());
    00252
    00253       // mutate all component using Gaussian mutation
    00254       ptMon = new eoNormalVecMutation<EOT>(boundsParam.value(), sigmaParam.value(), pNormalParam.value());
    00255       _state.storeFunctor(ptMon);
    00256       ptCombinedMonOp->add(*ptMon, normalMutRateParam.value());
    00257       _state.storeFunctor(ptCombinedMonOp);
    00258     }
    00259
    00260   // now build the eoGenOp:
    00261   // to simulate SGA (crossover with proba pCross + mutation with proba pMut
    00262   // we must construct
    00263   //     a sequential combination of
    00264   //          with proba 1, a proportional combination of
    00265   //                        a QuadCopy and our crossover
    00266   //          with proba pMut, our mutation
    00267
    00268   // the crossover - with probability pCross
    00269   eoProportionalOp<EOT> * cross = new eoProportionalOp<EOT> ;
    00270   _state.storeFunctor(cross);
    00271   ptQuad = new eoQuadCloneOp<EOT>;
    00272   _state.storeFunctor(ptQuad);
    00273   cross->add(*ptCombinedQuadOp, pCrossParam.value()); // user crossover
    00274   cross->add(*ptQuad, 1-pCrossParam.value()); // clone operator
    00275
    00276   // now the sequential
    00277   eoSequentialOp<EOT> & op =  _state.storeFunctor(new eoSequentialOp<EOT>);
    00278   op.add(*cross, 1.0);   // always crossover (but clone with prob 1-pCross
    00279   op.add(*ptCombinedMonOp, pMutParam.value());
    00280
    00281   // that's it!
    00282   return op;
    00283 }
    00284 #endif