NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
NeuroEvoPopulation.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2012, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
7  * under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language
16  * governing permissions and limitations under the License.
17 */
18 
27 #include "NeuroEvoPopulation.h"
28 // The C++ Standard Library
29 #include <string>
30 #include <vector>
31 #include <iostream>
32 #include <numeric>
33 #include <fstream>
34 #include <algorithm>
35 #include <stdexcept>
36 #include <cassert>
37 
38 using namespace std;
39 
40 NeuroEvoPopulation::NeuroEvoPopulation(int populationSize,configuration& config) :
41 m_config(config),
42 compareAverageScores(true),
43 clearScoresBetweenGenerations(false)
44 {
45  this->compareAverageScores=config.getintvalue("compareAverageScores");
46  this->clearScoresBetweenGenerations=config.getintvalue("clearScoresBetweenGenerations");
47 
48  for(int i=0;i<populationSize;i++)
49  {
50  cout<<" creating members"<<endl;
51  controllers.push_back(new NeuroEvoMember(config));
52  }
53 }
54 
55 NeuroEvoPopulation::~NeuroEvoPopulation()
56 {
57  for(std::size_t i=0;i<controllers.size();i++)
58  {
59  delete controllers[i];
60  }
61 }
62 
63 void NeuroEvoPopulation::mutate(std::tr1::ranlux64_base_01 *engPntr,std::size_t numMutate)
64 {
65  if(numMutate>controllers.size()/2)
66  {
67  cout<<"Trying to mutate more than half of the population"<<endl;
68  exit(0);
69  }
70  for(std::size_t i=0;i<numMutate;i++)
71  {
72  int copyFrom = i;
73  int copyTo = this->controllers.size()-1-i;
74  controllers.at(copyTo)->copyFrom(controllers.at(copyFrom));
75  controllers.at(copyTo)->mutate(engPntr);
76  }
77  return;
78 }
79 
80 void NeuroEvoPopulation::combineAndMutate(std::tr1::ranlux64_base_01 *eng, std::size_t numToMutate, std::size_t numToCombine)
81 {
82  std::tr1::uniform_real<double> unif(0, 1);
83 
84  if(numToMutate + numToCombine > controllers.size())
85  {
86  throw std::invalid_argument("Population will grow in size with these parameters");
87  }
88 
89  std::vector<double> probabilities = generateMatingProbabilities();
90 
91  std::vector<NeuroEvoMember*> newControllers;
92  for(int i = 0; i < numToCombine; i++)
93  {
94 
95  double val1 = unif(*eng);
96  double val2 = unif(*eng);
97 
98  int index1 = getIndexFromProbability(probabilities, val1);
99  int index2 = getIndexFromProbability(probabilities, val2);
100 
101  if(index1 == index2)
102  {
103  if(index2 == 0)
104  {
105  index2++;
106  }
107  else
108  {
109  index2--;
110  }
111  }
112 
113  NeuroEvoMember* newController = new NeuroEvoMember(m_config);
114  newController->copyFrom(controllers[index1], controllers[index2], eng);
115 
116  if(unif(*eng) > 0.9)
117  {
118  newController->mutate(eng);
119  }
120 
121  newControllers.push_back(newController);
122  }
123 
124  for(int i = 0; i < numToMutate; i++)
125  {
126  double val1 = unif(*eng);
127  int index1 = getIndexFromProbability(probabilities, val1);
128  NeuroEvoMember* newController = new NeuroEvoMember(m_config);
129  newController->copyFrom(controllers[index1]);
130  newController->mutate(eng);
131  newControllers.push_back(newController);
132  }
133 
134 
135  const std::size_t n = controllers.size();
136  const std::size_t m = newControllers.size();
137  while(controllers.size() > n - m)
138  {
139  controllers.pop_back();
140  }
141 
142  controllers.insert(controllers.end(), newControllers.begin(), newControllers.end());
143 
144  assert(controllers.size() == n);
145 }
146 
147 
148 void NeuroEvoPopulation::orderPopulation()
149 {
150  //calculate each member's average score
151  for(std::size_t i=0;i<this->controllers.size();i++)
152  {
153  double ave = std::accumulate(controllers[i]->pastScores.begin(),controllers[i]->pastScores.end(),0);
154 
155  double n = (double) controllers[i]->pastScores.size();
156  if (n > 0)
157  {
158  ave /= n;
159  }
160  else
161  {
162  ave = -100000;
163  }
164 
165  //assert(controllers[i]->pastScores.size() > 0);
166 
167  controllers[i]->averageScore=ave;
168  if(clearScoresBetweenGenerations)
169  controllers[i]->pastScores.clear();
170  }
171 // cout<<"ordering the whole population"<<endl;
172  if(compareAverageScores)
173  sort(controllers.begin(),controllers.end(),this->comparisonFuncForAverage);
174  else
175  sort(controllers.begin(),controllers.end(),this->comparisonFuncForMax);
176 
177 }
178 
179 std::vector<double> NeuroEvoPopulation::generateMatingProbabilities()
180 {
181  double totalScore = 0.0;
182  const std::size_t n = controllers.size();
183  std::vector<double> probabilties;
184  if (compareAverageScores)
185  {
186  double floor = controllers[n - 1]->averageScore;
187 
188  for (std::size_t i = 0; i < n; i++)
189  {
190  totalScore += (controllers[i]->averageScore - floor);
191  }
192 
193  probabilties.push_back((controllers[0]->averageScore - floor) / totalScore);
194  for (std::size_t i = 1; i < n; i++)
195  {
196  double nextScore = (controllers[i]->averageScore - floor) / totalScore + probabilties[i - 1];
197  probabilties.push_back(nextScore);
198  }
199  }
200  else
201  {
202  double floor = controllers[n - 1]->maxScore;
203 
204  for (std::size_t i = 0; i < n; i++)
205  {
206  totalScore += (controllers[i]->maxScore - floor);
207  }
208 
209  probabilties.push_back((controllers[0]->maxScore - floor) / totalScore);
210  for (std::size_t i = 1; i < n; i++)
211  {
212  double nextScore = (controllers[i]->maxScore - floor) / totalScore + probabilties[i - 1];
213  probabilties.push_back(nextScore);
214  }
215  }
216 
217  return probabilties;
218 }
219 
220 int NeuroEvoPopulation::getIndexFromProbability(std::vector<double>& probs, double val)
221 {
222  int i = 0;
223 
224  while(i < (probs.size() - 1) && probs[i] < val)
225  {
226  i++;
227  }
228 
229  return i;
230 }
231 
232 bool NeuroEvoPopulation::comparisonFuncForAverage(NeuroEvoMember * elm1, NeuroEvoMember * elm2)
233 {
234  return elm1->averageScore > elm2->averageScore;
235 }
236 bool NeuroEvoPopulation::comparisonFuncForMax(NeuroEvoMember * elm1, NeuroEvoMember * elm2)
237 {
238  return elm1->maxScore > elm2->maxScore;
239 }
A set of members that gets updated and mutated.