File: eoPop.h

package info (click to toggle)
gamera 1%3A3.4.3-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 15,912 kB
  • sloc: xml: 122,324; cpp: 50,730; python: 35,044; ansic: 258; makefile: 114; sh: 101
file content (379 lines) | stat: -rw-r--r-- 11,519 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-

//-----------------------------------------------------------------------------
// eoPop.h
// (c) GeNeura Team, 1998
/*
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Authors: 
    todos@geneura.ugr.es, http://geneura.ugr.es
    jmerelo
    gustavoromero
    mac
    maartenkeijzer
    kuepper
    okoenig
    evomarc
    Johann Dréo <johann.dreo@thalesgroup.com>
*/
//-----------------------------------------------------------------------------

#ifndef _EOPOP_H_
#define _EOPOP_H_

#include <algorithm>
#include <iostream>
#include <iterator> // needed for GCC 3.2
#include <vector>
#include <assert.h>

// EO includes
#include <eoOp.h> // for eoInit
#include <eoPersistent.h>
#include <eoInit.h>
#include <utils/rnd_generators.h>  // for shuffle method

/** A std::vector of EO object, to be used in all algorithms
 *      (selectors, operators, replacements, ...).
 *
 * We have no idea if a population can be
 * some other thing that a std::vector, but if somebody thinks of it, this concrete
 * implementation can be moved to "generic" and an abstract Population
 * interface be provided.
 *
 * The template can be instantiated with anything that accepts a "size"
 * and eoInit derived object. in the ctor.
 * EOT must also have a copy ctor, since temporaries are created and then
 * passed to the eoInit object
 *
 * @ingroup Core
 */
template<class EOT>
class eoPop: public std::vector<EOT>, public eoObject, public eoPersistent
{
    public:

        using std::vector<EOT>::size;
        using std::vector<EOT>::resize;
        using std::vector<EOT>::operator[];
        using std::vector<EOT>::begin;
        using std::vector<EOT>::end;

        typedef typename EOT::Fitness Fitness;
#if defined(__CUDACC__)
        typedef typename std::vector<EOT>::iterator iterator;
        typedef typename std::vector<EOT>::const_iterator const_iterator;
#endif

        /** Default ctor. Creates empty pop
        */
        eoPop()   : std::vector<EOT>(), eoObject(), eoPersistent() {};

        /** Ctor for the initialization of chromosomes

          @param _popSize total population size
          @param _chromInit Initialization routine, produces EO's, needs to be an eoInit
        */
        eoPop( unsigned _popSize, eoInit<EOT>& _chromInit )
            : std::vector<EOT>()
        {
            resize(_popSize);
            for ( unsigned i = 0; i < _popSize; i++ )
            {
                _chromInit(operator[](i));
            }
        }

        /** appends random guys at end of pop.
          Can be used to initialize it pop is empty

          @param _newPopSize total population size
          @param _chromInit Initialization routine, produces EO's, needs to be an eoInit
        */
        void append( unsigned _newPopSize, eoInit<EOT>& _chromInit )
        {
            unsigned oldSize = size();
            if (_newPopSize < oldSize)
            {
                throw std::runtime_error("New size smaller than old size in pop.append");
                return;
            }
            if (_newPopSize == oldSize)
                return;
            resize(_newPopSize);         // adjust the size
            for ( unsigned i = oldSize; i < _newPopSize; i++ )
            {
                _chromInit(operator[](i));
            }
        }


        /** Ctor from an std::istream; reads the population from a stream,
          each element should be in different lines
          @param _is the stream
        */
        eoPop( std::istream& _is ) :std::vector<EOT>() 
        {
            readFrom( _is );
        }


        /** Empty Dtor */
        virtual ~eoPop() {}


        /// helper struct for getting a pointer
        struct Ref { const EOT* operator()(const EOT& eot) { return &eot;}};

        /// helper struct for comparing on pointers
        struct Cmp {
            bool operator()(const EOT* a, const EOT* b) const
            { return b->operator<(*a); }
        };

        /// helper struct for comparing (EA or PSO)
        struct Cmp2
        {
            bool operator()(const EOT & a,const EOT & b) const
            {
                return b.operator<(a);
            }
        };


        /**
          sort the population. Use this member to sort in order
          of descending Fitness, so the first individual is the best!
        */
        void sort(void)
        {
            std::sort(begin(), end(), Cmp2());
        }


        /** creates a std::vector<EOT*> pointing to the individuals in descending order */
        void sort(std::vector<const EOT*>& result) const
        {
            result.resize(size());

            std::transform(begin(), end(), result.begin(), Ref());

            std::sort(result.begin(), result.end(), Cmp());
        }


        /**
          shuffle the population. Use this member to put the population
          in random order
        */
        void shuffle(void)
        {
            UF_random_generator<unsigned int> gen;
            std::random_shuffle(begin(), end(), gen);
        }


        /** creates a std::vector<EOT*> pointing to the individuals in random order */
        void shuffle(std::vector<const EOT*>& result) const
        {
            result.resize(size());

            std::transform(begin(), end(), result.begin(), Ref());

            UF_random_generator<unsigned int> gen;
            std::random_shuffle(result.begin(), result.end(), gen);
        }


        /** returns an iterator to the best individual DOES NOT MOVE ANYBODY */
#if defined(__CUDACC__)
        eoPop<EOT>::iterator it_best_element()
        {
            eoPop<EOT>:: iterator it = std::max_element(begin(), end());
#else
        typename eoPop<EOT>::iterator it_best_element()
        {
                assert( this->size() > 0 );
                typename eoPop<EOT>::iterator it = std::max_element(begin(), end());
#endif
                return it;
        }


        /** returns an iterator to the best individual DOES NOT MOVE ANYBODY */
        const EOT & best_element() const
        {
#if defined(__CUDACC__)
            eoPop<EOT>::const_iterator it = std::max_element(begin(), end());
#else
            typename eoPop<EOT>::const_iterator it = std::max_element(begin(), end());
#endif
            return (*it);
        }


        /** returns a const reference to the worse individual DOES NOT MOVE ANYBODY */
        const EOT & worse_element() const
        {
#if defined(__CUDACC__)
            eoPop<EOT>::const_iterator it = std::min_element(begin(), end());
#else
            assert( this->size() > 0 );
            typename eoPop<EOT>::const_iterator it = std::min_element(begin(), end());
#endif
            return (*it);
        }


        /** returns an iterator to the worse individual DOES NOT MOVE ANYBODY */
#if defined(__CUDACC__)
        eoPop<EOT>::iterator it_worse_element()
        {
            eoPop<EOT>::iterator it = std::min_element(begin(), end());
#else
        typename eoPop<EOT>::iterator it_worse_element()
        {
            assert( this->size() > 0 );
            typename eoPop<EOT>::iterator it = std::min_element(begin(), end());
#endif
            return it;
        }


        /**
          slightly faster algorithm than sort to find all individuals that are better
          than the nth individual. INDIVIDUALS ARE MOVED AROUND in the pop.
          */
#if defined(__CUDACC__)
        eoPop<EOT>::iterator nth_element(int nth)
        {
            eoPop<EOT>::iterator it = begin() + nth;
#else
        typename eoPop<EOT>::iterator nth_element(int nth)
        {
            assert( this->size() > 0 );
            typename eoPop<EOT>::iterator it = begin() + nth;
#endif
            std::nth_element(begin(), it, end(), std::greater<EOT>());
            return it;
        }


        struct GetFitness { Fitness operator()(const EOT& _eo) const { return _eo.fitness(); } };


        /** returns the fitness of the nth element */
        Fitness nth_element_fitness(int which) const
        { // probably not the fastest way to do this, but what the heck

            std::vector<Fitness> fitness(size());
            std::transform(begin(), end(), fitness.begin(), GetFitness());

            typename std::vector<Fitness>::iterator it = fitness.begin() + which;
            std::nth_element(fitness.begin(), it, fitness.end(), std::greater<Fitness>());
            return *it;
        }


        /** const nth_element function, returns pointers to sorted individuals
         * up the the nth
         */
        void nth_element(int which, std::vector<const EOT*>& result) const
        {

            assert( this->size() > 0 );
            result.resize(size());
            std::transform(begin(), end(), result.begin(), Ref());

            typename std::vector<const EOT*>::iterator it  = result.begin() + which;

            std::nth_element(result.begin(), it, result.end(), Cmp());
        }


        /** does STL swap with other pop */
        void swap(eoPop<EOT>& other)
        {
            std::swap(static_cast<std::vector<EOT>& >(*this), static_cast<std::vector<EOT>& >(other));
        }


        /**
         * Prints sorted pop but does NOT modify it!
         *
         * @param _os A std::ostream.
         */
        virtual void sortedPrintOn(std::ostream& _os) const
        {
            std::vector<const EOT*> result;
            sort(result);
            _os << size() << '\n';
            for (unsigned i = 0; i < size(); ++i)
            {
                _os << *result[i] << std::endl;
            }
        }


        /**
         * Write object. It's called printOn since it prints the object _on_ a stream.
         * @param _os A std::ostream.
         */
        virtual void printOn(std::ostream& _os) const
        {
            _os << size() << '\n';
            std::copy( begin(), end(), std::ostream_iterator<EOT>( _os, "\n") );
        }


        /** @name Methods from eoObject	*/
        //@{
        /**
         * Read object. The EOT class must have a ctor from a stream;
         * @param _is A std::istream.
         */
        virtual void readFrom(std::istream& _is)
        {
            size_t sz;
            _is >> sz;

            resize(sz);

            for (size_t i = 0; i < sz; ++i) {
                operator[](i).readFrom( _is );
            }
        }


        /** Inherited from eoObject. Returns the class name.
          @see eoObject
          */
        virtual std::string className() const {return "eoPop";};
        //@}


        /** Invalidate the whole population
         */
        virtual void invalidate()
        {
            for (unsigned i=0; i<size(); i++)
                this->operator[](i).invalidate();
        }

}; // class eoPop

#endif // _EOPOP_H_