31 #include <boost/random/uniform_real.hpp>
32 #include <boost/random/uniform_int.hpp>
33 #include <boost/random/variate_generator.hpp>
34 #include <boost/math/special_functions/binomial.hpp>
36 #include "../exceptions.h"
37 #include "../population.h"
38 #include "../problem/base.h"
39 #include "../island.h"
40 #include "../population.h"
41 #include "../problem/decompose.h"
42 #include "../util/discrepancy.h"
43 #include "../util/neighbourhood.h"
48 namespace pagmo {
namespace algorithm {
74 bool preserve_diversity
78 m_weight_generation(weight_generation),
84 m_preserve_diversity(preserve_diversity)
88 pagmo_throw(value_error,
"number of generations must be nonnegative");
92 pagmo_throw(value_error,
"non existing weight generation method");
95 if(realb > 1.0 || realb < 0) {
96 pagmo_throw(value_error,
"The neighbor type chance realb needs to be in [0,1]");
99 if(cr > 1.0 || cr < 0) {
100 pagmo_throw(value_error,
"Differential Evolution crossover cr needs to be in [0,1]");
103 if(f > 1.0 || f < 0) {
104 pagmo_throw(value_error,
"Differential Evolution f parameter needs to be in [0,1]");
108 pagmo_throw(value_error,
"Distribution index for the polynomial mutation needs to be > 0");
119 void moead::reksum(std::vector<std::vector<double> > &retval,
120 const std::vector<unsigned int>& X,
123 std::vector<double> eggs)
const {
126 if (std::find(X.begin(),X.end(),s) == X.end()) {
130 retval.push_back(eggs);
133 for (
unsigned int i=0; i<X.size(); ++i) {
134 eggs.push_back(X[i]);
135 reksum(retval,X,m-1,s-X[i],eggs);
156 pagmo_throw(value_error,
"To allow weight be generated correctly the number of weights must be strictly larger than the number of objectives");
160 boost::uniform_real<double> uniform(0.0,1.0);
161 boost::variate_generator<boost::lagged_fibonacci607 &, boost::uniform_real<double> > r_dist(
m_drng,uniform);
163 std::vector<fitness_vector> retval;
164 if(m_weight_generation ==
GRID) {
169 }
else if (n_f == 3) {
170 H = floor(0.5 * (sqrt(8*n_w + 1) - 3));
173 while(boost::math::binomial_coefficient<double>(H+n_f-1, n_f-1) <= n_w) {
180 if (fabs(n_w-(boost::math::binomial_coefficient<double>(H+n_f-1, n_f-1))) > 1E-8) {
181 std::ostringstream error_message;
182 error_message <<
"Invalid population size. Select " << boost::math::binomial_coefficient<double>(H+n_f-1, n_f-1)
183 <<
" or " << boost::math::binomial_coefficient<double>(H+1+n_f-1, n_f-1)
185 pagmo_throw(value_error,error_message.str());
189 std::vector<unsigned int> range;
190 for (
unsigned int i=0; i<H+1;++i) {
193 reksum(retval, range, n_f, H);
194 for(
unsigned int i=0; i< retval.size(); ++i) {
195 for(
unsigned int j=0; j< retval[i].size(); ++j) {
201 for(
unsigned int i = 0; i< n_f; ++i) {
206 for(
unsigned int i = n_f; i <n_w; ++i) {
207 retval.push_back(generator());
210 }
else if(m_weight_generation ==
RANDOM) {
211 pagmo::util::discrepancy::project_2_simplex projection(n_f);
212 for (
unsigned int i = 0; i<n_w; ++i) {
214 for(
unsigned int j = 0; j <n_f-1; ++j) {
217 retval.push_back(projection(dummy));
229 double rnd, delta1, delta2, mut_pow, deltaq;
230 double y, yl, yu, val, xy;
238 delta1 = (y-yl)/(yu-yl);
239 delta2 = (yu-y)/(yu-yl);
241 mut_pow = 1.0/(m_eta_m+1.0);
245 val = 2.0*rnd+(1.0-2.0*rnd)*(pow(xy,(m_eta_m+1.0)));
246 deltaq = pow(val,mut_pow) - 1.0;
251 val = 2.0*(1.0-rnd)+2.0*(rnd-0.5)*(pow(xy,(m_eta_m+1.0)));
252 deltaq = 1.0 - (pow(val,mut_pow));
254 y = y + deltaq*(yu-yl);
262 void moead::mating_selection(std::vector<population::size_type> &list,
int n,
int type,
const std::vector<std::vector<population::size_type> >& neigh_idx)
const {
264 std::vector<population::size_type>::size_type ss = neigh_idx[n].size(), p;
266 boost::uniform_int<int> idx(0,neigh_idx.size()-1);
267 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > p_idx(
m_urng,idx);
272 p = neigh_idx[n][p_idx()%ss];
278 for(std::vector<population::size_type>::size_type i=0; i<list.size(); i++)
286 if(flag) list.push_back(p);
301 pagmo_throw(value_error,
"The problem is not multiobjective, try some other algorithm than MOEA/D");
304 pagmo_throw(value_error,
"Too many neighbours specified");
313 boost::uniform_int<int> pop_idx(0,NP-1);
314 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > p_idx(
m_urng,pop_idx);
326 std::vector<std::vector<population::size_type> > neigh_idx;
328 for (
unsigned int i=0; i < neigh_idx.size();++i) {
329 neigh_idx[i].erase(neigh_idx[i].begin());
330 neigh_idx[i].erase(neigh_idx[i].begin()+m_T, neigh_idx[i].end());
340 std::vector<population::size_type> shuffle(NP);
346 for (
int g = 0; g<m_gen; ++g) {
348 std::random_shuffle(shuffle.begin(), shuffle.end(), p_idx);
354 if(
m_drng()<m_realb || !m_preserve_diversity) type = 1;
357 std::vector<population::size_type> p(2);
358 mating_selection(p,n,type,neigh_idx);
361 for(decision_vector::size_type kk=0;kk<prob.
get_dimension(); ++kk)
368 if(candidate[kk]<lb[kk]){
371 if(candidate[kk]>ub[kk]){
390 unsigned int size, time = 0;
396 pop.set_x(n,candidate);
400 if(type==1) size = neigh_idx[n].size();
402 std::vector<population::size_type> shuffle2(size);
404 std::random_shuffle(shuffle2.begin(), shuffle2.end(), p_idx);
405 for (
unsigned int k=0; k<shuffle2.size(); ++k) {
407 if(type==1) pick = neigh_idx[n][shuffle2[k]];
408 else pick = shuffle2[k];
414 pop.set_x(pick,candidate);
418 if(time>=m_limit && m_preserve_diversity)
break;
423 std::vector<decision_vector> X(NP,candidate);
441 std::ostringstream s;
442 s <<
"gen:" << m_gen <<
' ';
444 switch (m_weight_generation)
446 case RANDOM : s <<
"RANDOM" <<
' ';
450 case GRID : s <<
"GRID" <<
' ';
453 s <<
"neighbours:" << m_T <<
' ';
454 s <<
"realb:" << m_realb <<
' ';
455 s <<
"limit:" << m_limit <<
' ';
456 s <<
"cr:" << m_cr <<
' ';
457 s <<
"f:" << m_f <<
' ';
458 s <<
"preserve diversity:";
459 if (m_preserve_diversity) s <<
"True " ;
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.
Halton sequence projected on a simplex.
std::string human_readable_extra() const
Extra human readable algorithm info.
Weights are generated uniformly at random on the simplex.
fitness_vector cur_f
Current fitness vector.
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
fitness_vector compute_ideal() const
Compute and return the ideal objective vector.
size_type get_dimension() const
Return global dimension.
Weights are generated on a uniform grid layed down on the simplex.
void compute_original_fitness(fitness_vector &, const decision_vector &) const
Computes the original fitness.
Weights are generated on the simplex with low-discrepancy.
weight_generation_type
Mechanism used to generate the weight vectors.
void compute_decomposed_fitness(fitness_vector &, const fitness_vector &) const
Computes the decomposed fitness.
std::vector< double > fitness_vector
Fitness vector type.
const decision_vector & get_ub() const
Upper bounds getter.
container_type::size_type size_type
Population size type.
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.
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.
The Tchebycheff method is used to perform the decomposition.
rng_double m_drng
Random number generator for double-precision floating point values.
base_ptr clone() const
Clone method.
std::vector< fitness_vector > generate_weights(const unsigned int, const unsigned int) const
Weight generation.
std::string get_name() const
Algorithm name.
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
moead(int gen=100, weight_generation_type=GRID, population::size_type=20, double realb=0.9, unsigned int limit=2, double CR=1.0, double F=0.5, double eta_m=20, bool preserve_diversity=true)
Constructor.