-
Notifications
You must be signed in to change notification settings - Fork 0
/
SPEAmod.h
156 lines (138 loc) · 6.55 KB
/
SPEAmod.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
#ifndef SPEAMOD_H
#define SPEAMOD_H
#include "Circuit.h"
#include <random>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <filesystem>
class SPEAmod {
public:
std::random_device rd;
unsigned int generations;
Circuit original;
std::vector<std::pair<Circuit, unsigned int>> archive;// The archive saves a pair of a circuit and its errors (unsigned int)
CircuitParameters objective;
enum MutationType {
MUTATE_OUTPUT,
MUTATE_FUNCTION,
MUTATE_INPUT_0,
MUTATE_INPUT_1,
MUTATE_INVERT_INPUT_0,
MUTATE_INVERT_INPUT_1
};
SPEAmod(unsigned int generations, Circuit &original, CircuitParameters objective) :
generations(generations), original(original), objective(objective) {}
Circuit pointMutation(Circuit* parent) {
Circuit child = *parent;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> distMutationType(0, 5);
MutationType mutationType = static_cast<MutationType>(distMutationType(mt));
if(mutationType==MUTATE_OUTPUT){
std::uniform_int_distribution<unsigned int> distOutput(0, child.output_nodes.size() - 1);
unsigned int selectedOutput = distOutput(mt);
std::uniform_int_distribution<unsigned int> distNewOutput(0, child.gates.size() - 1);
unsigned int newOutput = distNewOutput(mt);
child.output_nodes[selectedOutput] = newOutput;
}else{
std::uniform_int_distribution<unsigned int> distGateToMutate(0, child.gates.size() - 1);
unsigned int gateToMutate = distGateToMutate(mt);
if(mutationType==MUTATE_FUNCTION){
std::uniform_int_distribution<int> distFunction(0, 1);
child.gates[gateToMutate]->logic_function = distFunction(mt) == 0 ? '&' : '|';
//Se o tamanho for menor que 2, gerar uma outra input aleatória
if(child.gates[gateToMutate]->inputs.size()<2){
std::uniform_int_distribution<int> distNewInput(-static_cast<int>(child.n_inputs), gateToMutate - 1);
int newInput = distNewInput(mt);
child.gates[gateToMutate]->inputs.push_back(newInput);
std::uniform_int_distribution<int> distBit(0, 1);
int randomBit = distBit(mt);
child.gates[gateToMutate]->invert_inputs.push_back(randomBit);
}
}else if(mutationType==MUTATE_INPUT_0 || mutationType==MUTATE_INPUT_1){
std::uniform_int_distribution<int> distNewInput(-static_cast<int>(child.n_inputs), gateToMutate - 1);
int newInput = distNewInput(mt);
//Se mutationType==3 (MUTATE_INPUT_1) => mutar input 1 (3-2)
child.gates[gateToMutate]->inputs[mutationType-2] = newInput;
}else if(mutationType==MUTATE_INVERT_INPUT_0 || mutationType==MUTATE_INVERT_INPUT_1){
std::uniform_int_distribution<int> distBit(0, 1);
int randomBit = distBit(mt);
//Se mutationType==5 (MUTATE_INVERT_INPUT_1) => mutar inverter input 1 (4-2)
if(mutationType==MUTATE_INVERT_INPUT_1 && child.gates[gateToMutate]->inputs.size()>1)
child.gates[gateToMutate]->invert_inputs[mutationType-4] = randomBit;
}
child.update();
}
return child;
}
unsigned int getErrors(Circuit *oneCircuit){
unsigned int errors = 0;
for(size_t out = 0; out < oneCircuit->output_nodes.size(); ++out) {
for (size_t i = 0; i < oneCircuit->gates[oneCircuit->output_nodes[out]]->output_states.size(); ++i) {
if (oneCircuit->gates[oneCircuit->output_nodes[out]]->output_states[i] != original.gates[original.output_nodes[out]]->output_states[i]) {
++errors;
}
}
}
return errors;
}
int dominates(Circuit *A,unsigned int errorsA,Circuit *B,unsigned int errorsB){
bool Adominates = false;
bool Bdominates = false;
if((A->parameters[objective] < B->parameters[objective]) || (errorsA < errorsB)){
Adominates = true;
}
if((A->parameters[objective] > B->parameters[objective]) || (errorsA > errorsB)){
Bdominates = true;
}
if(Adominates && !Bdominates){
return 1;
}else if(!Adominates && Bdominates){
return -1;
}
return 0;
}
void run(unsigned int lambda) {
archive.push_back(std::make_pair(original,0));
std::cout <<"generation,entropy,size,depth,errors" << std::endl;
for(unsigned int i = 0; i < generations; ++i) {
std::uniform_int_distribution<size_t> dist(0, archive.size() - 1);
int randomParent = dist(rd);
std::vector<std::pair<Circuit, unsigned int>> children;
for (int i = 0; i < lambda; ++i) {
Circuit child = pointMutation(&archive[randomParent].first);
unsigned int childErrors = getErrors(&child);
children.push_back(std::make_pair(child,childErrors));
}
for (auto &child : children) {
bool dominated = false;
for (int i =0;i<archive.size();++i) {
int childDominatesArchive = dominates(&child.first, child.second, &archive[i].first, archive[i].second);
if (childDominatesArchive<0) {
dominated = true;
}else if (childDominatesArchive>0){
archive.erase(archive.begin() + i);
}else{
bool allEqual = true;
for (int param = 0; param < 3; ++param) {
if (child.first.parameters[param] != archive[i].first.parameters[param]) {
allEqual = false;
break;
}
}
if (allEqual) {
archive.erase(archive.begin() + i);
}
}
}
if (!dominated) {
archive.push_back(child);
}
}
for (const auto &element : archive) {
std::cout << i << "," << element.first.parameters[ENTROPY] << "," << element.first.parameters[SIZE] << "," << element.first.parameters[DEPTH] << "," << element.second << std::endl;
}
}
}
};
#endif