📄 ex16.c
字号:
/* ---------------------------------------------------------------------------- ex16.C mbwall 5may95 Copyright (c) 1995-1996 Massachusetts Institute of Technology DESCRIPTION: Illustration of how to use a non-trivial object in the nodes of a treegenome. This example uses points in the nodes.---------------------------------------------------------------------------- */#include <stdio.h>#include <stdlib.h>#include <ga/ga.h>#include <ga/std_stream.h>#define cout STD_COUT#define ostream STD_OSTREAM// This is the object that we're going to put in the nodes. Each point has // three coordinates: x,y,z.class Point {public: Point(float x, float y, float z) { _x = x; _y = y; _z = z; } Point(const Point & p) { _x = p._x; _y = p._y; _z = p._z; } Point & operator=(const Point & p) { _x=p._x;_y=p._y;_z=p._z; return *this; } ~Point() {} float x() const { return _x; } float y() const { return _y; } float z() const { return _z; } float x(float val) { return _x=val; } float y(float val) { return _y=val; } float z(float val) { return _z=val; } friend ostream & operator<<(ostream & os, const Point & p){ os << "(" << p._x << ", " << p._y << ", " << p._z << ")"; return os; }protected: float _x, _y, _z;};// These are the declarations for the functions defined in this file. The // objective function is pretty standard. The tree initializer generates a// random tree. WriteNode is used in the write method for the tree - we // override (specialize) the write method to print out the contents of the// nodes rather than pointers to the contents.float objective(GAGenome &);void TreeInitializer(GAGenome &);void WriteNode(ostream & os, GANode<Point> * n);intmain(int argc, char **argv){ cout << "Example 16\n\n"; cout << "This example uses a SteadyState GA and Tree<int> genome. It\n"; cout << "tries to maximize the size of the tree genomes that it\n"; cout << "contains. The genomes contain points in its nodes. Two\n"; cout << "different runs are made: first with the swap subtree mutator,\n"; cout << "second with the destructive mutator.\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. unsigned int seed = 0; for(int ii=1; ii<argc; ii++) { if(strcmp(argv[ii++],"seed") == 0) { seed = atoi(argv[ii]); } } GATreeGenome<Point> genome(objective); genome.initializer(TreeInitializer); genome.crossover(GATreeGenome<Point>::OnePointCrossover); genome.mutator(GATreeGenome<Point>::SwapSubtreeMutator); GAPopulation swappop(genome, 50); genome.mutator(GATreeGenome<Point>::DestructiveMutator); GAPopulation destpop(genome, 50); GASteadyStateGA ga(genome); ga.nGenerations(10);// first do evolution with subtree swap mutator. ga.population(swappop); cout << "initializing..."; ga.initialize(seed); cout << "evolving for " << ga.nGenerations() << " generations..."; while(!ga.done()){ ga.step(); cout << "."; cout.flush(); } cout << "\n"; genome = ga.statistics().bestIndividual(); cout << "the ga generated a tree with " << genome.size(); cout << " nodes, " << genome.depth() << " levels deep.\n";// now do evolution with destructive swap mutator ga.population(destpop); cout << "\ninitializing..."; ga.initialize(); cout << "evolving for " << ga.nGenerations() << " generations..."; while(!ga.done()){ ga.step(); cout << "."; cout.flush(); } cout << "\n"; genome = ga.statistics().bestIndividual(); cout << "the ga generated a tree with " << genome.size(); cout << " nodes, " << genome.depth() << " levels deep.\n"; return 0;} /* ---------------------------------------------------------------------------- All we do in this objective function is try to maximize the size of the tree.Just return the tree size. This means that if you run this objective functionfor many generations you'll run out of memory! There is no limit to tree orlist sizes built-in to the GA library.---------------------------------------------------------------------------- */floatobjective(GAGenome & c) { GATreeGenome<Point> & chrom = (GATreeGenome<Point> &)c; return chrom.size();}/* ---------------------------------------------------------------------------- This initializer creates a tree of random size (within limits). The maximumnumber of children any node can have is limited, so is the maximum depth ofthe tree. We do it recursively. Each point that is inserted into the treehas random contents. The initializer must first destroy any pre-existing tree or else we have amemory leak (the initializer may be called more than once - for example whenyou re-run the GA).---------------------------------------------------------------------------- */const int MAX_DEPTH = 3;const int MAX_CHILDREN = 2;voidDoChild(GATreeGenome<Point> & tree, int depth) { if(depth >= MAX_DEPTH) return; int n = GARandomInt(0,MAX_CHILDREN); // maximum of 5 children Point p(GARandomFloat(0,25),GARandomFloat(0,25),GARandomFloat(0,25)); tree.insert(p,GATreeBASE::BELOW); for(int i=0; i<n; i++) DoChild(tree, depth+1); tree.parent(); // move the iterator up one level}voidTreeInitializer(GAGenome & c) { GATreeGenome<Point> &tree=(GATreeGenome<Point> &)c;// destroy any pre-existing tree tree.root(); tree.destroy();// create a root node with coordinates 0,0,0, then do the rest. Point p(0,0,0); tree.insert(p,GATreeBASE::ROOT); int n = GARandomInt(0,MAX_CHILDREN); // maximum of 5 children for(int i=0; i<n; i++) DoChild(tree, 0);}/* ---------------------------------------------------------------------------- This is a specialization of the write method for the TreeGenome class. Thedefault write method prints out pointers to the nodes. Here we print thecontents of the nodes. This is a recursive implementation (yuk) but it gets the job done. Beware that it could crash your machine if your stack is limited and your trees getvery big.---------------------------------------------------------------------------- */void WriteNode(ostream & os, GANode<Point> * n) { if(!n) return; GANodeBASE * node = (GANodeBASE *)n; os.width(10); os << ((GANode<Point> *)node)->contents << " "; os.width(10); if(node->parent) os << ((GANode<Point> *)node->parent)->contents << " "; else os << "." << " "; os.width(10); if(node->child) os << ((GANode<Point> *)node->child)->contents << " "; else os << "." << " "; os.width(10); if(node->next) os << ((GANode<Point> *)node->next)->contents << " "; else os << "." << " "; os.width(10); if(node->prev) os << ((GANode<Point> *)node->prev)->contents << "\n"; else os << ".\n"; WriteNode(os, (GANode<Point> *)node->child); for(GANodeBASE * tmp=node->next; tmp && tmp != node; tmp=tmp->next){ os.width(10); os << ((GANode<Point> *)tmp)->contents << " "; os.width(10); if(tmp->parent) os << ((GANode<Point> *)tmp->parent)->contents << " "; else os << "." << " "; os.width(10); if(tmp->child) os << ((GANode<Point> *)tmp->child)->contents << " "; else os << "." << " "; os.width(10); if(tmp->next) os << ((GANode<Point> *)tmp->next)->contents << " "; else os << "." << " "; os.width(10); if(tmp->prev) os << ((GANode<Point> *)tmp->prev)->contents << "\n"; else os << ".\n"; WriteNode(os, (GANode<Point> *)tmp->child); }}template <> intGATreeGenome<Point>::write(ostream & os) const { os << " node parent child next prev\n"; WriteNode(os, (GANode<Point> *)rt); return os.fail() ? 1 : 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/GATree.C>#include <ga/GATreeGenome.C>GALIB_INSTANTIATION_PREFIX GATreeGenome<Point>;GALIB_INSTANTIATION_PREFIX GATree<Point>;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -