Modernized GAlib  3.0.0 current
GASelector.h
1 // $Header$
2 /* ----------------------------------------------------------------------------
3  selector.h
4  mbwall 10aug94
5  Copyright (c) 1995 Massachusetts Institute of Technology
6  all rights reserved
7 
8  DESCRIPTION:
9  The selectors are functions that use information in fitness objects to pick
10 genomes from a population. There are a number of selection criteria, and
11 not every selection method will work with every fitness object.
12 
13  These are the pre-defined selection methods. A brief outline of what each
14 one does is given here, but for more details (especially the theoretical
15 foundations for each method), see Goldberg. See the source file for some
16 implementation details that Goldberg does not delve into.
17  The selection methods can, to some extent, be mixed and matched with the
18 various scaling methods.
19  If you want to do speciating selection (e.g. DeJong-style crowding with
20 Hamming distance) then you will have to write your own selection method.
21 
22  Rank - pick the genome with the best fitness (not objective score)
23 RouletteWheel - weighted selection where individuals with better fitness have
24  a greater chance of being selected than those with lower
25  scores.
26  Tournament - similar to roulette, but instead of choosing one, choose two
27  then pick the better of the two as the selected individuals
28  Uniform - stochastic uniform selection picks randomly from the
29  population. Each individual has as much chance as any other.
30  SRS - stochastic remainder selection does a preselection based on
31  the expected number of each genome, then a random sampling on
32  the preselected list.
33  DS - deterministic sampling is implemented as described in
34  Goldberg's book (as much as I could understand it, anyway).
35 ---------------------------------------------------------------------------- */
36 #ifndef _ga_selector_h_
37 #define _ga_selector_h_
38 
39 #include <gaid.h>
40 #include <cstring>
41 #include <vector>
42 
43 class GAGenome;
44 class GAPopulation;
45 
46 /* ----------------------------------------------------------------------------
47  The base class definition for the selector object defines the interface.
48 Any derived selector must define a clone member and a select member. If you
49 add any special data members then you should also define a copy member.
50  Any selector can do its business based on fitness or objective scores. The
51 base selector provides the mechanism for this. Derived classes can use it if
52 they want to, or ignore it.
53 ---------------------------------------------------------------------------- */
54 class GASelectionScheme : public GAID
55 {
56  public:
57  GADefineIdentity("GASelectionScheme", GAID::Selection);
58  enum
59  {
60  RAW,
61  SCALED
62  };
63 
64  explicit GASelectionScheme(int w = SCALED) { which = w; }
65  GASelectionScheme(const GASelectionScheme &orig) { copy(orig); }
66  GASelectionScheme &operator=(const GASelectionScheme &orig)
67  {
68  if (&orig != this) {
69  copy(orig);
70 }
71  return *this;
72  }
73  ~GASelectionScheme() override = default;
74  virtual GASelectionScheme *clone() const = 0;
75  virtual void copy(const GASelectionScheme &orig)
76  {
77  pop = orig.pop;
78  which = orig.which;
79  }
80  virtual void assign(GAPopulation &p) { pop = &p; }
81  virtual void update() {}
82  virtual GAGenome &select() const = 0;
83 
84  protected:
85  GAPopulation *pop;
86  int which; // should we use fitness or objective scores?
87 };
88 
89 /* ----------------------------------------------------------------------------
90  The rank selector simply picks the best individual in the population. You
91 can specify whether the selector should use the raw (objective) scores or the
92 scaled (fitness) scores to determine the best individual. Default is fitness.
93 ---------------------------------------------------------------------------- */
94 #if USE_RANK_SELECTOR == 1
95 class GARankSelector : public GASelectionScheme
96 {
97  public:
98  GADefineIdentity("GARankSelector", GAID::RankSelection);
99 
100  explicit GARankSelector(int w = GASelectionScheme::SCALED)
101  : GASelectionScheme(w)
102  {
103  }
104  GARankSelector(const GARankSelector &orig) : GASelectionScheme(orig)
105  {
106  copy(orig);
107  }
108  GARankSelector &operator=(const GASelectionScheme &orig)
109  {
110  if (&orig != this) {
111  copy(orig);
112 }
113  return *this;
114  }
115  ~GARankSelector() override = default;
116  GASelectionScheme *clone() const override
117  {
118  return new GARankSelector;
119  }
120  GAGenome &select() const override;
121 };
122 #endif
123 
124 /* ----------------------------------------------------------------------------
125  Roulette wheel uses a fitness-proportional algorithm for selecting
126 individuals.
127 ---------------------------------------------------------------------------- */
128 #if USE_ROULETTE_SELECTOR == 1 || USE_TOURNAMENT_SELECTOR == 1
129 class GARouletteWheelSelector : public GASelectionScheme
130 {
131  public:
132  GADefineIdentity("GARouletteWheelSelector", GAID::RouletteWheelSelection);
133 
134  explicit GARouletteWheelSelector(int w = GASelectionScheme::SCALED)
135  : GASelectionScheme(w)
136  {
137  psum.clear();
138  n = 0;
139  }
140  GARouletteWheelSelector(const GARouletteWheelSelector &orig)
141  : GASelectionScheme(orig)
142  {
143  psum.clear();
144  n = 0;
145  copy(orig);
146  }
147  GARouletteWheelSelector &operator=(const GASelectionScheme &orig)
148  {
149  if (&orig != this) {
150  copy(orig);
151 }
152  return *this;
153  }
154  ~GARouletteWheelSelector() override = default;
155  GASelectionScheme *clone() const override
156  {
157  return new GARouletteWheelSelector;
158  }
159  void copy(const GASelectionScheme &orig) override
160  {
161  GASelectionScheme::copy(orig);
162  const GARouletteWheelSelector &sel =
163  DYN_CAST(const GARouletteWheelSelector &, orig);
164  psum = sel.psum;
165  }
166  GAGenome &select() const override;
167  void update() override;
168 
169  protected:
170  int n;
171  std::vector<float> psum;
172 };
173 #endif
174 
175 /* ----------------------------------------------------------------------------
176  This version of the tournament selector does two roulette wheel selections
177 then picks the better of the two. We derive from the roulette wheel class so
178 that we can use its update method.
179 ---------------------------------------------------------------------------- */
180 #if USE_TOURNAMENT_SELECTOR == 1
181 class GATournamentSelector : public GARouletteWheelSelector
182 {
183  public:
184  GADefineIdentity("GATournamentSelector", GAID::TournamentSelection);
185 
186  explicit GATournamentSelector(int w = GASelectionScheme::SCALED)
187  : GARouletteWheelSelector(w)
188  {
189  }
190  GATournamentSelector(const GATournamentSelector &orig)
191  : GARouletteWheelSelector(orig)
192  {
193  copy(orig);
194  }
195  GATournamentSelector &operator=(const GASelectionScheme &orig)
196  {
197  if (&orig != this) {
198  copy(orig);
199 }
200  return *this;
201  }
202  ~GATournamentSelector() override = default;
203  GASelectionScheme *clone() const override
204  {
205  return new GATournamentSelector;
206  }
207  GAGenome &select() const override;
208 };
209 #endif
210 
211 /* ----------------------------------------------------------------------------
212  Stochastic uniform sampling selection. This is just a fancy name for
213 random sampling. Any individual in the population has as much chance of being
214 selected as any other.
215 ---------------------------------------------------------------------------- */
216 #if USE_UNIFORM_SELECTOR == 1
217 class GAUniformSelector : public GASelectionScheme
218 {
219  public:
220  GADefineIdentity("GAUniformSelector", GAID::UniformSelection);
221 
222  explicit GAUniformSelector(int w = GASelectionScheme::SCALED)
223  : GASelectionScheme(w)
224  {
225  }
226  GAUniformSelector(const GAUniformSelector &orig) : GASelectionScheme(orig)
227  {
228  copy(orig);
229  }
230  GAUniformSelector &operator=(const GASelectionScheme &orig)
231  {
232  if (&orig != this) {
233  copy(orig);
234 }
235  return *this;
236  }
237  ~GAUniformSelector() override = default;
238  GASelectionScheme *clone() const override
239  {
240  return new GAUniformSelector;
241  }
242  GAGenome &select() const override;
243 };
244 #endif
245 
246 /* ----------------------------------------------------------------------------
247  Stochastic remainder sampling selection.
248 ---------------------------------------------------------------------------- */
249 #if USE_SRS_SELECTOR == 1
250 class GASRSSelector : public GASelectionScheme
251 {
252  public:
253  GADefineIdentity("GASRSSelector", GAID::SRSSelection);
254 
255  explicit GASRSSelector(int w = GASelectionScheme::SCALED)
256  : GASelectionScheme(w)
257  {
258  n = 0;
259  }
260  GASRSSelector(const GASRSSelector &orig) : GASelectionScheme(orig)
261  {
262  n = 0;
263  copy(orig);
264  }
265  GASRSSelector &operator=(const GASelectionScheme &orig)
266  {
267  if (&orig != this) {
268  copy(orig);
269 }
270  return *this;
271  }
272  ~GASRSSelector() override = default;
273  GASelectionScheme *clone() const override
274  {
275  return new GASRSSelector;
276  }
277  void copy(const GASelectionScheme &orig) override
278  {
279  GASelectionScheme::copy(orig);
280  const GASRSSelector &sel = DYN_CAST(const GASRSSelector &, orig);
281  n = sel.n;
282  fraction = sel.fraction;
283  choices = sel.choices;
284  }
285  GAGenome &select() const override;
286  void update() override;
287 
288  protected:
289  std::vector<float> fraction;
290  std::vector<unsigned int> choices;
291  unsigned int n;
292 };
293 #endif
294 
295 /* ----------------------------------------------------------------------------
296  Deterministic sampling selection.
297 ---------------------------------------------------------------------------- */
298 #if USE_DS_SELECTOR == 1
299 class GADSSelector : public GASelectionScheme
300 {
301  public:
302  GADefineIdentity("GADSSelector", GAID::DSSelection);
303 
304  explicit GADSSelector(int w = GASelectionScheme::SCALED)
305  : GASelectionScheme(w)
306  {
307  n = 0;
308  }
309  GADSSelector(const GADSSelector &orig) : GASelectionScheme(orig)
310  {
311  n = 0;
312  copy(orig);
313  }
314  GADSSelector &operator=(const GASelectionScheme &orig)
315  {
316  if (&orig != this) {
317  copy(orig);
318 }
319  return *this;
320  }
321  ~GADSSelector() override = default;
322  GASelectionScheme *clone() const override
323  {
324  return new GADSSelector;
325  }
326  void copy(const GASelectionScheme &orig) override
327  {
328  GASelectionScheme::copy(orig);
329  const GADSSelector &sel = DYN_CAST(const GADSSelector &, orig);
330  n = sel.n;
331  fraction = sel.fraction;
332  choices = sel.choices;
333  idx = sel.idx;
334  }
335  GAGenome &select() const override;
336  void update() override;
337 
338  protected:
339  std::vector<float> fraction;
340  std::vector<unsigned int> choices;
341  std::vector<unsigned int> idx;
342  unsigned int n;
343 };
344 #endif
345 
346 #endif
The base genome class just defines the genome interface - how to mutate, crossover,...
Definition: GAGenome.h:200
This defines the identifiers for polymorphic classes.
Definition: gaid.h:20
Definition: GAPopulation.h:66
Definition: GASelector.h:55