Adding a simpler way of generating files for new genotypes (see EO.tpl
in EASEA).
This commit is contained in:
parent
06ac548f96
commit
61f9b51243
3 changed files with 338 additions and 0 deletions
28
eo/tutorial/Templates/MakeSimple.tmpl
Normal file
28
eo/tutorial/Templates/MakeSimple.tmpl
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# sample makefile for building an EA evolving a new genotype
|
||||||
|
|
||||||
|
# START eventually modify the name of EO dir
|
||||||
|
DIR_EO = ../../src
|
||||||
|
# END eventually modify the name of EO dir
|
||||||
|
LIB_EO = $(DIR_EO)/utils/libeoutils.a $(DIR_EO)/libeo.a
|
||||||
|
|
||||||
|
.cpp: ; c++ -DPACKAGE=\"eo\" -DVERSION=\"0.9.3\" -I. -I$(DIR_EO) -Wall -g -o $@ $*.cpp $(LIB_EO)
|
||||||
|
|
||||||
|
.cpp.o: ; c++ -DPACKAGE=\"eo\" -DVERSION=\"0.9.3\" -I. -I$(DIR_EO) -Wall -g -c $*.cpp
|
||||||
|
|
||||||
|
# local sources
|
||||||
|
SOURCES = MyStructEA.cpp \
|
||||||
|
eoMyStruct.h \
|
||||||
|
eoMyStructEvalFunc.h \
|
||||||
|
eoMyStructInit.h \
|
||||||
|
eoMyStructMutation.h \
|
||||||
|
eoMyStructQuadCrossover.h
|
||||||
|
|
||||||
|
MyStructEA : MyStructEA.cpp
|
||||||
|
c++ -I. -I$(DIR_EO) -g -o $@ MyStructEA.cpp $(LIB_EO) -lm
|
||||||
|
|
||||||
|
tar : ; tar czvf MyStruct.tgz *.h *.cpp Makefile
|
||||||
|
|
||||||
|
clean : ; /bin/rm *.o MyStructEA
|
||||||
|
|
||||||
|
########## local dependencies
|
||||||
|
MyStructEA : $(SOURCES)
|
||||||
252
eo/tutorial/Templates/MyStructSEA.cpp
Normal file
252
eo/tutorial/Templates/MyStructSEA.cpp
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
|
||||||
|
|
||||||
|
The above line is usefulin Emacs-like editors
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Template for creating a new representation in EO
|
||||||
|
================================================
|
||||||
|
|
||||||
|
This is the template main file.
|
||||||
|
It includes all other files that have been generated by the script create.sh
|
||||||
|
so it is the only file to compile.
|
||||||
|
|
||||||
|
In case you want to build up a separate library for your new Evolving Object,
|
||||||
|
you'll need some work - follow what's done in the src/ga dir, used in the
|
||||||
|
main file BitEA in tutorial/Lesson4 dir.
|
||||||
|
Or you can wait until we do it :-)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Miscilaneous include and declaration
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// eo general include
|
||||||
|
#include "eo"
|
||||||
|
// the real bounds (not yet in general eo include)
|
||||||
|
#include "utils/eoRealVectorBounds.h"
|
||||||
|
|
||||||
|
// include here whatever specific files for your representation
|
||||||
|
// Basically, this should include at least the following
|
||||||
|
|
||||||
|
/** definition of representation:
|
||||||
|
* class eoMyStruct MUST derive from EO<FitT> for some fitness
|
||||||
|
*/
|
||||||
|
#include "eoMyStruct.h"
|
||||||
|
|
||||||
|
/** definition of initilizqtion:
|
||||||
|
* class eoMyStructInit MUST derive from eoInit<eoMyStruct>
|
||||||
|
*/
|
||||||
|
#include "eoMyStructInit.h"
|
||||||
|
|
||||||
|
/** definition of evaluation:
|
||||||
|
* class eoMyStructEvalFunc MUST derive from eoEvalFunc<eoMyStruct>
|
||||||
|
* and should test for validity before doing any computation
|
||||||
|
* see tutorial/Templates/evalFunc.tmpl
|
||||||
|
*/
|
||||||
|
#include "eoMyStructEvalFunc.h"
|
||||||
|
|
||||||
|
/** definitions of operators: write as many classes as types of operators
|
||||||
|
* and include them here. In this simple example,
|
||||||
|
* one crossover (2->2) and one mutation (1->1) operators are used
|
||||||
|
*/
|
||||||
|
#include "eoMyStructQuadCrossover.h"
|
||||||
|
#include "eoMyStructMutation.h"
|
||||||
|
|
||||||
|
// GENOTYPE eoMyStruct ***MUST*** be templatized over the fitness
|
||||||
|
|
||||||
|
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||||
|
// START fitness type: double or eoMaximizingFitness if you are maximizing
|
||||||
|
// eoMinimizingFitness if you are minimizing
|
||||||
|
typedef eoMinimizingFitness MyFitT ; // type of fitness
|
||||||
|
// END fitness type
|
||||||
|
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||||
|
|
||||||
|
// Then define your EO objects using that fitness type
|
||||||
|
typedef eoMyStruct<MyFitT> Indi; // ***MUST*** derive from EO
|
||||||
|
|
||||||
|
|
||||||
|
// Use existing modules to define representation independent routines
|
||||||
|
|
||||||
|
// how to initialize the population
|
||||||
|
// it IS representation independent if an eoInit is given
|
||||||
|
#include <do/make_pop.h>
|
||||||
|
eoPop<Indi >& make_pop(eoParser& _parser, eoState& _state, eoInit<Indi> & _init)
|
||||||
|
{
|
||||||
|
return do_make_pop(_parser, _state, _init);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the stopping criterion
|
||||||
|
#include <do/make_continue.h>
|
||||||
|
eoContinue<Indi>& make_continue(eoParser& _parser, eoState& _state, eoEvalFuncCounter<Indi> & _eval)
|
||||||
|
{
|
||||||
|
return do_make_continue(_parser, _state, _eval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputs (stats, population dumps, ...)
|
||||||
|
#include <do/make_checkpoint.h>
|
||||||
|
eoCheckPoint<Indi>& make_checkpoint(eoParser& _parser, eoState& _state, eoEvalFuncCounter<Indi>& _eval, eoContinue<Indi>& _continue)
|
||||||
|
{
|
||||||
|
return do_make_checkpoint(_parser, _state, _eval, _continue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// evolution engine (selection and replacement)
|
||||||
|
#include <do/make_algo_scalar.h>
|
||||||
|
eoAlgo<Indi>& make_algo_scalar(eoParser& _parser, eoState& _state, eoEvalFunc<Indi>& _eval, eoContinue<Indi>& _continue, eoGenOp<Indi>& _op)
|
||||||
|
{
|
||||||
|
return do_make_algo_scalar(_parser, _state, _eval, _continue, _op);
|
||||||
|
}
|
||||||
|
|
||||||
|
// simple call to the algo. stays there for consistency reasons
|
||||||
|
// no template for that one
|
||||||
|
#include <do/make_run.h>
|
||||||
|
// the instanciating fitnesses
|
||||||
|
#include <eoScalarFitness.h>
|
||||||
|
void run_ea(eoAlgo<Indi>& _ga, eoPop<Indi>& _pop)
|
||||||
|
{
|
||||||
|
do_run(_ga, _pop);
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks for help demand, and writes the status file
|
||||||
|
// and make_help; in libutils
|
||||||
|
void make_help(eoParser & _parser);
|
||||||
|
|
||||||
|
// now use all of the above, + representation dependent things
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
eoParser parser(argc, argv); // for user-parameter reading
|
||||||
|
|
||||||
|
eoState state; // keeps all things allocated
|
||||||
|
|
||||||
|
// The fitness
|
||||||
|
//////////////
|
||||||
|
eoMyStructEvalFunc<Indi> plainEval/* (varType _anyVariable) */;
|
||||||
|
// turn that object into an evaluation counter
|
||||||
|
eoEvalFuncCounter<Indi> eval(plainEval);
|
||||||
|
|
||||||
|
// a genotype initializer
|
||||||
|
eoMyStructInit<Indi> init;
|
||||||
|
// or, if you need some parameters, you might as well
|
||||||
|
// - write a constructor of the eoMyStructInit that uses a parser
|
||||||
|
// - call it from here:
|
||||||
|
// eoMyStructInit<Indi> init(parser);
|
||||||
|
|
||||||
|
|
||||||
|
// Build the variation operator (any seq/prop construct)
|
||||||
|
// here, a simple example with only 1 crossover (2->2, a QuadOp) and
|
||||||
|
// one mutation, is given.
|
||||||
|
// Hints to have choice among multiple crossovers and mutations are given
|
||||||
|
|
||||||
|
// A (first) crossover (possibly use the parser in its Ctor)
|
||||||
|
eoMyStructQuadCrossover<Indi> cross /* (eoParser parser) */;
|
||||||
|
|
||||||
|
// IF MORE THAN ONE:
|
||||||
|
|
||||||
|
// read its relative rate in the combination
|
||||||
|
// double cross1Rate = parser.createParam(1.0, "cross1Rate", "Relative rate for crossover 1", '1', "Variation Operators").value();
|
||||||
|
|
||||||
|
// create the combined operator with the first one (rename it cross1 !!!)
|
||||||
|
// eoPropCombinedQuadOp<Indi> cross(cross1, cross1Rate);
|
||||||
|
|
||||||
|
// and as many as you want the following way:
|
||||||
|
// 1- write the new class by mimicking eoMyStructQuadCrossover.h
|
||||||
|
// 2- include that file here together with eoMyStructQuadCrossover above
|
||||||
|
// 3- uncomment and duplicate the following lines:
|
||||||
|
//
|
||||||
|
// eoMyStructSecondCrossover<Indi> cross2(eoParser parser);
|
||||||
|
// double cross2Rate = parser.createParam(1.0, "cross2Rate", "Relative rate for crossover 2", '2', "Variation Operators").value();
|
||||||
|
// cross.add(cross2, cross2Rate);
|
||||||
|
|
||||||
|
// NOTE: if you want some gentle output, the last one shoudl be like
|
||||||
|
// cross.add(cross, crossXXXRate, true);
|
||||||
|
|
||||||
|
/////////////// Same thing for MUTATION
|
||||||
|
|
||||||
|
// a (first) mutation (possibly use the parser in its Ctor)
|
||||||
|
eoMyStructMutation<Indi> mut /* (eoParser parser) */;
|
||||||
|
|
||||||
|
// IF MORE THAN ONE:
|
||||||
|
|
||||||
|
// read its relative rate in the combination
|
||||||
|
// double mut1Rate = parser.createParam(1.0, "mut1Rate", "Relative rate for mutation 1", '1', "Variation Operators").value();
|
||||||
|
|
||||||
|
// create the combined operator with the first one (rename it cross1 !!!)
|
||||||
|
// eoPropCombinedMonOp<Indi> mut(mut1, mut1Rate);
|
||||||
|
|
||||||
|
// and as many as you want the following way:
|
||||||
|
// 1- write the new class by mimicking eoMyStructMutation.h
|
||||||
|
// 2- include that file here together with eoMyStructMutation above
|
||||||
|
// 3- uncomment and duplicate the following lines:
|
||||||
|
//
|
||||||
|
// eoMyStructSecondMutation<Indi> mut2(eoParser parser);
|
||||||
|
// double mut2Rate = parser.createParam(1.0, "mut2Rate", "Relative rate for mutation 2", '2', "Variation Operators").value();
|
||||||
|
// mut.add(mut2, mut2Rate);
|
||||||
|
|
||||||
|
// NOTE: if you want some gentle output, the last one shoudl be like
|
||||||
|
// mut.add(mut, mutXXXRate, true);
|
||||||
|
|
||||||
|
// now encapsulate your crossover(s) and mutation(s) into an eoGeneralOp
|
||||||
|
// so you can fully benefit of the existing evolution engines
|
||||||
|
|
||||||
|
// First read the individual level parameters
|
||||||
|
double pCross = parser.createParam(0.6, "pCross", "Probability of Crossover", 'C', "Variation Operators" ).value();
|
||||||
|
// minimum check
|
||||||
|
if ( (pCross < 0) || (pCross > 1) )
|
||||||
|
throw runtime_error("Invalid pCross");
|
||||||
|
|
||||||
|
double pMut = parser.createParam(0.1, "pMut", "Probability of Mutation", 'M', "Variation Operators" ).value();
|
||||||
|
// minimum check
|
||||||
|
if ( (pMut < 0) || (pMut > 1) )
|
||||||
|
throw runtime_error("Invalid pMut");
|
||||||
|
|
||||||
|
// now create the generalOp
|
||||||
|
eoSGAGenOp<Indi> op(cross, pCross, mut, pMut);
|
||||||
|
|
||||||
|
|
||||||
|
//// Now the representation-independent things
|
||||||
|
//
|
||||||
|
// YOU SHOULD NOT NEED TO MODIFY ANYTHING BEYOND THIS POINT
|
||||||
|
// unless you want to add specific statistics to the checkpoint
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
|
||||||
|
// initialize the population
|
||||||
|
// yes, this is representation indepedent once you have an eoInit
|
||||||
|
eoPop<Indi>& pop = make_pop(parser, state, init);
|
||||||
|
|
||||||
|
// stopping criteria
|
||||||
|
eoContinue<Indi> & term = make_continue(parser, state, eval);
|
||||||
|
// output
|
||||||
|
eoCheckPoint<Indi> & checkpoint = make_checkpoint(parser, state, eval, term);
|
||||||
|
// algorithm (need the operator!)
|
||||||
|
eoAlgo<Indi>& ga = make_algo_scalar(parser, state, eval, checkpoint, op);
|
||||||
|
|
||||||
|
///// End of construction of the algorithm
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// to be called AFTER all parameters have been read!!!
|
||||||
|
make_help(parser);
|
||||||
|
|
||||||
|
//// GO
|
||||||
|
///////
|
||||||
|
// evaluate intial population AFTER help and status in case it takes time
|
||||||
|
apply<Indi>(eval, pop);
|
||||||
|
// if you want to print it out
|
||||||
|
// cout << "Initial Population\n";
|
||||||
|
// pop.sortedPrintOn(cout);
|
||||||
|
// cout << endl;
|
||||||
|
|
||||||
|
run_ea(ga, pop); // run the ga
|
||||||
|
|
||||||
|
cout << "Final Population\n";
|
||||||
|
pop.sortedPrintOn(cout);
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(exception& e)
|
||||||
|
{
|
||||||
|
cout << e.what() << endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
58
eo/tutorial/Templates/createSimple
Executable file
58
eo/tutorial/Templates/createSimple
Executable file
|
|
@ -0,0 +1,58 @@
|
||||||
|
#! /bin/tcsh -f
|
||||||
|
if ($PWD:t != Templates) then
|
||||||
|
echo You must be in the Template dir to run that script
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ($#argv < 1) then
|
||||||
|
echo "Usage $0 ApplicationName [TargetDirName]"
|
||||||
|
echo " will create ../TargetDirName if necessary"
|
||||||
|
echo " (default dir name = ApplicationName),"
|
||||||
|
echo " and will put there all files that are strictly necessary"
|
||||||
|
echo " to compile and run you Application from there"
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
|
||||||
|
echo " " # we're going to do something
|
||||||
|
|
||||||
|
if ($#argv == 1) then
|
||||||
|
set TargetDir = ../$1
|
||||||
|
else
|
||||||
|
set TargetDir = ../$2
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (! -e $TargetDir) then
|
||||||
|
mkdir $TargetDir
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ( (-f $TargetDir/eo$1.h) || (-f $TargetDir/eo$1Init.h) || (-f $TargetDir/eo$1EvalFunc.h) || (-f $TargetDir/eo$1Mutation.h) || (-f $TargetDir/eo$1QuadCrossover.h) || (-f $TargetDir/$1EA.cpp) || (-f $TargetDir/make_genotype_$1.h) || (-f $TargetDir/make_op_$1.h) ) then
|
||||||
|
echo WARNING: some files already exist there.
|
||||||
|
echo -n "Overwrite ALL (yes/no)? "
|
||||||
|
set REP = $<
|
||||||
|
if ($REP != "yes") then
|
||||||
|
echo Nothing done!
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (-f $TargetDir/Makefile) then
|
||||||
|
echo A Makefile already exists there.
|
||||||
|
echo I'm creating Makefile.$1. You'll have to merge them both,
|
||||||
|
echo OR to call make -f Makefile.$1
|
||||||
|
set MakeName = Makefile.$1
|
||||||
|
else
|
||||||
|
set MakeName = Makefile
|
||||||
|
endif
|
||||||
|
|
||||||
|
echo Creating source files for application $1 in $TargetDir/
|
||||||
|
|
||||||
|
sed s/MyStruct/$1/g eoMyStruct.tmpl > $TargetDir/eo$1.h
|
||||||
|
sed s/MyStruct/$1/g init.tmpl > $TargetDir/eo$1Init.h
|
||||||
|
sed s/MyStruct/$1/g evalFunc.tmpl > $TargetDir/eo$1EvalFunc.h
|
||||||
|
sed s/MyStruct/$1/g mutation.tmpl > $TargetDir/eo$1Mutation.h
|
||||||
|
sed s/MyStruct/$1/g quadCrossover.tmpl > $TargetDir/eo$1QuadCrossover.h
|
||||||
|
sed s/MyStruct/$1/g MyStructSEA.cpp > $TargetDir/$1EA.cpp
|
||||||
|
sed s/MyStruct/$1/g MakeSimple.tmpl > $TargetDir/$MakeName
|
||||||
|
|
||||||
|
echo Done!
|
||||||
|
|
||||||
Reference in a new issue