📄 gene.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 + -