-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSimpleGeneticAlgorithm.cpp
More file actions
179 lines (158 loc) · 6.11 KB
/
SimpleGeneticAlgorithm.cpp
File metadata and controls
179 lines (158 loc) · 6.11 KB
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
177
178
179
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
#include "Individual.h"
#include "SimpleGeneticAlgorithm.h"
using namespace std;
//Constructor of the class SimpleGeneticAlgorithm
SimpleGeneticAlgorithm::SimpleGeneticAlgorithm(int chromosome_size, int population_size, int tournament_size, int generations, double mutation_probability, double cross_probability) {
this->chromosome_size = chromosome_size;
this->population_size = population_size;
this->tournament_size = tournament_size;
this->generations = generations;
this->mutation_probability = mutation_probability;
this->cross_probability = cross_probability;
this->population = vector<Individual>(this->population_size);
this->initializePopulation();
this->best_output = this->evaluateIndividual(this->best);
this->best.evaluation = this->best_output;
cout << "Best individual of generation 0 " << this->best.print() << endl;
}
//Destructor of the class SimpleGeneticAlgorithm
SimpleGeneticAlgorithm::~SimpleGeneticAlgorithm() { this->population.resize(0); }
//This function return a random number in an interval between to integers
int SimpleGeneticAlgorithm::getRandomNumber(int low, int high){ return ((int) rand() / RAND_MAX) * (high-low) + low; }
//This function initializes the population of the algorithm
void SimpleGeneticAlgorithm::initializePopulation() {
for(int i=0; i < this->population_size; i++)
this->population[i] = Individual(this->chromosome_size);
this->best = this->population[0];
}
//This function obtains the fenotype of an individual
string SimpleGeneticAlgorithm::getFenotype(Individual ind) {
string fenotype = "";
for(int i=0; i<ind.size(); i++) {
if(ind.getBit(i))
fenotype += "1";
else
fenotype += "0";
}
return fenotype;
}
//Returns the string representation of the best individual of a given generation
string getBestLine(int i, Individual best, double error) {
string representation = "";
representation += to_string(i) + "," + best.print() + ",";
representation += to_string(1.0 - error);
return representation;
}
//This function get the error of a single individual
double SimpleGeneticAlgorithm::evaluateIndividual(Individual ind) {
double errors = 0;
for(int i=0; i<this->chromosome_size; i++)
if(!ind.getBit(i))
errors += 0.1;
return errors;
}
double SimpleGeneticAlgorithm::evaluate() {
double min_error = 100.0;
double sum_error = 0.0;
for(int i=0; i < this->population_size; i++) {
double error = this->evaluateIndividual(this->population[i]);
this->population[i].evaluation = error;
//cout << "Evaluating individual " << i << " ->" << this->population[i].print() << " Score: " << this->population[i].evaluation << endl;
cout << "Evaluating individual " << i << " ->" << this->getFenotype(this->population[i]) << " Score: " << this->population[i].evaluation << endl;
if(error < min_error) {
min_error = error;
if(this->best_output >= error)
this->best = this->population[i];
this->best_output = error;
}//End in case the error is less than min
sum_error += error;
}//End foreach individual in the population
this->mse = sum_error/(double)this->population_size;
return this->mse;
}
//We select the best individuals for a tournament
void SimpleGeneticAlgorithm::select() {
vector<Individual> new_population(this->population_size);
int individuals[this->tournament_size];
for(int i=0; i<this->population_size; i++) {
for(int j=0; j<this->tournament_size; j++)
if(i+j >= this->population_size)
individuals[j] = i+j - population_size;
else
individuals[j] = i+j;
int local_best = individuals[0];
for(int j=1; j<this->tournament_size; j++) {
//cout << "Evaluating " << local_best << " against " << individuals[j] << endl;
double local_best_error = this->population[local_best].evaluation;
if(this->population[individuals[j]].evaluation <= local_best_error) {
local_best = individuals[j];
//cout << "New Local Best " << local_best << " chromosome " << this->population[individuals[j]].print() << endl;
}
}
new_population[i] = this->population[local_best].copy();
}//End population size
this->population = new_population;
}
//We cross the population and make a new population
void SimpleGeneticAlgorithm::cross() {
Coin c = Coin(this->cross_probability);
//Shuffle index
vector<Individual> new_population(this->population_size);
int i=0;
for(i=0; i<this->population_size/2;i++) {
Individual i1 = this->population[2*i];
Individual i2 = this->population[2*i + 1];
if(c.toss()) {
int cross_point = this->getRandomNumber(0, this->chromosome_size);
vector<Individual> c =i1.cross(cross_point, i2);
i1 = c[0];
i2 = c[1];
}
new_population[2*i] = i1;
new_population[2*i + 1] = i2;
}
if(this->population_size %2 !=0) {
new_population[2*i] = this->population[2*i];
}
this->population = new_population;
}
//We pass for each individual and chromosome and check if it should be mutated
void SimpleGeneticAlgorithm::mutate() {
Coin c = Coin(this->mutation_probability);
for(int i=0; i<this->population_size;i++)
for(int j=0; j<this->chromosome_size; j++)
if(c.toss()) {
this->population[i].toogleBit(j);
//cout << "Mutating individual " << i << " and chromosome bit " << j << endl;
}
}
double SimpleGeneticAlgorithm::runGeneration() {
this->evaluate();
this->select();
this->cross();
this->mutate();
return this->mse;
}
vector<double> SimpleGeneticAlgorithm::crosssValidation() {
ofstream error, individuals;
error.open ("error.txt");
individuals.open ("individuals.txt");
vector<double> errorSum(this->generations);
for(int i=0; i<this->generations -1; i++) {
errorSum[i] =this->runGeneration();
cout << "Error " << this->mse << endl;
cout << "Best individual of generation " << i << " " << this->best.print() << endl;
error << this->mse << ",";
individuals << getBestLine(i, this->best, best_output) << "\n";
}
errorSum[this->generations -1] =this->runGeneration();
error << this->mse << "\n";
individuals << getBestLine(this->generations, this->best, this->best_output) << "\n";
error.close();
individuals.close();
return errorSum;
}