00001 #include "GeneralGA.h"
00002 #include <cmath>
00003 #include <iostream>
00004 #include <numeric>
00005 #include <sstream>
00006 #include <map>
00007 #include "statutils.h"
00008 #include "VecMat.h"
00009 #include "FatalException.h"
00010 #include <boost/bind.hpp>
00011 #include <algorithm>
00012 #include <cassert>
00013 #include <unistd.h>
00014 #ifdef _OPENMP
00015 #include <omp.h>
00016 #endif
00017 using namespace std;
00018
00019 namespace gplib
00020 {
00021
00022 struct CopyFromPointer
00023 {
00024 boost::shared_ptr<GeneralObjective> operator()(boost::shared_ptr<
00025 GeneralObjective> param)
00026 {
00027 return boost::shared_ptr<GeneralObjective>(param->clone());
00028 }
00029 };
00030
00031
00032 struct GenObjective
00033 {
00034 GeneralGA::tObjectiveVector operator()(
00035 const GeneralGA::tObjectiveVector &IndObjective)
00036 {
00037 GeneralGA::tObjectiveVector result(IndObjective.size());
00038 transform(IndObjective.begin(), IndObjective.end(), result.begin(),
00039 CopyFromPointer());
00040 return result;
00041 }
00042 };
00043
00044
00045 std::string MakeParallelID(const int j, const int i,
00046 const int iterationnumber, const int Programnum)
00047 {
00048 ostringstream filename;
00049 filename << "j" << j << "i" << i << "g" << iterationnumber << "p"
00050 << Programnum;
00051 return filename.str();
00052 }
00053
00054 GeneralGA::GeneralGA(GeneralPropagation* const LocalPropagation,
00055 GeneralPopulation* const LocalPopulation,
00056 GeneralTranscribe* const LocalTranscribe,
00057 const tObjectiveVector &IndObjective, const int nthreads) :
00058 CombMisFit(LocalPopulation->GetPopsize()), AvgFit(IndObjective.size()),
00059 MaxFit(IndObjective.size()), MinFit(IndObjective.size()), Weights(
00060 IndObjective.size(), 1), nobjective(IndObjective.size()),
00061 Transcribed(LocalPopulation->GetPopsize(),
00062 LocalTranscribe->GetNparams()), MisFit(IndObjective.size(),
00063 LocalPopulation->GetPopsize()), Objective(IndObjective),
00064 Propagation(LocalPropagation), Population(LocalPopulation),
00065 Transcribe(LocalTranscribe)
00066 {
00067 Threads = nthreads;
00068 Elitist = true;
00069 Programnum = getpid();
00070 }
00071
00072 GeneralGA::~GeneralGA()
00073 {
00074 }
00075
00076
00077 void GeneralGA::SetupParams(const ttranscribed &member,
00078 tparamvector ¶ms)
00079 {
00080 for (unsigned int i = 0; i < nobjective; ++i)
00081 for (unsigned int j = 0; j < ParameterIndices.at(i).size(); ++j)
00082 {
00083 params.at(i)(j) = member(ParameterIndices.at(i).at(j));
00084 }
00085 }
00086
00087 void GeneralGA::SetWeights(const std::vector<double> &LocalWeights)
00088 {
00089 if (LocalWeights.size() != Weights.size())
00090 throw FatalException(
00091 "Configured number of weights does not match number of objective functions !");
00092 Weights = LocalWeights;
00093 }
00094
00095 void GeneralGA::SetParameterIndices(const tparamindv &Indices)
00096 {
00097 ParameterIndices = Indices;
00098 }
00099
00100 void GeneralGA::PrintFitStat(std::ostream &output)
00101 {
00102 for (unsigned int i = 0; i < nobjective; ++i)
00103 {
00104 output << MaxFit.at(i) << " " << MinFit.at(i) << " "
00105 << AvgFit.at(i) << " ";
00106 }
00107 output << CombMaxFit << " " << CombMinFit << " " << CombAvgFit << " ";
00108 output << endl << flush;
00109 }
00110
00111 void GeneralGA::PrintMisfit(std::ostream &output)
00112 {
00113 const unsigned int isize = MisFit.size1();
00114 const unsigned int jsize = MisFit.size2();
00115
00116 for (unsigned int i = 0; i < isize; ++i)
00117 {
00118 for (unsigned int j = 0; j < jsize; ++j)
00119 output << MisFit(i, j) << " ";
00120 output << endl;
00121 }
00122 copy(CombMisFit.begin(), CombMisFit.end(), ostream_iterator<double> (
00123 output, " "));
00124 output << endl << endl;
00125 }
00126
00127 void GeneralGA::PrintTranscribed(std::ostream &output)
00128 {
00129 const unsigned int isize = Transcribed.size1();
00130 const unsigned int jsize = Transcribed.size2();
00131 unsigned int i, j;
00132 for (i = 0; i < isize; ++i)
00133 {
00134 for (j = 0; j < jsize; ++j)
00135 output << Transcribed(i, j) << " ";
00136 output << endl;
00137 }
00138 output << endl << flush;
00139 }
00140
00141 void GeneralGA::PrintBestMisfit(std::ostream &output)
00142 {
00143 std::vector<int> Indices(GetBestModelIndices());
00144 const unsigned int isize = Indices.size();
00145 const unsigned int jsize = MisFit.size1();
00146
00147 for (unsigned int i = 0; i < isize; ++i)
00148 {
00149 const int currindex = Indices.at(i);
00150 for (unsigned int j = 0; j < jsize; ++j)
00151 output << MisFit(j, currindex) << " ";
00152 output << endl;
00153 }
00154 output << endl << endl;
00155 }
00156
00157 void GeneralGA::CalcMisfit(const int iterationnumber)
00158 {
00159 int calculatecount = 0;
00160 int newcount = 0;
00161
00162 const int popsize = Population->GetPopsize();
00163 ublas::vector<bool> AlreadyCalculated(popsize);
00164 tfitvec fitvec(nobjective);
00165
00166 tparamvector LocalParameters(nobjective);
00167 for (unsigned int k = 0; k < nobjective; ++k)
00168 {
00169 LocalParameters.at(k).resize(ParameterIndices.at(k).size(), false);
00170 }
00171
00172 for (int i = 0; i < popsize; ++i)
00173 {
00174 row(Transcribed, i) = Transcribe->GetValues(row(
00175 Population->GetPopulation(), i));
00176 AlreadyCalculated(i) = UniquePopHist.Find(row(Transcribed, i),
00177 fitvec);
00178 if (!AlreadyCalculated(i))
00179 {
00180 SetupParams(row(Transcribed, i), LocalParameters);
00181 for (unsigned int j = 0; j < nobjective; ++j)
00182 {
00183 Objective.at(j)->SetParallelID(MakeParallelID(j, i,
00184 iterationnumber, Programnum));
00185 if (Weights.at(j) != 0)
00186 {
00187 MisFit(j, i) = Weights.at(j)
00188 * Objective.at(j)->CalcPerformance(
00189 LocalParameters.at(j));
00190 CombMisFit.at(i) += MisFit(j, i);
00191 }
00192 else
00193 {
00194 MisFit(j, i) = 0;
00195 }
00196 }
00197 tfitvec fitvector(column(MisFit, i));
00198 UniquePopHist.Insert(fitvector, ublas::matrix_row<gplib::rmat>(
00199 Transcribed, i));
00200 newcount++;
00201 }
00202 else
00203 {
00204 column(MisFit, i) = fitvec;
00205 CombMisFit.at(i) = ublas::sum(fitvec);
00206 calculatecount++;
00207 }
00208 }
00209 cout << "New models: " << newcount << " Re-used models: "
00210 << calculatecount << endl;
00211 }
00212
00213 void GeneralGA::DoIteration(const int iterationnumber, const bool last)
00214 {
00215 cout << endl << endl << "Iteration: " << iterationnumber + 1 << endl;
00216 cout << "Calculating Misfit ...";
00217 CalcMisfit(iterationnumber);
00218 cout << " done" << endl << flush;
00219
00220
00221 cout << endl;
00222 if ((iterationnumber >= 1) && Elitist)
00223 {
00224 Elitism(iterationnumber);
00225 }
00226 CalcMisfit(iterationnumber);
00227
00228 CalcProbabilities(iterationnumber, MisFit, *Population);
00229 for (unsigned int i = 0; i < nobjective; ++i)
00230
00231 {
00232 ublas::matrix_row<gplib::rmat> mr(MisFit, i);
00233 AvgFit.at(i) = Mean(mr.begin(), mr.end());
00234 MaxFit.at(i) = *max_element(mr.begin(), mr.end());
00235 MinFit.at(i) = *min_element(mr.begin(), mr.end());
00236 }
00237 CombAvgFit = Mean(CombMisFit.begin(), CombMisFit.end());
00238 CombMaxFit = *max_element(CombMisFit.begin(), CombMisFit.end());
00239 CombMinFit = *min_element(CombMisFit.begin(), CombMisFit.end());
00240 if (!last)
00241
00242 {
00243 Population->StoreOldPopulation();
00244 OldMisFit = MisFit;
00245 Propagation->NextGeneration();
00246 }
00247 }
00248 }