-
Notifications
You must be signed in to change notification settings - Fork 0
/
mutation.cpp
86 lines (76 loc) · 2.74 KB
/
mutation.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
#include <armadillo>
#include <bits/stdc++.h>
/**
* @brief Polynomial mutation
* Code length has been decreased significantly.
* Inspired from DEAP/mutation.py https://github.com/DEAP/deap/blob/d328fe6b68e7528b2d2d990bb2ab1ad1786e6f58/deap/tools/mutation.py#L51
* Naming convention followed.
* g++ mutation.cpp -g -o mutation -larmadillo
*
*/
//Variables to be defined for polynomial mutation
double perturbationIndex = 30; //eta_m
double mutationProb = 1; // For testing
size_t numVariables = 5;
arma::vec lowerBound {-10, -10, -10, -10, -10};
arma::vec upperBound {10, 10, 10, 10, 10};
void enforceBounds(arma::vec& child)
{
child = arma::min(arma::max(child, lowerBound), upperBound);
}
void PolynomialMutation(const arma::vec& parent, arma::vec& child)
{
for(size_t geneIdx=0; geneIdx < numVariables; ++geneIdx)
{
if(arma::randu() > mutationProb) //Should these gene be mutated?
continue;
double geneRange = upperBound[geneIdx] - lowerBound[geneIdx];
//Normalised distance from bounds
double lowerDelta = (parent[geneIdx] - lowerBound[geneIdx]) / geneRange;
double upperDelta = (upperBound[geneIdx] - parent[geneIdx]) / geneRange;
double mutationPower = 1. / (perturbationIndex + 1.0);
double value; //Intermediatery
double perturbationFactor;
double rand = arma::randu();
if(rand < 0.5)
{
value = 2. * rand + (1. - 2. * rand) *
std::pow(upperDelta, perturbationIndex + 1.0);
perturbationFactor = std::pow(value, mutationPower) - 1.;
}
else
{
value = 2. * (1. - rand) + 2.*(rand - 0.5) *
std::pow(lowerDelta, perturbationIndex + 1.0);
perturbationFactor = 1. - std::pow(value, mutationPower);
}
child[geneIdx] += perturbationFactor * geneRange;
}
enforceBounds(child);
}
//Vectorised WIP!
void PolynomialMutationVector(const arma::vec& parent, arma::vec& child)
{
arma::vec geneRange = upperBound- lowerBound;
arma::vec lowerDelta = (parent - lowerBound) / geneRange;
arma::vec upperDelta = (upperBound - parent) / geneRange;
double mutationPower = 1. / (perturbationIndex + 1.0);
arma::vec value(numVariables, arma::fill::zeros);
arma::vec perturbationFactor;
arma::vec rand = arma::randu(numVariables, 1);
value = 2. * rand + (1. - 2. * rand) *
arma::pow(upperDelta, 1 / mutationPower) % (rand < 0.5);
value += 2. * (1. - rand) + 2.*(rand - 0.5) *
arma::pow(lowerDelta, 1 / mutationPower) % (rand >= 0.5);
// perturbationFactor arma::pow(value, mutationPower) - 1.
child += perturbationFactor* geneRange;
// chidl %= arma::randu
enforceBounds(child);
}
int main()
{
arma::vec parentA { 1., 2., 3., 4., 5.};
arma::vec childA = parentA;
PolynomialMutation(parentA, childA);
std::cout << childA << std::endl;
}