00001
00002
00003
00004
00005 #ifndef __EVOFUNC_H
00006 #define __EVOFUNC_H
00007
00008 #include <iostream>
00009 #include <fstream>
00010 #include <vector>
00011 #include <math.h>
00012 #include "map_functions/Map.h"
00013 #include "Population.h"
00014
00015 using namespace std;
00016
00017
00018 class EvoView;
00019
00020
00021
00022
00023
00024 template<class Traits, class ParTraits>
00025 class EvoFunc
00026 {
00027
00028 public:
00029
00030 typedef typename Traits::SourceType SourceType;
00031 typedef typename Traits::TransformedSourceType TransformedSourceType;
00032 typedef typename Traits::TargetType TargetType;
00033
00034 typedef typename Traits::MapType MapType;
00035 typedef typename Traits::ErrorType ErrorType;
00036
00037
00038 EvoFunc(SourceType& source, TargetType& target, const Traits& evo_traits);
00039 EvoFunc(SourceType& source, TransformedSourceType& transformed_source, TargetType& target, const Traits& evo_traits);
00040 ~EvoFunc() { delete pop_p; }
00041
00042 void init();
00043
00044 Population<ParTraits> *get_pop_p() { return pop_p; }
00045
00046 void run(int max_nr_iterations = ParTraits::MAX_ITERATIONS);
00047 void run_2d_grid(int index[2], vector<vector<double> >& fitness_matrix);
00048 void run_1d_array(int index, vector<double>& fitness_array);
00049
00050 double evaluate();
00051 double evaluate_individual(Indiv& ind);
00052 Indiv *get_best_indiv() { return (*pop_p)[pop_p->get_best_index()]; }
00053 int get_nr_iterations() { return current_iteration; }
00054
00055 friend class EvoView;
00056
00057
00058 private:
00059
00060 SourceType& source;
00061 TransformedSourceType& transformed_source;
00062 TargetType& target;
00063 const Traits& evo_traits;
00064
00065 MapType& map;
00066 ErrorType& error;
00067
00068 Population<ParTraits> *pop_p;
00069
00070
00071 int check_terminate(double best_fitness);
00072 double prev_fitness;
00073
00074 static const int DELTA_WINDOW_SIZE = 5;
00075 double fitness_deltas[DELTA_WINDOW_SIZE];
00076 int current_iteration;
00077
00078 static const int GRID_NR_STEPS = 50;
00079 static const int ARRAY_NR_STEPS = 50;
00080
00081
00082 };
00083
00084
00085
00086
00087
00088
00089
00090 template<class Traits, class ParTraits>
00091 EvoFunc<Traits, ParTraits>::EvoFunc(SourceType& source_ref, TransformedSourceType& transformed_source_ref,
00092 TargetType& target_ref, const Traits& evo_traits_ref) :
00093 source(source_ref),
00094 transformed_source(transformed_source_ref),
00095 target(target_ref),
00096 evo_traits(evo_traits_ref),
00097 map(evo_traits.map_object()),
00098 error(evo_traits.error_object())
00099 {
00100 pop_p = 0;
00101 init();
00102
00103 }
00104
00105
00106
00107 template<class Traits, class ParTraits>
00108 EvoFunc<Traits, ParTraits>::EvoFunc(SourceType& source_ref, TargetType& target_ref, const Traits& evo_traits_ref) :
00109 source(source_ref),
00110 transformed_source(target_ref),
00111 target(target_ref),
00112 evo_traits(evo_traits_ref),
00113 map(evo_traits.map_object()),
00114 error(evo_traits.error_object())
00115 {
00116 pop_p = 0;
00117 init();
00118
00119 }
00120
00121
00122
00123 template<class Traits, class ParTraits>
00124 void
00125 EvoFunc<Traits, ParTraits>::init()
00126 {
00127 if (pop_p) delete pop_p;
00128 pop_p = new Population<ParTraits>();
00129
00130
00131
00132
00133 prev_fitness = 1e6;
00134 current_iteration = 0;
00135
00136
00137 vector<double>& par_ranges = map.get_parameter_ranges();
00138 pop_p->init(par_ranges);
00139
00140 }
00141
00142
00143
00144 template<class Traits, class ParTraits>
00145 void
00146 EvoFunc<Traits, ParTraits>::run(int max_nr_iterations)
00147 {
00148
00149 int t = 0;
00150
00151
00152 double best_fit = evaluate();
00153 if (check_terminate(best_fit)) return;
00154
00155 int done = 0;
00156
00157 while(!done) {
00158
00159
00160 t++;
00161 current_iteration = t;
00162
00163
00164 pop_p->select_parents();
00165
00166
00167
00168
00169
00170 pop_p->recombine();
00171
00172
00173 pop_p->mutate();
00174
00175
00176 double best_fit = evaluate();
00177
00178
00179 pop_p->select_survivors();
00180
00181 done = (t == max_nr_iterations) || check_terminate(best_fit);
00182
00183 if (ParTraits::VERBOSITY)
00184 cout << "\rdone with iteration " << t << ", best error = " << best_fit << " " << flush;
00185
00186 }
00187
00188
00189 }
00190
00191
00192
00193 template<class Traits, class ParTraits>
00194 double
00195 EvoFunc<Traits, ParTraits>::evaluate()
00196 {
00197
00198
00199 double best_fit = 1e9;
00200 int nr = pop_p->get_size();
00201 TransformedSourceType result;
00202
00203 for(int i=0; i < nr; i++) {
00204
00205 Indiv *ind_p = (*pop_p)[i];
00206 map(source, result, ind_p->get_pars());
00207
00208 double err = error(result, target);
00209 ind_p->set_fitness(err);
00210
00211 if (err < best_fit) {
00212 best_fit = err;
00213 pop_p->set_best_index(i);
00214 }
00215
00216 }
00217
00218 return best_fit;
00219
00220 }
00221
00222
00223
00224 template<class Traits, class ParTraits>
00225 int
00226 EvoFunc<Traits, ParTraits>::check_terminate(double best_fitness)
00227 {
00228 if (!finite(best_fitness)) {
00229 cout << "error: fitness value is not finite" << endl;
00230 return 1;
00231 }
00232
00233 if (best_fitness < ParTraits::TERMINATION_FITNESS_CUTOFF) {
00234 if (ParTraits::VERBOSITY)
00235 cout << "terminating because fitness " << best_fitness << " < " << ParTraits::TERMINATION_FITNESS_CUTOFF << endl;
00236 return 1;
00237 }
00238
00239 double delta = fabs(best_fitness - prev_fitness);
00240 prev_fitness = best_fitness;
00241
00242 int delta_index = current_iteration % DELTA_WINDOW_SIZE;
00243 fitness_deltas[delta_index] = delta;
00244
00245 if (current_iteration >= DELTA_WINDOW_SIZE) {
00246 double fitness_delta_sum = 0;
00247 for(int i=0; i < DELTA_WINDOW_SIZE; i++) fitness_delta_sum += fitness_deltas[i];
00248
00249 double avg_delta = fitness_delta_sum / DELTA_WINDOW_SIZE;
00250 if (avg_delta < ParTraits::TERMINATION_FITNESS_EPSILON) {
00251 if (ParTraits::VERBOSITY) {
00252 cout << "terminating because average difference between consecutive fitness values over " << DELTA_WINDOW_SIZE
00253 << " steps < " << ParTraits::TERMINATION_FITNESS_EPSILON << endl;
00254 }
00255 return 1;
00256 }
00257 }
00258
00259 return 0;
00260
00261 }
00262
00263
00264
00265 template<class Traits, class ParTraits>
00266 void
00267 EvoFunc<Traits, ParTraits>::run_1d_array(int index, vector<double>& fitness_array)
00268 {
00269 char output_filespec[80];
00270 sprintf(output_filespec, "array_%d.dat", index);
00271 ofstream *out = new ofstream(output_filespec);
00272 if (ParTraits::VERBOSITY)
00273 cout << "EvoFunc::run_1d_array, writing to [" << output_filespec << "]" << endl;
00274
00275
00276 fitness_array.clear();
00277
00278 vector<double>& par_ranges = map.get_parameter_ranges();
00279 vector<double>& parameters = map.get_parameters();
00280
00281 double p_start = par_ranges[index * 2];
00282 double p_end = par_ranges[index * 2 + 1];
00283 double p_delta = (p_end - p_start) / ARRAY_NR_STEPS;
00284
00285 if (ParTraits::VERBOSITY)
00286 cout << "single loop running from " << p_start << " to " << p_end << ", step " << p_delta << endl;
00287
00288
00289 int nr_pars = parameters.size();
00290 Indiv ind(nr_pars);
00291
00292 vector<double>& pars = ind.get_pars();
00293 for(int i=0; i < nr_pars; i++) pars[i] = parameters[i];
00294
00295
00296 TransformedSourceType result;
00297 for(double p = p_start; p <= p_end; p += p_delta) {
00298 pars[index] = p;
00299
00300 map(source, result, ind.get_pars());
00301 double err = error(result, target);
00302 ind.set_fitness(err);
00303
00304 *out << p << " " << err << endl;
00305 fitness_array.push_back(err);
00306
00307 }
00308
00309 out->close();
00310 delete out;
00311
00312 }
00313
00314
00315
00316 template<class Traits, class ParTraits>
00317 void
00318 EvoFunc<Traits, ParTraits>::run_2d_grid(int index[2], vector<vector<double> >& fitness_matrix)
00319 {
00320 char output_filespec[80];
00321 sprintf(output_filespec, "grid_%d%d.dat", index[0], index[1]);
00322 ofstream *out = new ofstream(output_filespec);
00323 if (ParTraits::VERBOSITY)
00324 cout << "EvoFunc::run_2d_grid, writing to [" << output_filespec << "]" << endl;
00325
00326
00327 for(unsigned int i=0; i < fitness_matrix.size(); i++) fitness_matrix[i].clear();
00328 fitness_matrix.clear();
00329
00330 for(int i=0; i <= GRID_NR_STEPS; i++) {
00331 vector<double> temp;
00332 fitness_matrix.push_back(temp);
00333 for(int j=0; j <= GRID_NR_STEPS; j++) {
00334 fitness_matrix[i].push_back(0);
00335 }
00336 }
00337
00338 vector<double>& par_ranges = map.get_parameter_ranges();
00339 vector<double>& parameters = map.get_parameters();
00340
00341
00342 double p_start[2], p_end[2], p_delta[2];
00343 for(int i=0; i < 2; i++) {
00344 p_start[i] = par_ranges[index[i] * 2];
00345 p_end[i] = par_ranges[index[i] * 2 + 1];
00346 p_delta[i] = (p_end[i] - p_start[i]) / GRID_NR_STEPS;
00347 if (ParTraits::VERBOSITY)
00348 cout << "loop " << i << " running from " << p_start[i] << " to " << p_end[i] << ", step " << p_delta[i] << endl;
00349 }
00350
00351
00352 int nr_pars = parameters.size();
00353 Indiv ind(nr_pars);
00354
00355 vector<double>& pars = ind.get_pars();
00356 for(int i=0; i < nr_pars; i++) pars[i] = parameters[i];
00357
00358
00359 int i1 = 0;
00360 TransformedSourceType result;
00361
00362 for(double p1 = p_start[0]; p1 <= p_end[0]; p1 += p_delta[0]) {
00363 pars[index[0]] = p1;
00364
00365 int i2 = 0;
00366 for(double p2 = p_start[1]; p2 <= p_end[1]; p2 += p_delta[1]) {
00367 pars[index[1]] = p2;
00368
00369 map(source, result, ind.get_pars());
00370 double err = error(result, target);
00371 ind.set_fitness(err);
00372
00373
00374 *out << p1 << " " << p2 << " " << err << endl;
00375 fitness_matrix[i1][i2] = err;
00376 i2++;
00377
00378 }
00379 *out << endl;
00380 i1++;
00381
00382 }
00383
00384 out->close();
00385 delete out;
00386
00387 }
00388
00389
00390
00391 template<class Traits, class ParTraits>
00392 double
00393 EvoFunc<Traits, ParTraits>::evaluate_individual(Indiv& ind)
00394 {
00395 TransformedSourceType result;
00396 map(source, result, ind.get_pars());
00397 double err = error(result, target);
00398 ind.set_fitness(err);
00399 return err;
00400
00401 }
00402
00403
00404
00405 #endif
00406