25 #include <boost/numeric/conversion/cast.hpp>
26 #include <boost/random/uniform_int.hpp>
27 #include <boost/thread/barrier.hpp>
28 #include <boost/tuple/tuple.hpp>
29 #include <boost/tuple/tuple_io.hpp>
30 #include <boost/random/uniform_int.hpp>
31 #include <boost/random/variate_generator.hpp>
40 #include "archipelago.h"
41 #include "algorithm/base.h"
42 #include "base_island.h"
43 #include "exceptions.h"
45 #include "population.h"
46 #include "problem/base.h"
48 #include "topology/base.h"
49 #include "topology/unconnected.h"
54 void archipelago::check_migr_attributes()
const
56 if (m_dist_type < 0 || m_dist_type > 1 ||m_migr_dir < 0 || m_migr_dir > 1) {
57 pagmo_throw(value_error,
"invalid value for migration attribute (destination and/or direction)");
69 m_dist_type(dt),m_migr_dir(md),
72 check_migr_attributes();
85 m_islands_sync_point(),m_topology(),m_dist_type(dt),m_migr_dir(md),
90 check_migr_attributes();
108 m_islands_sync_point(),m_topology(new topology::unconnected()),m_dist_type(dt),m_migr_dir(md),
111 check_migr_attributes();
112 for (
size_type i = 0; i < boost::numeric_cast<size_type>(n); ++i) {
130 for (
size_type i = 0; i < a.m_container.size(); ++i) {
131 m_container.push_back(a.m_container[i]->clone());
132 m_container.back()->m_archi =
this;
134 m_topology = a.m_topology->clone();
135 m_dist_type = a.m_dist_type;
136 m_migr_dir = a.m_migr_dir;
137 m_migr_map = a.m_migr_map;
140 m_migr_hist = a.m_migr_hist;
158 for (
size_type i = 0; i < a.m_container.size(); ++i) {
159 m_container.push_back(a.m_container[i]->clone());
160 m_container.back()->m_archi =
this;
162 m_topology = a.m_topology->clone();
163 m_dist_type = a.m_dist_type;
164 m_migr_dir = a.m_migr_dir;
165 m_migr_map = a.m_migr_map;
168 m_migr_hist = a.m_migr_hist;
180 pagmo_assert(destruction_checks());
189 const const_iterator it_f = m_container.end();
190 for (const_iterator it = m_container.begin(); it != it_f; ++it) {
201 const_iterator it = m_container.begin();
202 for (; it != m_container.end(); ++it) {
203 if (&(*(*it)) == &isl) {
207 return std::distance(m_container.begin(),it);
223 pagmo_throw(value_error,
"cannot push_back() incompatible island");
225 m_container.push_back(isl.
clone());
227 m_container.back()->m_archi =
this;
229 m_topology->push_back();
244 if (idx >= m_container.size()) {
245 pagmo_throw(index_error,
"invalid island index");
247 m_container[idx]->set_algorithm(a);
257 return m_container.size();
272 std::ostringstream oss;
273 oss <<
"-= Archipelago =-\n\n";
274 oss <<
"Number of islands:\t" << m_container.size() <<
"\n\n";
275 oss << m_topology->human_readable_terse() <<
'\n';
276 for (
size_type i = 0; i < m_container.size(); ++i) {
277 oss <<
"Island index: #" << i <<
"\n\n";
278 oss << m_container[i]->human_readable_terse() <<
'\n';
290 return m_topology->clone();
305 if (m_container.size() < boost::numeric_cast<
size_type>(t->get_number_of_vertices())) {
306 pagmo_throw(value_error,
"invalid topology, too many vertices");
309 for (
size_type i = boost::numeric_cast<size_type>(t->get_number_of_vertices());
310 i < m_container.size(); ++i)
357 if (m_container.size() && (!isl.
m_pop.problem().
is_compatible(m_container[0]->m_pop.problem()))) {
365 void archipelago::reset_barrier(
const size_type &size)
368 m_islands_sync_point.reset(
new boost::barrier(boost::numeric_cast<unsigned int>(size)));
373 bool archipelago::destruction_checks()
const
376 if (m_container[i].use_count() != 1 || m_container[i]->m_archi !=
this) {
384 void archipelago::build_immigrants_vector(std::vector<std::pair<population::size_type, individual_type > > &immigrants,
const base_island &src_isl,
385 base_island &dest_isl,
const std::vector<individual_type> &candidates)
const
387 for (std::vector<individual_type>::const_iterator ind_it = candidates.begin();
388 ind_it != candidates.end(); ++ind_it)
392 if (!dest_isl.m_pop.problem().verify_x(ind_it->cur_x)) {
395 immigrants.push_back(std::make_pair(locate_island(src_isl),*ind_it));
400 void archipelago::reevaluate_immigrants(std::vector<std::pair<population::size_type, individual_type> > &immigrants,
const base_island &isl)
const
403 tmp.
cur_v.resize(isl.m_pop.problem().get_dimension());
404 tmp.cur_f.resize(isl.m_pop.problem().get_f_dimension());
405 tmp.cur_c.resize(isl.m_pop.problem().get_c_dimension());
406 for (std::vector<std::pair<population::size_type, individual_type> >::iterator ind_it = immigrants.begin(); ind_it != immigrants.end(); ++ind_it) {
407 tmp.cur_x = (*ind_it).second.cur_x;
408 isl.m_pop.problem().objfun(tmp.cur_f,tmp.cur_x);
409 isl.m_pop.problem().compute_constraints(tmp.cur_c,tmp.cur_x);
413 tmp.best_x = tmp.cur_x;
414 tmp.best_f = tmp.cur_f;
415 tmp.best_c = tmp.cur_c;
416 (*ind_it).second = tmp;
440 pagmo_assert(isl.
m_archi ==
this);
442 pagmo_assert(m_container.size());
444 const size_type isl_idx = locate_island(isl);
445 pagmo_assert(isl_idx < m_container.size());
447 std::vector<std::pair<population::size_type, individual_type> > immigrants;
448 switch (m_migr_dir) {
451 lock_type lock(m_migr_mutex);
456 for (boost::unordered_map<
size_type,std::vector<individual_type> >::iterator it = m_migr_map[isl_idx].begin();
457 it != m_migr_map[isl_idx].end(); ++it)
459 pagmo_assert(it->first < m_container.size());
460 build_immigrants_vector(immigrants,*m_container[it->first],isl,it->second);
463 m_migr_map.erase(isl_idx);
470 const std::vector<topology::base::vertices_size_type> inv_adj_islands(m_topology->get_v_inv_adjacent_vertices(boost::numeric_cast<topology::base::vertices_size_type>(isl_idx)));
472 if (inv_adj_islands.size()) {
473 switch (m_dist_type) {
476 lock_type lock(m_migr_mutex);
478 boost::uniform_int<std::vector<topology::base::vertices_size_type>::size_type> u_int(0,inv_adj_islands.size() - 1);
479 const size_type rn_isl_idx = boost::numeric_cast<
size_type>(inv_adj_islands[u_int(m_urng)]);
482 pagmo_assert(m_migr_map[rn_isl_idx].size() <= 1);
484 double next_rng = m_drng();
485 double migr_prob = m_topology->get_weight(rn_isl_idx, isl_idx);
486 if (next_rng < migr_prob) {
487 build_immigrants_vector(immigrants,*m_container[rn_isl_idx],isl,m_migr_map[rn_isl_idx][rn_isl_idx]);
493 lock_type lock(m_migr_mutex);
495 for (std::vector<topology::base::vertices_size_type>::size_type i = 0; i < inv_adj_islands.size(); ++i) {
497 pagmo_assert(m_migr_map[src_isl_idx].size() <= 1);
498 double next_rng = m_drng();
499 double migr_prob = m_topology->get_weight(src_isl_idx, isl_idx);
500 if (next_rng < migr_prob) {
501 build_immigrants_vector(immigrants,*m_container[src_isl_idx],isl,m_migr_map[src_isl_idx][src_isl_idx]);
509 if (immigrants.size()) {
513 reevaluate_immigrants(immigrants,isl);
515 std::vector<std::pair<population::size_type, size_type> > rec_history;
516 rec_history = isl.accept_immigrants(immigrants);
517 lock_type lock(m_migr_mutex);
519 for (
size_t i =0; i< rec_history.size(); ++i) {
520 m_migr_hist.push_back( boost::make_tuple(
521 rec_history[i].first,
522 rec_history[i].second,
532 void archipelago::post_evolution(base_island &isl)
535 pagmo_assert(isl.m_archi ==
this);
537 pagmo_assert(m_container.size());
539 const size_type isl_idx = locate_island(isl);
540 pagmo_assert(isl_idx < m_container.size());
542 std::vector<individual_type> emigrants;
543 switch (m_migr_dir) {
547 const std::vector<topology::base::vertices_size_type> adj_islands(m_topology->get_v_adjacent_vertices(boost::numeric_cast<topology::base::vertices_size_type>(isl_idx)));
548 if (adj_islands.size()) {
549 emigrants = isl.get_emigrants();
551 if (emigrants.size()) {
556 lock_type lock(m_migr_mutex);
558 boost::uniform_int<std::vector<topology::base::vertices_size_type>::size_type> u_int(0,adj_islands.size() - 1);
559 const size_type chosen_adj = boost::numeric_cast<
size_type>(adj_islands[u_int(m_urng)]);
560 double next_rng = m_drng();
561 double migr_prob = m_topology->get_weight(isl_idx, chosen_adj);
562 if (next_rng < migr_prob) {
563 m_migr_map[chosen_adj][isl_idx].insert(m_migr_map[chosen_adj][isl_idx].end(),emigrants.begin(),emigrants.end());
569 lock_type lock(m_migr_mutex);
571 for (std::vector<topology::base::vertices_size_type>::size_type i = 0; i < adj_islands.size(); ++i) {
572 double next_rng = m_drng();
573 double migr_prob = m_topology->get_weight(isl_idx, adj_islands[i]);
574 if (next_rng < migr_prob) {
575 m_migr_map[boost::numeric_cast<
size_type>(adj_islands[i])][isl_idx]
576 .insert(m_migr_map[boost::numeric_cast<size_type>(adj_islands[i])][isl_idx].end(),
577 emigrants.begin(),emigrants.end());
589 emigrants = isl.get_emigrants();
590 lock_type lock(m_migr_mutex);
591 pagmo_assert(m_migr_map[isl_idx].size() <= 1);
592 m_migr_map[isl_idx][isl_idx].swap(emigrants);
606 const iterator it_f = m_container.end();
608 reset_barrier(m_container.size());
609 for (iterator it = m_container.begin(); it != it_f; ++it) {
628 container_type::size_type arch_size = this->
get_size();
630 std::vector<population::size_type> pop_order(arch_size);
637 boost::uniform_int<int> pop_idx(0,arch_size-1);
638 boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > p_idx(m_urng,pop_idx);
639 std::random_shuffle(pop_order.begin(), pop_order.end(), p_idx);
642 for(
size_type p = 0; p < arch_size/b + 1; ++p) {
643 if(p == arch_size/b) {
644 reset_barrier(arch_size - p*b);
648 for(
size_type i=0; i<b && p*b+i < arch_size; ++i) {
649 m_container[pop_order[p*b+i]]->evolve(n);
651 for(
size_type i=0; i<b && p*b+i < arch_size; ++i) {
652 m_container[pop_order[p*b+i]]->join();
666 const iterator it_f = m_container.end();
667 reset_barrier(m_container.size());
668 for (iterator it = m_container.begin(); it != it_f; ++it) {
679 const const_iterator it_f = m_container.end();
680 for (const_iterator it = m_container.begin(); it != it_f; ++it) {
694 const iterator it_f = m_container.end();
695 for (iterator it = m_container.begin(); it != it_f; ++it) {
711 if (idx >= m_container.size()) {
712 pagmo_throw(index_error,
"invalid island index");
731 if (idx >= m_container.size()) {
732 pagmo_throw(index_error,
"invalid island index");
735 pagmo_throw(value_error,
"cannot set incompatible island");
737 m_container[idx] = isl.
clone();
739 m_container[idx]->m_archi =
this;
749 std::vector<base_island_ptr> retval;
751 retval.push_back(m_container[i]->clone());
753 retval.back()->m_archi = 0;
760 void archipelago::sync_island_start()
const
762 m_islands_sync_point->wait();
773 std::ostringstream oss;
774 for (migr_hist_type::const_iterator it = m_migr_hist.begin(); it != m_migr_hist.end(); ++it) {
775 oss <<
"(" << (*it).get<0>()
776 <<
"," << (*it).get<1>()
777 <<
"," << (*it).get<2>() <<
")"
virtual base_island_ptr clone() const =0
Clone method.
migration_direction
Migration direction.
Generic thread-safe generator of pseudo-random number generators.
container_type::size_type size_type
Archipelago size type.
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base topology.
std::ostream & operator<<(std::ostream &s, const archipelago &a)
Overload stream operator for pagmo::archipelago.
bool busy() const
Query the status of the archipelago.
This rng returns an unsigned integer in the [0,2**32-1] range.
topology::base_ptr get_topology() const
Return a copy of the topology.
~archipelago()
Destructor.
virtual base_ptr clone() const =0
Clone method.
size_type get_size() const
Get the size of the archipelago.
distribution_type
Distribution type for migrating individuals.
bool check_island(const base_island &) const
Check whether an island is compatible with the archipelago.
Immigrants flow is initiated by the destination island.
void evolve_t(int)
Run the evolution for a minimum amount of time.
base_island_ptr get_island(const size_type &) const
Island getter.
archipelago & operator=(const archipelago &)
Assignment operator.
std::vector< base_island_ptr > get_islands() const
Get vector of islands in the archipelago.
virtual void join() const
Join island.
void push_back(const base_island &)
Add an island to the archipelago.
population::individual_type individual_type
Individual type.
void set_seeds(unsigned int)
Sets the seed of the random number generators of the archipelago.
void clear_migr_history()
Clears the archipelago migration history.
void join() const
Wait until evolution on each island has terminated.
std::string human_readable() const
Return human readable representation of the archipelago.
Individuals migrate to all the island's neighbours.
bool is_compatible(const base &) const
Compatibility operator.
void evolve_batch(int, unsigned int, bool=true)
Run the evolution for the given number of iterations in batches.
std::string dump_migr_history() const
Dumps the archipelago migration history.
archipelago * m_archi
Pointer that, if not null, points to the archipelago containing the island.
void set_island(const size_type &, const base_island &)
Island setter.
decision_vector cur_v
Current velocity vector.
boost::shared_ptr< base_island > base_island_ptr
Alias for the shared pointer to a pagmo::base_island.
void evolve(int=1)
Run the evolution for the given number of iterations.
population m_pop
Population.
distribution_type get_distribution_type() const
Return a copy of the distribution type.
container_type::size_type size_type
Population size type.
void set_topology(const topology::base &)
Set topology.
Individuals migrate to one of the island's neighbours.
Immigrants flow is initiated by the source island.
archipelago(distribution_type=point_to_point, migration_direction=destination)
Default constructor.
void interrupt()
Interrupt ongoing evolution.
void set_algorithm(const size_type &, const algorithm::base &)
Set island algorithm.
void set_distribution_type(const distribution_type &)
Set distribution type.
This rng returns a double in the [0,1[ range.