ECF 1.5
APGenotype.cpp
1#include <ECF/ECF.h>
2#include <iostream>
3#include <cmath>
4#include "APGenotype.h"
5
6
7namespace Tree {
8
9
10void APGenotype::registerParameters(StateP state)
11{
12 registerParameter(state, "lbound", (voidP) new double(-10), ECF::DOUBLE,
13 "lower bound for each variable (mandatory)");
14 registerParameter(state, "ubound", (voidP) new double(10), ECF::DOUBLE,
15 "upper bound for each variable (mandatory)");
16 registerParameter(state, "dimension", (voidP) new uint(1), ECF::UINT,
17 "number of real valued variables (mandatory)");
18
19 registerParameter(state, "functionset", (voidP)(new std::string), ECF::STRING,
20 "set of functional tree elements (mandatory)");
21 registerParameter(state, "terminalset", (voidP)(new std::string), ECF::STRING,
22 "set of terminal tree elements (mandatory)");
23}
24
25
26bool APGenotype::addFunction(PrimitiveP func)
27{
28 userFunctions_.push_back(func);
29 return true;
30}
31
32
33bool APGenotype::addTerminal(PrimitiveP term)
34{
35 userTerminals_.push_back(term);
36 return true;
37}
38
39
40bool APGenotype::initialize(StateP state)
41{
42 if (!isParameterDefined(state, "lbound") ||
43 !isParameterDefined(state, "ubound") ||
44 !isParameterDefined(state, "dimension")) {
45 ECF_LOG_ERROR(state, "Error: required parameters not defined (lbound, ubound, dimension)!");
46 throw("");
47 }
48
49 state_ = state;
50
51 voidP genp = getParameterValue(state, "lbound");
52 minValue_ = *((double*)genp.get());
53
54 genp = getParameterValue(state, "ubound");
55 maxValue_ = *((double*)genp.get());
56
57 if (minValue_ >= maxValue_) {
58 ECF_LOG_ERROR(state, "Error: 'lbound' must be smaller than 'ubound'!");
59 throw("");
60 }
61
62 genp = getParameterValue(state, "dimension");
63 nDimension_ = *((uint*)genp.get());
64
65 if (nDimension_ < 1) {
66 ECF_LOG_ERROR(state, "Error: 'dimension' must be > 0 !");
67 throw("");
68 }
69
70
71 this->primitiveSet = (PrimitiveSetAPP)(new PrimitiveSetAP);
72 this->primitiveSet->initialize(state);
73
74 // add user defined functions to primitiveSet
75 for (int i = 0; i < (int)userFunctions_.size(); i++) {
76 primitiveSet->mAllPrimitives_[userFunctions_[i]->getName()] = userFunctions_[i];
77 primitiveSet->mAllPrimitives_[userFunctions_[i]->getName()]->initialize(state);
78 }
79
80 voidP sptr = getParameterValue(state, "functionset");
81 std::stringstream names;
82 std::string name;
83 names << *((std::string*) sptr.get());
84 while (names >> name) {
85 if (!primitiveSet->addFunction(name)) {
86 ECF_LOG_ERROR(state, "Error: unknown function in function set (\'" + name + "\')!");
87 throw("");
88 }
89
90 }
91
92 if (primitiveSet->getFunctionSetSize() == 0) {
93 ECF_LOG_ERROR(state, "AP genotype: empty function set!");
94 throw("");
95 }
96
97 // set default terminal type
98 Primitives::terminal_type currentType = Primitives::Double;
99 type_iter typeIter;
100
101 // read terminal set from the configuration
102 std::stringstream tNames;
103 sptr = getParameterValue(state, "terminalset");
104 tNames << *((std::string*) sptr.get());
105
106 while (tNames >> name)
107 {
108 // read current terminal type (if set)
109 typeIter = primitiveSet->mTypeNames_.find(name);
110 if (typeIter != primitiveSet->mTypeNames_.end()) {
111 currentType = typeIter->second;
112 continue;
113 }
114
115 // see if it's a user-defined terminal
116 uint iTerminal = 0;
117 for (; iTerminal < userTerminals_.size(); iTerminal++)
118 if (userTerminals_[iTerminal]->getName() == name)
119 break;
120 if (iTerminal < userTerminals_.size()) {
121 userTerminals_[iTerminal]->initialize(state);
122 primitiveSet->addTerminal(userTerminals_[iTerminal]);
123 continue;
124 }
125
126
127 // read ERC definition (if set)
128 // ERC's are defined as interval [x y] or set {a b c}
129 if (name[0] == '[' || name[0] == '{') {
130
131 std::string ercValues = "";
132
133 // name this ERC (ERC's name is its value!)
134 PrimitiveP erc;
135 switch (currentType) {
136 case Primitives::Double:
137 erc = (PrimitiveP)(new Primitives::ERCD);
138 ercValues = DBL_PREFIX;
139 break;
140 case Primitives::Int:
141 erc = (PrimitiveP)(new Primitives::ERC<int>);
142 ercValues = INT_PREFIX;
143 break;
144 case Primitives::Bool:
145 erc = (PrimitiveP)(new Primitives::ERC<bool>);
146 ercValues = BOOL_PREFIX;
147 break;
148 case Primitives::Char:
149 erc = (PrimitiveP)(new Primitives::ERC<char>);
150 ercValues = CHR_PREFIX;
151 break;
152 case Primitives::String:
153 erc = (PrimitiveP)(new Primitives::ERC<std::string>);
154 ercValues = STR_PREFIX;
155 break;
156 }
157
158 while (name[name.size() - 1] != ']' && name[name.size() - 1] != '}') {
159 ercValues += " " + name;
160 tNames >> name;
161 }
162 ercValues += " " + name;
163
164 // ERC ocekuje "D_ [<value> <value> ...]" kao ime prije initialize()
165 erc->setName(ercValues);
166 erc->initialize(state);
167 primitiveSet->addTerminal(erc);
168
169 continue;
170 }
171
172
173 // otherwise, read terminal of current type
174 PrimitiveP terminal;
175 switch (currentType)
176 {
177 case Primitives::Double:
178 terminal = (PrimitiveP)(new Primitives::Terminal); break;
179 case Primitives::Int:
180 terminal = (PrimitiveP)(new Primitives::TerminalT<int>); break;
181 case Primitives::Bool:
182 terminal = (PrimitiveP)(new Primitives::TerminalT<bool>); break;
183 case Primitives::Char:
184 terminal = (PrimitiveP)(new Primitives::TerminalT<char>); break;
185 case Primitives::String:
186 terminal = (PrimitiveP)(new Primitives::TerminalT<std::string>); break;
187 }
188
189 // if the 'name' can be identified as a value of the 'currentType', then it's a _constant terminal_ (of that value)
190 // otherwise, it's a regular terminal with 'name'
191 std::istringstream ss(name);
192 switch (currentType)
193 {
194 case Primitives::Double:
195 double dblValue;
196 ss >> dblValue;
197 if (ss.fail() == false)
198 terminal->setValue(&dblValue);
199 break;
200 case Primitives::Int:
201 int intValue;
202 ss >> intValue;
203 if (ss.fail() == false)
204 terminal->setValue(&intValue);
205 break;
206 case Primitives::Bool:
207 bool boolValue;
208 ss >> boolValue;
209 if (name == "true")
210 boolValue = true;
211 else if (name == "false")
212 boolValue = false;
213 if (ss.fail() == false || name == "true" || name == "false") {
214 if (boolValue)
215 name = "true";
216 else
217 name = "false";
218 terminal->setValue(&boolValue);
219 }
220 break;
221 case Primitives::Char:
222 char charValue;
223 ss >> charValue;
224 if (ss.fail() == false)
225 terminal->setValue(&charValue);
226 break;
227 case Primitives::String:
228 std::string stringValue;
229 ss >> stringValue;
230 if (ss.fail() == false)
231 terminal->setValue(&stringValue);
232 break;
233 }
234 terminal->setName(name);
235 primitiveSet->addTerminal(terminal);
236
237 }
238
239 if (primitiveSet->getTerminalSetSize() == 0) {
240 ECF_LOG_ERROR(state, "APGenotype: Empty terminal set!");
241 throw("");
242 }
243
244
245 realValue.resize(nDimension_);
246 // randomly create each dimension
247 for (uint i = 0; i < nDimension_; i++) {
248 realValue[i] = (minValue_ + (maxValue_ - minValue_) * state->getRandomizer()->getRandomDouble());
249 }
250
251 return true;
252}
253
254
255std::vector<uint> APGenotype::getDiscreteIndices()
256{
257 std::vector<uint> discrete;
258 discrete.resize(nDimension_);
259
260 double dindex, diff, delta;
261 int imax = primitiveSet->getPrimitivesSize() - 1, dis_index;
262 diff = maxValue_ - minValue_;
263 delta = 1.0 / (double)primitiveSet->getPrimitivesSize();
264
265 for (uint i = 0; i < nDimension_; i++) {
266 dis_index = 0;
267 dindex = (realValue[i] - minValue_) / diff;
268
269 dindex -= delta;
270 while (dindex > 0 && dis_index != imax) {
271 dindex -= delta;
272 dis_index++;
273 }
274
275 discrete[i] = dis_index;
276 }
277
278 return discrete;
279}
280
281
282void APGenotype::buildTree(std::vector<uint> indices, uint current, uint depth)
283{
284 Node* node = new Node();
285 node->depth_ = depth;
286
287 uint index = current - 1;
288
289 uint numArgs = primitiveSet->getPrimitiveByIndex(index)->getNumberOfArguments();
290
291 if (numArgs < toEnd) {
292 node->setPrimitive(primitiveSet->getPrimitiveByIndex(index));
293 nodes.push_back(static_cast<NodeP> (node));
294 } else if (toEnd >= 2 && toEnd <= numArgs && primitiveSet->getGFSTwoSetSize() != 0) {
295 node->setPrimitive(primitiveSet->getGFSTwoByIndex(index));
296 nodes.push_back(static_cast<NodeP> (node));
297 } else if (toEnd == 1 && primitiveSet->getGFSOneSetSize() != 0) {
298 node->setPrimitive(primitiveSet->getGFSOneByIndex(index));
299 nodes.push_back(static_cast<NodeP> (node));
300 } else {
301 node->setPrimitive(primitiveSet->getTerminalByIndex(index));
302 nodes.push_back(static_cast<NodeP> (node));
303 }
304
305 numArgs = node->primitive_->getNumberOfArguments();
306
307 toEnd -= numArgs;
308
309 if (numArgs > 0) {
310 std::vector<uint> passableIndices(indices.begin(), indices.begin() + numArgs);
311 indices.erase(indices.begin(), indices.begin() + numArgs - 1);
312
313 for (uint i = 0; i < numArgs; i++) {
314 buildTree(indices, passableIndices[i], depth + 1);
315 }
316 }
317}
318
319
320Tree* APGenotype::convertToPhenotype()
321{
322 std::vector<uint> indices = getDiscreteIndices();
323
324 toEnd = nDimension_ - 1;
325 uint first = indices[0];
326 nodes.clear();
327
328 indices.erase(indices.begin());
329
330 buildTree(indices, first, 0);
331
332 Tree* tree = new Tree();
333 for (uint i = 0; i < nodes.size(); i++) {
334 tree->addNode(nodes[i]);
335 }
336
337 std::stringstream sValue;
338 for (uint i = 0; i < tree->size(); i++) {
339 sValue << (*tree)[i]->primitive_->getName() << " ";
340 }
341
342 //cout << sValue.str() << endl;
343
344 return tree;
345}
346
347
348void APGenotype::setTerminalValue(Tree* tree, std::string name, void* value)
349{
350 PrimitiveP term = primitiveSet->getTerminalByName(name);
351 if (term == PrimitiveP()) {
352 ECF_LOG_ERROR(state_, "AP genotype: invalid terminal name referenced in setTerminalValue()!");
353 throw("");
354 }
355
356 term->setValue(value);
357}
358
359
360void APGenotype::write(XMLNode &xFloatingPoint)
361{
362 xFloatingPoint = XMLNode::createXMLTopNode("APGenotype");
363 std::stringstream sValue;
364 sValue << nDimension_;
365 xFloatingPoint.addAttribute("size", sValue.str().c_str());
366
367 sValue.str("");
368 for (uint iVar = 0; iVar < nDimension_; iVar++)
369 sValue << "\t" << realValue[iVar];
370 xFloatingPoint.addText(sValue.str().c_str());
371}
372
373
374void APGenotype::read(XMLNode& xFloatingPoint)
375{
376 XMLCSTR values = xFloatingPoint.getText();
377 std::stringstream sValues;
378 sValues << values;
379
380 for (uint iVar = 0; iVar < nDimension_; iVar++) {
381 sValues >> realValue[iVar];
382 }
383}
384
385
386}
voidP getParameterValue(StateP state, std::string name)
Read single parameter value from Registry.
Definition: Genotype.cpp:10
std::string getName()
Return genotype's name (each genotype is uniquely identified with its name).
Definition: Genotype.h:86
bool registerParameter(StateP state, std::string name, voidP value, enum ECF::type T, std::string description="")
Register a single parameter.
Definition: Genotype.cpp:4
bool isParameterDefined(StateP state, std::string name)
Check if parameter is defined in the configuration.
Definition: Genotype.cpp:22
uint nDimension_
dimensionality
double minValue_
lower bound
double maxValue_
upper bound
std::vector< double > realValue
vector of floating point values
void write(XMLNode &xFloatingPoint)
Write genotype data to XMLNode.
Definition: APGenotype.cpp:379
void read(XMLNode &xFloatingPoint)
Read genotype data from XMLNode.
Definition: APGenotype.cpp:393
bool initialize(StateP state)
Initialize a genotype object (read parameters, perform sanity check, build data)
Definition: APGenotype.cpp:39
void registerParameters(StateP)
Register genotype's parameters (called before Genotype::initialize)
Definition: APGenotype.cpp:9
Definition: nodes.h:92