-
Notifications
You must be signed in to change notification settings - Fork 0
/
ga.cpp
89 lines (73 loc) · 3.19 KB
/
ga.cpp
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
/***************************************************************************
* Copyright (C) Anders Larsen *
* *
* Use of a Genetic Algoritm to solve a Traveling Salesman Problem. *
* The code can easily be adapted to other types problems as long as *
* solutions can be expressed as fixed length arrays of integers. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
// A class to create and submit a population of solutions to genetic evolution
#include "ga.h"
#include <math.h>
#include <assert.h>
#include <iostream>
#include <cstdlib>
// To disable the asserts use:
// #define NDEBUG
Ga::Ga(Problem *pr, int ps, int e, double sp, double mf) {
popSize = ps; assert(ps >= 10);
newPopSize = ps;
elitism = e; assert(e < ps);
problem = pr; assert(pr);
selPres = sp; assert((sp >= 1.0) && (sp < 10.0));
mutFreq = mf; assert((mf >= 0.0) && (mf <= 1.0));
crossovers = 0;
newPop.clear();
oldPop.clear();
while(newPop.size() < popSize) {
Sol temp;
problem->encode(temp);
newPop.insert(std::make_pair(problem->evaluate(temp), temp));
}
}
void Ga::generation(void) {
std::swap(oldPop, newPop);
newPop.clear();
// Handle elitism - copy over some of the best solutions
PopIter p = oldPop.begin();
for(int i = 0; i != elitism; i++) {
newPop.insert(std::make_pair(p->first, p->second));
p++;
}
// Note that actual populationsize sometimes may be one more than requested
while(newPop.size() < newPopSize) {
PopIter p = oldPop.begin(),
q = oldPop.begin();
int i = popSize * pow(drand(), selPres),
j = popSize * pow(drand(), selPres);
std::advance(p, i); // Should use some random access container instead?
std::advance(q, j); // But then I'd have to sort it instead...
Sol &a = p->second,
&b = q->second,
c, d;
problem->crossover(a, b, c, d);
crossovers += 2;
if(mutFreq > drand()) {
problem->mutate(c);
problem->mutate(d);
}
newPop.insert(std::make_pair(problem->evaluate(c), c));
newPop.insert(std::make_pair(problem->evaluate(d), d));
}
popSize = newPopSize;
}