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

📄 gene.cc

📁 genetic programming in C++ Adam Fraser University Of Salford, Salford, M5 4WT, United Kingdom
💻 CC
字号:
// gene.cc

//--------------------------------------------------------------------------
// 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
//--------------------------------------------------------------------------


// The base class of the genetic program is the gene which is contains
// the value of the gene and pointers to further genes within the program

//  !!!V.Important... The gene functions contained here are generally of a
//    recursive nature. Therefore a design decision has been made to keep
//    the number of error checking components to a minimum it is therefore
//    imperative that any function that calls these functions must check
//    for any possible errors. Once a correct data structure has been sent
//    checking will be contained within the recursive loop. Thanks.. APF

// RECENT IMPROVEMENTS

// ADF's mean that Gene::Choose is now directly called to find a position
// in a genetic program ( as we have to know which adf we are in as crossover
// between adfs is not a good idea ).  This alters both this function and
// Gene::Nth slightly and also means GP::Nth and GP::Choose are defunct
// and have been lost to history....


// include the gene class def'ns
#include "gene.hpp"
// for random number generator
#include "gprand.hpp"  


// MAIN CODE...


// Print functions..... using iostream
ostream& operator << ( ostream& os, Gene *pg )
{
// print out the string which is returned from the value of this gene.
// note that I also send the value of ostream to this function.....
	TranslatePrint( os, pg );

// if ypu have a child..loop back to print out this child 
	if ( pg->pgChild ) os << pg->pgChild;

// if you have a next member loop back to print this out 
	if ( pg->pgNext )  os << pg->pgNext;
// otherwise you are the last on your group and close up the bracket
	else               os << " )";

// while os is actually a reference C++ likes to return the value..
	return os;
}

// Your fancy constructor debugging tool more than anything else
Gene::Gene( unsigned int iVal )
{
// set iValue to whatever value you wish 
	iValue = iVal;
// set gene so it has no children or next member
	pgChild = NULL;

	pgNext = NULL;
}

// standard destructor this will delete all related genes as well
Gene::~Gene()
{
// if you have a child loop back and delete that
	if ( pgChild ) delete pgChild;
// if you have a next member loop back and delete that
	if ( pgNext )   delete pgNext;
}

// This constructor copies the data from a previously defined gene into the new Gene
// note the lack of error checking of the input being sent to it that is up to you...
Gene::Gene( Gene *pg )
{
// copy the value of a old gene
	iValue = pg->iValue;

// if gene to copy  has a child allocate a new member and loop around
// again with child as gene to copy into new member
	if ( pg->pgChild ) { if ( !(pgChild = new Gene( pg->pgChild )) )        ExitSystem("Gene::Gene");       }
	else pgChild = NULL;

// if gene to copy  has a next allocate a new member and loop around
// again with next as gene to copy into new member
	if ( pg->pgNext ) { if ( !(pgNext = new Gene( pg->pgNext )) ) ExitSystem("Gene::Gene"); }
	else pgNext = NULL;
}

// this copy function is to be used as an overwriting function.  Note that gene must
// therefore already have been created......
void Gene::Copy( Gene *pg )
{
// copy the value of a old gene
	iValue = pg->iValue;

// check for child and next and delete this if they occur.....
	if ( pgChild ) delete pgChild;
	if ( pgNext )  delete pgNext;

// if gene to copy  has a child allocate a new member and loop around
// again with child as gene to copy into new member
	if ( pg->pgChild ) {if  ( !(pgChild = new Gene( pg->pgChild )) ) ExitSystem( "Gene::Copy" );}
	else pgChild = NULL;

// if gene to copy  has a next allocate a new member and loop around
// again with next as gene to copy into new member
	if ( pg->pgNext ) {     if  ( !(pgNext = new Gene( pg->pgNext )) ) ExitSystem( "Gene::Copy" ); }
	else pgNext = NULL;
}

// calculates the length of a genetic program called by GP::Length()
void Gene::Length( unsigned int& riLength )
{
// increment length reference variable
	riLength++;
// check for child and next member and loop back through function if they occur....                         
	if ( pgChild ) pgChild->Length( riLength );
	if ( pgNext )  pgNext->Length( riLength );
}

// calculates the depth called by GP::Depth()
int Gene::Depth( unsigned int iDepth, unsigned int& riMaxdepth )
{
// if the depth now is greater than ever before make maxdepth this depth
	if ( iDepth > riMaxdepth ) riMaxdepth = iDepth;

// check for child and next and loop back through function increasing the depth
// ONLY if a child has been found.
	if ( pgChild ) iDepth = pgChild->Depth( ++iDepth, riMaxdepth );
	if ( pgNext )    iDepth = pgNext->Depth( iDepth, riMaxdepth );

// return 0 depth because by this point we are at bottom of out tree,,,
	return 0;
}


// Returns the Nth gene of the GP AND all its further ancestors. This function
// is useful  for crossover...........                                  APF 9/06/93
Gene* Gene::Nth( unsigned int &iLengthCount )
{
// decrement the length so far and return if this is == 0
	if ( --iLengthCount == 0 ) return this;

// set up pointer to a gene to check if we find a solution
	Gene *pg = NULL;

// if this gene has a child loop back around to function
	if ( pgChild ) pg = pgChild->Nth( iLengthCount );

// check if this gene has a next and also that the solution was not found in
// the previous child section and try to find it in next member
	if ( ( pgNext ) && ( pg == NULL ) ) pg = pgNext->Nth( iLengthCount );

// return pointer to gene which will contain correct pointer at the end
	return pg;
}

// returns the a random gene selected by random number generator
// obviously it is quite important to know the length of the gp
//  before calling this function..

// this also adds a component laid down by Koza that there will be a 90%
//   chance of getting a function. This is produced by going through a loop
//   10 times and returning ONLY if a function is found. This should give a
//   greater chance of getting a function. Note that if you have a single node
//   this function will not hang unlike other components I have written (!).
Gene* Gene::Choose()
{
	unsigned int iTotalLength = 0;
	Gene *pg = NULL;

// calculate the total length of the whole genetic program so far starting at this gene
	Length( iTotalLength );

// loop 10 times
	for ( int i = 0; i < 10; i++ )
	{
// calculate a random number between 1-> TotalLength
		unsigned int iLengthCount = ( gp_rand() % iTotalLength ) + 1;
// find gene with this value.....
		pg = Nth( iLengthCount );
// if this pointer points to a function rather than terminal return this value else
// keep going around the loop
		if ( pg->pgChild ) return pg;
	}
// if after 10 loops still don't have function o/p terminal
	return pg;     
}

// gene.cc

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -