-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgenetic.h
153 lines (134 loc) · 4.21 KB
/
genetic.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
#ifndef GA_H
#define GA_H
#include <vector>
#include <unordered_map>
#include "data.h"
#include "dataloader.h"
#include <SDL2/SDL.h>
// INIT - create random candidate solutions X
// EVALUATE each candidate X
// WHILE( I < GENERATION NUMBER )
// SELECT PARENTS X
// RECOMBINE PAIRS OF PARENTS X
// MUTATE OFFSPRING
// EVALUATE NEW CANDIDATES
// SELECT CANDIDATES FOR NEXT GENERATION
std::vector<City> generateRandomCandidate(std::vector<City> cities);
double candidateEvaluation(const std::vector<City>& candidate, const std::unordered_map< std::pair<City, City>, double, pairhash>& distances);
class Candidate{
private:
std::vector<City> candidate;
double totalDistance;
double normalizedFitnessValue; // [0..1]
public:
Candidate(std::vector<City> candidate, const std::unordered_map< std::pair<City, City>, double, pairhash>& distances):candidate(candidate){
totalDistance = candidateEvaluation(candidate, distances);
}
double getTotalDistance() const{
return totalDistance;
}
void setFitness(double fitness){
normalizedFitnessValue = fitness;
}
double getFitness() const{
return normalizedFitnessValue;
}
std::vector<City>& getCandidate(){
return candidate;
}
std::vector<City> getCandidate() const{
return candidate;
}
void ReEvaluate(const std::unordered_map< std::pair<City, City>, double, pairhash>& distances){
totalDistance = candidateEvaluation(candidate,distances);
}
void PrintRoute(){
std::cout << "Route:\n";
for(int i = 0; i < candidate.size(); i++){
std::cout << i << " => " << candidate.at(i) << "\n";
}
}
bool isUnique(){
int count;
for(const auto& c : candidate){
count = 0;
for(const auto& city : candidate){
if(city == c)
count++;
}
if(count > 1)
return false;
}
return true;
}
};
inline std::ostream& operator<<(std::ostream& out, const Candidate& c){
out << "Total Distance: " << c.getTotalDistance() << " Fitness: " << c.getFitness();
return out;
}
inline bool operator<(const Candidate& lhs, const Candidate& rhs){
return lhs.getFitness() < rhs.getFitness();
};
inline bool operator==(const Candidate& lhs, const Candidate& rhs){
bool result = true;
for(int i = 0; i < lhs.getCandidate().size(); i++){
if(lhs.getCandidate().at(i) == lhs.getCandidate().at(i)){
}
else {
result = false;
break;
}
}
return lhs.getFitness() < rhs.getFitness();
};
class GA{
private:
int populationSize;
int populationBreadersPercentage;
int mutationPercentage;
int mutationPower;
int targetGenerationNumber;
int currentGeneration;
int maxXPosition;
int maxYPosition;
std::unordered_map< std::pair<City, City>, double, pairhash> distances;
std::vector<City> baseCityVector; //probably I don't need this
std::vector<Candidate> population;
std::vector<Candidate> parentsPopulation;
std::vector<Candidate> newPopulation;
void Initialize(std::string filePath);
void NormalizeCandidates();
void SortCandidates();
void SelectParents(int);
Candidate PMXCrossover(const Candidate& p1, const Candidate& p2);
int PMXCrossover_FindDestPosition(const std::vector<City>& p1cities, const std::vector<City>& p2cities, const int& startPos, const int& endPos, int currentPos);
void CycleCrossover(Candidate p1, Candidate p2);
void CycleCrossover_MixGenes(std::vector<City>& p1, std::vector<City>& p2, int& currentGene, const int& startingGene);
void Mutate(Candidate& c, int mutationPower);
public:
GA(std::string filePath, int populationSize, int breedersPercentage, int targetGeneration, int mutationPercentage, int mutationPower)
:populationSize(populationSize),
populationBreadersPercentage(breedersPercentage),
mutationPercentage(mutationPercentage),
mutationPower(mutationPower),
targetGenerationNumber(targetGeneration)
{
Initialize(filePath);
NormalizeCandidates();
}
std::unordered_map< std::pair<City, City>, double, pairhash> getDistances(){
return distances;
}
std::vector< Candidate > getPopulation(){
return population;
}
std::vector<Candidate> getParentPopulation(){
return parentsPopulation;
}
// void Execute(SDL_Renderer *renderer);
void Execute();
int getCurrentGeneration() const {
return currentGeneration;
}
};
#endif