📄 symbreg2.cc
字号:
// symbreg2.cc.................28 April 1994
//--------------------------------------------------------------------------
// This code is a component of Genetic Programming in C++ (Version 0.40)
// Copyright Adam P. Fraser, 1993,1994
// This code is released for non-commercial use only.
// For comments, improvements, additions (or even money !?) contact:
// Adam Fraser, Postgraduate Section, Dept of Elec & Elec Eng,
// Maxwell Building, University Of Salford, Salford, M5 4WT, United Kingdom.
// Internet: a.fraser@eee.salford.ac.uk
// Tel: (UK) 061 745 5000 x3633
// Fax: (UK) 061 745 5999
//--------------------------------------------------------------------------
// a slightly more difficult problem function which needs some real numbers to solve it
// Code designed and created by Adam P. Fraser 8 February 1994 for gpcpp v0.4
// This produces a genetic program which attempts to evolve a function which fits
// the curve outlined by that defined in FUNCTION. It does this by taking 10 points
// between 0->10 and evaluating for each point. The accumulated difference between
// the two set of values should tend to zero as the genetic program gets closer to
// the function.
// if you give the system a population = 500 and generations = 50 it will probably
// come up with a solution. There are no certainties in this game......
// Include header files of genetic programming system.
#include "gpmain.hpp"
#include "function.hpp"
#include "terminal.hpp"
// global def'ns
// define the returning value of each block within the genetic program..............
#define FITNESS float
// define the function to be symbolically regressed.................................
#define FUNCTION( x ) x*x*x*x - 3*x*x*x - 2*x*x + x
// Global function set..............................................................
FS *FunctionSets[1];
TS *TerminalSets[1];
// set up question and answer array with 10 points for the function.................
float ques[10];
float answ[10];
// this variable will be used by genetic programming system.........................
float globalX;
// For ADFs really but can also be used when we dont need ADF's
GP *pgpGlobal;
#define ROOT *(pgpGlobal->ppgHeader)
// These four functions MUST be included and written................................
unsigned int EvaluateFitness( Gene *,int );
ostream& (*TranslatePrint)( ostream&, Gene* );
void InitialiseGPS();
void CleanUpGPS();
FITNESS (*Translate)( Gene* );
FITNESS TranslateROOT( Gene* );
ostream& TranslatePrintROOT( ostream&, Gene* );
// divide with closure property.....................................................
FITNESS Divide( Gene* );
// main block of code...
// The evaluate of function generally the most difficult to define for a problem
unsigned int EvaluateFitness( GP *pgp, int Evals )
{
FITNESS rawfitness = 0, diff = 0;
// set up global genetic program variable to use ROOT macro defined above
// this is useful for ADFs but not particularly helpful here
pgpGlobal = pgp;
// this next line is included just to stop any warnings in compilation
// it makes no difference to the code and can be deleted if wished...
Evals--;
// the evaluation function checks with 10 values of the mathematical function
for ( int i = 0; i < 10; i++ )
{
float tempGPAnswer;
// set up X variable for mathematical function.......................
globalX = ques[i];
// calculate genetic programs answer.....................................
tempGPAnswer = Translate( ROOT );
// calculate difference between the genetic program and the actual answer
if ( answ[i] > tempGPAnswer ) diff = answ[i] - tempGPAnswer;
else diff = tempGPAnswer - answ[i];
// if this is really big don't make it to big................................
if ( diff > 100 ) diff = 100;
// add this difference to total rawfitness.................................
rawfitness += diff;
}
// in this case the higher the rawfitness ( or accumulated differences ) the
// lower the fitness hence the next line..............................
return (1000 - (unsigned int)rawfitness );
}
// The translate function for the procedural calls from GP iValues
FITNESS TranslateROOT( Gene *pg )
{
switch ( pg->iValue )
{
// FUNCTIONS
// The multiplier values.........................................................
case 1: return Translate( pg->pgChild ) * Translate( pg->pgChild->pgNext );
// the summation values..........................................................
case 2: return Translate( pg->pgChild ) + Translate( pg->pgChild->pgNext );
// the subtraction values........................................................
case 3: return Translate( pg->pgChild ) - Translate( pg->pgChild->pgNext );
// divide is a special operator in GP (no closure property) so is somewhere else.
case 4: return Divide( pg->pgChild );
// TERMINALS
// only one the X variable which is set in evaluatefitness()
case 5: return globalX;
// the default which returns a value between 0 and 9.........................
default: return (unsigned int)(pg->iValue - 32768);
}
}
// The translateprint function for the character strings from GP iValues
ostream& TranslatePrintROOT( ostream& os, Gene *pg )
{
switch ( pg->iValue )
{
// FUNCTIONS
// The multiplier values.........................................................
case 1: os << " ( *";
break;
// the summation values..........................................................
case 2: os << " ( +";
break;
// the subtraction values........................................................
case 3: os << " ( -";
break;
// special form of divide which has closure traditonally shown as a %............
case 4: os << " ( %";
break;
// TERMINALS
// only one the X variable which is set in evaluatefitness()
case 5: os << " X";
break;
// the default which return a real number between 0 and 9.....................
default: os << " " << (unsigned int)(pg->iValue - 32768);
break;
}
// return this even though you probably don't need to as you have been acting
// on a reference all along better to be safe than sorry in my opinion...
return os;
}
// Unfortunately because of ADFS and the need to alter the printing style of GPs
// the GP operator << needs to know reside here..................................
// This does not need to be understood just used by example if you wish..........
ostream& operator <<(ostream& os, GP *pgp )
{
if ( pgp )
{
// set up global genetic program variable to use ROOT macro defined above
// this is useful for ADFs but not particularly helpful here
pgpGlobal = pgp;
// prints out a GP simple really isnt here. The initial bracket is a hack to get
// the total number of opening and closing number of brackets right.............
os << "(" << ROOT << endl;
}
// must return this value even though it isnt really needed.....................
return os;
}
// This function is called right at the start of the GP system before creating any GPs
// at all. This means all global variable, function and terminal set should be defined
// here. Also all Translate function should have all their initial pointers set up here
// In gpcpp all function and terminals are considered as number this tells the system
// what those number should be so they can be use in Translate...() functions
void InitialiseGPS()
{
// F(main) = { *,+,-,% }
// T(main) = { X }
if (!(FunctionSets[0] = new FS( 3, 1,2,3, 2,2,2 )) ) ExitSystem( "Initialise");
if (!(TerminalSets[0] = new TS( 2, 5, RandomReal, 10 )) ) ExitSystem( "Initialise" );
// only need to be set up once so use global ....
Translate = TranslateROOT;
TranslatePrint = TranslatePrintROOT;
// Run through the function and values working out answers to function defined at
// the beginning of this file.....................................................
for ( int i = 0; i < 10; i++ )
{
ques[i] = (float)i;
answ[i] = FUNCTION( (float)i );
}
}
//This is called right at the end of the GP system and can clear up all global variables
// created in InitialiseGPS() and anywhere else.........................................
void CleanUpGPS()
{
delete FunctionSets[0];
delete TerminalSets[0];
}
// this function is the divide with closure basically if you divide anything by zero you
// get an error so we have to stop this process. We check for a denom == 0 and return 0.
FITNESS Divide( Gene *pg )
{
FITNESS numer = Translate( pg );
FITNESS denom = Translate( pg->pgNext );
if ( denom == 0.0 ) return 0.0;
else return numer / denom;
}
// symbreg.cc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -