00001 #include <algorithm>
00002 #include <functional>
00003 #include <iostream>
00004 #include <numeric>
00005
00006 #include <NLstl_utils.h>
00007
00008 #include "GLLogicError.h"
00009 #include "GLMutatorCombined.h"
00010 #include "GLRandomNumbersGenerator.h"
00011
00016 GLMutatorCombined::GLMutatorCombined(const GLMutatorCombined& mutator):
00017 GLBaseMutator(mutator),
00018 m_apply_mutators(mutator.m_apply_mutators),
00019 mv_weights(mutator.mv_weights),
00020 mv_norm_cumul_weights(mutator.mv_norm_cumul_weights)
00021
00022 {
00023
00024 mv_mutators.resize(mutator.mv_mutators.size());
00025 for(size_t i = 0; i < mv_mutators.size(); i++)
00026 mv_mutators[i] = mutator.mv_mutators[i]->copy();
00027 }
00028
00032 GLMutatorCombined::~GLMutatorCombined()
00033 {
00034
00035 for_each(mv_mutators.begin(), mv_mutators.end(),
00036 nlutils::DeleteObject());
00037 }
00038
00044 void GLMutatorCombined::checkAndInit()
00045 {
00046
00047 if (mv_mutators.empty())
00048 {
00049 char errormsg[1000];
00050 sprintf(errormsg, "\nGLMutatorCombined::GLMutatorCombined\n"
00051 "Empty vector of mutators passed to the "
00052 "constructor");
00053 throw GLLogicError(errormsg);
00054 }
00055
00056 vector<GLBaseMutator*>::const_iterator null_pointer =
00057 find(mv_mutators.begin(), mv_mutators.end(), (GLBaseMutator*)NULL);
00058 if (null_pointer != mv_mutators.end())
00059 {
00060 char errormsg[1000];
00061 sprintf(errormsg, "\nGLMutatorCombined::GLMutatorCombined\n"
00062 "Vector with mutators contains NULL pointer at %i\n",
00063 (int)(null_pointer - mv_mutators.begin()));
00064 }
00065
00066 if (m_apply_mutators == SEPARATE)
00067 {
00068 if (mv_weights.size() != mv_mutators.size())
00069 {
00070 char errormsg[1000];
00071 sprintf(errormsg, "\nGLMutatorCombined::GLMutatorCombined\n"
00072 "Mutators usage set to SEPARATE and the "
00073 "number of weights (%i) != number of mutators (%i)"
00074 "passed\n",
00075 (int)mv_weights.size(), (int)mv_mutators.size());
00076 throw GLLogicError(errormsg);
00077 }
00078
00079 vector<double>::const_iterator not_positive =
00080 find_if(mv_weights.begin(), mv_weights.end(),
00081 bind2nd(less_equal<double>(), 0.0));
00082 if (not_positive != mv_weights.end())
00083 {
00084 char errormsg[1000];
00085 sprintf(errormsg, "\nGLMutatorCombined::GLMutatorCombined\n"
00086 "Mutators usage set to SEPARATE and the "
00087 "weights[%i] is not positive (== %e)\n",
00088 int(not_positive - mv_weights.begin()),
00089 (*not_positive));
00090 throw GLLogicError(errormsg);
00091 }
00092
00093 processWeights();
00094 }
00095 }
00096
00102 bool GLMutatorCombined::mutateCombined(GLBaseOrganism* organism)
00103 {
00104 bool result = false;
00105
00106 vector<GLBaseMutator*>::iterator it;
00107 for(it = mv_mutators.begin(); it != mv_mutators.end(); ++it)
00108 {
00109 bool res = (*it)->mutateOrganism(organism);
00110 result |= res;
00111 }
00112 return result;
00113 }
00114
00121 bool GLMutatorCombined::mutateOrganism(GLBaseOrganism* organism)
00122 {
00123 bool result = false;
00124
00125 if (GLRandomNumbersGenerator::getRandomUniform(0, 1) > getMutationRate())
00126 {
00127 return result;
00128 }
00129
00130
00131 switch(m_apply_mutators)
00132 {
00133 case SEPARATE:
00134 result = mutateSeparately(organism);
00135 break;
00136 case COMBINED:
00137 result = mutateCombined(organism);
00138 break;
00139 }
00140 return result;
00141 }
00142
00150 bool GLMutatorCombined::mutateSeparately(GLBaseOrganism* organism)
00151 {
00152 bool result = false;
00153
00154 double rand = GLRandomNumbersGenerator::getRandomUniform(0, 1);
00155
00156
00157
00158 vector<double>::const_iterator it =
00159 find_if(mv_norm_cumul_weights.begin(),
00160 mv_norm_cumul_weights.end(),
00161 bind2nd(greater_equal<double>(), rand));
00162 size_t i = it - mv_norm_cumul_weights.begin();
00163
00164 if (i == mv_norm_cumul_weights.size()) i--;
00165
00166
00167 result = mv_mutators[i]->mutateOrganism(organism);
00168 return result;
00169 }
00170
00176 void GLMutatorCombined::processWeights()
00177 {
00178 mv_norm_cumul_weights.resize(mv_weights.size());
00179
00180 if (mv_weights.empty()) return;
00181
00182 partial_sum(mv_weights.begin(), mv_weights.end(),
00183 mv_norm_cumul_weights.begin());
00184
00185 double total = mv_norm_cumul_weights.back();
00186
00187
00188 if (total <= 0)
00189 {
00190 char errormsg[1000];
00191 sprintf(errormsg, "\nGLMutatorCombined::processWeights\n"
00192 "Total weight (%e) is <= 0, why?!\n",
00193 total);
00194 throw GLLogicError(errormsg);
00195 }
00196
00197 for_each(mv_norm_cumul_weights.begin(), mv_norm_cumul_weights.end(),
00198 bind2nd(divides<double>(), total));
00199
00200 mv_norm_cumul_weights.back() = 1.0;
00201 }
00202