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>
34 #include "../exceptions.h"
35 #include "../population.h"
36 #include "../problem/base.h"
41 namespace pagmo {
namespace algorithm {
57 m_sel_m(sel_m),m_cr(cr),m_eta_c(eta_c),m_m(m),m_eta_m(eta_m)
59 validate_parameters();
69 m_cr(orig.m_cr),m_eta_c(orig.m_eta_c),m_m(orig.m_m),m_eta_m(orig.m_eta_m)
71 if (orig.m_hv_algorithm) {
72 m_hv_algorithm = orig.m_hv_algorithm->clone();
91 m_gen(gen),m_sel_m(sel_m), m_cr(cr),m_eta_c(eta_c),m_m(m),m_eta_m(eta_m)
93 m_hv_algorithm = hv_algorithm;
94 validate_parameters();
105 return m_hv_algorithm;
114 void sms_emoa::validate_parameters()
117 pagmo_throw(value_error,
"number of generations must be nonnegative");
119 if (m_sel_m < 1 || m_sel_m > 2) {
120 pagmo_throw(value_error,
"selection method must be equal to 1 (least contributor) or 2 (domination count)");
122 if (m_cr >= 1 || m_cr < 0) {
123 pagmo_throw(value_error,
"crossover probability must be in the [0,1] range");
125 if (m_m < 0 || m_m > 1) {
126 pagmo_throw(value_error,
"mutation probability must be in the [0,1] range");
128 if (m_eta_c <1 || m_eta_c >= 100) {
129 pagmo_throw(value_error,
"Distribution index for crossover must be in 1..100");
131 if (m_eta_m <1 || m_eta_m >= 100) {
132 pagmo_throw(value_error,
"Distribution index for mutation must be in 1..100");
145 double y1,y2,yl,yu, rand, beta, alpha, betaq, c1, c2;
153 if ( (
m_drng() <= 0.5) && (std::fabs(parent1[i]-parent2[i]) ) > 1.0e-14) {
154 if (parent1[i] < parent2[i]) {
165 beta = 1.0 + (2.0*(y1-yl)/(y2-y1));
166 alpha = 2.0 - std::pow(beta,-(m_eta_c+1.0));
167 if (rand <= (1.0/alpha))
169 betaq = std::pow((rand*alpha),(1.0/(m_eta_c+1.0)));
171 betaq = std::pow((1.0/(2.0 - rand*alpha)),(1.0/(m_eta_c+1.0)));
173 c1 = 0.5*((y1+y2)-betaq*(y2-y1));
175 beta = 1.0 + (2.0*(yu-y2)/(y2-y1));
176 alpha = 2.0 - std::pow(beta,-(m_eta_c+1.0));
177 if (rand <= (1.0/alpha))
179 betaq = std::pow((rand*alpha),(1.0/(m_eta_c+1.0)));
181 betaq = std::pow((1.0/(2.0 - rand*alpha)),(1.0/(m_eta_c+1.0)));
183 c2 = 0.5*((y1+y2)+betaq*(y2-y1));
185 if (c1<lb[i]) c1=lb[i];
186 if (c2<lb[i]) c2=lb[i];
187 if (c1>ub[i]) c1=ub[i];
188 if (c2>ub[i]) c2=ub[i];
190 child1[i] = c1; child2[i] = c2;
192 child1[i] = c2; child2[i] = c1;
202 boost::uniform_int<int> in_dist(0,Di-1);
203 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > ra_num(
m_urng,in_dist);
206 if (site1 > site2) std::swap(site1,site2);
207 for(
int j=0; j<site1; j++)
209 child1[j] = parent1[j];
210 child2[j] = parent2[j];
212 for(
int j=site1; j<site2; j++)
214 child1[j] = parent2[j];
215 child2[j] = parent1[j];
219 child1[j] = parent1[j];
220 child2[j] = parent2[j];
224 child1[i] = parent1[i];
225 child2[i] = parent2[i];
237 double rnd, delta1, delta2, mut_pow, deltaq;
238 double y, yl, yu, val, xy;
247 delta1 = (y-yl)/(yu-yl);
248 delta2 = (yu-y)/(yu-yl);
250 mut_pow = 1.0/(m_eta_m+1.0);
254 val = 2.0*rnd+(1.0-2.0*rnd)*(pow(xy,(m_eta_m+1.0)));
255 deltaq = pow(val,mut_pow) - 1.0;
260 val = 2.0*(1.0-rnd)+2.0*(rnd-0.5)*(pow(xy,(m_eta_m+1.0)));
261 deltaq = 1.0 - (pow(val,mut_pow));
263 y = y + deltaq*(yu-yl);
276 boost::uniform_int<int> in_dist(yl,yu-1);
277 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > ra_num(
m_urng,in_dist);
279 if (gen_num >= y) gen_num = gen_num + 1;
289 std::vector< std::vector< population::size_type> > fronts = pop.compute_pareto_fronts();
291 const std::vector< population::size_type> &last_front = fronts.back();
293 if (last_front.size() == 1) {
294 return last_front[0];
298 if (m_sel_m == 1 || fronts.size() == 1) {
299 std::vector<fitness_vector> points;
300 points.resize(last_front.size());
303 points[idx] =
fitness_vector(pop.get_individual(last_front[idx]).cur_f);
311 if (m_hv_algorithm) {
312 least_idx = hypvol.least_contributor(r, m_hv_algorithm);
314 least_idx = hypvol.least_contributor(r);
317 return last_front[least_idx];
324 if (current_dom_count > max_dom_count) {
325 max_dom_count = current_dom_count;
326 individual_idx = idx;
329 return last_front[individual_idx];
349 if ( prob_c_dimension != 0 ) {
350 pagmo_throw(value_error,
"The problem is not box constrained and SMS-EMOA is not suitable to solve it");
354 pagmo_throw(value_error,
"The problem is not multiobjective, try some other algorithm than SMS-EMOA");
366 for (
int g = 0; g < m_gen; g++) {
368 parent1_idx =
m_urng() % NP;
369 parent2_idx = ((
m_urng() % (NP-1)) + parent1_idx) % NP;
371 crossover(child1, child2, parent1_idx, parent2_idx, pop);
374 pop.push_back(child1);
375 pop.erase(evaluate_s_metric_selection(pop));
382 return "S-Metric Selection Evolutionary Multiobjective Optimisation Algorithm (SMS-EMOA)";
391 std::ostringstream s;
392 s <<
"gen:" << m_gen <<
' ';
393 s <<
"cr:" << m_cr <<
' ';
394 s <<
"eta_c:" << m_eta_c <<
' ';
395 s <<
"m:" << m_m <<
' ';
396 s <<
"eta_m:" << m_eta_m <<
' ';
397 s <<
"hv_algorithm:";
398 if (m_hv_algorithm) {
399 s << m_hv_algorithm->get_name();
401 s <<
"Chosen dynamically";
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
void evolve(population &) const
Evolve implementation.
std::vector< double > decision_vector
Decision vector type.
base_ptr clone() const
Clone method.
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
pagmo::util::hv_algorithm::base_ptr get_hv_algorithm() const
Get the hypervolume algorithm used for the computation.
size_type get_dimension() const
Return global dimension.
std::string get_name() const
Algorithm name.
S-metric selection evolutionary multiobjective optimisation algorithm (SMS-EMOA)
unsigned int m_fevals
A counter for the number of function evaluations.
size_type get_i_dimension() const
Return integer dimension.
std::vector< double > fitness_vector
Fitness vector type.
boost::shared_ptr< base > base_ptr
Base hypervolume algorithm class.
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.
decision_vector cur_x
Current decision vector.
rng_uint32 m_urng
Random number generator for unsigned integer values.
sms_emoa(const sms_emoa &)
Copy constructor.
f_size_type get_f_dimension() const
Return fitness dimension.
std::string human_readable_extra() const
Extra human readable algorithm info.
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.