NTRT Simulator  v1.1
 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 {
43  compareAverageScores=true;
44  clearScoresBetweenGenerations=false;
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  ave /= (double) controllers[i]->pastScores.size();
155  controllers[i]->averageScore=ave;
156  if(clearScoresBetweenGenerations)
157  controllers[i]->pastScores.clear();
158  }
159 // cout<<"ordering the whole population"<<endl;
160  if(compareAverageScores)
161  sort(controllers.begin(),controllers.end(),this->comparisonFuncForAverage);
162  else
163  sort(controllers.begin(),controllers.end(),this->comparisonFuncForMax);
164 
165 }
166 
167 std::vector<double> NeuroEvoPopulation::generateMatingProbabilities()
168 {
169  double totalScore = 0.0;
170  const std::size_t n = controllers.size();
171  for (std::size_t i = 0; i < n; i++)
172  {
173  totalScore += controllers[i]->maxScore;
174  }
175 
176  std::vector<double> probabilties;
177  probabilties.push_back(controllers[0]->maxScore / totalScore);
178  for (std::size_t i = 1; i < n; i++)
179  {
180  double nextScore = controllers[i]->maxScore / totalScore + probabilties[i - 1];
181  probabilties.push_back(nextScore);
182  }
183 
184  // 1.0 is too strict, so just get close
185  assert(probabilties[n - 1] >= .99);
186 
187  return probabilties;
188 }
189 
190 int NeuroEvoPopulation::getIndexFromProbability(std::vector<double>& probs, double val)
191 {
192  int i = 0;
193 
194  while(i < (probs.size() - 1) && probs[i] < val)
195  {
196  i++;
197  }
198 
199  return i;
200 }
201 
202 bool NeuroEvoPopulation::comparisonFuncForAverage(NeuroEvoMember * elm1, NeuroEvoMember * elm2)
203 {
204  return elm1->averageScore > elm2->averageScore;
205 }
206 bool NeuroEvoPopulation::comparisonFuncForMax(NeuroEvoMember * elm1, NeuroEvoMember * elm2)
207 {
208  return elm1->maxScore > elm2->maxScore;
209 }
A set of members that gets updated and mutated.