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

📄 ga1dbinstrgenome.cpp

📁 遗传算法工具箱C++
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// $Header$/* ----------------------------------------------------------------------------  binstr1.C  mbwall 19apr95  Copyright (c) 1995 Massachusetts Institute of Technology                     all rights reserved DESCRIPTION:  Source file for the 1D binary string genome.---------------------------------------------------------------------------- */#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include "gaerror.h"#include "garandom.h"#include "GA1DBinStrGenome.h"#include "GAMask.h"#define SWAP(a,b) {unsigned int tmp=a; a=b; b=tmp;}/* ----------------------------------------------------------------------------   Genome class definition---------------------------------------------------------------------------- */// Set all the initial values to NULL or zero, then allocate the space we'll// need (using the resize method).  We do NOT call the initialize method at// this point - initialization must be done explicitly by the user of the// genome (eg when the population is created or reset).  If we called the// initializer routine here then we could end up with multiple initializations// and/or calls to dummy initializers (for example when the genome is // created with a dummy initializer and the initializer is assigned later on).GA1DBinaryStringGenome::GA1DBinaryStringGenome(unsigned int len, 		       GAGenome::Evaluator f, void * u) :GABinaryString(len),GAGenome(DEFAULT_1DBINSTR_INITIALIZER, 	 DEFAULT_1DBINSTR_MUTATOR,	 DEFAULT_1DBINSTR_COMPARATOR) {  evaluator(f);  userData(u);  crossover(DEFAULT_1DBINSTR_CROSSOVER); // assign the default sexual crossover  nx=minX=maxX=0;  resize(len);}// This is the copy initializer.  We set everything to the default values, then// copy the original.  The BinaryStringGenome creator takes care of zeroing// the data and sz members.GA1DBinaryStringGenome::GA1DBinaryStringGenome(const GA1DBinaryStringGenome& orig) :GABinaryString(orig.GABinaryString::size()),GAGenome() {  nx=minX=maxX=0;  GA1DBinaryStringGenome::copy(orig);}GA1DBinaryStringGenome::~GA1DBinaryStringGenome() {}// The clone member creates a duplicate (exact or just attributes, depending// on the flag).  The caller is responsible for freeing the memory that is // allocated by this method.GAGenome*GA1DBinaryStringGenome::clone(GAGenome::CloneMethod flag) const {  GA1DBinaryStringGenome *cpy = new GA1DBinaryStringGenome(nx);  if(flag == CONTENTS){    cpy->copy(*this);  }  else{    cpy->GAGenome::copy(*this);    cpy->maxX = maxX; cpy->minX = minX;  }  return cpy;}// This is the class-specific copy method.  It will get called by the super// class since the superclass operator= is set up to call ccopy (and that is// what we define here - a virtual function).  We should check to be sure that// both genomes are the same class and same dimension.  This function tries// to be smart about they way it copies.  If we already have data, then we do// a memcpy of the one we're supposed to copy.  If we don't or we're not the // same size as the one we're supposed to copy, then we adjust ourselves.//   The BinaryStringGenome takes care of the resize in its copy method.// It also copies the bitstring for us.voidGA1DBinaryStringGenome::copy(const GAGenome & orig){  if(&orig == this) return;  const GA1DBinaryStringGenome* c =     DYN_CAST(const GA1DBinaryStringGenome*, &orig);  if(c) {    GAGenome::copy(*c);    GABinaryString::copy(*c);    nx = c->nx; minX = c->minX; maxX = c->maxX;  }}//   Resize the genome.  If someone specifies ANY_RESIZE then we pick a random// size within the behaviour limits that have been set.  If limits have been// set and someone passes us something outside the limits, we resize to the// closest bound.  If the genome is fixed size (ie min limit equals max limit)// then we resize to the specified value and move the min/max to match it.intGA1DBinaryStringGenome::resize(int l){  if(l == STA_CAST(int, nx)) return nx;  if(l == GAGenome::ANY_SIZE)    l = GARandomInt(minX, maxX);  else if(l < 0)    return nx;			// do nothing  else if(minX == maxX)    minX=maxX=l;  else{    if(l < STA_CAST(int, minX)) l=minX;    if(l > STA_CAST(int, maxX)) l=maxX;  }  GABinaryString::resize(l);  if(l > STA_CAST(int, nx))    for(int i=nx; i<l; i++)      bit(i, GARandomBit());  nx = l;  _evaluated = gaFalse;  return sz;}#ifdef GALIB_USE_STREAMS// We read data from a stream as a series of 1's and 0's.  We want a continuous// stream (ie no spaces) but if there are spaces then we can handle them.  We// ignore all whitespace.  We ignore anything that is not a digit.  If it is a// zero then we set to zero.  Anything else is a 1.intGA1DBinaryStringGenome::read(STD_ISTREAM & is){  static char c;  unsigned int i=0;  while(!is.fail() && !is.eof() && i<nx) {    is >> c;    if(isdigit(c)) gene(i++, ((c == '0') ? 0 : 1));  }  _evaluated = gaFalse;  if(is.eof() && i < nx){    GAErr(GA_LOC, className(), "read", gaErrUnexpectedEOF);    is.clear(STD_IOS_BADBIT | is.rdstate());    return 1;  }  return 0;}// When we write the data to a stream we do it without any spaces.  Also, there// is no newline at the end of the stream of digits.intGA1DBinaryStringGenome::write(STD_OSTREAM & os) const{  for(unsigned int i=0; i<nx; i++)    os << gene(i);  return 0;}#endif//   Set the resize behaviour of the genome.  A genome can be fixed// length, resizeable with a max and min limit, or resizeable with no limits// (other than an implicit one that we use internally).//   A value of 0 means no resize, a value less than zero mean unlimited // resize, and a positive value means resize with that value as the limit.//   We return the upper limit of the genome's size.intGA1DBinaryStringGenome::resizeBehaviour(unsigned int lower, unsigned int upper){  if(upper < lower){    GAErr(GA_LOC, className(), "resizeBehaviour", gaErrBadResizeBehaviour);    return resizeBehaviour();  }  minX = lower; maxX = upper;  if(nx > upper) resize(upper);  if(nx < lower) resize(lower);  return resizeBehaviour();}int GA1DBinaryStringGenome::resizeBehaviour() const {  int val = maxX;  if(maxX == minX) val = FIXED_SIZE;  return val;}int GA1DBinaryStringGenome::equal(const GA1DBinaryStringGenome& c,      unsigned int dest, unsigned int src, unsigned int len) const {  return GABinaryString::equal(c,dest,src,len);}int GA1DBinaryStringGenome::equal(const GAGenome & c) const {  if(this == &c) return 1;  const GA1DBinaryStringGenome* b = DYN_CAST(const GA1DBinaryStringGenome*,&c);  int eq = 0;  if(b) {    eq = ((nx != b->nx) ? 0 : GABinaryString::equal(*b,0,0,nx));  }  return eq;}/* ----------------------------------------------------------------------------   Operators---------------------------------------------------------------------------- *///   Set the bits of the genome to random values.  We use the library's// random bit function so we don't have to worry about machine-specific stuff.//   We also do a resize so the genome can resize itself (randomly) if it// is a resizeable genome.void GA1DBinaryStringGenome::UniformInitializer(GAGenome & c){  GA1DBinaryStringGenome &child=DYN_CAST(GA1DBinaryStringGenome &, c);  child.resize(GAGenome::ANY_SIZE); // let chrom resize if it can  for(int i=child.length()-1; i>=0; i--)    child.gene(i, GARandomBit()); // initial values are all random}//   Unset all of the bits in the genome.void GA1DBinaryStringGenome::UnsetInitializer(GAGenome & c){  GA1DBinaryStringGenome &child=DYN_CAST(GA1DBinaryStringGenome &, c);  child.resize(GAGenome::ANY_SIZE); // let chrom resize if it can  child.unset(0, child.length());}//   Set all of the bits in the genome.void GA1DBinaryStringGenome::SetInitializer(GAGenome & c){  GA1DBinaryStringGenome &child=DYN_CAST(GA1DBinaryStringGenome &, c);  child.resize(GAGenome::ANY_SIZE); // let chrom resize if it can  child.set(0, child.length());}// This function gets called a lot (especially for the simple ga) so it must// be as streamlined as possible.  If the mutation probability is small, then// we must call random on each bit in the string.  Otherwise, can can simply// mutate a known number of bits (based on the mutation rate).  We don't check// to see how many bits we flip, nor do we keep track of which ones got flipped// so this can result in an actual mutation that is lower than that specified,// but the bigger the genome and the smaller the mutation probability, the// better the chance that it will match the desired mutation rate.//   If nMut is greater than 1, then we round up, so a mutation of 2.2 would// be 3 mutations, and 2.9 would be 3 as well.  nMut of 3 would be 3 mutations.int GA1DBinaryStringGenome::FlipMutator(GAGenome & c, float pmut){  GA1DBinaryStringGenome &child=DYN_CAST(GA1DBinaryStringGenome &, c);  register int n, i;  if(pmut <= 0.0) return(0);  float nMut = pmut * STA_CAST(float, child.length());  if(nMut < 1.0){		// we have to do a flip test on each bit    nMut = 0;    for(i=child.length()-1; i>=0; i--){      if(GAFlipCoin(pmut)){	child.gene(i, ((child.gene(i) == 0) ? 1 : 0));	nMut++;      }    }  }  else{				// only flip the number of bits we need to flip    for(n=0; n<nMut; n++){      i = GARandomInt(0, child.length()-1); // the index of the bit to flip      child.gene(i, ((child.gene(i) == 0) ? 1 : 0));    }  }  return(STA_CAST(int, nMut));}// Return a number from 0 to 1 to indicate how similar two genomes are.  For // the binary strings we compare bits.  We count the number of bits that are// the same then divide by the number of bits.  If the genomes are different// length then we return a -1 to indicate that we cannot calculate the // similarity.//   Normal hamming distance makes use of population information - this is not// a hamming measure!  This is a similarity measure of two individuals, not// two individuals relative to the rest of the population.  This comparison is// independent of the population!  (you can do Hamming measure in the scaling// object)floatGA1DBinaryStringGenome::BitComparator(const GAGenome& a, const GAGenome& b){  const GA1DBinaryStringGenome &sis=DYN_CAST(const GA1DBinaryStringGenome&, a);  const GA1DBinaryStringGenome &bro=DYN_CAST(const GA1DBinaryStringGenome&, b);  if(sis.length() != bro.length()) return -1;  if(sis.length() == 0) return 0;  float count = 0.0;  for(int i=sis.length()-1; i>=0; i--)    count += ((sis.gene(i) == bro.gene(i)) ? 0 : 1);  return count/sis.length();}// Randomly take bits from each parent.  For each bit we flip a coin to see if// that bit should come from the mother or the father.  This operator can be // used on genomes of different lengths, but the crossover is truncated to the// shorter of the parents and child.intGA1DBinaryStringGenome::UniformCrossover(const GAGenome& p1, const GAGenome& p2,		 GAGenome* c1, GAGenome* c2){  const GA1DBinaryStringGenome &mom=    DYN_CAST(const GA1DBinaryStringGenome &, p1);  const GA1DBinaryStringGenome &dad=    DYN_CAST(const GA1DBinaryStringGenome &, p2);  int n=0;  int i;  if(c1 && c2){    GA1DBinaryStringGenome &sis=DYN_CAST(GA1DBinaryStringGenome &, *c1);    GA1DBinaryStringGenome &bro=DYN_CAST(GA1DBinaryStringGenome &, *c2);    if(sis.length() == bro.length() &&

⌨️ 快捷键说明

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