GPLIB++
GeneralGA.cpp
Go to the documentation of this file.
1 #include "GeneralGA.h"
2 #include <cmath>
3 #include <iostream>
4 #include <numeric>
5 #include <sstream>
6 #include <map>
7 #include "statutils.h"
8 #include "VecMat.h"
9 #include "FatalException.h"
10 #include <boost/bind.hpp>
11 #include <algorithm>
12 #include <cassert>
13 #include <unistd.h>
14 #ifdef _OPENMP
15 #include <omp.h>
16 #endif
17 using namespace std;
18 
19 namespace gplib
20  {
21  //!Copy the objective function within the shared pointer
23  {
24  boost::shared_ptr<GeneralObjective> operator()(boost::shared_ptr<
25  GeneralObjective> param)
26  {
27  return boost::shared_ptr<GeneralObjective>(param->clone());
28  }
29  };
30 
31  //! Generate a new copy of the Objective function vector
32  struct GenObjective
33  {
35  const GeneralGA::tObjectiveVector &IndObjective)
36  {
37  GeneralGA::tObjectiveVector result(IndObjective.size()); //allocate space
38  transform(IndObjective.begin(), IndObjective.end(), result.begin(),
39  CopyFromPointer());//copy each objective function into result
40  return result;
41  }
42  };
43 
44  //! Generate a unique ID for filenames etc. so we can call generated scripts in parallel
45  std::string MakeParallelID(const int j, const int i,
46  const int iterationnumber, const int Programnum)
47  {
48  ostringstream filename;
49  filename << "j" << j << "i" << i << "g" << iterationnumber << "p"
50  << Programnum;
51  return filename.str();
52  }
53 
54  GeneralGA::GeneralGA(GeneralPropagation* const LocalPropagation,
55  GeneralPopulation* const LocalPopulation,
56  GeneralTranscribe* const LocalTranscribe,
57  const tObjectiveVector &IndObjective, const int nthreads) :
58  CombMisFit(LocalPopulation->GetPopsize()), AvgFit(IndObjective.size()),
59  MaxFit(IndObjective.size()), MinFit(IndObjective.size()), Weights(
60  IndObjective.size(), 1), nobjective(IndObjective.size()),
61  Transcribed(LocalPopulation->GetPopsize(),
62  LocalTranscribe->GetNparams()), MisFit(IndObjective.size(),
63  LocalPopulation->GetPopsize()), Objective(IndObjective),
64  Propagation(LocalPropagation), Population(LocalPopulation),
65  Transcribe(LocalTranscribe)
66  {
67  Threads = nthreads;
68  Elitist = true;
69  Programnum = getpid();
70  }
71 
73  {
74  }
75 
76  //Prepare the appropriate parameters for each objective function
78  tparamvector &params)
79  {
80  for (unsigned int i = 0; i < nobjective; ++i)
81  for (unsigned int j = 0; j < ParameterIndices.at(i).size(); ++j)
82  {
83  params.at(i)(j) = member(ParameterIndices.at(i).at(j));
84  }
85  }
86 
87  void GeneralGA::SetWeights(const std::vector<double> &LocalWeights)
88  {
89  if (LocalWeights.size() != Weights.size()) //Weights has been pre allocated based on the number of objective functions
90  throw FatalException(
91  "Configured number of weights does not match number of objective functions !");
92  Weights = LocalWeights;
93  }
94 
96  {
97  ParameterIndices = Indices;
98  }
99 
100  void GeneralGA::PrintFitStat(std::ostream &output)
101  {
102  for (unsigned int i = 0; i < nobjective; ++i)
103  {
104  output << MaxFit.at(i) << " " << MinFit.at(i) << " "
105  << AvgFit.at(i) << " ";
106  }
107  output << CombMaxFit << " " << CombMinFit << " " << CombAvgFit << " ";
108  output << endl << flush;
109  }
110 
111  void GeneralGA::PrintMisfit(std::ostream &output)
112  {
113  const unsigned int isize = MisFit.size1();
114  const unsigned int jsize = MisFit.size2();
115 
116  for (unsigned int i = 0; i < isize; ++i)
117  {
118  for (unsigned int j = 0; j < jsize; ++j)
119  output << MisFit(i, j) << " ";
120  output << endl;
121  }
122  copy(CombMisFit.begin(), CombMisFit.end(), ostream_iterator<double> (
123  output, " "));
124  output << endl << endl;
125  }
126 
127  void GeneralGA::PrintTranscribed(std::ostream &output)
128  {
129  const unsigned int isize = Transcribed.size1();
130  const unsigned int jsize = Transcribed.size2();
131  unsigned int i, j;
132  for (i = 0; i < isize; ++i)
133  {
134  for (j = 0; j < jsize; ++j)
135  output << Transcribed(i, j) << " ";
136  output << endl;
137  }
138  output << endl << flush;
139  }
140 
141  void GeneralGA::PrintBestMisfit(std::ostream &output)
142  {
143  std::vector<int> Indices(GetBestModelIndices());
144  const unsigned int isize = Indices.size();
145  const unsigned int jsize = MisFit.size1();
146 
147  for (unsigned int i = 0; i < isize; ++i)
148  {
149  const int currindex = Indices.at(i);
150  for (unsigned int j = 0; j < jsize; ++j)
151  output << MisFit(j, currindex) << " ";
152  output << endl;
153  }
154  output << endl << endl;
155  }
156 
157  void GeneralGA::CalcMisfit(const int iterationnumber)
158  {
159  int calculatecount = 0;
160  int newcount = 0;
161  // popsize cannot be unsigned because loop variables for openmp have to be signed
162  const int popsize = Population->GetPopsize();
163  ublas::vector<bool> AlreadyCalculated(popsize);
164  tfitvec fitvec(nobjective);
165 
166 #pragma omp parallel for default(shared)
167  for (int i = 0; i < popsize; ++i)
168  {
169  tparamvector LocalParameters(nobjective);
170  for (unsigned int k = 0; k < nobjective; ++k)
171  {
172  LocalParameters.at(k).resize(ParameterIndices.at(k).size(),
173  false);
174  }
175  row(Transcribed, i) = Transcribe->GetValues(row(
176  Population->GetPopulation(), i));
177  AlreadyCalculated(i) = UniquePopHist.Find(row(Transcribed, i),
178  fitvec);
179  if (!AlreadyCalculated(i))
180  {
181  SetupParams(row(Transcribed, i), LocalParameters);
182  tObjectiveVector LocalObjective(GenObjective()(Objective));
183  for (unsigned int j = 0; j < nobjective; ++j)
184  {
185  LocalObjective.at(j)->SetParallelID(MakeParallelID(j, i,
186  iterationnumber, Programnum));
187  if (Weights.at(j) != 0)
188  {
189 #pragma omp critical
190  {
191  LocalObjective.at(j)->PreParallel(
192  LocalParameters.at(j));
193  }
194  LocalObjective.at(j)->SafeParallel(
195  LocalParameters.at(j));
196 #pragma omp critical
197  {
198  MisFit(j, i) = Weights.at(j)
199  * LocalObjective.at(j)->PostParallel(
200  LocalParameters.at(j));
201  CombMisFit.at(i) += MisFit(j, i);
202  }
203 
204  }
205  else
206  {
207  MisFit(j, i) = 0;
208  }
209  }
210  tfitvec fitvector(column(MisFit, i));
211 #pragma omp critical
212  {
213  UniquePopHist.Insert(fitvector, ublas::matrix_row<
214  gplib::rmat>(Transcribed, i));
215  }
216  newcount++;
217  }
218  else // if already calculated
219  {
220  column(MisFit, i) = fitvec;
221  CombMisFit.at(i) = ublas::sum(fitvec);
222  calculatecount++;
223  }
224  }
225  cout << "New models: " << newcount << " Re-used models: "
226  << calculatecount << endl;
227  }
228 
229  void GeneralGA::DoIteration(const int iterationnumber, const bool last)
230  {
231  cout << endl << endl << "Iteration: " << iterationnumber + 1 << endl;
232  cout << "Calculating Misfit ...";
233  CalcMisfit(iterationnumber);
234  cout << " done" << endl << flush;
235  //cout << "Before Elitism " << endl;
236  //PrintMisfit(cout);
237  cout << endl;
238  if ((iterationnumber >= 1) && Elitist)
239  {
240  Elitism(iterationnumber);
241  }
242  CalcMisfit(iterationnumber); // we have to update the misfit after elitism
243  //because we cache the misfit values, the cost is low for this
244  CalcProbabilities(iterationnumber, MisFit, *Population);
245  for (unsigned int i = 0; i < nobjective; ++i) // do some statistics on the misfit
246 
247  {
248  ublas::matrix_row<gplib::rmat> mr(MisFit, i);
249  AvgFit.at(i) = Mean(mr.begin(), mr.end());
250  MaxFit.at(i) = *max_element(mr.begin(), mr.end());
251  MinFit.at(i) = *min_element(mr.begin(), mr.end());
252  }
253  CombAvgFit = Mean(CombMisFit.begin(), CombMisFit.end());
254  CombMaxFit = *max_element(CombMisFit.begin(), CombMisFit.end());
255  CombMinFit = *min_element(CombMisFit.begin(), CombMisFit.end());
256  if (!last) // if we're not in the last iteration, we store the last population for elitism
257 
258  {
260  OldMisFit = MisFit;
262  }
263  }
264  }
The base class for the population of a genetic algorithm, implements storage and access functions...
std::string MakeParallelID(const int j, const int i, const int iterationnumber, const int Programnum)
Generate a unique ID for filenames etc. so we can call generated scripts in parallel.
Definition: GeneralGA.cpp:45
ublas::vector< double > ttranscribed
Definition: gentypes.h:21
GeneralPopulation *const Population
A pointer to an object holding the population.
Definition: GeneralGA.h:74
bool Insert(const tfitvec &fitness, const ttranscribed &popmember)
Definition: UniquePop.cpp:17
std::iterator_traits< InputIterator >::value_type Mean(InputIterator begin, InputIterator end)
Calculate the mean for a given range.
Definition: statutils.h:21
void PrintTranscribed(std::ostream &output)
Print transcribed values for each member to output.
Definition: GeneralGA.cpp:127
virtual void DoIteration(const int iterationnumber, const bool last)
Do one iteration of the GA.
Definition: GeneralGA.cpp:229
virtual std::vector< int > GetBestModelIndices()=0
Return the indices of the best models.
virtual void Elitism(const int iterationnumber)
default implementation does nothing, this can be overriden
Definition: GeneralGA.h:78
bool Find(const ttranscribed &popmember, tfitvec &fitness)
Definition: UniquePop.cpp:25
Copy the objective function within the shared pointer.
Definition: GeneralGA.cpp:22
gplib::rmat OldMisFit
Definition: GeneralGA.h:62
Generate a new copy of the Objective function vector.
Definition: GeneralGA.cpp:32
const unsigned int nobjective
The number of objective functions we're using.
Definition: GeneralGA.h:64
The base class for genetic algorithm propagation methods.
virtual ttranscribed GetValues(const tpopmember &member)=0
gplib::rmat MisFit
Misfit first index objective function second index population member.
Definition: GeneralGA.h:68
std::vector< gplib::rvec > tparamvector
We provide some typedefs that are used in other parts as well.
Definition: GeneralGA.h:29
void PrintFitStat(std::ostream &output)
Print Fitness statistics for each objective function to output.
Definition: GeneralGA.cpp:100
void PrintBestMisfit(std::ostream &output)
Print misfit of the best population members.
Definition: GeneralGA.cpp:141
std::vector< std::vector< int > > tparamindv
Definition: GeneralGA.h:32
GeneralTranscribe *const Transcribe
A pointer to an object translating genes to model vectors.
Definition: GeneralGA.h:76
tObjectiveVector Objective
The vector holding the objective functions.
Definition: GeneralGA.h:70
General Transcribe base class for genetic algorithm parameter transcription.
void SetWeights(const std::vector< double > &LocalWeights)
Set the weights for each objective function.
Definition: GeneralGA.cpp:87
The basic object for any objective function, mainly an interface class and some storage.
virtual ~GeneralGA()
Definition: GeneralGA.cpp:72
virtual void CalcProbabilities(const int iterationnumber, gplib::rmat &LocalMisFit, GeneralPopulation &LocalPopulation)=0
Calculate the Probabilities.
const tpopulation & GetPopulation() const
ublas::vector< double > tfitvec
Definition: gentypes.h:23
GeneralPropagation *const Propagation
A pointer to an object dealing with propagation.
Definition: GeneralGA.h:72
GeneralGA::tObjectiveVector operator()(const GeneralGA::tObjectiveVector &IndObjective)
Definition: GeneralGA.cpp:34
const int size
Definition: perftest.cpp:14
boost::shared_ptr< GeneralObjective > operator()(boost::shared_ptr< GeneralObjective > param)
Definition: GeneralGA.cpp:24
void SetParameterIndices(const tparamindv &Indices)
Configure which parts of the complete parameter vector are used in each objective function...
Definition: GeneralGA.cpp:95
virtual void NextGeneration()=0
std::vector< boost::shared_ptr< GeneralObjective > > tObjectiveVector
Definition: GeneralGA.h:31
gplib::rmat Transcribed
A matrix holding the numerical model vectors (transcribed from the genes) for each population member...
Definition: GeneralGA.h:66
void SetupParams(const ttranscribed &member, tparamvector &params)
Copy the appropriate parameter values from the transcribed vector for use with the objective function...
Definition: GeneralGA.cpp:77
void PrintMisfit(std::ostream &output)
Print misfit for each member to output.
Definition: GeneralGA.cpp:111
The basic exception class for all errors that arise in gplib.