ECF 1.5
AntEvalOp.cpp
1#include <cmath>
2#include <ecf/ECF.h>
3#include "AntEvalOp.h"
4#include <iostream>
5#include <fstream>
6#include <vector>
7#include <iostream>
8#include <string>
9using namespace std;
10
11
12bool AntEvalOp::trace = false;
13bool AntEvalOp::step = false;
14const char AntEvalOp::LEFT = '<';
15const char AntEvalOp::RIGHT = '>';
16const char AntEvalOp::UP = '^';
17const char AntEvalOp::DOWN = 'v';
18
19
23ostream& operator<<(ostream& os, AntEvalOp& ant)
24{
25 for (uint j = 0; j < ant.tmpRow; j++) {
26 os << endl;
27 for (uint k = 0; k < ant.tmpColumn; k++)
28 os << ant.tmpBoard[j * ant.tmpColumn + k];
29 }
30 os << endl;
31 return os;
32}
33
34
36{
37 state->getRegistry()->registerEntry("learning_trails", (voidP) (new std::string("learning_trails.txt")), ECF::STRING);
38 state->getRegistry()->registerEntry("test_trails", (voidP) (new std::string("test_trails.txt")), ECF::STRING);
39}
40
41
45bool AntEvalOp::initialize(StateP state)
46{
47 state_ = state;
48 // set the environment pointer to this object (so Tree elements can access the simulator)
49 state->getContext()->environment = this;
50
51 voidP sptr = state->getRegistry()->getEntry("learning_trails"); // get parameter value
52 std::string filePath = *((std::string*) sptr.get()); // convert from voidP to user defined type
53
54 ifstream file;
55 file.open(filePath.c_str());
56
57 if(!file.is_open()) {
58 ECF_LOG_ERROR(state, "Error: can't open input file " + filePath);
59 return false;
60 }
61
62 // read number of training trails
63 file >> boardNo;
64
65 // read parameters for every trail
66 for (uint k = 0; k < boardNo; k++) {
67 tmpRow = tmpColumn = tmpMaxSteps = 0;
68 file >> tmpRow;
69 file >> tmpColumn;
70 file >> tmpFoodNo;
71 file.ignore(1);
72 file >> tmpMaxSteps;
73
74 rowNo.push_back(tmpRow);
75 columnNo.push_back(tmpColumn);
76 maxSteps.push_back(tmpMaxSteps);
77 foodNo.push_back(tmpFoodNo);
78
79 tmpBoard = (char*) malloc (tmpRow * tmpColumn);
80
81 // read trail
82 for (uint i = 0; i < tmpRow; i++ )
83 for (uint j = 0; j < tmpColumn; j++)
84 file >> tmpBoard[i * tmpColumn + j];
85
86 board.push_back(tmpBoard);
87 }
88
89 file.close();
90
91 return true;
92}
93
94
98FitnessP AntEvalOp::evaluate(IndividualP individual)
99{
100 // greater fitness means better individual
101 FitnessP fitness (new FitnessMax);
102
103 // get tree from the individual
104 Tree::Tree* tree = (Tree::Tree*) individual->getGenotype().get();
105
106 //create output if necessary (for subsequent evaluation)
107 ofstream output;
108 if (trace) {
109 currentTree = tree->toString();
110 output.open("./output.txt");
111 output << "Number of trails: " << boardNo << endl;
112 }
113
114 int allTheFood = 0;
115 for (uint i = 0; i < boardNo; i++) {
116 // reset ant properties
117 x_ = y_ = 0;
118 moves_ = 0;
119 facing_ = 0;
120 foodEaten_ = 0;
121
122 // read one of the 'boards'
123 tmpRow = rowNo[i];
124 tmpColumn = columnNo[i];
125 tmpMaxSteps = maxSteps[i];
126 tmpFoodNo = foodNo[i];
127
128 tmpBoard = (char*) malloc (tmpRow * tmpColumn);
129
130 // create tmpBoard for every individual
131 for (uint j = 0; j < tmpRow; j++)
132 for (uint k = 0; k < tmpColumn; k++)
133 tmpBoard[j * tmpColumn + k] = board[i][j * tmpColumn + k];
134
135 // if the food is on position (0,0)
136 if (tmpBoard[0] == 'x')
137 foodEaten_++;
138 // if trace is set, mark where the ant was
139 if (trace)
140 if (tmpBoard[0] == 'x')
141 tmpBoard[0] = -2;
142 else tmpBoard[0] = 'o';
143
144 // repeat moving around until maxSteps is reached or all the food was eaten
145 while(moves_ < tmpMaxSteps && foodEaten_< tmpFoodNo) {
146 tree->execute(this);
147 }
148 allTheFood += foodEaten_;
149
150 // if trace is set, save the 'board' in output file
151 if (trace) {
152 output << "Dimension: " << tmpColumn << "x" << tmpRow << endl;
153 output << "Food: " << tmpFoodNo << endl;
154 output << "Max Steps: " << tmpMaxSteps << endl;
155 output << "Fitness (eaten food): " << foodEaten_ << endl;
156 output << *this << endl;
157 }
158
159 // and print it on stdout
160 if (trace) {
161 cout << *this;
162 cout << "Eaten food: " << foodEaten_ << endl;
163 }
164 free(tmpBoard);
165 }
166
167 // total fitness - after the ant traverses all the enviroments
168 if (trace) {
169 cout << "Food eaten in all the enviroments: " << allTheFood << endl;
170 output << "Total fitness: " << allTheFood << endl;
171 output.close();
172 }
173
174 fitness->setValue(allTheFood);
175
176 return fitness;
177}
178
179
184{
185 if (moves_ >= tmpMaxSteps) return;
186 moves_++;
187 // four directions: 0, 1, 2, 3
188 facing_ = (facing_ - 1) % 4;
189 if(trace && step)
190 showStep("left");
191}
192
193
198{
199 if (moves_ >= tmpMaxSteps) return;
200 moves_++;
201 // four directions: 0, 1, 2, 3
202 facing_ = (facing_ + 1) % 4;
203 if(trace && step)
204 showStep("right");
205}
206
207
212{
213 if (moves_ >= tmpMaxSteps) return;
214 moves_++;
215 // move forward
216 // facing: 0,2 - right left
217 // 1,3 - down up
218 switch (facing_)
219 {
220 case 3: //up
221 y_ = (y_ - 1) % tmpRow;
222 break;
223 case 2: //left
224 x_ = (x_ - 1) % tmpColumn;
225 break;
226 case 1: //down
227 y_ = (y_ + 1) % tmpRow;
228 break;
229 case 0: //right
230 x_ = (x_ + 1) % tmpColumn;
231 break;
232 default:
233 break;
234 }
235
236 // if ant is on the food, remove food from 'board' and increase the number of eaten food
237 if (tmpBoard[y_*tmpColumn+x_] == 'x') {
238 foodEaten_++;
239 if (trace)
240 tmpBoard[y_*tmpColumn+x_] = -2;
241 else
242 tmpBoard[y_*tmpColumn+x_] = '.';
243 }
244 if(trace) {
245 if(tmpBoard[y_*tmpColumn+x_] == '.')
246 tmpBoard[y_*tmpColumn+x_] = 'o';
247 if(step)
248 showStep("move");
249 }
250}
251
252
257{
258 int x1,y1;
259 x1 = x_;
260 y1 = y_;
261 switch (facing_)
262 {
263 case 3: y1 = (y_==0 ? tmpRow-1 : y_-1); break; // up
264 case 2: x1 = (x_==0 ? tmpColumn-1 : x_-1); break; // left
265 case 1: y1 = (y_+1)%tmpRow; break; // down
266 case 0: x1 = (x_+1)%tmpColumn; break; // right
267 }
268 if (tmpBoard[y1 * tmpColumn + x1] == 'x')
269 return true;
270 return false;
271}
272
273
277void AntEvalOp::showStep(string action)
278{
279 cout << "Ant: " << currentTree << endl;
280 cout << "Action: " << action << ", moves: " << moves_ << "/" << tmpMaxSteps << endl;
281
282 char ant, position = tmpBoard[y_ * tmpColumn + x_];
283 switch (facing_) {
284 case 3: ant = UP; break;
285 case 2: ant = LEFT; break;
286 case 1: ant = DOWN; break;
287 case 0: ant = RIGHT; break;
288 }
289
290 tmpBoard[y_ * tmpColumn + x_] = ant;
291 cout << *this;
292 tmpBoard[y_ * tmpColumn + x_] = position;
293
294 cout << "(Enter to continue...)";
295 string dummy;
296 getline(cin, dummy);
297}
Artificial ant evaluation class (and environment simulator)
Definition: AntEvalOp.h:51
void turnRight()
Turn ant on the right.
Definition: AntEvalOp.cpp:197
void showStep(string action)
Show the ant's current action (interactive)
Definition: AntEvalOp.cpp:277
bool initialize(StateP)
Initialize the simulator, read environments from input file.
Definition: AntEvalOp.cpp:45
static bool step
show the ant's movement interactive step by step (no effect if trace is false!)
Definition: AntEvalOp.h:86
static bool trace
trace the ant's movement in the simulator (for visual output)
Definition: AntEvalOp.h:85
void moveAhead()
Move ant ahead.
Definition: AntEvalOp.cpp:211
void registerParameters(StateP)
Register evaluator parameters. Called before EvaluateOp::initialize method.
Definition: AntEvalOp.cpp:35
FitnessP evaluate(IndividualP individual)
Evaluation function, simulates ant movement and counts the eaten food.
Definition: AntEvalOp.cpp:98
bool facingFood()
Check if there's food in front.
Definition: AntEvalOp.cpp:256
void turnLeft()
Turn ant on the left.
Definition: AntEvalOp.cpp:183
Fitness for maximization problems.
Definition: FitnessMax.h:13
std::string toString()
Output genotype to string.
Definition: Genotype.h:98
Tree class - implements genotype as a tree.
Definition: Tree_c.h:29
void execute(void *)
Execute current tree.
Definition: Tree.cpp:362