PaGMO  1.1.5
spea2.cpp
1 /*****************************************************************************
2  * Copyright (C) 2004-2015 The PaGMO development team, *
3  * Advanced Concepts Team (ACT), European Space Agency (ESA) *
4  * *
5  * https://github.com/esa/pagmo *
6  * *
7  * act@esa.int *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the *
21  * Free Software Foundation, Inc., *
22  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23  *****************************************************************************/
24 
25 
26 #include <string>
27 #include <vector>
28 #include <algorithm>
29 #include <ctime>
30 
31 #include <boost/math/special_functions/binomial.hpp>
32 #include <boost/random/uniform_real.hpp>
33 #include <boost/random/uniform_int.hpp>
34 #include <boost/random/variate_generator.hpp>
35 
36 #include "../exceptions.h"
37 #include "../population.h"
38 #include "../problem/base.h"
39 #include "../population.h"
40 #include "../util/neighbourhood.h"
41 #include "base.h"
42 #include "spea2.h"
43 
44 
45 namespace pagmo { namespace algorithm {
47 
59 spea2::spea2(int gen, double cr, double eta_c, double m, double eta_m, int archive_size):base(),
60  m_gen(gen),m_cr(cr),m_eta_c(eta_c),m_m(m),m_eta_m(eta_m),m_archive_size(archive_size)
61 {
62  if (gen < 0) {
63  pagmo_throw(value_error,"number of generations must be nonnegative");
64  }
65  if (cr >= 1 || cr < 0) {
66  pagmo_throw(value_error,"crossover probability must be in the [0,1[ range");
67  }
68  if (m < 0 || m > 1) {
69  pagmo_throw(value_error,"mutation probability must be in the [0,1] range");
70  }
71  if (eta_c <1 || eta_c >= 100) {
72  pagmo_throw(value_error,"Distribution index for crossover must be in 1..100");
73  }
74  if (eta_m <1 || eta_m >= 100) {
75  pagmo_throw(value_error,"Distribution index for mutation must be in 1..100");
76  }
77  if ((archive_size!=0) && (archive_size<5)) {
78  pagmo_throw(value_error,"archive_size must larger than 4 or 0 (in this last case the archive size is set to the population size)");
79  }
80  if (archive_size%4) {
81  pagmo_throw(value_error,"archive_size must be a multiple of 4");
82  }
83 }
84 
87 {
88  return base_ptr(new spea2(*this));
89 }
90 
92 
97 void spea2::evolve(population &pop) const
98 {
99  // Let's store some useful variables.
100  const problem::base &prob = pop.problem();
101  const problem::base::size_type D = prob.get_dimension(), prob_i_dimension = prob.get_i_dimension(), prob_c_dimension = prob.get_c_dimension(), prob_f_dimension = prob.get_f_dimension();
102  const problem::base::size_type Dc = D - prob_i_dimension;
103  const population::size_type NP = pop.size();
104  population::size_type archive_size;
105 
106  if(m_archive_size == 0) {
107  archive_size = NP;
108  } else {
109  archive_size = static_cast<population::size_type>(m_archive_size);
110  }
111 
112  //We perform some checks to determine wether the problem/population are suitable for PSO
113  if( Dc == 0 ){
114  pagmo_throw(value_error,"There is no continuous part in the problem decision vector for spea2 to optimise");
115  }
116 
117  if( prob_c_dimension != 0 ){
118  pagmo_throw(value_error,"The problem is not box constrained and spea2 is not suitable to solve it");
119  }
120 
121  if( prob_f_dimension < 2 ){
122  pagmo_throw(value_error,"The problem is not multi-objective. Use a single-objectie optimization algorithm instead");
123  }
124 
125  if (NP < 5 || (NP % 4 != 0) ) {
126  pagmo_throw(value_error, "for SPEA2 at least 5 individuals in the population are needed and the population size must be a multiple of 4");
127  }
128 
129  // Get out if there is nothing to do.
130  if (NP == 0 || m_gen == 0) {
131  return;
132  }
133 
134  if (archive_size > NP) {
135  pagmo_throw(value_error,"archive_size must be smaller than the population size");
136  }
137 
138  std::vector<spea2_individual> new_pop(NP,spea2_individual());
139  for(unsigned int i=0; i < NP; ++i) {
140  new_pop[i].x = pop.get_individual(i).cur_x;
141  new_pop[i].f = pop.get_individual(i).cur_f;
142  new_pop[i].c = pop.get_individual(i).cur_c;
143  }
144 
145  std::vector<spea2_individual> archive(archive_size,spea2_individual());
146  std::vector<population::size_type> ordered_by_fitness;
147 
148  //the cycle is until m_gen+1, at the last generation we just calculate the archive and return it as new population (no variation operatotions are performed)
149  for(int g = 0; g <= m_gen; ++g) {
150 
151  if(g != 0) { //no need to do that in the first generation since the archive would be empty
152  for(unsigned int i=0; i < archive.size(); ++i) {
153  new_pop.push_back(archive[i]);
154  }
155  }
156 
157  std::vector<double> F(new_pop.size(),0);
158 
159 
160  //1 - Computation of individuals' fitness (according to raw fitness and density)
161  compute_spea2_fitness(F, sqrt(new_pop.size()), new_pop, prob);
162 
163  ordered_by_fitness = pagmo::util::neighbourhood::order(F);
164 
165  unsigned int n_non_dominated;
166  for(n_non_dominated = 0; n_non_dominated < F.size() && F[ordered_by_fitness[n_non_dominated]] < 1; ++n_non_dominated);
167 
168  //2 - Fill the archive (Environmental selection)
169  if(n_non_dominated > archive_size) { //truncate according to delta
170 
171  archive = std::vector<spea2_individual>(n_non_dominated,spea2_individual());
172  for(unsigned int i = 0; i < n_non_dominated; ++i) {
173  archive[i] = new_pop[ordered_by_fitness[i]];
174  }
175 
176  //fitness vector of the non-dominated individuals
177  std::vector<fitness_vector> fit_nd(n_non_dominated);
178  for ( population::size_type i = 0; i<n_non_dominated; i++ ) {
179  fit_nd[i] = archive[i].f;
180  }
181 
182  //computing K-NN distances for K=0,...,n_non_dominated
183  std::vector<std::vector<pagmo::population::size_type> > neighbours_nd;
185  std::vector<population::size_type> rv(n_non_dominated);
186  for(unsigned int i=0; i<n_non_dominated; ++i) rv[i] = i;
187 
188  while(archive.size() > archive_size) {
189 
190  //Calculate which is the worst element according to the distance sorter
191  pagmo::population::size_type idx_to_delete = *(std::max_element(rv.begin(), rv.end(), distance_sorter(neighbours_nd, fit_nd)));
192 
193  //Remove the element from rv, archive and fit_nd
194  rv.erase(rv.end()-1);
195  archive.erase(archive.begin() + idx_to_delete);
196  fit_nd.erase(fit_nd.begin() + idx_to_delete);
197 
198  //Remove the row of neighbours_nd coresponding to idx_to_delete
199  neighbours_nd.erase(neighbours_nd.begin() + idx_to_delete);
200 
201  for(unsigned int i=0; i < neighbours_nd.size(); ++i) {
202  for(unsigned int j=0; j < neighbours_nd[i].size(); ++j) {
203  //Remove all the occurencies of idx_to_delete
204  if (neighbours_nd[i][j] == idx_to_delete) {
205  neighbours_nd[i].erase(neighbours_nd[i].begin() + j);
206  j--;
207  //Adjust all the indexes after idx_to_delete
208  } else if (neighbours_nd[i][j] > idx_to_delete) {
209  neighbours_nd[i][j]--;
210  }
211  }
212  }
213 
214  }
215 
216  } else { //fill with the best dominated individuals
217  for(unsigned int i = 0; i < archive_size; ++i) {
218  archive[i] = new_pop[ordered_by_fitness[i]];
219  }
220  }
221 
222  if(g != m_gen) { //no need to do recomination/mutation in the last generation
223 
224  //3 - We perform the genetic operations on the archive individuals and fill the population
225  boost::uniform_int<int> pop_idx(0,archive_size-1);
226  boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > p_idx(m_urng,pop_idx);
227 
228  population::size_type parent1_idx, parent2_idx;
229  decision_vector child1_x(D), child2_x(D);
230 
231 
232  //We create a pseudo-random permutation of the poulation indexes
233  std::vector<population::size_type> shuffle(archive_size);
234  for(pagmo::population::size_type i=0; i < archive_size; ++i) {
235  shuffle[i] = i;
236  }
237 
238 
239  std::vector<fitness_vector> archive_fit(archive_size);
240  std::vector<constraint_vector> archive_cons(archive_size);
241  for ( population::size_type i = 0; i<archive_size; i++ ) {
242  archive_fit[i] = archive[i].f;
243  archive_cons[i] = archive[i].c;
244  }
245 
246  std::vector<std::vector<population::size_type> > domination_list = compute_domination_list(prob, archive_fit,archive_cons);
247  std::vector<population::size_type> pareto_rank = compute_pareto_rank(domination_list);
248 
249  population::size_type idx = 0;
250 
251  while(idx < NP) {
252  std::random_shuffle(shuffle.begin(),shuffle.end(), p_idx);
253  //We then loop thorugh all individuals with increment 4 to select two pairs of parents that will
254  //each create 2 new offspring
255  for (pagmo::population::size_type i=0; idx < NP && i<archive_size; i+=4) {
256  // We create two offsprings using the shuffled list 1
257  parent1_idx = tournament_selection(shuffle[i], shuffle[i+1], pareto_rank);
258  parent2_idx = tournament_selection(shuffle[i+2], shuffle[i+3], pareto_rank);
259  crossover(child1_x, child2_x, parent1_idx,parent2_idx,archive, prob);
260  mutate(child1_x,prob);
261  mutate(child2_x,prob);
262 
263  spea2_individual child1;
264  child1.x = child1_x;
265  child1.f = prob.objfun(child1_x);
266  child1.c = prob.compute_constraints(child1_x);
267 
268  spea2_individual child2;
269  child2.x = child2_x;
270  child2.f = prob.objfun(child2_x);
271  child2.c = prob.compute_constraints(child2_x);
272 
273  new_pop[idx++] = child1;
274  new_pop[idx++] = child2;
275  }
276  }
277  //resize new_pop to NP individuals
278  new_pop.resize(NP);
279  }
280  }
281 
282  //4 - return the current archive as population
283  pop.clear();
284  for(unsigned int i=0; i<NP; ++i) {
285  if(i<archive_size){
286  pop.push_back(archive[i].x);
287  }
288  else{
289  pop.push_back(new_pop[ordered_by_fitness[i]].x);
290  }
291  }
292 }
293 
294 
296 std::string spea2::get_name() const
297 {
298  return "Strength Pareto Evolutionary Algorithm (SPEA2)";
299 }
300 
302 
305 std::string spea2::human_readable_extra() const
306 {
307  std::ostringstream s;
308  s << "gen:" << m_gen << ' ';
309  s << "cr: " << m_cr << ' ';
310  s << "eta_c: " << m_eta_c << ' ';
311  s << "m: " << m_m << ' ';
312  s << "eta_m: " << m_eta_m << ' ';
313  s << "archive_size: " << m_archive_size << ' ';
314  return s.str();
315 }
316 
317 std::vector<std::vector<population::size_type> > spea2::compute_domination_list(const pagmo::problem::base &prob,
318  const std::vector<fitness_vector> &fit,
319  const std::vector<constraint_vector> &cons) const
320 {
321  std::vector<population::size_type> dummy;
322  std::vector<std::vector<population::size_type> > domination_list(fit.size(), dummy);
323 
324  for(unsigned int i=0; i<fit.size();++i) {
325  for(unsigned int j=0; j<fit.size(); ++j) {
326  // Check if individual in position i dominates individual in position n.
327  if(prob.compare_fc(fit[i],cons[i],fit[j],cons[j])) {
328  domination_list[i].push_back(j);
329  }
330  }
331  }
332 
333  return domination_list;
334 }
335 
336 void spea2::compute_spea2_fitness(std::vector<double> &F,
337  int K,
338  const std::vector<spea2_individual> &pop,
339  const pagmo::problem::base &prob) const
340 {
341 
342  const population::size_type NP = pop.size();
343  std::vector<int> S(NP, 0);
344 
345 
346  std::vector<fitness_vector> fit(NP);
347  std::vector<fitness_vector> cons(NP);
348  for ( population::size_type i = 0; i<NP; i++ ) {
349  fit[i] = pop[i].f;
350  cons[i] = pop[i].c;
351  }
352  std::vector<std::vector<pagmo::population::size_type> > neighbours;
354 
355  std::vector<std::vector<population::size_type> > domination_list = compute_domination_list(prob, fit,cons);
356 
357  for(unsigned int i=0; i<NP; ++i) {
358  S[i] = domination_list[i].size();
359  }
360 
361  std::fill(F.begin(), F.end(), 0);
362 
363  for(unsigned int i=0; i<NP; ++i) {
364  for(unsigned int j=0; j<domination_list[i].size(); ++j) {
365  F[domination_list[i][j]] += S[i];
366  }
367  }
368 
369  for(unsigned int i=0; i<NP; ++i) {
370  F[i] = F[i] +
371  (1.0 / (pagmo::util::neighbourhood::euclidian::distance(fit[i], fit[neighbours[i][K]]) + 2));
372  }
373 }
374 
375 pagmo::population::size_type spea2::tournament_selection(pagmo::population::size_type idx1, pagmo::population::size_type idx2, const std::vector<population::size_type> &pareto_rank) const
376 {
377  if (pareto_rank[idx1] < pareto_rank[idx2]) return idx1;
378  if (pareto_rank[idx1] > pareto_rank[idx2]) return idx2;
379  return ((m_drng() > 0.5) ? idx1 : idx2);
380 }
381 
382 std::vector<population::size_type> spea2::compute_domination_count(const std::vector<std::vector<population::size_type> > &dom_list) const
383 {
384  std::vector<population::size_type> domination_count(dom_list.size(),0);
385  for(unsigned int i=0; i<dom_list.size(); ++i) {
386  for(unsigned int j = 0; j < dom_list[i].size(); ++j) {
387  domination_count[dom_list[i][j]]++;
388  }
389  }
390 
391  return domination_count;
392 }
393 
394 std::vector<population::size_type> spea2::compute_pareto_rank(const std::vector<std::vector<population::size_type> > &dom_list) const
395 {
396  std::vector<population::size_type> pareto_rank(dom_list.size(),0);
397 
398  // We define some utility vectors .....
399  std::vector<population::size_type> F,S;
400 
401  // And make a copy of the domination count (number of individuals that dominating one individual)
402  std::vector<population::size_type> dom_count = compute_domination_count(dom_list);
403 
404  // 1 - Find the first Pareto Front
405  for (population::size_type idx = 0; idx < dom_count.size(); ++idx){
406  if (dom_count[idx] == 0) {
407  F.push_back(idx);
408  }
409  }
410 
411  unsigned int irank = 1;
412 
413  // We loop to find subsequent fronts
414  while (F.size()!=0) {
415  //For each individual F in the current front
416  for (population::size_type i=0; i < F.size(); ++i) {
417  //For each individual dominated by F
418  for (population::size_type j=0; j<dom_list[F[i]].size(); ++j) {
419  dom_count[dom_list[F[i]][j]]--;
420  if (dom_count[dom_list[F[i]][j]] == 0){
421  S.push_back(dom_list[F[i]][j]);
422  pareto_rank[dom_list[F[i]][j]] = irank;
423  }
424  }
425  }
426  F = S;
427  S.clear();
428  irank++;
429  }
430 
431  //std::cout << "pareto rank before return " << pareto_rank << std::endl;
432  return pareto_rank;
433 }
434 
435 
436 void spea2::crossover(decision_vector& child1, decision_vector& child2, pagmo::population::size_type parent1_idx, pagmo::population::size_type parent2_idx,
437  const std::vector<spea2_individual> &pop, const pagmo::problem::base &prob) const
438 {
439 
442  problem::base::size_type Dc = D - Di;
443  const decision_vector &lb = prob.get_lb(), &ub = prob.get_ub();
444  const decision_vector& parent1 = pop[parent1_idx].x;
445  const decision_vector& parent2 = pop[parent2_idx].x;
446  double y1,y2,yl,yu, rand, beta, alpha, betaq, c1, c2;
447  child1 = parent1;
448  child2 = parent2;
449  int site1, site2;
450 
451  //This implements a Simulated Binary Crossover SBX
452  if (m_drng() <= m_cr) {
453  for (pagmo::problem::base::size_type i = 0; i < Dc; i++) {
454  if ( (m_drng() <= 0.5) && (std::fabs(parent1[i]-parent2[i]) ) > 1.0e-14) {
455  if (parent1[i] < parent2[i]) {
456  y1 = parent1[i];
457  y2 = parent2[i];
458  } else {
459  y1 = parent2[i];
460  y2 = parent1[i];
461  }
462  yl = lb[i];
463  yu = ub[i];
464  rand = m_drng();
465 
466  beta = 1.0 + (2.0*(y1-yl)/(y2-y1));
467  alpha = 2.0 - std::pow(beta,-(m_eta_c+1.0));
468  if (rand <= (1.0/alpha))
469  {
470  betaq = std::pow((rand*alpha),(1.0/(m_eta_c+1.0)));
471  } else {
472  betaq = std::pow((1.0/(2.0 - rand*alpha)),(1.0/(m_eta_c+1.0)));
473  }
474  c1 = 0.5*((y1+y2)-betaq*(y2-y1));
475 
476  beta = 1.0 + (2.0*(yu-y2)/(y2-y1));
477  alpha = 2.0 - std::pow(beta,-(m_eta_c+1.0));
478  if (rand <= (1.0/alpha))
479  {
480  betaq = std::pow((rand*alpha),(1.0/(m_eta_c+1.0)));
481  } else {
482  betaq = std::pow((1.0/(2.0 - rand*alpha)),(1.0/(m_eta_c+1.0)));
483  }
484  c2 = 0.5*((y1+y2)+betaq*(y2-y1));
485 
486  if (c1<lb[i]) c1=lb[i];
487  if (c2<lb[i]) c2=lb[i];
488  if (c1>ub[i]) c1=ub[i];
489  if (c2>ub[i]) c2=ub[i];
490  if (m_drng() <= 0.5) {
491  child1[i] = c1; child2[i] = c2;
492  } else {
493  child1[i] = c2; child2[i] = c1;
494  }
495  }
496  }
497 
498  }
499 
500  //This implements two point binary crossover
501  for (pagmo::problem::base::size_type i = Dc; i < D; i++) {
502  if (m_drng() <= m_cr) {
503  boost::uniform_int<int> in_dist(0,Di-1);
504  boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > ra_num(m_urng,in_dist);
505  site1 = ra_num();
506  site2 = ra_num();
507  if (site1 > site2) std::swap(site1,site2);
508  for(int j=0; j<site1; j++)
509  {
510  child1[j] = parent1[j];
511  child2[j] = parent2[j];
512  }
513  for(int j=site1; j<site2; j++)
514  {
515  child1[j] = parent2[j];
516  child2[j] = parent1[j];
517  }
518  for(pagmo::problem::base::size_type j=site2; j<Di; j++)
519  {
520  child1[j] = parent1[j];
521  child2[j] = parent2[j];
522  }
523  }
524  else {
525  child1[i] = parent1[i];
526  child2[i] = parent2[i];
527  }
528  }
529 }
530 
531 void spea2::mutate(decision_vector& child, const pagmo::problem::base& prob) const
532 {
533 
536  problem::base::size_type Dc = D - Di;
537  const decision_vector &lb = prob.get_lb(), &ub = prob.get_ub();
538  double rnd, delta1, delta2, mut_pow, deltaq;
539  double y, yl, yu, val, xy;
540  int gen_num;
541 
542  //This implements the real polinomial mutation of an individual
543  for (pagmo::problem::base::size_type j=0; j < Dc; ++j){
544  if (m_drng() <= m_m) {
545  y = child[j];
546  yl = lb[j];
547  yu = ub[j];
548  delta1 = (y-yl)/(yu-yl);
549  delta2 = (yu-y)/(yu-yl);
550  rnd = m_drng();
551  mut_pow = 1.0/(m_eta_m+1.0);
552  if (rnd <= 0.5)
553  {
554  xy = 1.0-delta1;
555  val = 2.0*rnd+(1.0-2.0*rnd)*(pow(xy,(m_eta_m+1.0)));
556  deltaq = pow(val,mut_pow) - 1.0;
557  }
558  else
559  {
560  xy = 1.0-delta2;
561  val = 2.0*(1.0-rnd)+2.0*(rnd-0.5)*(pow(xy,(m_eta_m+1.0)));
562  deltaq = 1.0 - (pow(val,mut_pow));
563  }
564  y = y + deltaq*(yu-yl);
565  if (y<yl) y = yl;
566  if (y>yu) y = yu;
567  child[j] = y;
568  }
569  }
570 
571  //This implements the integer mutation for an individual
572  for (pagmo::problem::base::size_type j=Dc; j < D; ++j){
573  if (m_drng() <= m_m) {
574  y = child[j];
575  yl = lb[j];
576  yu = ub[j];
577  boost::uniform_int<int> in_dist(yl,yu-1);
578  boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > ra_num(m_urng,in_dist);
579  gen_num = ra_num();
580  if (gen_num >= y) gen_num = gen_num + 1;
581  child[j] = gen_num;
582  }
583  }
584 }
585 
586 
587 
588 }} //namespaces
589 
590 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::algorithm::spea2)
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
Root PaGMO namespace.
spea2(int gen=100, double cr=0.95, double eta_c=10, double m=0.01, double eta_m=50, int archive_size=0)
Constructor.
Definition: spea2.cpp:59
std::vector< double > decision_vector
Decision vector type.
Definition: types.h:40
"Strength Pareto Evolutionary Algorithm (SPEA2)"
Definition: spea2.h:80
fitness_vector cur_f
Current fitness vector.
Definition: population.h:89
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
Definition: population.cpp:277
Base algorithm class.
constraint_vector cur_c
Current constraint vector.
Definition: population.h:87
Base problem class.
Definition: problem/base.h:148
Population class.
Definition: population.h:70
std::vector< population::size_type > order(const std::vector< T > &values)
Sort according the the values in the values vector but return the permutation.
Definition: neighbourhood.h:55
size_type get_dimension() const
Return global dimension.
fitness_vector objfun(const decision_vector &) const
Return fitness of pagmo::decision_vector.
size_type get_i_dimension() const
Return integer dimension.
static double distance(const std::vector< double > &, const std::vector< double > &)
std::string get_name() const
Algorithm name.
Definition: spea2.cpp:296
void evolve(population &) const
Evolve implementation.
Definition: spea2.cpp:97
constraint_vector compute_constraints(const decision_vector &) const
Compute constraints and return constraint vector.
c_size_type get_c_dimension() const
Return global constraints dimension.
const decision_vector & get_ub() const
Upper bounds getter.
container_type::size_type size_type
Population size type.
Definition: population.h:192
static void compute_neighbours(std::vector< std::vector< pagmo::population::size_type > > &, const std::vector< std::vector< double > > &)
decision_vector cur_x
Current decision vector.
Definition: population.h:83
rng_uint32 m_urng
Random number generator for unsigned integer values.
f_size_type get_f_dimension() const
Return fitness dimension.
bool compare_fc(const fitness_vector &, const constraint_vector &, const fitness_vector &, const constraint_vector &) const
Simultaneous fitness-constraint comparison.
const decision_vector & get_lb() const
Lower bounds getter.
std::string human_readable_extra() const
Extra human readable algorithm info.
Definition: spea2.cpp:305
rng_double m_drng
Random number generator for double-precision floating point values.
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
Definition: problem/base.h:160
base_ptr clone() const
Clone method.
Definition: spea2.cpp:86