⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symbreg2.cc

📁 genetic programming in C++ Adam Fraser University Of Salford, Salford, M5 4WT, United Kingdom
💻 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 + -