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

📄 ex14.cpp

📁 这是一个面向对象的GA遗传算法库GAlib: A C++ Library of Genetic Algorithm Components)
💻 CPP
字号:
/* ----------------------------------------------------------------------------  ex14.C  mbwall 29apr95  Copyright (c) 1995-1996  Massachusetts Institute of Technology DESCRIPTION:   Example program for a composite genome derived from the GAGenome andcontaining a list of lists.  This example shows how to derive your own genomeclass and illustrates the use of one of the template genomes (GAListGenome) from the GAlib.---------------------------------------------------------------------------- */#include <stdio.h>#include <stdlib.h>#include <ga/ga.h>#include <ga/std_stream.h>#define cout STD_COUT#define cerr STD_CERR#define endl STD_ENDL#define istream STD_ISTREAM#define ostream STD_OSTREAM// Here we specify how big the lists will be and how many lists will be in each// composite genome.  These are the default values - you can change them from// the command line.  Beware that this program will break if nrobots is bigger// than the size of the lists.int listsize = 10;int nrobots = 6;// This is the class definition.  We override the methods of the base class and// define a few methods of our own to access the protected members.  The list// genomes in the composite genome are assigned the 'List' operators// by default (they can be overridden by using the 'Operator' members on the// lists explicitly).//   The ID can be any number over 200 (IDs under 200 are reserved for use by// GAlib objects).class RobotPathGenome : public GAGenome {public:  GADefineIdentity("RobotPathGenome", 251);  static void Initializer(GAGenome&);  static int Mutator(GAGenome&, float);  static float Comparator(const GAGenome&, const GAGenome&);  static float Evaluator(GAGenome&);  static void PathInitializer(GAGenome&);  static int Crossover(const GAGenome&, const GAGenome&, GAGenome*, GAGenome*);public:  RobotPathGenome(int nrobots, int pathlength);  RobotPathGenome(const RobotPathGenome & orig) { n=l=0; list=0; copy(orig); }  RobotPathGenome operator=(const GAGenome & arg) { copy(arg); return *this; }  virtual ~RobotPathGenome();  virtual GAGenome *clone(GAGenome::CloneMethod) const ;  virtual void copy(const GAGenome & c);  virtual int equal(const GAGenome& g) const;  virtual int read(istream & is);  virtual int write(ostream & os) const ;  GAListGenome<int> & path(const int i){return *list[i];}  int npaths() const { return n; }  int length() const { return l; }protected:  int n, l;  GAListGenome<int> **list;};RobotPathGenome::RobotPathGenome(int nrobots, int pathlength) :GAGenome(Initializer, Mutator, Comparator){  evaluator(Evaluator); crossover(Crossover); n = nrobots; l = pathlength;  list = (n ? new GAListGenome<int> * [n] : (GAListGenome<int> **)0);  for(int i=0; i<n; i++){    list[i] = new GAListGenome<int>;    list[i]->initializer(PathInitializer);    list[i]->mutator(GAListGenome<int>::SwapMutator);  }}voidRobotPathGenome::copy(const GAGenome& g) {  if(&g != this && sameClass(g)){    GAGenome::copy(g);		// copy the base class part    RobotPathGenome & genome = (RobotPathGenome &)g;    if(n == genome.n){      for(int i=0; i<n; i++)	list[i]->copy(*genome.list[i]);    }    else{      int i;      for(i=0; i<n; i++)	delete list[i];      delete [] list;      n = genome.n;      list = new GAListGenome<int> * [n];      for(i=0; i<n; i++)	list[i] = (GAListGenome<int> *)genome.list[i]->clone();    }  }}RobotPathGenome::~RobotPathGenome(){  for(int i=0; i<n; i++)    delete list[i];  delete [] list;}GAGenome*RobotPathGenome::clone(GAGenome::CloneMethod) const {  return new RobotPathGenome(*this); }int RobotPathGenome::equal(const GAGenome& g) const {  RobotPathGenome& genome = (RobotPathGenome&)g;  int flag=0;  for(int i=0; i<n && flag==0; i++)    flag = list[i]->equal(*genome.list[i]);  return flag;}int RobotPathGenome::read(istream & is) {  for(int i=0; i<n; i++)    is >> *(list[i]);  return is.fail() ? 1 : 0;}int RobotPathGenome::write(ostream & os) const {  for(int i=0; i<n; i++)    os << "list " << i << ":\t" << *(list[i]) << "\n";  return os.fail() ? 1 : 0;}// These are the definitions of the operators for the robot path genome.void RobotPathGenome::Initializer(GAGenome& g) {  RobotPathGenome & genome = (RobotPathGenome &)g;  for(int i=0; i<genome.npaths(); i++)    genome.path(i).initialize();  genome._evaluated = gaFalse;}int RobotPathGenome::Mutator(GAGenome& g, float pmut) {  RobotPathGenome & genome = (RobotPathGenome &)g;  int nMut = 0;  for(int i=0; i<genome.npaths(); i++)    nMut += genome.path(i).mutate(pmut);  if(nMut) genome._evaluated = gaFalse;  return nMut;}floatRobotPathGenome::Comparator(const GAGenome& a, const GAGenome& b) {  RobotPathGenome& sis = (RobotPathGenome &)a;  RobotPathGenome& bro = (RobotPathGenome &)b;  float diff = 0;  for(int i=0; i<sis.npaths(); i++)    diff += sis.path(i).compare(bro.path(i));  return diff/sis.npaths();}// The objective function should evaluate the genomes.  This one tries to// put the node with value 0 into the nth position where n is the number of the// list in the composite genome.  We're assuming that there are more nodes// in the list than there are lists in the composite genome.floatRobotPathGenome::Evaluator(GAGenome & c) {  RobotPathGenome & genome = (RobotPathGenome &)c;  float score=0;  for(int i=0; i<genome.npaths(); i++)    if(*genome.path(i).warp(i) == 0) score += 1;  return score;}// This crossover method assumes that all of the robot path genomes have the // same number of paths in them.  With a few modifications you could make the// paths be variable length, but then you must use a crossover method other// than the partial match crossover used here (defined in the robot path// crossover object).intRobotPathGenome::Crossover(const GAGenome& a, const GAGenome& b, GAGenome* c, GAGenome* d) {  RobotPathGenome& mom = (RobotPathGenome &)a;  RobotPathGenome& dad = (RobotPathGenome &)b;  int n=0;  if(c && d){    RobotPathGenome& sis = (RobotPathGenome &)*c;    RobotPathGenome& bro = (RobotPathGenome &)*d;    for(int i=0; i<mom.npaths(); i++)      GAListGenome<int>::PartialMatchCrossover(mom.path(i), dad.path(i),					       &sis.path(i), &bro.path(i));    sis._evaluated = gaFalse;    bro._evaluated = gaFalse;    n=2;  }  else if(c) {    RobotPathGenome& sis = (RobotPathGenome &)*c;    for(int i=0; i<mom.npaths(); i++)      GAListGenome<int>::PartialMatchCrossover(mom.path(i), dad.path(i),					       &sis.path(i), 0);    sis._evaluated = gaFalse;    n=1;  }  else if(d) {    RobotPathGenome& bro = (RobotPathGenome &)*d;    for(int i=0; i<mom.npaths(); i++)      GAListGenome<int>::PartialMatchCrossover(mom.path(i), dad.path(i),					       0, &bro.path(i));    bro._evaluated = gaFalse;    n=1;  }  return n;}// This is the initialization operator for our lists.  We create a list that is// n long and whose nodes contain numbers in sequence.//   The first thing to do in the initializer is to clear out any old // contents - we do not want to build our new list on a previously existing// one!  Notice that we have to cast the genome into the type of // genome we're using (in this case a list).  The GA always operates on// generic genomes.//   All of our lists must be the same length since we're going to use the// ordered crossover operators.void RobotPathGenome::PathInitializer(GAGenome & c){  GAListGenome<int> & list = (GAListGenome<int> &)c;// We must first destroy any pre-existing list.  while(list.head()) list.destroy();// Insert the head of the list.  This node has a random number in it, but the// number is in a range different than those in the rest of the list.  This// way we'll be able to see how the lists get scrambled up.  Since we're using// ordered crossover (see the header file) we should never end up with more // than one node in each list that has a given value.  list.insert(0, GAListBASE::HEAD);// Loop through n times and append nodes onto the end of the list.  int i;  for(i=0; i<listsize-1; i++)    list.insert(i+20, GAListBASE::AFTER);// Now randomize the contents of the list.  for(i=0; i<listsize; i++)    if(GARandomBit()) list.swap(i, GARandomInt(0, listsize-1));}// Here is the specialization of the write method for our lists.  The default // write method just prints out pointers to the contents of the nodes (it has// no way of knowing in advance how you'll want things printed).  Here we // do almost the same thing, but print out the contents of the nodes rather// than the pointers to the contents.template <> intGAListGenome<int>::write(ostream & os) const {  int *cur, *head;  GAListIter<int> iter(*this);  if((head=iter.head()) != 0) os << *head << " ";  for(cur=iter.next(); cur && cur != head; cur=iter.next())    os << *cur << " ";  return os.fail() ? 1 : 0;}intmain(int argc, char *argv[]){  cout << "Example 14\n\n";  cout << "This example shows how to create a genome that contains\n";  cout << "a list of lists.  We create a composite genome that has\n";  cout << "lists in it.  Each list has some nodes, only one of which\n";  cout << "contains the number 0.  The objective is to move the node with\n";  cout << "number 0 in it to the nth position where n is the number of the\n";  cout << "list within the composite genome.\n\n";  cout.flush();// See if we've been given a seed to use (for testing purposes).  When you// specify a random seed, the evolution will be exactly the same each time// you use that seed number.  int i;  for(i=1; i<argc; i++){    if(strcmp("nr", argv[i]) == 0){      if(++i >= argc){        cerr << argv[0] << ": number of robots needs a value.\n";        exit(1);      }      else{	nrobots = atoi(argv[i]);        continue;      }    }    else if(strcmp("pl", argv[i]) == 0){      if(++i >= argc){        cerr << argv[0] << ": path length needs a value.\n";        exit(1);      }      else{	listsize = atoi(argv[i]);        continue;      }    }    else if(strcmp(argv[i],"seed") == 0) {      if(++i >= argc){        cerr << argv[0] << ": seed needs a value.\n";        exit(1);      }      else {	GARandomSeed((unsigned int)atoi(argv[i]));      }    }    else if(strcmp("help",argv[i]) == 0){      cerr << "valid arguements include standard GAlib arguments plus:\n";      cerr << "  nr\tnumber of robots (" << nrobots << ")\n";      cerr << "  pl\tlength of the paths (" << listsize << ")\n";      cerr << "\n";      exit(1);    }  }  if(listsize < nrobots) {    cerr << "path length must be greater than the number of robots.\n";    exit(1);  }  RobotPathGenome genome(nrobots, listsize);  GASteadyStateGA ga(genome);  ga.parameters(argc,argv);  ga.evolve();  genome.initialize();  cout << "a randomly-generated set of paths:\n" << genome << endl;  cout << "the ga generated:\n" << ga.statistics().bestIndividual() << "\n";  return 0;}// force instantiations for compilers that do not do auto instantiation.// for some compilers (e.g. metrowerks) this must come after any// specializations or you will get 'multiply-defined errors when you compile.#if !defined(GALIB_USE_AUTO_INST)#include <ga/GAList.C>#include <ga/GAListGenome.C>GALIB_INSTANTIATION_PREFIX GAList<int>;GALIB_INSTANTIATION_PREFIX GAListGenome<int>;#endif

⌨️ 快捷键说明

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