diff --git a/eo/test/t-eoSymreg.cpp b/eo/test/t-eoSymreg.cpp index 2dbe570e..63bfae68 100644 --- a/eo/test/t-eoSymreg.cpp +++ b/eo/test/t-eoSymreg.cpp @@ -1,276 +1,277 @@ -#pragma warning(disable:4786) - -#include "eoParseTree.h" -#include "eoEvalFunc.h" - -using namespace gp_parse_tree; -using namespace std; - -//----------------------------------------------------------------------------- - -class SymregNode -{ -public : - - enum Operator {X = 'x', Plus = '+', Min = '-', Mult = '*', PDiv = '/'}; - - SymregNode(void) { init(); } - SymregNode(Operator _op) { op = _op; } - virtual ~SymregNode(void) {} - - // arity function - int arity(void) const { return op == X? 0 : 2; } - - // evaluation function, single case, using first argument to give value of variable - template - double operator()(double var, Children args) const - { - switch (op) - { - case Plus : return args[0].apply(var) + args[1].apply(var); - case Min : return args[0].apply(var) - args[1].apply(var); - case Mult : return args[0].apply(var) * args[1].apply(var); - case PDiv : - { - double arg1 = args[1].apply(var); - if (arg1 == 0.0) - return 1.0; // protection a la Koza, realistic implementations should maybe throw an exception - - return args[0].apply(var) / arg1; - } - - case X : return var; - } - - return var; // to avoid compiler error - } - - /// 'Pretty' print to ostream function - template - string operator()(string dummy, Children args) - { - static const string lb = "("; - static const string rb = ")"; - char opStr[4] = " "; - opStr[1] = op; - - if (arity() == 0) - { - return string("x"); - } - // else - string result = lb + args[0].apply(dummy); - result += opStr; - result += args[1].apply(dummy) + rb; - return result; - } - - Operator getOp(void) const { return op; } - -protected : - - void init(void) { op = X; } - -private : - - Operator op; // the type of node -}; - -/// initializor -static SymregNode init_sequence[5] = {SymregNode::X, SymregNode::Plus, SymregNode::Min, SymregNode::Mult, SymregNode::PDiv}; // needed for intialization - -//----------------------------------------------------------- -// saving, loading - -std::ostream& operator<<(std::ostream& os, const SymregNode& eot) -{ - os << static_cast(eot.getOp()); - return os; -} - -std::istream& operator>>(std::istream& is, SymregNode& eot) -{ - char type; - type = (char) is.get(); - eot = SymregNode(static_cast(type)); - return is; -} - - -//----------------------------------------------------------------------------- -/** Implementation of a function evaluation object. */ - -float targetFunction(float x) -{ - return x * x * x * x - x * x * x + x * x * x - x * x + x - 1; -} - -// parameters controlling the sampling of points -const float xbegin = -10.0f; -const float xend = 10.0f; -const float xstep = 1.3f; - -template struct RMS: public eoEvalFunc< eoParseTree > -{ -public : - - typedef eoParseTree EoType; - - typedef eoParseTree argument_type; - typedef double fitness_type; - - RMS(void) : eoEvalFunc() - { - int n = int( (xend - xbegin) / xstep); - - inputs.resize(n); - target.resize(n); - - int i = 0; - - for (double x = xbegin; x < xend && i < n; ++i) - { - target[i] = targetFunction(x); - inputs[i] = x; - } - } - - ~RMS() {} - - void operator()( EoType & _eo ) const - { - vector outputs; - outputs.resize(inputs.size()); - - double fitness = 0.0; - - for (int i = 0; i < inputs.size(); ++i) - { - outputs[i] = _eo.apply(inputs[i]); - fitness += (outputs[i] - target[i]) * (outputs[i] - target[i]); - } - - fitness /= (double) target.size(); - fitness = sqrt(fitness); - - if (fitness > 1e+20) - fitness = 1e+20; - - _eo.fitness(fitness); - } - -private : - vector inputs; - vector target; -}; - -#include "eoTerm.h" - -template -class eoGenerationTerm : public eoTerm -{ - public : - eoGenerationTerm(size_t _ngen) : eoTerm(), ngen(_ngen) {} - - bool operator()(const eoPop&) - { - cout << '.'; // pacifier - cout.flush(); - - return --ngen > 0; - } - private : - unsigned ngen; -}; - -template -void print_best(eoPop& pop) -{ - cout << endl; - FitnessType best = pop[0].fitness(); - int index = 0; - - for (int i = 1; i < pop.size(); ++i) - { - if (best < pop[i].fitness()) - { - best = pop[i].fitness(); - index = i; - } - } - - cout << "\t"; - - string str = pop[index].apply(string()); - - cout << str.c_str(); - cout << endl << "Error = " << pop[index].fitness() << endl; -} - - -#include -#include "eoGOpBreeder.h" -#include "eoSequentialGOpSelector.h" -#include "eoProportionalGOpSelector.h" -#include "eoDetTournamentIndiSelector.h" -#include "eoDetTournamentInserter.h" -#include "eoSteadyStateEA.h" -#include "eoScalarFitness.h" - -void main() -{ - typedef eoScalarFitness > FitnessType; - typedef SymregNode GpNode; - - typedef eoParseTree EoType; - typedef eoPop Pop; - - const int MaxSize = 75; - const int nGenerations = 50; - - // Initializor sequence, contains the allowable nodes - vector init(init_sequence, init_sequence + 5); - - // Depth Initializor, defaults to grow method. - eoGpDepthInitializer initializer(10, init); - - // Root Mean Squared Error Measure - RMS eval; - - Pop pop(500, MaxSize, initializer, eval); - - eoSubtreeXOver xover(MaxSize); - eoBranchMutation mutation(initializer, MaxSize); - - eoSequentialGOpSel seqSel; - - seqSel.addOp(mutation, 0.25); - seqSel.addOp(xover, 0.75); - - eoDetTournamentIndiSelector selector(5); - - eoDetTournamentInserter inserter(eval, 5); - - // Terminators - eoGenerationTerm term(nGenerations); - - // GP generation - eoSteadyStateEA gp(seqSel, selector, inserter, term); - - cout << "Initialization done" << endl; - - print_best(pop); - - try - { - gp(pop); - } - catch (exception& e) - { - cout << "exception: " << e.what() << endl;; - exit(EXIT_FAILURE); - } - - print_best(pop); -} - +#pragma warning(disable:4786) + +#include "eoParseTree.h" +#include "eoEvalFunc.h" + +using namespace gp_parse_tree; +using namespace std; + +//----------------------------------------------------------------------------- + +class SymregNode +{ +public : + + enum Operator {X = 'x', Plus = '+', Min = '-', Mult = '*', PDiv = '/'}; + + SymregNode(void) { init(); } + SymregNode(Operator _op) { op = _op; } + virtual ~SymregNode(void) {} + + // arity function + int arity(void) const { return op == X? 0 : 2; } + + // evaluation function, single case, using first argument to give value of variable + template + double operator()(double var, Children args) const + { + switch (op) + { + case Plus : return args[0].apply(var) + args[1].apply(var); + case Min : return args[0].apply(var) - args[1].apply(var); + case Mult : return args[0].apply(var) * args[1].apply(var); + case PDiv : + { + double arg1 = args[1].apply(var); + if (arg1 == 0.0) + return 1.0; // protection a la Koza, realistic implementations should maybe throw an exception + + return args[0].apply(var) / arg1; + } + + case X : return var; + } + + return var; // to avoid compiler error + } + + /// 'Pretty' print to ostream function + template + string operator()(string dummy, Children args) + { + static const string lb = "("; + static const string rb = ")"; + char opStr[4] = " "; + opStr[1] = op; + + if (arity() == 0) + { + return string("x"); + } + // else + string result = lb + args[0].apply(dummy); + result += opStr; + result += args[1].apply(dummy) + rb; + return result; + } + + Operator getOp(void) const { return op; } + +protected : + + void init(void) { op = X; } + +private : + + Operator op; // the type of node +}; + +/// initializor +static SymregNode init_sequence[5] = {SymregNode::X, SymregNode::Plus, SymregNode::Min, SymregNode::Mult, SymregNode::PDiv}; // needed for intialization + +//----------------------------------------------------------- +// saving, loading + +std::ostream& operator<<(std::ostream& os, const SymregNode& eot) +{ + os << static_cast(eot.getOp()); + return os; +} + +std::istream& operator>>(std::istream& is, SymregNode& eot) +{ + char type; + type = (char) is.get(); + eot = SymregNode(static_cast(type)); + return is; +} + + +//----------------------------------------------------------------------------- +/** Implementation of a function evaluation object. */ + +float targetFunction(float x) +{ + return x * x * x * x - x * x * x + x * x * x - x * x + x - 1; +} + +// parameters controlling the sampling of points +const float xbegin = -10.0f; +const float xend = 10.0f; +const float xstep = 1.3f; + +template struct RMS: public eoEvalFunc< eoParseTree > +{ +public : + + typedef eoParseTree EoType; + + typedef eoParseTree argument_type; + typedef double fitness_type; + + RMS(void) : eoEvalFunc() + { + int n = int( (xend - xbegin) / xstep); + + inputs.resize(n); + target.resize(n); + + int i = 0; + + for (double x = xbegin; x < xend && i < n; ++i) + { + target[i] = targetFunction(x); + inputs[i] = x; + } + } + + ~RMS() {} + + void operator()( EoType & _eo ) const + { + vector outputs; + outputs.resize(inputs.size()); + + double fitness = 0.0; + + for (int i = 0; i < inputs.size(); ++i) + { + outputs[i] = _eo.apply(inputs[i]); + fitness += (outputs[i] - target[i]) * (outputs[i] - target[i]); + } + + fitness /= (double) target.size(); + fitness = sqrt(fitness); + + if (fitness > 1e+20) + fitness = 1e+20; + + _eo.fitness(fitness); + } + +private : + vector inputs; + vector target; +}; + +#include "eoTerm.h" + +template +class eoGenerationTerm : public eoTerm +{ + public : + eoGenerationTerm(size_t _ngen) : eoTerm(), ngen(_ngen) {} + + bool operator()(const eoPop&) + { + cout << '.'; // pacifier + cout.flush(); + + return --ngen > 0; + } + private : + unsigned ngen; +}; + +template +void print_best(eoPop& pop) +{ + cout << endl; + FitnessType best = pop[0].fitness(); + int index = 0; + + for (int i = 1; i < pop.size(); ++i) + { + if (best < pop[i].fitness()) + { + best = pop[i].fitness(); + index = i; + } + } + + cout << "\t"; + + string str = pop[index].apply(string()); + + cout << str.c_str(); + cout << endl << "Error = " << pop[index].fitness() << endl; +} + + +#include +#include "eoGOpBreeder.h" +#include "eoSequentialGOpSelector.h" +#include "eoProportionalGOpSelector.h" +#include "eoDetTournamentIndiSelector.h" +#include "eoDetTournamentInserter.h" +#include "eoSteadyStateEA.h" +#include "eoScalarFitness.h" + +void main() +{ + typedef eoScalarFitness > FitnessType; + typedef SymregNode GpNode; + + typedef eoParseTree EoType; + typedef eoPop Pop; + + const int MaxSize = 75; + const int nGenerations = 50; + + // Initializor sequence, contains the allowable nodes + vector init(init_sequence, init_sequence + 5); + + // Depth Initializor, defaults to grow method. + eoGpDepthInitializer initializer(10, init); + + // Root Mean Squared Error Measure + RMS eval; + + Pop pop(500, MaxSize, initializer, eval); + + eoSubtreeXOver xover(MaxSize); + eoBranchMutation mutation(initializer, MaxSize); + + eoSequentialGOpSel seqSel; + + seqSel.addOp(mutation, 0.25); + seqSel.addOp(xover, 0.75); + + eoDetTournamentIndiSelector selector(5); + + eoDetTournamentInserter inserter(eval, 5); + + // Terminators + eoGenerationTerm term(nGenerations); + + // GP generation + eoSteadyStateEA gp(seqSel, selector, inserter, term); + + cout << "Initialization done" << endl; + + print_best(pop); + + try + { + gp(pop); + } + catch (exception& e) + { + cout << "exception: " << e.what() << endl;; + exit(EXIT_FAILURE); + } + + print_best(pop); +} + +