EvolvingObjects
|
00001 00024 //----------------------------------------------------------------------------- 00025 00026 #ifndef _eoReduceMergeReduce_h 00027 #define _eoReduceMergeReduce_h 00028 00029 00030 //----------------------------------------------------------------------------- 00031 #include <eoPop.h> 00032 #include <eoFunctor.h> 00033 #include <eoMerge.h> 00034 #include <eoReduce.h> 00035 #include <utils/eoHowMany.h> 00036 //----------------------------------------------------------------------------- 00037 00048 template <class EOT> 00049 class eoReduceMergeReduce : public eoReplacement<EOT> 00050 { 00051 public: 00052 eoReduceMergeReduce(eoHowMany _howManyElite, 00053 bool _strongElitism, 00054 eoHowMany _howManyReducedParents, 00055 eoReduce<EOT> & _reduceParents, 00056 eoHowMany _howManyReducedOffspring, 00057 eoReduce<EOT> & _reduceOffspring, 00058 eoReduce<EOT> & _reduceFinal) : 00059 howManyElite(_howManyElite), 00060 strongElitism(_strongElitism), 00061 howManyReducedParents(_howManyReducedParents), 00062 howManyReducedOffspring (_howManyReducedOffspring), 00063 reduceParents(_reduceParents), 00064 reduceOffspring(_reduceOffspring), 00065 reduceFinal(_reduceFinal) 00066 {} 00067 00068 void operator()(eoPop<EOT> & _parents, eoPop<EOT> & _offspring) 00069 { 00070 eoPop<EOT> temp; 00071 unsigned int finalPopSize = _parents.size(); 00072 unsigned int offSize = _offspring.size(); 00073 00074 unsigned int elite = howManyElite(finalPopSize); 00075 if (elite) // some parents MUST be saved somewhere 00076 { 00077 temp.resize(elite); 00078 _parents.nth_element(elite); 00079 std::copy(_parents.begin(), _parents.begin()+elite, temp.begin()); 00080 _parents.erase(_parents.begin(), _parents.begin()+elite); 00081 } 00082 00083 // the reduce steps. First the parents 00084 unsigned reducedParentSize = howManyReducedParents(_parents.size()); 00085 if (!reducedParentSize) 00086 _parents.clear(); 00087 else if (reducedParentSize != _parents.size()) 00088 reduceParents(_parents, reducedParentSize); 00089 00090 // then the offspring 00091 unsigned reducedOffspringSize = howManyReducedOffspring(offSize); 00092 if (!reducedOffspringSize) 00093 throw std::runtime_error("No offspring left after reduction!"); 00094 if (reducedOffspringSize != offSize) // need reduction 00095 reduceOffspring(_offspring, reducedOffspringSize); 00096 00097 // now merge reduced populations 00098 _parents.resize(reducedParentSize + _offspring.size()); 00099 std::copy(_offspring.begin(), _offspring.end(), 00100 _parents.begin()+reducedParentSize); 00101 00102 // reduce the resulting population 00103 // size depstd::ends on elitism 00104 if (elite && strongElitism) 00105 { 00106 if (_parents.size() != finalPopSize-elite) 00107 reduceFinal(_parents, finalPopSize-elite); 00108 // and put back the elite 00109 unsigned oldPSize = _parents.size(); 00110 _parents.resize(_parents.size()+elite); 00111 std::copy(temp.begin(), temp.end(), _parents.begin()+oldPSize); 00112 } 00113 else 00114 { // only reduce final pop to right size 00115 if (_parents.size() != finalPopSize) 00116 reduceFinal(_parents, finalPopSize); 00117 if (elite) // then treat weak elitism 00118 { 00119 unsigned toSave = 0; 00120 _parents.sort(); 00121 EOT & eoLimit = _parents[elite-1]; 00122 unsigned index=0; 00123 while ( (temp[index++] > eoLimit) && (index < temp.size()) ) 00124 toSave++; 00125 if (toSave) 00126 for (unsigned i=0; i<toSave; i++) 00127 _parents[finalPopSize-1-i] = temp[i]; 00128 } 00129 } 00130 } 00131 00132 private: 00133 eoHowMany howManyElite; // if 0, no elitism at all 00134 bool strongElitism; // if false -> weak estd::listism 00135 eoHowMany howManyReducedParents; // if 0, no parent in final replacement 00136 eoHowMany howManyReducedOffspring; // if 0, std::runtime_error 00137 // the reducers 00138 eoReduce<EOT> & reduceParents; 00139 eoReduce<EOT> & reduceOffspring; 00140 eoReduce<EOT> & reduceFinal; 00141 }; 00142 00143 #endif