-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathGene.cpp
More file actions
143 lines (124 loc) · 3.08 KB
/
Copy pathGene.cpp
File metadata and controls
143 lines (124 loc) · 3.08 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
#include <cassert>
#include <cmath>
#include "Gene.hpp"
#include "Random.hpp"
unsigned Gene::m_num_args = 0;
unsigned Gene::m_num_genes = 0;
Gene::Gene(unsigned gene_count) :
m_idx(gene_count)
{
m_type = _getNewType();
m_value = _getNewValue();
}
void Gene::mutate()
{
auto gene_id = m_idx;
auto num_args = m_num_args;
auto type = m_type;
m_value = _getNewValue();
// Confirm that the object invariants were not modified
assert(gene_id == m_idx);
assert(num_args == m_num_args);
assert(type == m_type);
}
void Gene::init(unsigned num_args, unsigned num_genes)
{
m_num_args = num_args;
m_num_genes = num_genes;
}
Type Gene::_getNewType() const
{
Type type;
auto right_idx = 2*m_idx + 2;
if (right_idx >= m_num_genes) {
if (Random::UnsignedUniform(0,9) > 4) {
type = Type::Constant;
} else {
type = Type::Variable;
}
} else {
type = Type::Operator;
}
return type;
}
int Gene::_getNewValue() const
{
auto value = 0u;
if (m_type == Type::Variable) {
value = Random::UnsignedUniform(0, m_num_args-1);
} else if (m_type == Type::Operator) {
value = Random::UnsignedUniform(0, 3);
} else {
value = Random::UnsignedUniform(0, 9);
}
return value;
}
unsigned Gene::getValue() const
{
return m_value;
}
Type Gene::getType() const
{
return m_type;
}
unsigned Gene::getIdx() const
{
return m_idx;
}
std::string Gene::toString() const
{
std::string response;
if (m_type == Type::Variable) {
response = "x" + std::to_string(m_value);
} else if (m_type == Type::Operator) {
auto value = m_value == 2 ? 5 : m_value;
response = std::string(1, static_cast<char>(value+42));
} else {
response = std::to_string(m_value);
}
return response;
}
// * = 42 = 0 + 42
// + = 43 = 1 + 42
// - = 45 = 3 + 42
// / = 47 = 5 + 42
bool Gene::_isOperator(char op) const {
auto op_val = static_cast<unsigned>(op) - 42;
auto response = false;
if (op_val == m_value) {
response = true;
} else if (op_val == 5 && m_value == 2) {
response = true;
}
return response;
}
double Gene::getValue(const std::vector<double>& args) const {
assert(m_type != Type::Operator);
double value;
if (m_type == Type::Variable) {
value = args[m_value];
} else {
value = static_cast<double>(m_value);
}
return value;
}
double Gene::doOperation(double val1, double val2) const
{
double response;
if (val1 == std::numeric_limits<double>::max()) {
response = val1;
} else if (val2 == std::numeric_limits<double>::max()) {
response = val2;
} else if (_isOperator('+')) {
response = val1 + val2;
} else if (_isOperator('-')) {
response = val1 - val2;
} else if (_isOperator('*')) {
response = val1 * val2;
} else if (_isOperator('/') && val2 != 0) {
response = val1 / val2;
} else {
response = std::numeric_limits<double>::max();
}
return response;
}