30 #include <boost/math/special_functions/binomial.hpp>
31 #include <boost/random/uniform_real.hpp>
32 #include <boost/random/uniform_int.hpp>
33 #include <boost/random/variate_generator.hpp>
35 #include "../exceptions.h"
36 #include "../population.h"
37 #include "../problem/base.h"
38 #include "../archipelago.h"
39 #include "../island.h"
40 #include "../population.h"
41 #include "../topology/fully_connected.h"
42 #include "../topology/custom.h"
43 #include "../topology/watts_strogatz.h"
44 #include "../problem/decompose.h"
45 #include "../util/discrepancy.h"
46 #include "../util/neighbourhood.h"
47 #include "../migration/worst_r_policy.h"
48 #include "../migration/best_s_policy.h"
53 namespace pagmo {
namespace algorithm {
76 m_solver(solver.clone()),
78 m_weight_generation(weight_generation),
82 pagmo_throw(value_error,
"number of generations must be nonnegative");
87 pagmo_throw(value_error,
"non existing weight generation method");
95 m_threads(algo.m_threads),
96 m_method(algo.m_method),
97 m_solver(algo.m_solver->clone()),
99 m_weight_generation(algo.m_weight_generation),
110 void pade::reksum(std::vector<std::vector<double> > &retval,
111 const std::vector<unsigned int>& X,
114 std::vector<double> eggs)
const {
117 if (std::find(X.begin(),X.end(),s) == X.end()) {
121 retval.push_back(eggs);
124 for (
unsigned int i=0; i<X.size(); ++i) {
125 eggs.push_back(X[i]);
126 reksum(retval,X,m-1,s-X[i],eggs);
144 pagmo_throw(value_error,
"To allow weight be generated correctly the number of weights must be strictly larger than the number of objectives");
148 boost::uniform_real<double> uniform(0.0,1.0);
149 boost::variate_generator<boost::lagged_fibonacci607 &, boost::uniform_real<double> > r_dist(
m_drng,uniform);
151 std::vector<fitness_vector> retval;
152 if(m_weight_generation ==
GRID) {
157 }
else if (n_f == 3) {
158 H = floor(0.5 * (sqrt(8*n_w + 1) - 3));
161 while(boost::math::binomial_coefficient<double>(H+n_f-1, n_f-1) <= n_w) {
168 if (fabs(n_w-(boost::math::binomial_coefficient<double>(H+n_f-1, n_f-1))) > 1E-8) {
169 std::ostringstream error_message;
170 error_message <<
"Invalid population size. Select " << boost::math::binomial_coefficient<double>(H+n_f-1, n_f-1)
171 <<
" or " << boost::math::binomial_coefficient<double>(H+1+n_f-1, n_f-1)
173 pagmo_throw(value_error,error_message.str());
177 std::vector<unsigned int> range;
178 for (
unsigned int i=0; i<H+1;++i) {
181 reksum(retval, range, n_f, H);
182 for(
unsigned int i=0; i< retval.size(); ++i) {
183 for(
unsigned int j=0; j< retval[i].size(); ++j) {
189 for(
unsigned int i = 0; i< n_f; ++i) {
194 for(
unsigned int i = n_f; i <n_w; ++i) {
195 retval.push_back(generator());
198 }
else if(m_weight_generation ==
RANDOM) {
199 pagmo::util::discrepancy::project_2_simplex projection(n_f);
200 for (
unsigned int i = 0; i<n_w; ++i) {
202 for(
unsigned int j = 0; j <n_f-1; ++j) {
205 retval.push_back(projection(dummy));
225 pagmo_throw(value_error,
"The problem is not multiobjective, try some other algorithm than PaDE");
229 pagmo_throw(value_error,
"Too many neighbours specified");
238 std::vector<decision_vector> X(NP,dummy);
249 std::vector<std::vector<population::size_type> > indices;
269 std::vector<pagmo::problem::base_ptr> problems_vector;
275 std::vector<population::size_type> shuffle(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);
281 std::random_shuffle(shuffle.begin(), shuffle.end(), p_idx);
285 std::vector<int> assignation_list(NP);
286 std::vector<bool> selected_list(NP,
false);
290 while(selected_list[j]) j++;
293 double minFit = dec_fit[0];
297 if(!selected_list[j]) {
299 if(dec_fit[0] < minFit) {
305 assignation_list[shuffle[i]] = minFitPos;
306 selected_list[minFitPos] =
true;
315 decomposed_pop.push_back(X[assignation_list[i]]);
317 decomposed_pop.push_back(X[assignation_list[indices[i][j]]]);
321 decomposed_pop.push_back(X[j]);
331 for(
unsigned int i = 0; i < NP; ++i) {
334 for(
unsigned int i = 0; i < NP; ++i) {
335 for(
unsigned int j = 1; j <= m_T; ++j) {
344 if(m_threads >= NP) {
348 for(
int g = 0; g < m_gen; ++g) {
357 popnew.push_back(arch.
get_island(i)->get_population().champion().x);
359 std::vector<population::size_type> selected_idx = popnew.get_best_idx(NP);
372 return "Parallel Decomposition (PaDe)";
381 std::ostringstream s;
382 s <<
"gen:" << m_gen <<
' ';
383 s <<
"threads:" << m_threads <<
' ';
384 s <<
"solver:" << m_solver->get_name() <<
' ';
385 s <<
"neighbours:" << m_T <<
' ';
386 s <<
"decomposition:";
397 switch (m_weight_generation)
399 case RANDOM : s <<
"RANDOM" <<
' ';
403 case GRID : s <<
"GRID" <<
' ';
406 s <<
"ref. point" << m_z;
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
std::vector< double > decision_vector
Decision vector type.
Halton sequence projected on a simplex.
Weights are generated on the simplex with low-discrepancy.
fitness_vector cur_f
Current fitness vector.
std::string human_readable_extra() const
Extra human readable algorithm info.
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
size_type get_size() const
Get the size of the archipelago.
void evolve(population &) const
Evolve implementation.
The Boundary Intersection method is used to perform the decomposition.
Worst replacement policy.
"Choose best" migration selection policy.
Parallel Decomposition (PaDe)
void add_edge(int, int, double=1.0)
Add an edge.
base_ptr clone() const
Clone method.
std::vector< fitness_vector > generate_weights(const unsigned int, const unsigned int) const
Generates the weights used in the problem decomposition.
base_island_ptr get_island(const size_type &) const
Island getter.
pade(int gen=10, unsigned int max_parallelism=1, pagmo::problem::decompose::method_type=pagmo::problem::decompose::BI, const pagmo::algorithm::base &=pagmo::algorithm::jde(100), population::size_type=8, weight_generation_type=LOW_DISCREPANCY, const fitness_vector &=std::vector< double >())
Constructor.
Weights are generated on a uniform grid layed down on the simplex.
void push_back(const base_island &)
Add an island to the archipelago.
void set_seeds(unsigned int)
Sets the seed of the random number generators of the archipelago.
void join() const
Wait until evolution on each island has terminated.
Individuals migrate to all the island's neighbours.
std::vector< double > fitness_vector
Fitness vector type.
void evolve_batch(int, unsigned int, bool=true)
Run the evolution for the given number of iterations in batches.
void evolve(int=1)
Run the evolution for the given number of iterations.
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 > > &)
void set_topology(const topology::base &)
Set topology.
Weights are generated uniformly at random on the simplex.
decision_vector cur_x
Current decision vector.
method_type
Mechanism used to perform the problem decomposition.
rng_uint32 m_urng
Random number generator for unsigned integer values.
f_size_type get_f_dimension() const
Return fitness dimension.
The fitness function is the weighted sum of the multiple original fitnesses.
weight_generation_type
Mechanism used to generate the weight vectors.
void push_back()
Push back vertex.
Fully-connected topology.
The Tchebycheff method is used to perform the decomposition.
std::string get_name() const
Algorithm name.
rng_double m_drng
Random number generator for double-precision floating point values.