# eoPop.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // eoPop.h
    00005 // (c) GeNeura Team, 1998
    00006 /*
    00007     This library is free software; you can redistribute it and/or
    00008     modify it under the terms of the GNU Lesser General Public
    00009     License as published by the Free Software Foundation; either
    00010     version 2 of the License, or (at your option) any later version.
    00011
    00012     This library is distributed in the hope that it will be useful,
    00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015     Lesser General Public License for more details.
    00016
    00017     You should have received a copy of the GNU Lesser General Public
    00018     License along with this library; if not, write to the Free Software
    00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00020
    00021     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
    00022  */
    00023 //-----------------------------------------------------------------------------
    00024
    00025 #ifndef _EOPOP_H
    00026 #define _EOPOP_H
    00027
    00028 #include <algorithm>
    00029 #include <iostream>
    00030 #include <iterator> // needed for GCC 3.2
    00031 #include <vector>
    00032
    00033 // EO includes
    00034 #include <eoOp.h> // for eoInit
    00035 #include <eoPersistent.h>
    00036 #include <eoInit.h>
    00037 #include <utils/rnd_generators.h>  // for shuffle method
    00038
    00053 template<class EOT>
    00054 class eoPop: public std::vector<EOT>, public eoObject, public eoPersistent
    00055 {
    00056
    00057  public:
    00058
    00059      using std::vector<EOT>::size;
    00060      using std::vector<EOT>::resize;
    00061      using std::vector<EOT>::operator[];
    00062      using std::vector<EOT>::begin;
    00063      using std::vector<EOT>::end;
    00064
    00065      typedef typename EOT::Fitness Fitness;
    00068         eoPop()   : std::vector<EOT>(), eoObject(), eoPersistent() {};
    00069
    00075     eoPop( unsigned _popSize, eoInit<EOT>& _chromInit )
    00076       :std::vector<EOT>()
    00077     {
    00078         resize(_popSize);
    00079           for ( unsigned i = 0; i < _popSize; i++ )
    00080       {
    00081                 _chromInit(operator[](i));
    00082           }
    00083         };
    00084
    00091     void append( unsigned _newPopSize, eoInit<EOT>& _chromInit )
    00092     {
    00093       unsigned oldSize = size();
    00094       if (_newPopSize < oldSize)
    00095         {
    00096           throw std::runtime_error("New size smaller than old size in pop.append");
    00097           return;
    00098         }
    00099       if (_newPopSize == oldSize)
    00100         return;
    00101       resize(_newPopSize);         // adjust the size
    00102       for ( unsigned i = oldSize; i < _newPopSize; i++ )
    00103         {
    00104           _chromInit(operator[](i));
    00105         }
    00106     };
    00107
    00108
    00113   eoPop( std::istream& _is ) :std::vector<EOT>() {
    00114     readFrom( _is );
    00115   }
    00116
    00118         virtual ~eoPop() {};
    00119
    00120
    00122       struct Ref { const EOT* operator()(const EOT& eot) { return &eot;}};
    00124       struct Cmp {
    00125           bool operator()(const EOT* a, const EOT* b) const
    00126             { return b->operator<(*a); }
    00127       };
    00128
    00133   void sort(void)
    00134   {
    00135       std::sort(begin(), end(), std::greater<EOT>());
    00136   }
    00137
    00139   void sort(std::vector<const EOT*>& result) const
    00140   {
    00141       result.resize(size());
    00142
    00143       std::transform(begin(), end(), result.begin(), Ref());
    00144
    00145       std::sort(result.begin(), result.end(), Cmp());
    00146   }
    00147
    00152   void shuffle(void)
    00153   {
    00154     UF_random_generator<unsigned int> gen;
    00155       std::random_shuffle(begin(), end(), gen);
    00156   }
    00157
    00159   void shuffle(std::vector<const EOT*>& result) const
    00160   {
    00161       result.resize(size());
    00162
    00163       std::transform(begin(), end(), result.begin(), Ref());
    00164
    00165       UF_random_generator<unsigned int> gen;
    00166       std::random_shuffle(result.begin(), result.end(), gen);
    00167   }
    00168
    00170   typename eoPop<EOT>::iterator it_best_element()
    00171   {
    00172     typename eoPop<EOT>::iterator it = std::max_element(begin(), end());
    00173     return it;
    00174   }
    00175
    00177   const EOT & best_element() const
    00178   {
    00179     typename eoPop<EOT>::const_iterator it = std::max_element(begin(), end());
    00180     return (*it);
    00181   }
    00182
    00184   const EOT & worse_element() const
    00185   {
    00186     typename eoPop<EOT>::const_iterator it = std::min_element(begin(), end());
    00187     return (*it);
    00188   }
    00189
    00191   typename eoPop<EOT>::iterator it_worse_element()
    00192   {
    00193     typename eoPop<EOT>::iterator it = std::min_element(begin(), end());
    00194     return it;
    00195   }
    00196
    00201   typename eoPop<EOT>::iterator nth_element(int nth)
    00202   {
    00203       typename eoPop<EOT>::iterator it = begin() + nth;
    00204       std::nth_element(begin(), it, end(), std::greater<EOT>());
    00205       return it;
    00206   }
    00207
    00208   struct GetFitness { Fitness operator()(const EOT& _eo) const { return _eo.fitness(); } };
    00209
    00211   Fitness nth_element_fitness(int which) const
    00212   { // probably not the fastest way to do this, but what the heck
    00213
    00214       std::vector<Fitness> fitness(size());
    00215       std::transform(begin(), end(), fitness.begin(), GetFitness());
    00216
    00217       typename std::vector<Fitness>::iterator it = fitness.begin() + which;
    00218       std::nth_element(fitness.begin(), it, fitness.end(), std::greater<Fitness>());
    00219       return *it;
    00220   }
    00221
    00225   void nth_element(int which, std::vector<const EOT*>& result) const
    00226   {
    00227
    00228       result.resize(size());
    00229       std::transform(begin(), end(), result.begin(), Ref());
    00230
    00231       typename std::vector<const EOT*>::iterator it  = result.begin() + which;
    00232
    00233       std::nth_element(result.begin(), it, result.end(), Cmp());
    00234   }
    00235
    00237   void swap(eoPop<EOT>& other)
    00238   {
    00239       std::swap(static_cast<std::vector<EOT>& >(*this), static_cast<std::vector<EOT>& >(other));
    00240   }
    00241
    00247   virtual void sortedPrintOn(std::ostream& _os) const
    00248   {
    00249     std::vector<const EOT*> result;
    00250     sort(result);
    00251     _os << size() << '\n';
    00252     for (unsigned i = 0; i < size(); ++i)
    00253       {
    00254         _os << *result[i] << std::endl;
    00255       }
    00256   }
    00257
    00262   virtual void printOn(std::ostream& _os) const
    00263   {
    00264         _os << size() << '\n';
    00265         std::copy( begin(), end(), std::ostream_iterator<EOT>( _os, "\n") );
    00266   }
    00267
    00274   virtual void readFrom(std::istream& _is)
    00275   {
    00276     size_t sz;
    00277     _is >> sz;
    00278
    00279     resize(sz);
    00280
    00281     for (size_t i = 0; i < sz; ++i) {
    00282         operator[](i).readFrom( _is );
    00283     }
    00284   }
    00285
    00289   virtual std::string className() const {return "eoPop";};
    00291
    00292   virtual void invalidate()
    00293   {
    00294     for (unsigned i=0; i<size(); i++)
    00295       this->operator[](i).invalidate();
    00296   }
    00297
    00298
    00299  protected:
    00300
    00301 };
    00302
    00303 #endif
    00304