00001
00002
00003
00004
00005 #ifndef __Population_h
00006 #define __Population_h
00007
00008 #include <iostream>
00009 #include <vector>
00010 #include <assert.h>
00011 #include "Indiv.h"
00012 #include "MyRandom.h"
00013
00014 using namespace std;
00015
00016
00017 #define EVODEBUG(x)
00018
00019
00020
00021
00022
00023 template<class ParTraits>
00024 class Population
00025 {
00026
00027 public:
00028
00029 Population();
00030 ~Population();
00031
00032 void init(vector<double>& parameter_ranges);
00033
00034 void add_indiv(Indiv *indiv_p);
00035
00036 int get_size() { return indivs.size(); }
00037
00038 void select_parents();
00039 void shuffle();
00040
00041 void recombine();
00042
00043 void make_children(Indiv *parent1, Indiv *parent2);
00044
00045 void mutate();
00046
00047 void select_survivors();
00048
00049 int get_best_index() { return best_index; }
00050 void set_best_index(int new_index) { best_index = new_index; }
00051
00052 inline Indiv * operator[](int index) const { return indivs[index]; }
00053
00054
00055 private:
00056
00057 std::vector<Indiv *> indivs;
00058
00059 int nr_parameters;
00060
00061 int best_index;
00062
00063
00064 };
00065
00066
00067
00068
00069
00070
00071
00072 template<class ParTraits>
00073 Population<ParTraits>::Population()
00074 {
00075
00076 }
00077
00078
00079
00080 template<class ParTraits>
00081 Population<ParTraits>::~Population()
00082 {
00083 int pop_size = indivs.size();
00084 for(int i=0; i < pop_size; i++) delete indivs[i];
00085
00086 }
00087
00088
00089
00090 template<class ParTraits>
00091 void
00092 Population<ParTraits>::init(vector<double>& parameter_ranges)
00093 {
00094 nr_parameters = parameter_ranges.size() / 2;
00095
00096 if (ParTraits::VERBOSITY) {
00097 cout << "Population::init, creating " << ParTraits::POPULATION_SIZE << " individuals" << endl;
00098 cout << " nr_parameters = " << nr_parameters << endl;
00099 }
00100
00101 for(int i=0; i < ParTraits::POPULATION_SIZE; i++) {
00102 Indiv *ind_p = new Indiv(nr_parameters);
00103 ind_p->init(parameter_ranges);
00104 add_indiv(ind_p);
00105 }
00106
00107 }
00108
00109
00110
00111 template<class ParTraits>
00112 void
00113 Population<ParTraits>::add_indiv(Indiv *indiv_p)
00114 {
00115 indivs.push_back(indiv_p);
00116
00117 }
00118
00119
00120
00121 template<class ParTraits>
00122 void
00123 Population<ParTraits>::make_children(Indiv *parent1, Indiv *parent2)
00124 {
00125 EVODEBUG(cout << "Population::make_children" << endl);
00126
00127 for(int i=0; i < ParTraits::NR_CHILDREN; i++) {
00128 Indiv *ind_p = new Indiv(nr_parameters);
00129 add_indiv(ind_p);
00130
00131
00132
00133
00134 ind_p->recombine(parent1, parent2);
00135
00136 }
00137
00138 }
00139
00140
00141
00142 template<class ParTraits>
00143 void
00144 Population<ParTraits>::mutate()
00145 {
00146
00147 for(unsigned int i=0; i < indivs.size(); i++) {
00148 indivs[i]->mutate(i == 0);
00149 }
00150
00151 }
00152
00153
00154
00155
00156 template<class ParTraits>
00157 void
00158 Population<ParTraits>::select_survivors()
00159 {
00160 EVODEBUG(cout << "Population::select_survivors" << endl);
00161
00162 int pop_size = indivs.size();
00163 int *keep = new int[pop_size];
00164 for(int i=0; i < pop_size; i++) keep[i] = 0;
00165
00166
00167 for(int i=0; i < ParTraits::POPULATION_SIZE; i++) {
00168 double best_fitness = 1e6;
00169 int cur_best_index = -1;
00170 for(int j=0; j < pop_size; j++) {
00171 double fitness = indivs[j]->get_fitness();
00172 if ((fitness < best_fitness) && !keep[j]) {
00173 best_fitness = fitness;
00174 cur_best_index = j;
00175 }
00176 }
00177 keep[cur_best_index] = 1;
00178 if (i == 0) best_index = cur_best_index;
00179
00180 }
00181
00182 int nr_removed = 0;
00183 int index = 0;
00184 for(int i=0; i < pop_size; i++) {
00185 if (keep[i]) {
00186
00187 Indiv *ind_p = indivs[index];
00188 indivs[index] = indivs[i];
00189 indivs[i] = ind_p;
00190
00191 if (i == best_index) best_index = index;
00192 index++;
00193 }
00194 else
00195 nr_removed++;
00196
00197 }
00198
00199 delete[] keep;
00200
00201 int new_size = ParTraits::POPULATION_SIZE;
00202 for(int i = new_size; i < pop_size; i++) delete indivs[i];
00203 indivs.erase(indivs.begin() + new_size, indivs.end());
00204
00205 EVODEBUG(cout << "done, removed " << nr_removed << " individuals, population size now " << indivs.size() << endl);
00206
00207 }
00208
00209
00210
00211 template<class ParTraits>
00212 void
00213 Population<ParTraits>::select_parents()
00214 {
00215 int pop_size = indivs.size();
00216 EVODEBUG(cout << "Population::select_parents, population size is " << pop_size << endl);
00217 for(int i=0; i < pop_size; i++) indivs[i]->set_parent(0);
00218
00219 int nr_desired_parents = (int)(floor(pop_size * ParTraits::PARENTS_PERCENTAGE / 100.0 + 0.5));
00220 if ((nr_desired_parents % 2) == 1) {
00221
00222 if (nr_desired_parents < pop_size) nr_desired_parents++;
00223 else nr_desired_parents--;
00224 }
00225
00226
00227 double sum = 0;
00228 for(int i=0; i < pop_size; i++) sum += indivs[i]->get_fitness();
00229 double avg = sum / pop_size;
00230
00231
00232 int nr_selected = 0;
00233
00234
00235 int nr_passes = 0;
00236 while((nr_selected < nr_desired_parents) && (nr_passes < ParTraits::MAX_PARENT_SELECTION_PASSES)) {
00237
00238
00239 int *candidates = new int[pop_size];
00240 for(int i=0; i < pop_size; i++) candidates[i] = i;
00241 for(int i=0; i < pop_size; i++) {
00242 int rand_index = rand() % pop_size;
00243 int temp = candidates[rand_index];
00244 candidates[rand_index] = candidates[i];
00245 candidates[i] = temp;
00246 }
00247
00248
00249
00250 for(int i=0; i < pop_size; i++) {
00251 if (!indivs[i]->is_parent()) {
00252 double value = indivs[i]->get_fitness();
00253
00254 double threshold = value / (2 * avg);
00255 double random = MyRandom::uniform(0, 1) * (nr_passes + 1);
00256 if (random > threshold) {
00257 indivs[i]->set_parent(1);
00258 nr_selected++;
00259 }
00260 }
00261 }
00262
00263 nr_passes++;
00264
00265 }
00266
00267 EVODEBUG(cout << "Population::select_parents: selected " << nr_desired_parents << " parents" << endl);
00268
00269 }
00270
00271
00272
00273 template<class ParTraits>
00274 void
00275 Population<ParTraits>::shuffle()
00276 {
00277
00278
00279 int pop_size = indivs.size();
00280 int nr_remaining = pop_size;
00281 for(int i=0; i < pop_size; i++) {
00282 int rand_index = rand() % nr_remaining + i;
00283 assert((rand_index >= 0) && (rand_index < pop_size));
00284
00285 Indiv *temp_p = indivs[i];
00286 indivs[i] = indivs[rand_index];
00287 indivs[rand_index] = temp_p;
00288
00289 nr_remaining--;
00290 }
00291
00292 }
00293
00294
00295
00296 template<class ParTraits>
00297 void
00298 Population<ParTraits>::recombine()
00299 {
00300
00301
00302 int p[2];
00303 int nr_parents = 0;
00304
00305 int pop_size = indivs.size();
00306 for(int i=0; i < pop_size; i += 2) {
00307
00308 if (indivs[i]->is_parent()) {
00309 p[nr_parents] = i;
00310 nr_parents++;
00311
00312 if (nr_parents == 2) {
00313 make_children(indivs[p[0]], indivs[p[1]]);
00314 nr_parents = 0;
00315 }
00316 }
00317
00318 }
00319
00320 }
00321
00322
00323
00324 #endif
00325
00326