├── gui ├── rect.h ├── rect.cpp ├── color.h ├── color.cpp ├── screen.h ├── grid.h ├── widget.h ├── graph.h ├── widget.cpp └── screen.cpp ├── sinTest.h ├── layer.h ├── main.cpp ├── Makefile ├── population.h ├── net.h ├── genetic.h ├── layer.cpp ├── sinTest.cpp ├── string.h ├── neuron.h ├── array.h ├── README.md ├── population.cpp ├── string.cpp ├── net.cpp ├── neuron.cpp └── genetic.cpp /gui/rect.h: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifndef _RECT_H_ 4 | #define _RECT_H_ 5 | 6 | class Rect{ 7 | public: Rect(); 8 | Rect(int,int,int,int); 9 | int x,y,w,h; 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /gui/rect.cpp: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include "rect.h" 4 | 5 | Rect::Rect(){ 6 | } 7 | Rect::Rect(int x, int y, int w, int h){ 8 | this->x = x; 9 | this->y = y; 10 | this->w = w; 11 | this->h = h; 12 | } 13 | -------------------------------------------------------------------------------- /gui/color.h: -------------------------------------------------------------------------------- 1 | // color.h - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifndef _COLOR_H_ 4 | #define _COLOR_H_ 5 | 6 | class Color{ 7 | public: Color(); 8 | Color(double r, double g, double b); 9 | Color &operator=(const Color &c); 10 | double red,green,blue; 11 | }; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /gui/color.cpp: -------------------------------------------------------------------------------- 1 | // color.cpp - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include "color.h" 4 | 5 | Color::Color(){ 6 | } 7 | 8 | Color::Color(double r, double g, double b){ 9 | red = r; 10 | green = g; 11 | blue = b; 12 | } 13 | 14 | Color &Color::operator=(const Color &c){ 15 | red = c.red; 16 | green = c.green; 17 | blue = c.blue; 18 | return *this; 19 | } 20 | -------------------------------------------------------------------------------- /sinTest.h: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifndef _SINTEST_H_ 4 | #define _SINTEST_H_ 5 | 6 | #include "genetic.h" 7 | #include "array.h" 8 | 9 | class Net; 10 | 11 | class SinTest : Genetic{ 12 | public: SinTest(); 13 | void evaluate(Net *net); 14 | void calibrate(Net *net); 15 | bool criteria(Net *net); 16 | void go(); 17 | int hist_i; 18 | Array board; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /layer.h: -------------------------------------------------------------------------------- 1 | // layer.h - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | class Neuron; 4 | 5 | class Layer{ 6 | public: Layer(int inputs, int outputs, double a, double b); 7 | ~Layer(); 8 | void run(); 9 | void init(double a, double b); 10 | void setInputs(Layer *l); 11 | Layer &operator=(Layer &); 12 | private: 13 | friend class Net; 14 | int inputs,outputs; 15 | Neuron **input; 16 | Neuron *neuron; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /gui/screen.h: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #include "widget.h" 5 | 6 | using namespace std; 7 | 8 | class Screen : public Widget{ 9 | public: Screen(int w, int h); 10 | ~Screen(); 11 | void render(Rect r); 12 | private: 13 | static void fillRect(Rect, Color); 14 | static void drawLine(int,int,int,int, Color); 15 | static void drawCircle(int,int,int, Color); 16 | static SDL_Surface *scr; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifdef HAVE_CONFIG_H 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | #include "sinTest.h" 10 | //#include "trader.h" 11 | 12 | using namespace std; 13 | 14 | int main(int argc, char *argv[]){ 15 | #if 1 16 | // predict sin function 17 | SinTest test; 18 | test.go(); 19 | #else 20 | // do the real thing - predict stock market 21 | Trader trader; 22 | trader.go(); 23 | #endif 24 | 25 | return EXIT_SUCCESS; 26 | } 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # genetic algorithms - evolution of neural networks using genetic algorithms 3 | 4 | OBJECTS = main.o genetic.o population.o net.o layer.o neuron.o sinTest.o gui/widget.o gui/rect.o string.o gui/color.o gui/screen.o 5 | 6 | all: ga 7 | 8 | clean: 9 | rm ga $(OBJECTS) 10 | 11 | ga: $(OBJECTS) 12 | g++ -o ga $(OBJECTS) -framework SDL -framework Cocoa 13 | 14 | %.o: %.cpp 15 | g++ -DHEAVY -DHISTORY=15 -DFUTURE=15 -I/Library/Frameworks/SDL.framework/Headers -c -O2 -o $@ $< # -framework SDL -framework Cocoa 16 | 17 | 18 | -------------------------------------------------------------------------------- /population.h: -------------------------------------------------------------------------------- 1 | // population.h - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | class Net; 4 | 5 | class Population{ 6 | public: Population(int individuals, int inputs, int outputs, double a, double b); 7 | void init(int induvidual, double a, double b); 8 | void mix(int i, int j); 9 | void mutate(int induvidual, double level); 10 | void copy(int individual1, int individual2); 11 | void copy(int individual1, Population *population, int individual2); 12 | void swap(int individual1, int individual2); 13 | Net *getIndividual(int i); 14 | void sort(int safearea, class Genetic *gen); 15 | private: 16 | int individuals; 17 | Net **individual; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /net.h: -------------------------------------------------------------------------------- 1 | // net.h - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include "layer.h" 4 | #include "neuron.h" 5 | 6 | class Net{ 7 | public: Net(int inputs, int outputs, int layers, double a, double b); 8 | void init(double a, double b); 9 | void run(); 10 | void mix(); 11 | void mix(int n1, int n2); 12 | void mix(Net *); 13 | void mutate(double dev); 14 | Net &operator=(Net &); 15 | double getScore();//{ return score; } 16 | void setInput(int n, float val){ 17 | layer[0]->input[n]->val = val; 18 | } 19 | double *getOutput(){ return output; } 20 | void breed(Net *a, Net *b); 21 | void setCalibration(double min, double max); 22 | int getAge(){ return age; } 23 | private: 24 | friend class Population; 25 | friend class Genetic; 26 | int neurons,layers; 27 | Neuron **neuron; 28 | Layer **layer; 29 | double score; 30 | int outputs; 31 | double *output; 32 | int age; 33 | double max,min; 34 | bool calibrated; 35 | int name; 36 | }; 37 | -------------------------------------------------------------------------------- /gui/grid.h: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include "widget.h" 4 | #include 5 | 6 | class Grid : public Widget{ 7 | public: Grid(Widget *p); 8 | void render(Rect r); 9 | }; 10 | 11 | Grid::Grid(Widget *p) : Widget(p){ 12 | } 13 | 14 | void Grid::render(Rect r){ 15 | 16 | if(!getChildren()->getCount()) return; 17 | 18 | int hb = int(sqrt(double(getChildren()->getCount()))+.5); //log2(getChildren()->getCount()); 19 | if(hb==0) hb=1; 20 | int vb = getChildren()->getCount()/hb; 21 | if(vb*hbgetCount()) vb++; 22 | 23 | int bw = r.w/hb; 24 | int bh = r.h/vb; 25 | int n=0; 26 | for(int yb=0; ybgetCount()){ 29 | Widget *w = (*getChildren())[n++]; 30 | w->Widget::render(Rect(r.x+xb*bw,r.y+yb*bh,r.w/hb,r.h/vb)); 31 | }else fillRect(Rect(r.x+xb*bw,r.y+yb*bh,r.w/hb,r.h/vb),Color(0,0,0)); 32 | } 33 | } 34 | // for(int n=0; ngetCount(); n++){ 35 | // Widget *w = (*getChildren())[n]; 36 | // w->Widget::render(Rect(r.x,r.y,r.w/hb,r.h/vb)); 37 | // } 38 | noRender(); 39 | } 40 | -------------------------------------------------------------------------------- /gui/widget.h: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifndef _WIDGET_H_ 4 | #define _WIDGET_H_ 5 | 6 | #include 7 | #ifdef HAVE_SDL_TTF 8 | #include 9 | #endif 10 | #include "color.h" 11 | #include "rect.h" 12 | #include "../array.h" 13 | 14 | class Widget{ 15 | public: Widget(); 16 | Widget(Widget *parent); 17 | ~Widget(); 18 | Widget *getParent() const; 19 | const Array *getChildren() const; 20 | void attach(Widget *child); 21 | void detach(Widget *child); 22 | virtual void render(Rect r); 23 | // Rect getView(); 24 | // void setView(Rect r); 25 | static void (*fillRect)(Rect r, Color c); 26 | static void (*drawLine)(int x, int y, int x1, int y1, Color c); 27 | static void (*drawCircle)(int x, int y, int d, Color c); 28 | void noRender(){ dorender = false; } 29 | void drawClippedLine(int x, int y, int x1, int y1, Color c); 30 | private: 31 | friend class Screen; 32 | friend class TickerWidget; 33 | #ifdef HAVE_SDL_TTF 34 | static TTF_Font *font; 35 | #endif 36 | Widget *parent; 37 | Array children; 38 | Rect view; 39 | bool dorender; 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /genetic.h: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifndef _GENETIC_H 4 | #define _GENETIC_H 5 | 6 | class Population; 7 | class Net; 8 | 9 | class Genetic{ 10 | public: Genetic(int populations, int induviduals, int inputs, int outputs); 11 | virtual ~Genetic(){} 12 | 13 | Population *getPopulation(int n){ return population[n]; } 14 | void nextGeneration(); 15 | void stimulate(Net *net, double score); 16 | void setTrainingPeriod(int start, int end); 17 | virtual void initGeneration(){} 18 | virtual double getInput(int t){ return 0; } 19 | virtual void evaluate(Net *) = 0; 20 | virtual void calibrate(Net *net){} 21 | virtual bool criteria(Net *net){ return true; } 22 | double getEval(int t); 23 | void setEval(int t, double v); 24 | double getBoardScore(){ return board_score; } 25 | int getBoardAge(){ return board_age; } 26 | private: 27 | int inputs; 28 | int startscore; 29 | int start; 30 | int stop; 31 | int generation; 32 | int individuals; 33 | int populations; 34 | Population **population; 35 | bool newgen; 36 | double min,max; 37 | double *val; 38 | int lastage; 39 | double board_score; 40 | int board_age; 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /gui/graph.h: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | // simple template for drawing graphs 4 | 5 | template class Graph : public Array, public Widget{ 6 | public: Graph() : Array(), Widget(){ 7 | } 8 | ~Graph(){ 9 | } 10 | 11 | void add(T v){ 12 | if(Array::getCount()==0) min=max=v; 13 | else{ 14 | if(v>max) max=v; 15 | else if(v::add(v); 18 | } 19 | 20 | void render(Rect r){ 21 | fillRect(r,Color(1,1,1)); 22 | 23 | int w = r.w; 24 | int h = r.h; 25 | int base = h/10; 26 | int border = base + h/20; 27 | 28 | drawLine(r.x,r.y+h-1,r.x+r.w,r.y+h-1,Color(0,0,0)); 29 | drawLine(r.x+r.w-1,r.y,r.x+r.w,r.y+h-1,Color(0,0,0)); 30 | 31 | // baseline 32 | drawLine(r.x,r.y+h-base,r.x+r.w,r.y+h-base,Color(0,0,0)); 33 | // double high = log2(max); 34 | // double low = log2(min); 35 | double high = max; 36 | double low = min; 37 | 38 | // main graph 39 | if(Array::getCount()){ 40 | int lastx,lasty; 41 | for(int n=0; n::getCount(); n++){ 42 | int tox= r.x + n*w/Array::getCount(); 43 | // int toy= r.y + int(h-base-(log2((*this)[n])-low)*(h-border)/(high-low)); 44 | int toy= r.y + int(h-base-(((*this)[n])-low)*(h-border)/(high-low)); 45 | if(n){ 46 | drawClippedLine( 47 | lastx, 48 | lasty, 49 | tox, 50 | toy,Color(0,0,0)); 51 | } 52 | lasty=toy; 53 | lastx=tox; 54 | } 55 | } 56 | } 57 | private: 58 | T min,max; 59 | }; 60 | -------------------------------------------------------------------------------- /layer.cpp: -------------------------------------------------------------------------------- 1 | // population.cpp - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #include 5 | #include 6 | #include "layer.h" 7 | #include "neuron.h" 8 | 9 | using namespace std; 10 | 11 | inline int irand( int range ){ 12 | return( rand() % range ); 13 | } 14 | 15 | // Create a layer of neurons 16 | // input: inputs = number of inputs 17 | // outputs = number of outputs 18 | // a & b = normalization value for the neurons (min & max) 19 | 20 | Layer::Layer(int inputs, int outputs, double a, double b){ 21 | this->inputs = inputs; 22 | this->outputs = outputs; 23 | typedef Neuron* nptr; 24 | input = new nptr[inputs]; 25 | neuron = new Neuron[outputs]; 26 | for(int n=0; noutputs; i++){ 45 | input[i] = &l->neuron[i]; 46 | } 47 | } 48 | 49 | Layer &Layer::operator=(Layer &s){ 50 | if(outputs!=s.outputs){ 51 | cerr << "Layer::operator = cannot copy layer!" << endl; 52 | exit(EXIT_FAILURE); 53 | } 54 | for(int n=0; nsetCalibration(-1,1); 18 | } 19 | 20 | // evaluate and stimulate a neural net. Todo?: Futuristic punishment/reward 21 | // inputs: net = neural net to evaluate 22 | 23 | void SinTest::evaluate(Net *net){ 24 | int i=rand()%1000; 25 | for(int n=0; n<8; n++) net->setInput(n,double(i)/1000.0); 26 | net->run(); 27 | stimulate(net,-fabs(sin(double(i*3)/1000.0)-*net->getOutput())); 28 | } 29 | 30 | bool SinTest::criteria(Net *net){ 31 | if(net->getAge()<60) return false; // keep youngsters out of the score board 32 | return true; 33 | } 34 | 35 | 36 | // start evolution of neural networks! 37 | 38 | void SinTest::go(){ 39 | Screen scr(640,512); 40 | Graph score; 41 | Graph age; 42 | Graph sample; 43 | Graph sample2; 44 | Grid grid(&scr); 45 | grid.attach(&score); 46 | grid.attach(&sample); 47 | grid.attach(&age); 48 | grid.attach(&sample2); 49 | while(true){ 50 | for(int n=0; n<10; n++) nextGeneration(); 51 | sample.clear(); 52 | sample2.clear(); 53 | Net *net = getPopulation(0)->getIndividual(0); 54 | for(int i=0; i<100; i++){ 55 | for(int n=0; n<8; n++) net->setInput(n,double(i)/100.0); 56 | net->run(); 57 | sample.add(*net->getOutput()); 58 | sample2.add(sin(double(i*3)/100.0)); 59 | } 60 | score.add(getBoardScore()); 61 | age.add(getBoardAge()); 62 | scr.render(Rect(0,0,640,512)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /string.h: -------------------------------------------------------------------------------- 1 | // string.h - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifndef __STRING__H 4 | #define __STRING__H 5 | 6 | #include "array.h" 7 | //#include "streams.h" 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Socket; 13 | 14 | class String : public /*base::*/Array{ 15 | public: String(); 16 | String(const String &str); 17 | String(const char *str); 18 | ~String(); 19 | void toLower(); 20 | //const char *getString() const{ return buffer; } 21 | const char *getString() const{ 22 | //return list; 23 | static char str[1024]; 24 | char *d = str; 25 | for(int n=0; n(const String &str) const; 41 | String &operator=(const String &str); 42 | String operator+(const String &); 43 | String &operator<<(const char *str); 44 | String &operator<<(const String &str); 45 | String &operator<<(const char c); 46 | String &operator<<(const Socket &); 47 | //friend ostream &operator<<(ostream &out, const String &in); 48 | //friend Socket &operator<<(Socket &out, const String &in); 49 | 50 | //friend OStream &operator<<(OStream &out, const String &in); 51 | //friend IStream &operator>>(IStream &i, String &o); 52 | 53 | // Socket &operator<<(const String); 54 | //friend void operator<<(Socket &,const String&); 55 | 56 | /* 57 | friend class Socket &operator<<(String &out, Socket &in); 58 | */ 59 | //private: 60 | // char *buffer; 61 | }; 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /gui/widget.cpp: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #include "widget.h" 5 | 6 | using namespace std; 7 | 8 | #ifdef HAVE_SDL_TTF 9 | TTF_Font *Widget::font; 10 | #endif 11 | void (*Widget::fillRect)(Rect, Color) = 0; 12 | void (*Widget::drawLine)(int,int,int,int,Color) = 0; 13 | void (*Widget::drawCircle)(int,int,int,Color) = 0; 14 | 15 | Widget::Widget(){ 16 | parent = 0; 17 | } 18 | Widget::Widget(Widget *p){ 19 | p->attach(this); 20 | // parent=p; 21 | } 22 | Widget::~Widget(){ 23 | if(parent) parent->detach(this); 24 | } 25 | 26 | Widget *Widget::getParent() const{ return parent; } 27 | const Array *Widget::getChildren() const{ return &children; } 28 | 29 | void Widget::render(Rect r){ 30 | view = r; 31 | dorender = true; 32 | if(parent) render(r); 33 | if(dorender){ 34 | for(int n=0; nWidget::render(r); 37 | } 38 | } 39 | } 40 | 41 | void Widget::attach(Widget *child){ 42 | children.add(child); 43 | // child->view = view; 44 | child->parent = this; 45 | } 46 | void Widget::detach(Widget *child){ 47 | for(int n=0; n=r.x+r.w&&x1>=r.x+r.w) return; 58 | if(y=r.x+r.w){ 61 | int lx = x; 62 | int ly = y; 63 | while(x1!=r.x+r.w-1){ 64 | int x=(lx+x1)>>1; 65 | if(x>=r.x+r.w-1){ 66 | x1=x; 67 | y1=(ly+y1)>>1; 68 | }else{ 69 | lx=x; 70 | ly=(ly+y1)>>1; 71 | } 72 | } 73 | } 74 | if(y1>1; 81 | if(y<=r.y){ 82 | y1=y; 83 | x1=(lx+x1)>>1; 84 | }else{ 85 | ly=y; 86 | lx=(lx+x1)>>1; 87 | } 88 | } 89 | } 90 | 91 | if(y=r.y+r.h||y1>=r.y+r.h) return; 94 | if(x>=r.x+r.w||x1>=r.x+r.w) return; 95 | 96 | drawLine(x,y,x1,y1,c); 97 | } 98 | -------------------------------------------------------------------------------- /neuron.h: -------------------------------------------------------------------------------- 1 | // neuron.h - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #ifndef M_PI 5 | # define M_PI 3.14159265358979323846 6 | #endif 7 | 8 | class Neuron{ 9 | public: Neuron(){} 10 | Neuron(Neuron **inp, int inputs, int type, double a, double b); 11 | ~Neuron(); 12 | 13 | void construct(Neuron **inp, int inputs, int type, double a, double b); 14 | void init(int type, double a, double b); 15 | 16 | // genetic manipulators 17 | void mix(Neuron *n); 18 | void mutate(double level); 19 | void breed(double w, Neuron *a, Neuron *b); 20 | 21 | Neuron &operator=(Neuron &); 22 | 23 | // ********* inline optimized functions ************ 24 | 25 | inline double scalar_mult(float *w){ 26 | double val=0; 27 | for(int n=0; nval*w[n]; 28 | return val/inputs; 29 | } 30 | 31 | // fire neuron 32 | inline void run(){ 33 | // scalar multiply 34 | #ifndef HEAVY 35 | val = 0; 36 | for(int n=0; nval*weight[n]; 37 | switch(function){ 38 | case 0: // atan transfer function 39 | val = float(M_PI*atan(val+base)/1.6); 40 | break; 41 | case 1: // hardlim transfer function 42 | val = float((val+base)>0); 43 | break; 44 | default: // linear transfer function 45 | val+=base; 46 | } 47 | #else 48 | double a1 = M_PI*atan( scalar_mult(&weight[0*inputs]) + base[0] )/1.6; /* atan transfer function */ 49 | double a2 = M_PI*atan( scalar_mult(&weight[1*inputs]) + base[1] )/1.6; /* atan transfer function */ 50 | int a3 = ( scalar_mult(&weight[2*inputs]) + base[2] ) > 0; /* hardlim transfer function */ 51 | int a4 = ( scalar_mult(&weight[3*inputs]) + base[3] ) > 0; /* hardlim transfer function */ 52 | double a5 = scalar_mult(&weight[4*inputs]) + base[4] ; /* linear transfer function */ 53 | double a6 = scalar_mult(&weight[5*inputs]) + base[5] ; /* linear transfer function */ 54 | val = 55 | a1*weight[6*inputs+0] + 56 | a2*weight[6*inputs+1] + 57 | a3*weight[6*inputs+2] + 58 | a4*weight[6*inputs+3] + 59 | a5*weight[6*inputs+4] + 60 | a6*weight[6*inputs+5] + base[6]; /* hardlim transfer function */ 61 | #endif 62 | } 63 | 64 | 65 | private: 66 | friend class Net; 67 | 68 | unsigned short inputs; 69 | Neuron **input; 70 | float *weight; 71 | #ifdef HEAVY 72 | float base[7]; 73 | #else 74 | unsigned short function; 75 | float base; 76 | #endif 77 | float val; 78 | }; 79 | 80 | -------------------------------------------------------------------------------- /array.h: -------------------------------------------------------------------------------- 1 | // array.h - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #ifndef _ARRAY_H_ 4 | #define _ARRAY_H_ 5 | 6 | #include 7 | #include 8 | 9 | //class OStream; 10 | 11 | #define __bs 32 12 | 13 | //namespace base{ 14 | 15 | template class Array{ 16 | public: Array(){ 17 | count=0; 18 | list=0; 19 | } 20 | Array(int n){ 21 | count=0; 22 | list=0; 23 | init(n); 24 | } 25 | Array(const Array &a){ 26 | count = a.count; 27 | list = (T**)malloc(count*sizeof(T*)); 28 | for(int n=0; n &operator=(const Array &a){ 45 | if(list){ 46 | for(int n=0; n=at+1; n--) list[n]=list[n-1]; 71 | list[at]=new T(); 72 | *list[at]=t; 73 | } 74 | void add(T t){ 75 | count++; 76 | list = (T**)realloc(list,sizeof(T*)*count); 77 | list[count-1]=new T(); 78 | *list[count-1]=t; 79 | } 80 | int getCount() const{ return count; } 81 | T &operator[](int i) const{ 82 | assert(i>=0&&i &in){ return in.out(out); } 86 | //OStream &out(OStream &out) const{ 87 | // out << count; 88 | // for(int n=0; n 4 | #include 5 | #include 6 | #include "population.h" 7 | #include "net.h" 8 | #include "genetic.h" 9 | 10 | using namespace std; 11 | 12 | inline int irand( int range ){ 13 | return( rand() % range ); 14 | } 15 | 16 | // Create a population of individual neural networks 17 | // input: individuals = the number of neural networks to create in the population 18 | // inputs = the number of inputs in every neural network 19 | // outputs = the number of outputs in every neural network 20 | // a & b = neuron normalization values (min & max) 21 | 22 | Population::Population(int individuals, int inputs, int outputs, double a, double b){ 23 | this->individuals = individuals; 24 | int layers = 0; 25 | for(int n=inputs; n>outputs; n/=2) layers++; 26 | typedef Net* netptr; 27 | individual = new netptr[individuals]; 28 | for(int n=0; ninit(a,b); 39 | } 40 | 41 | // mutate a single neuron with another by randomized blending 42 | // input: i = the neural network to mix a random neuron in 43 | // j = the other neural network to mix a random neuron with (random source neuron) 44 | 45 | void Population::mix(int i, int j){ 46 | individual[i]->mix(individual[j]); 47 | } 48 | 49 | // mutate a random neuron in a neural network by radiation (noise blending) 50 | // input: i = whch neural network to radiate a random neuron 51 | // level = radiation level 52 | 53 | void Population::mutate(int i, double level){ 54 | individual[i]->mutate(level); 55 | } 56 | 57 | void Population::copy(int i1, int i2){ 58 | (*individual[i1]) = (*individual[i2]); 59 | } 60 | 61 | void Population::copy(int i1, Population *pop, int i2){ 62 | *individual[i1] = *pop->getIndividual(i2); 63 | } 64 | 65 | void Population::swap(int i1, int i2){ 66 | Net *t = individual[i1]; 67 | individual[i1] = individual[i2]; 68 | individual[i2] = t; 69 | } 70 | 71 | Net *Population::getIndividual(int i){ 72 | return individual[i]; 73 | } 74 | 75 | // inperfectly sort the population according to fitness 76 | // input: cnt = the number of iterations in the sort algorithm (simple bouble sorting) 77 | // gen = the gene pool the population belong to 78 | 79 | void Population::sort(int cnt, Genetic *gen){ 80 | // first evaluate all individuals in population 81 | double *scores = new double[individuals]; 82 | for(int n=0; nevaluate(individual[n]); 84 | scores[n]=individual[n]->getScore(); 85 | if(isinf(scores[n])) scores[n]=-10000000; 86 | } 87 | 88 | // then sort the entire population according to score (lame sort) 89 | for(int n=0; nscores[i]){ 92 | swap(i,i+1); 93 | double a=scores[i]; 94 | scores[i]=scores[i+1]; 95 | scores[i+1]=a; 96 | } 97 | } 98 | } 99 | delete []scores; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /gui/screen.cpp: -------------------------------------------------------------------------------- 1 | // copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #include "screen.h" 5 | 6 | using namespace std; 7 | 8 | SDL_Surface *Screen::scr; 9 | 10 | Screen::Screen(int w, int h) : Widget(){ 11 | if(SDL_Init(SDL_INIT_VIDEO)<0){ 12 | cerr << "Couldn't initialize SDL: " << SDL_GetError() << endl; 13 | exit(1); 14 | } 15 | 16 | #ifdef HAVE_SDL_TTF 17 | if(TTF_Init()<0){ 18 | fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError()); 19 | exit(2); 20 | } 21 | atexit(TTF_Quit); 22 | #endif 23 | 24 | int videoflags = SDL_SWSURFACE/*|SDL_FULLSCREEN*/; 25 | scr = SDL_SetVideoMode(w,h, 24, videoflags); 26 | if(scr==NULL){ 27 | cerr << "Couldn't set display mode: " << SDL_GetError() << endl; 28 | SDL_Quit(); 29 | exit(5); 30 | } 31 | #ifdef HAVE_SDL_TTF 32 | font = TTF_OpenFont("/usr/X11R6/lib/X11/fonts/truetype/verdana.ttf", 18); 33 | if(font==NULL){ 34 | fprintf(stderr, "Couldn't load %d pt font: %s\n", 18, SDL_GetError()); 35 | exit(2); 36 | } 37 | TTF_SetFontStyle(font, TTF_STYLE_NORMAL); 38 | #endif 39 | 40 | Widget::fillRect = fillRect; 41 | Widget::drawLine = drawLine; 42 | Widget::drawCircle = drawCircle; 43 | 44 | // view = Rect(0,0,w,h); 45 | } 46 | Screen::~Screen(){ 47 | } 48 | 49 | void Screen::fillRect(Rect r, Color c){ 50 | unsigned char *fb=(unsigned char*)scr->pixels; 51 | unsigned char R=char(c.red*255.0); 52 | unsigned char G=char(c.green*255.0); 53 | unsigned char B=char(c.blue*255.0); 54 | for(int y=0; yw+r.x+x; 57 | fb[n*3+0]=B; 58 | fb[n*3+1]=G; 59 | fb[n*3+2]=R; 60 | } 61 | } 62 | } 63 | void Screen::drawLine(int x, int y, int x1, int y1, Color c){ 64 | 65 | unsigned char r = char(c.red*255); 66 | unsigned char g = char(c.green*255); 67 | unsigned char b = char(c.blue*255); 68 | 69 | unsigned char *fb=(unsigned char*)scr->pixels; 70 | int w=scr->w; 71 | int dx=x1-x; 72 | int dy=y1-y; 73 | if(abs(dx)>abs(dy)&&dx){ 74 | y<<=16; 75 | dy<<=16; 76 | if(dx) dy/=abs(dx); 77 | else dy=0; 78 | if(dx>=0) dx=1; 79 | else dx=-1; 80 | do{ //for(;x>16)*w+x)*3+0]=b; 82 | fb[((y>>16)*w+x)*3+1]=g; 83 | fb[((y>>16)*w+x)*3+2]=r; 84 | y+=dy; 85 | x+=dx; 86 | }while(x!=x1); 87 | }else if(dy){ 88 | x<<=16; 89 | dx<<=16; 90 | if(dy) dx/=abs(dy); 91 | else dx=0; 92 | if(dy>0) dy=1; 93 | else dy=-1; 94 | do{ //for(;y>16))*3+0]=b; 96 | fb[(y*w+(x>>16))*3+1]=g; 97 | fb[(y*w+(x>>16))*3+2]=r; 98 | x+=dx; 99 | y+=dy; 100 | }while(y!=y1); 101 | } 102 | } 103 | 104 | void Screen::drawCircle(int x, int y, int d, Color c){ 105 | double rad=d/2.0; 106 | for(int n=0; n<32; n++){ 107 | double a=n*M_PI*4.0/32.0; 108 | double b=(n+1)*M_PI*4.0/32.0; 109 | drawLine(int(x+sin(a)*rad),int(y+cos(a)*rad),int(x+sin(b)*rad),int(y+cos(b)*rad),c); 110 | } 111 | } 112 | 113 | void Screen::render(Rect r){ 114 | if(SDL_MUSTLOCK(scr)){ 115 | if(SDL_LockSurface(scr)<0){ 116 | fprintf(stderr, "Couldn't lock display surface: %s\n",SDL_GetError()); 117 | return; 118 | } 119 | } 120 | 121 | Widget::render(r); 122 | 123 | if(SDL_MUSTLOCK(scr)) SDL_UnlockSurface(scr); 124 | SDL_UpdateRect(scr, 0, 0, 0, 0); 125 | } 126 | -------------------------------------------------------------------------------- /string.cpp: -------------------------------------------------------------------------------- 1 | // string.cpp - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | //#include "network/socket.h" 4 | #include 5 | #include 6 | #include 7 | #include "string.h" 8 | 9 | //using namespace base; 10 | 11 | String::String() : Array(){ 12 | add(0); 13 | } 14 | String::String(const String &str) : Array(str){ 15 | } 16 | String::String(const char *str) : Array(){ 17 | for(unsigned int n=0; n='a'&&(*this)[n]<='z') (*this)[n]=(*this)[n]-'a'+'A'; 67 | } 68 | } 69 | 70 | String String::trim(){ 71 | int i0 = 0; 72 | int i1 = length()-1; 73 | 74 | cout << "3" << endl; 75 | for ( ;(i0 <= i1) && ((*this)[i0] <= ' '); i0++ ); 76 | if ( i0 > i1 ) return ""; 77 | for ( ;(i1 > i0) && ((*this)[i1] <= ' '); i1-- ); 78 | cout << "4" << endl; 79 | 80 | return substring( i0, i1+1); 81 | } 82 | 83 | bool String::operator==(const String &str) const{ 84 | for(int n=0; n(const String &str) const{ 93 | for(int n=0; nstr[n]) return true; 96 | return false; 97 | } 98 | } 99 | 100 | String &String::operator=(const String &str){ 101 | clear(); 102 | int len=str.length(); 103 | for(int n=0; n>(IStream &i, String &o){ 146 | // unsigned int len; 147 | // i >> len; 148 | char c; 149 | i >> c; 150 | while(c){ 151 | o << c; 152 | i >> c; 153 | } 154 | return i; 155 | } 156 | */ 157 | -------------------------------------------------------------------------------- /net.cpp: -------------------------------------------------------------------------------- 1 | // population.cpp - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #include 5 | #include 6 | #include "net.h" 7 | #include "genetic.h" 8 | 9 | using namespace std; 10 | 11 | inline int irand( int range ){ 12 | return( rand() % range ); 13 | } 14 | 15 | // Create a neural network 16 | // input: inputs = number of input 17 | // outputs = number of outputs 18 | // layers = the number of layers of neurons to have in the neural net 19 | // a & b = normalization values for the neurons (min & max) 20 | 21 | Net::Net(int inputs, int outputs, int layers, double a, double b){ 22 | this->layers = layers; 23 | this->outputs = outputs; 24 | typedef Layer* layerptr; 25 | layer = new layerptr[layers]; 26 | output = new double[outputs]; 27 | int ip = inputs; 28 | int op = inputs/2; 29 | for(int n=0; noutputs?op:outputs,a,b); 31 | ip/=2; 32 | op/=2; 33 | } 34 | for(int n=0; ninputs; n++) layer[0]->input[n] = new Neuron((Neuron**)0,0,0,a,b); 35 | for(int n=1; nsetInputs(layer[n-1]); 36 | neurons = 0; 37 | for(int n=0; noutputs; 38 | typedef Neuron* nptr; 39 | neuron = new nptr[neurons]; 40 | int ni=0; 41 | for(int n=0; noutputs; i++) neuron[ni++] = &layer[n]->neuron[i]; 43 | } 44 | if(ni!=neurons){ cout << "!!!!!!!!!!!!!!" << endl; exit(0); } 45 | age = 30;//irand(10); 46 | score=0; 47 | max=1; 48 | min=0; 49 | calibrated = false; 50 | 51 | name = 0x12345678; 52 | } 53 | 54 | // initialize the net with random weights 55 | // input: a & b = normalization values (min & max) 56 | 57 | void Net::init(double a, double b){ 58 | for(int n=0; ninit(a,b); 59 | age = 0;//irand(10); 60 | score=0; 61 | max=1; 62 | min=0; 63 | calibrated = false; 64 | } 65 | 66 | // mutate a single neuron with another by randomized blending 67 | 68 | void Net::mix(){ 69 | neuron[irand(neurons)]->mix(neuron[irand(neurons)]); 70 | } 71 | 72 | // fire all neurons in the net (basic propagation algorithm) 73 | 74 | void Net::run(){ 75 | for(int n=0; nrun(); 76 | for(int n=0; nneuron[n].val-min)/(max-min); 77 | } 78 | 79 | // mutate a single neuron with another from other net (in population) by randomized blending 80 | // input: other neural network 81 | 82 | void Net::mix(Net *net){ 83 | neuron[irand(neurons)]->mix(net->neuron[irand(net->neurons)]); 84 | } 85 | 86 | // mutate neural net by radiation (noise blending) 87 | // input: dev = radiation factor 88 | 89 | void Net::mutate(double dev){ 90 | int cnt=rand()%neurons; 91 | for(int n=0; nmutate(dev/double(cnt)); 92 | age=0; 93 | score=0; 94 | min=0; 95 | max=1; 96 | calibrated=false; 97 | } 98 | 99 | // 100 | 101 | double Net::getScore(){ 102 | return score/double(age); 103 | } 104 | 105 | Net &Net::operator=(Net &s){ 106 | if(neurons!=s.neurons||layers!=s.layers){ 107 | cerr << "bad!" << endl; 108 | exit(EXIT_FAILURE); 109 | } 110 | for(int n=0; nbreed(w,a->neuron[n],b->neuron[n]); 130 | } 131 | //neuron[rand()%neurons]->mutate(.001); 132 | mutate(drand()+.5); 133 | age=0; 134 | score=0; 135 | min=0; 136 | max=1; 137 | calibrated=false; 138 | } 139 | 140 | void Net::setCalibration(double min, double max){ 141 | this->min = min-(min-max)*.5; 142 | this->max = max-(min-max)*.5; 143 | calibrated = true; 144 | } 145 | 146 | -------------------------------------------------------------------------------- /neuron.cpp: -------------------------------------------------------------------------------- 1 | // neuron.cpp - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #include 5 | #include 6 | #include "neuron.h" 7 | 8 | using namespace std; 9 | 10 | inline int irand( int range ){ 11 | return( rand() % range ); 12 | } 13 | 14 | inline double drand(){ 15 | return double((rand()%10000)-5000)/10000.0; 16 | } 17 | 18 | // Create a single neuron and connect it to input neurons 19 | // input: input = input neurons 20 | // inputs = number of input neurons 21 | // type = unused 22 | // a & b = normalization (min & max) 23 | 24 | Neuron::Neuron(Neuron **input, int inputs, int type, double a, double b){ 25 | if(inputs>5){ 26 | // clamp if we have more then 5 inputs, and use 5 random'ish of them 27 | this->input = input+rand()%(inputs-5); 28 | inputs = 5; 29 | }else{ 30 | this->input = input; 31 | } 32 | this->inputs = inputs; 33 | #ifdef HEAVY 34 | weight = new float[7*inputs]; 35 | for(int n=0; n4){ 56 | // clamp if we have more then 4 inputs, and use 4 random'ish of them 57 | this->input = input+rand()%(inputs-4); 58 | inputs = 4; 59 | }else{ 60 | this->input = input; 61 | } 62 | this->inputs = inputs; 63 | #ifdef HEAVY 64 | weight = new float[7*inputs]; 65 | for(int n=0; ninputs){ 94 | for(int i=0; iweight[i])*.5+drand()*.01; 95 | for(int i=0; i<7; i++) base[i] = (base[i]+n->base[i])*.5+drand()*.01; 96 | } 97 | #else 98 | if((inputs==n->inputs)&&function==n->function){ 99 | for(int i=0; iweight[i])/2.0; 100 | base = (base+n->base)/2.0; 101 | } 102 | #endif 103 | } 104 | 105 | Neuron &Neuron::operator=(Neuron &s){ 106 | if(inputs!=s.inputs){ 107 | cerr << "bad!" << endl; 108 | exit(EXIT_FAILURE); 109 | } 110 | #ifdef HEAVY 111 | for(int n=0; n 1) 125 | 126 | void Neuron::breed(double w, Neuron *a, Neuron *b){ 127 | if(a->inputs!=b->inputs&&inputs!=a->inputs){ 128 | cerr << "!!!!!!!!!!" << endl; 129 | } 130 | for(int n=0; nweight[n]*w+b->weight[n]*(1.0-w); 131 | for(int n=0; n<7; n++) base[n]=a->base[n]*w+b->base[n]*(1.0-w); 132 | val=a->val*w+b->val*(1.0-w); 133 | } 134 | 135 | #define MAX 1.0 136 | 137 | // Apply a litte radiation to this neuron and mutate weights a bit 138 | // input: v = radiation 139 | 140 | void Neuron::mutate(double v){ 141 | int i = irand(inputs*8); 142 | if(iMAX) weight[i]=MAX; 145 | else if(weight[i]<-MAX) weight[i]=-MAX; 146 | }else{ 147 | i-=inputs*7; 148 | base[i]+=drand()*v; 149 | if(base[i]>MAX) base[i]=MAX; 150 | else if(base[i]<-MAX) base[i]=-MAX; 151 | } 152 | } 153 | 154 | -------------------------------------------------------------------------------- /genetic.cpp: -------------------------------------------------------------------------------- 1 | // population.cpp - copyright (C) 2001-2011 by Patrick Hanevold 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "genetic.h" 8 | #include "population.h" 9 | #include "net.h" 10 | 11 | using namespace std; 12 | 13 | inline int irand( int range ){ 14 | return( rand() % range ); 15 | } 16 | 17 | // Create a genetic pool. A pool of many populations of neural networks that will evolve through evolution. 18 | // input: pupulations = the number of populations 19 | // individuals = the number of neural networks in each population 20 | // inputs = the number of inputs for each neural network 21 | // outputs = the number of outputs for each neural network 22 | 23 | Genetic::Genetic(int populations, int individuals, int inputs, int outputs){ 24 | generation = 0; 25 | this->populations = populations; 26 | this->individuals = individuals; 27 | this->inputs = inputs; 28 | double a=1; 29 | double b=2; 30 | startscore = 20000; 31 | start = 0; 32 | stop = 0; 33 | typedef Population* popptr; 34 | population = new popptr[populations]; 35 | for(int n=0; ngetIndividual(i)->age++; 64 | population[p]->sort(50,this); 65 | } 66 | 67 | // mutate and interbreed populations 68 | for(int p=0 ; p1&&(generation%mixgen)==0){ 71 | // population[p]->copy(i, population[irand(populations)], newpop?irand(newpop):0); 72 | // population[p]->mix(i,newpop?irand(newpop):0); 73 | //}else{ 74 | switch(irand(4)){ 75 | case 0: 76 | // clone and mutate 77 | population[p]->copy(i,irand(newpop)); 78 | switch(irand(7)){ 79 | case 0: population[p]->getIndividual(i)->mutate(double(irand(1000000))/100000000.0); break; 80 | case 1: population[p]->getIndividual(i)->mutate(double(irand(1000000))/10000000.0); break; 81 | case 2: population[p]->getIndividual(i)->mutate(double(irand(1000000))/1000000.0); break; 82 | case 3: population[p]->getIndividual(i)->mutate(double(irand(1000000))/100000.0); break; 83 | case 4: population[p]->getIndividual(i)->mutate(double(irand(1000000))/10000.0); break; 84 | case 5: population[p]->getIndividual(i)->mutate(double(irand(1000000))/1000.0); break; 85 | case 6: population[p]->getIndividual(i)->mutate(double(irand(1000000))/100.0); break; 86 | } 87 | break; 88 | case 1: 89 | // mix populations 90 | population[p]->copy(i, population[irand(populations)], newpop?irand(newpop):0); 91 | population[p]->mix(i,newpop?irand(newpop):0); 92 | break; 93 | case 2: 94 | // randomize weights 95 | population[p]->getIndividual(i)->init(0,0); 96 | break; 97 | default: 98 | // breed 99 | int a=irand(selpop); 100 | int b=irand(selpop); 101 | while(b==a) b=irand(selpop); 102 | population[p]->getIndividual(i)->breed(population[p]->getIndividual(a),population[p]->getIndividual(b)); 103 | } 104 | //} 105 | } 106 | } 107 | 108 | // sumarize how the poluation is doing (evolving) 109 | generation++; 110 | board_score=0; 111 | board_age=0; 112 | for(int p=0 ; pgetIndividual(n)->getScore(); 115 | board_age+=population[p]->getIndividual(n)->getAge(); 116 | } 117 | } 118 | board_score/=bestpop*populations; 119 | board_age/=bestpop*populations; 120 | } 121 | 122 | // award neural net with score 123 | // inputs: net = neural network to award 124 | // score = the score given to the network during evaluation 125 | 126 | void Genetic::stimulate(Net *net, double score){ 127 | if(!net->calibrated) calibrate(net); 128 | if(newgen){ max=min=score; newgen=false; } 129 | else{ 130 | if(scoremax) max=score; 132 | } 133 | net->score += score; 134 | } 135 | 136 | void Genetic::setTrainingPeriod(int start, int stop){ 137 | this->start = start; 138 | this->stop = stop; 139 | if(val) delete val; 140 | val = new double[stop-start]; 141 | } 142 | 143 | /* 144 | void Genetic::setEval(int t, double v){ 145 | val[t-start] = v; 146 | } 147 | 148 | double Genetic::getEval(int t){ 149 | return val[t-start]; 150 | } 151 | */ 152 | --------------------------------------------------------------------------------