-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCga.h
176 lines (123 loc) · 5.18 KB
/
Cga.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#ifndef CGA_H
#define CGA_H
//------------------------------------------------------------------------
//
// Name: Cga.h
//
// Author: Mat Buckland 2002
//
// Desc: The evolutionary algorithm class used in the implementation of
// Kenneth Owen Stanley's and Risto Miikkulainen's NEAT idea.
//
//------------------------------------------------------------------------
#include <vector>
#include <windows.h>
#include <fstream>
#include "phenotype.h"
#include "genotype.h"
#include "CSpecies.h"
#include "CParams.h"
using namespace std;
//------------------------------------------------------------------------
//
// this structure is used in the creation of a network depth lookup
// table.
//------------------------------------------------------------------------
struct SplitDepth
{
double val;
int depth;
SplitDepth(double v, int d):val(v), depth(d){}
};
//------------------------------------------------------------------------
//
//------------------------------------------------------------------------
class Cga
{
private:
//current population
vector<CGenome> m_vecGenomes;
//keep a record of the last generations best genomes. (used to render
//the best performers to the display if the user presses the 'B' key)
vector<CGenome> m_vecBestGenomes;
//all the species
vector<CSpecies> m_vecSpecies;
//to keep track of innovations
CInnovation* m_pInnovation;
//current generation
int m_iGeneration;
int m_iNextGenomeID;
int m_iNextSpeciesID;
int m_iPopSize;
//adjusted fitness scores
double m_dTotFitAdj,
m_dAvFitAdj;
//index into the genomes for the fittest genome
int m_iFittestGenome;
double m_dBestEverFitness;
//this holds the precalculated split depths. They are used
//to calculate a neurons x/y position for rendering and also
//for calculating the flush depth of the network when a
//phenotype is working in 'snapshot' mode.
vector<SplitDepth> vecSplits;
//used in Crossover
void AddNeuronID(int nodeID, vector<int> &vec);
//this function resets some values ready for the next epoch, kills off
//all the phenotypes and any poorly performing species.
void ResetAndKill();
//separates each individual into its respective species by calculating
//a compatibility score with every other member of the population and
//niching accordingly. The function then adjusts the fitness scores of
//each individual by species age and by sharing and also determines
//how many offspring each individual should spawn.
void SpeciateAndCalculateSpawnLevels();
//adjusts the fitness scores depending on the number sharing the
//species and the age of the species.
void AdjustSpeciesFitnesses();
CGenome Crossover(CGenome& mum, CGenome& dad);
CGenome TournamentSelection(const int NumComparisons);
//searches the lookup table for the dSplitY value of each node in the
//genome and returns the depth of the network based on this figure
void CalculateNetDepth(CGenome &gen);
//sorts the population into descending fitness, keeps a record of the
//best n genomes and updates any fitness statistics accordingly
void SortAndRecord();
//this automatically adjusts the compatibility threshold in an attempt
//to keep the number of species at a constant value
void AdjustCompatibilityThreshold();
//a recursive function used to calculate a lookup table of split
//depths
vector<SplitDepth> Split(double low, double high, int depth);
public:
//normal constructor. Creates a population starting with minimal
//genomes consisting of specified number of inputs and outputs.
Cga(int size,
int inputs,
int outputs);
~Cga();
//create a population from a genome defined in a data file
bool CreatePopulationFromGenome(const char* szFileName);
vector<CNeuralNet*> Epoch(const vector<double> &FitnessScores);
//iterates through the population and creates the phenotypes
vector<CNeuralNet*> CreatePhenotypes();
//keeps a record of the n best genomes from the last population.
//(used to display the best genomes)
void StoreBestGenomes();
//renders the best performing species statistics and a visual aid
//showing the distribution.
void RenderSpeciesInfo(HDC &surface, RECT db);
//returns a vector of the n best phenotypes from the previous generation
vector<CNeuralNet*> GetBestPhenotypesFromLastGeneration();
//writes the entire state of the GA to a file
bool WriteState(char* szFileName);
//given an index into m_vecGenomes, writes a single genome to a file
bool WriteGenome(const char* szFileName, const int idxGenome);
//writes the species info to a file
bool SpeciesDump(const char* szFileName);
//----------------------------------------------------accessor methods
int NumSpecies()const{return m_vecSpecies.size();}
double BestEverFitness()const{return m_dBestEverFitness;}
void SetFitness(int genome, double fitness){m_vecGenomes[genome].SetFitness(fitness);}
int Generation(){return m_iGeneration;}
};
#endif