25 #include <boost/random/uniform_int.hpp>
26 #include <boost/random/uniform_real.hpp>
27 #include <boost/random/variate_generator.hpp>
28 #include <boost/random/normal_distribution.hpp>
29 #include <boost/math/special_functions/round.hpp>
36 #include "../exceptions.h"
37 #include "../population.h"
38 #include "../problem/base.h"
43 namespace pagmo {
namespace algorithm {
56 nsga2::nsga2(
int gen,
double cr,
double eta_c,
double m,
double eta_m):
base(),m_gen(gen),m_cr(cr),m_eta_c(eta_c),m_m(m),m_eta_m(eta_m)
59 pagmo_throw(value_error,
"number of generations must be nonnegative");
61 if (cr >= 1 || cr < 0) {
62 pagmo_throw(value_error,
"crossover probability must be in the [0,1[ range");
65 pagmo_throw(value_error,
"mutation probability must be in the [0,1] range");
67 if (eta_c <1 || eta_c >= 100) {
68 pagmo_throw(value_error,
"Distribution index for crossover must be in 1..100");
70 if (eta_m <1 || eta_m >= 100) {
71 pagmo_throw(value_error,
"Distribution index for mutation must be in 1..100");
87 return ((
m_drng() > 0.5) ? idx1 : idx2);
99 double y1,y2,yl,yu, rand, beta, alpha, betaq, c1, c2;
107 if ( (
m_drng() <= 0.5) && (std::fabs(parent1[i]-parent2[i]) ) > 1.0e-14) {
108 if (parent1[i] < parent2[i]) {
119 beta = 1.0 + (2.0*(y1-yl)/(y2-y1));
120 alpha = 2.0 - std::pow(beta,-(m_eta_c+1.0));
121 if (rand <= (1.0/alpha))
123 betaq = std::pow((rand*alpha),(1.0/(m_eta_c+1.0)));
125 betaq = std::pow((1.0/(2.0 - rand*alpha)),(1.0/(m_eta_c+1.0)));
127 c1 = 0.5*((y1+y2)-betaq*(y2-y1));
129 beta = 1.0 + (2.0*(yu-y2)/(y2-y1));
130 alpha = 2.0 - std::pow(beta,-(m_eta_c+1.0));
131 if (rand <= (1.0/alpha))
133 betaq = std::pow((rand*alpha),(1.0/(m_eta_c+1.0)));
135 betaq = std::pow((1.0/(2.0 - rand*alpha)),(1.0/(m_eta_c+1.0)));
137 c2 = 0.5*((y1+y2)+betaq*(y2-y1));
139 if (c1<lb[i]) c1=lb[i];
140 if (c2<lb[i]) c2=lb[i];
141 if (c1>ub[i]) c1=ub[i];
142 if (c2>ub[i]) c2=ub[i];
144 child1[i] = c1; child2[i] = c2;
146 child1[i] = c2; child2[i] = c1;
156 boost::uniform_int<int> in_dist(0,Di-1);
157 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > ra_num(
m_urng,in_dist);
160 if (site1 > site2) std::swap(site1,site2);
161 for(
int j=0; j<site1; j++)
163 child1[j] = parent1[j];
164 child2[j] = parent2[j];
166 for(
int j=site1; j<site2; j++)
168 child1[j] = parent2[j];
169 child2[j] = parent1[j];
173 child1[j] = parent1[j];
174 child2[j] = parent2[j];
178 child1[i] = parent1[i];
179 child2[i] = parent2[i];
191 double rnd, delta1, delta2, mut_pow, deltaq;
192 double y, yl, yu, val, xy;
201 delta1 = (y-yl)/(yu-yl);
202 delta2 = (yu-y)/(yu-yl);
204 mut_pow = 1.0/(m_eta_m+1.0);
208 val = 2.0*rnd+(1.0-2.0*rnd)*(pow(xy,(m_eta_m+1.0)));
209 deltaq = pow(val,mut_pow) - 1.0;
214 val = 2.0*(1.0-rnd)+2.0*(rnd-0.5)*(pow(xy,(m_eta_m+1.0)));
215 deltaq = 1.0 - (pow(val,mut_pow));
217 y = y + deltaq*(yu-yl);
230 boost::uniform_int<int> in_dist(yl,yu-1);
231 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > ra_num(
m_urng,in_dist);
233 if (gen_num >= y) gen_num = gen_num + 1;
255 if ( prob_c_dimension != 0 ) {
256 pagmo_throw(value_error,
"The problem is not box constrained and NSGA-II is not suitable to solve it");
259 if (NP < 5 || (NP % 4 != 0) ) {
260 pagmo_throw(value_error,
"for NSGA-II at least 5 individuals in the population are needed and the population size must be a multiple of 4");
264 pagmo_throw(value_error,
"The problem is not multiobjective, try some other algorithm than NSGA-II");
272 std::vector<population::size_type> best_idx(NP), shuffle1(NP),shuffle2(NP);
279 boost::uniform_int<int> pop_idx(0,NP-1);
280 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > p_idx(
m_urng,pop_idx);
283 for (
int g = 0; g<m_gen; g++) {
290 std::random_shuffle(shuffle1.begin(),shuffle1.end(),p_idx);
291 std::random_shuffle(shuffle2.begin(),shuffle2.end(),p_idx);
297 parent1_idx = tournament_selection(shuffle1[i], shuffle1[i+1],pop);
298 parent2_idx = tournament_selection(shuffle1[i+2], shuffle1[i+3],pop);
299 crossover(child1, child2, parent1_idx,parent2_idx,pop);
302 popnew.push_back(child1);
303 popnew.push_back(child2);
306 parent1_idx = tournament_selection(shuffle2[i], shuffle2[i+1],pop);
307 parent2_idx = tournament_selection(shuffle2[i+2], shuffle2[i+3],pop);
308 crossover(child1, child2, parent1_idx,parent2_idx,pop);
311 popnew.push_back(child1);
312 popnew.push_back(child2);
317 best_idx = popnew.get_best_idx(NP);
328 return "Nondominated Sorting Genetic Algorithm II (NSGA-II)";
337 std::ostringstream s;
338 s <<
"gen:" << m_gen <<
' ';
339 s <<
"cr:" << m_cr <<
' ';
340 s <<
"eta_c:" << m_eta_c <<
' ';
341 s <<
"m:" << m_m <<
' ';
342 s <<
"eta_m:" << m_eta_m << std::endl;
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
std::vector< double > decision_vector
Decision vector type.
nsga2(int gen=100, double cr=0.95, double eta_c=10, double m=0.01, double eta_m=50)
Constructor.
Nondominated Sorting genetic algorithm II (NSGA-II)
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
void update_pareto_information() const
Update Pareto Information.
size_type get_dimension() const
Return global dimension.
size_type get_i_dimension() const
Return integer dimension.
double get_crowding_d(const size_type &) const
Get Crowding Distance.
base_ptr clone() const
Clone method.
c_size_type get_c_dimension() const
Return global constraints dimension.
void evolve(population &) const
Evolve implementation.
const decision_vector & get_ub() const
Upper bounds getter.
container_type::size_type size_type
Population size type.
decision_vector cur_x
Current decision vector.
size_type get_pareto_rank(const size_type &) const
Get Pareto rank.
std::string human_readable_extra() const
Extra human readable algorithm info.
rng_uint32 m_urng
Random number generator for unsigned integer values.
f_size_type get_f_dimension() const
Return fitness dimension.
const decision_vector & get_lb() const
Lower bounds getter.
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.
std::string get_name() const
Algorithm name.