28 #include <boost/numeric/conversion/cast.hpp>
29 #include <boost/random/uniform_int.hpp>
30 #include <boost/random/uniform_real.hpp>
37 #include "problem/base.h"
38 #include "problem/base_stochastic.h"
39 #include "exceptions.h"
40 #include "population.h"
43 #include "util/racing.h"
44 #include "util/race_pop.h"
46 #include "algorithm/base.h"
47 #include "problem/con2uncon.h"
72 pagmo_throw(value_error,
"number of individuals cannot be negative");
76 const fitness_vector::size_type f_size = m_prob->get_f_dimension();
77 const constraint_vector::size_type c_size = m_prob->get_c_dimension();
78 const decision_vector::size_type p_size = m_prob->get_dimension();
82 m_dom_list.push_back(std::vector<size_type>());
83 m_dom_count.push_back(0);
85 m_container.back().cur_x.resize(p_size);
86 m_container.back().cur_v.resize(p_size);
87 m_container.back().cur_c.resize(c_size);
88 m_container.back().cur_f.resize(f_size);
89 m_container.back().best_x.resize(p_size);
90 m_container.back().best_c.resize(c_size);
91 m_container.back().best_f.resize(f_size);
104 m_champion(p.m_champion), m_pareto_rank(p.m_pareto_rank), m_crowding_d(p.m_crowding_d),m_drng(p.m_drng),m_urng(p.m_urng)
118 pagmo_assert(m_prob && p.m_prob);
120 m_prob = p.m_prob->clone();
121 m_container = p.m_container;
122 m_dom_list = p.m_dom_list;
123 m_dom_count = p.m_dom_count;
124 m_champion = p.m_champion;
125 m_pareto_rank = p.m_pareto_rank;
126 m_crowding_d = p.m_crowding_d;
134 void population::update_dom(
const size_type &n)
142 const size_type size = m_container.size();
143 pagmo_assert(m_dom_list.size() == size && m_dom_count.size() == size && n < size);
146 for (
size_type i = 0; i < m_dom_list[n].size(); ++i) {
147 m_dom_count[ m_dom_list[n][i] ]--;
151 m_dom_list[n].clear();
158 if (m_prob->compare_fc(m_container[i].best_f,m_container[i].best_c,m_container[n].best_f,m_container[n].best_c)) {
163 if (std::find(m_dom_list[i].begin(),m_dom_list[i].end(),n) == m_dom_list[i].end()) {
164 m_dom_list[i].push_back(n);
168 std::vector<size_type>::iterator it = std::find(m_dom_list[i].begin(),m_dom_list[i].end(),n);
169 if (it != m_dom_list[i].end()) {
170 m_dom_list[i].erase(it);
174 if (m_prob->compare_fc(m_container[n].best_f,m_container[n].best_c,m_container[i].best_f,m_container[i].best_c)) {
175 m_dom_list[n].push_back(i);
183 void population::init_velocity(
const size_type &idx)
185 const decision_vector::size_type p_size = m_prob->get_dimension();
187 for (decision_vector::size_type j = 0; j < p_size; ++j) {
190 width = (m_prob->get_ub()[j] - m_prob->get_lb()[j]) / 2;
191 m_container[idx].cur_v[j] = boost::uniform_real<double>(-width,width)(m_drng);
199 pagmo_throw(zero_division_error,
"Population has no individuals, no mean velocity can be computed.");
202 const decision_vector::size_type p_size = m_prob->get_dimension();
206 for (decision_vector::size_type j = 0; j < p_size; ++j) {
207 tmp += m_container[i].cur_v[j]*m_container[i].cur_v[j];
209 ret += std::sqrt(tmp);
211 return (ret / pop_size);
239 pagmo_throw(index_error,
"invalid index");
241 const decision_vector::size_type p_size = m_prob->get_dimension(), i_size = m_prob->get_i_dimension();
243 for (decision_vector::size_type j = 0; j < p_size - i_size; ++j) {
244 m_container[idx].cur_x[j] = boost::uniform_real<double>(m_prob->get_lb()[j],m_prob->get_ub()[j])(m_drng);
247 for (decision_vector::size_type j = p_size - i_size; j < p_size; ++j) {
248 m_container[idx].cur_x[j] = boost::uniform_int<int>(m_prob->get_lb()[j],m_prob->get_ub()[j])(m_urng);
253 m_prob->compute_constraints(m_container[idx].cur_c,m_container[idx].cur_x);
255 m_prob->objfun(m_container[idx].cur_f,m_container[idx].cur_x);
257 m_container[idx].best_x = m_container[idx].cur_x;
258 m_container[idx].best_f = m_container[idx].cur_f;
259 m_container[idx].best_c = m_container[idx].cur_c;
261 update_champion(idx);
280 pagmo_throw(index_error,
"invalid index");
282 return m_container[idx];
299 pagmo_throw(index_error,
"invalid index");
301 return m_dom_list[idx];
317 pagmo_throw(index_error,
"invalid index");
319 return m_dom_count[idx];
336 if (idx >= m_pareto_rank.size()) {
337 pagmo_throw(index_error,
"invalid index");
339 return m_pareto_rank[idx];
358 if (idx >= m_crowding_d.size()) {
359 pagmo_throw(index_error,
"invalid index");
361 return m_crowding_d[idx];
366 struct one_dim_fit_comp {
367 one_dim_fit_comp(
const population &pop, fitness_vector::size_type dim):m_pop(pop), m_dim(dim) {};
370 return m_pop.get_individual(idx1).cur_f[m_dim] < m_pop.get_individual(idx2).cur_f[m_dim];
372 const population& m_pop;
373 fitness_vector::size_type m_dim;
386 m_pareto_rank.resize(size());
387 m_crowding_d.resize(size());
390 std::fill(m_pareto_rank.begin(), m_pareto_rank.end(), 0);
391 std::fill(m_crowding_d.begin(), m_crowding_d.end(), 0);
394 std::vector<population::size_type> F,S;
397 std::vector<population::size_type> dom_count_copy(m_dom_count);
401 if (m_dom_count[idx] == 0) {
406 unsigned int irank = 1;
409 while (F.size()!=0) {
411 population::update_crowding_d(F);
416 dom_count_copy[m_dom_list[F[i]][j]]--;
417 if (dom_count_copy[m_dom_list[F[i]][j]] == 0){
418 S.push_back(m_dom_list[F[i]][j]);
419 m_pareto_rank[m_dom_list[F[i]][j]] = irank;
440 void population::update_crowding_d(std::vector<population::size_type> I)
const {
445 one_dim_fit_comp funct(*
this,0);
448 for (fitness_vector::size_type i = 0; i < problem().
get_f_dimension(); ++i) {
451 std::sort(I.begin(),I.end(), funct );
453 m_crowding_d[I[0]] = std::numeric_limits<double>::max();
454 m_crowding_d[I[lastidx]] = std::numeric_limits<double>::max();
459 m_crowding_d[I[j]] += 0.0;
476 std::vector<std::vector<population::size_type> > retval;
482 if (m_pareto_rank[idx] >= retval.size()) {
483 retval.resize(m_pareto_rank[idx] + 1);
485 retval[m_pareto_rank[idx]].push_back(idx);
502 fitness_vector ideal(problem().get_f_dimension(),std::numeric_limits<double>::max());
504 if (m_pareto_rank[idx] == 0) {
505 for(fitness_vector::size_type i = 0; i < ideal.size(); ++i) {
506 if (m_container[idx].cur_f[i] < ideal[i]) {
507 ideal[i] = m_container[idx].cur_f[i];
528 if (m_pareto_rank[idx] == 0) {
529 for(fitness_vector::size_type i = 0; i < nadir.size(); ++i) {
530 if (m_container[idx].cur_f[i] > nadir[i]) {
531 nadir[i] = m_container[idx].cur_f[i];
552 population::crowded_comparison_operator::crowded_comparison_operator(
const population &pop):m_pop(pop)
554 if (m_pop.size() < 2) {
555 pagmo_throw(value_error,
"the population seems to contain one or zero individuals, comparisons between individuals do not make sense");
557 if (m_pop.problem().get_f_dimension() < 2) {
558 pagmo_throw(value_error,
"The crowded comparison operator can only operate on multi-objective problems.");
576 bool population::crowded_comparison_operator::operator()(
const individual_type &i1,
const individual_type &i2)
const
578 if (!(&i1 >= &m_pop.m_container.front() && &i1 <= &m_pop.m_container.back())) {
579 pagmo_throw(value_error,
"operator called on individuals that do not belong to the population");
582 if (!(&i2 >= &m_pop.m_container.front() && &i2 <= &m_pop.m_container.back())) {
583 pagmo_throw(value_error,
"operator called on individuals that do not belong to the population");
585 const size_type idx1 = &i1 - &m_pop.m_container.front(), idx2 = &i2 - &m_pop.m_container.front();
586 if (m_pop.m_pareto_rank[idx1] == m_pop.m_pareto_rank[idx2]) {
587 return (m_pop.m_crowding_d[idx1] > m_pop.m_crowding_d[idx2]);
590 return (m_pop.m_pareto_rank[idx1] < m_pop.m_pareto_rank[idx2]);
608 bool population::crowded_comparison_operator::operator()(
const size_type &idx1,
const size_type &idx2)
const
610 if (idx1 >= m_pop.size() || idx2 >= m_pop.size()) {
611 pagmo_throw(index_error,
"operator called on out of bound indexes");
614 if (m_pop.m_pareto_rank[idx1] == m_pop.m_pareto_rank[idx2]) {
615 return (m_pop.m_crowding_d[idx1] > m_pop.m_crowding_d[idx2]);
618 return (m_pop.m_pareto_rank[idx1] < m_pop.m_pareto_rank[idx2]);
633 population::trivial_comparison_operator::trivial_comparison_operator(
const population &pop):m_pop(pop) {}
644 bool population::trivial_comparison_operator::operator()(
const individual_type &i1,
const individual_type &i2)
const
646 if (!(&i1 >= &m_pop.m_container.front() && &i1 <= &m_pop.m_container.back())) {
647 pagmo_throw(value_error,
"operator called on individuals that do not belong to the population");
650 if (!(&i2 >= &m_pop.m_container.front() && &i2 <= &m_pop.m_container.back())) {
651 pagmo_throw(value_error,
"operator called on individuals that do not belong to population");
653 const size_type idx1 = &i1 - &m_pop.m_container.front(), idx2 = &i2 - &m_pop.m_container.front();
654 return m_pop.problem().compare_fc(m_pop.get_individual(idx1).cur_f, m_pop.get_individual(idx1).cur_c, m_pop.get_individual(idx2).cur_f,m_pop.get_individual(idx2).cur_c);
666 bool population::trivial_comparison_operator::operator()(
const size_type &idx1,
const size_type &idx2)
const
668 if (idx1 >= m_pop.size() || idx2 >= m_pop.size()) {
669 pagmo_throw(index_error,
"operator called on out of bound indexes");
671 return m_pop.problem().compare_fc(m_pop.get_individual(idx1).cur_f, m_pop.get_individual(idx1).cur_c, m_pop.get_individual(idx2).cur_f,m_pop.get_individual(idx2).cur_c);
695 pagmo_throw(value_error,
"empty population, cannot compute position of worst individual");
697 container_type::const_iterator it;
698 if (m_prob->get_f_dimension() == 1) {
699 it = std::max_element(m_container.begin(),m_container.end(),trivial_comparison_operator(*
this));
703 it = std::max_element(m_container.begin(),m_container.end(),crowded_comparison_operator(*
this));
705 return boost::numeric_cast<
size_type>(std::distance(m_container.begin(),it));
728 pagmo_throw(value_error,
"empty population, cannot compute position of best individual");
730 container_type::const_iterator it;
731 if (m_prob->get_f_dimension() == 1) {
732 it = std::min_element(m_container.begin(),m_container.end(),trivial_comparison_operator(*
this));
736 it = std::min_element(m_container.begin(),m_container.end(),crowded_comparison_operator(*
this));
737 }
return boost::numeric_cast<
size_type>(std::distance(m_container.begin(),it));
761 pagmo_throw(value_error,
"empty population, cannot compute position of best individual");
764 pagmo_throw(value_error,
"Best N individuals requested, but population has size smaller than N");
766 std::vector<population::size_type> retval;
767 retval.reserve(size());
771 if (m_prob->get_f_dimension() == 1) {
772 std::sort(retval.begin(),retval.end(),trivial_comparison_operator(*
this));
776 std::sort(retval.begin(),retval.end(),crowded_comparison_operator(*
this));
797 pagmo_throw(index_error,
"invalid individual position");
804 if(m_prob->feasibility_c(current_c)) {
812 pop_repair.push_back(current_x);
814 repair_algo->evolve(pop_repair);
816 this->set_x(idx,pop_repair.champion().x);
831 std::string population::human_readable_terse()
const
833 std::ostringstream oss;
834 oss << (*m_prob) <<
'\n';
835 oss <<
"Number of individuals: " << size() <<
'\n';
848 std::string population::human_readable()
const
850 std::ostringstream oss;
851 oss << human_readable_terse();
853 oss <<
"\nList of individuals:\n";
855 oss <<
'#' << i <<
":\n";
856 oss << m_container[i] <<
"\tDominates:\t\t\t" << m_dom_list[i] <<
'\n';
857 oss <<
"\tIs dominated by:\t\t" << m_dom_count[i] <<
"\tindividuals" <<
'\n';
860 if (m_champion.
x.size()) {
861 oss <<
"Champion:\n";
862 oss << m_champion <<
'\n';
864 pagmo_assert(!size());
865 oss <<
"No champion yet.\n";
871 void population::update_champion(
const size_type &idx)
873 pagmo_assert(idx < m_container.size());
874 if (!m_champion.
x.size() || m_prob->compare_fc(m_container[idx].best_f,m_container[idx].best_c,m_champion.
f,m_champion.
c)) {
875 m_champion.
x = m_container[idx].best_x;
876 m_champion.
f = m_container[idx].best_f;
877 m_champion.
c = m_container[idx].best_c;
891 pagmo_throw(index_error,
"invalid individual position");
893 if (!m_prob->verify_x(x)) {
894 pagmo_throw(value_error,
"decision vector is not compatible with problem");
898 m_container[idx].cur_x = x;
900 m_prob->objfun(m_container[idx].cur_f,x);
902 m_prob->compute_constraints(m_container[idx].cur_c,x);
907 pagmo_assert((!m_container[idx].best_x.size() && !m_container[idx].best_f.size()) ||
908 (m_container[idx].best_x.size() && m_container[idx].best_f.size()));
909 if (!m_container[idx].best_x.size() ||
910 m_prob->compare_fc(m_container[idx].cur_f,m_container[idx].cur_c,m_container[idx].best_f,m_container[idx].best_c))
912 m_container[idx].best_x = m_container[idx].cur_x;
913 m_container[idx].best_f = m_container[idx].cur_f;
914 m_container[idx].best_c = m_container[idx].cur_c;
917 update_champion(idx);
934 pagmo_assert(m_dom_list.size() == size() && m_dom_count.size() == size() && idx < size());
937 pagmo_throw(index_error,
"invalid individual position");
940 m_dom_count[m_dom_list[idx][i]]--;
942 m_container.erase(m_container.begin() + idx);
943 m_dom_count.erase(m_dom_count.begin() + idx);
944 m_dom_list.erase(m_dom_list.begin() + idx);
948 if (m_dom_list[i][j] == idx) {
949 m_dom_list[i].erase(m_dom_list[i].begin()+j);
951 if (m_dom_list[i].size() > j) {
953 if (m_dom_list[i][j] > idx) m_dom_list[i][j]--;
956 else if (m_dom_list[i][j] > idx) m_dom_list[i][j]--;
970 if (!m_prob->verify_x(x)) {
971 pagmo_throw(value_error,
"decision vector is not compatible with problem");
975 const fitness_vector::size_type f_size = m_prob->get_f_dimension();
976 const constraint_vector::size_type c_size = m_prob->get_c_dimension();
977 const decision_vector::size_type p_size = m_prob->get_dimension();
979 m_container.push_back(individual_type());
980 m_dom_list.push_back(std::vector<size_type>());
981 m_dom_count.push_back(0);
983 m_container.back().cur_x.resize(p_size);
984 m_container.back().cur_v.resize(p_size);
985 m_container.back().cur_c.resize(c_size);
986 m_container.back().cur_f.resize(f_size);
990 set_x(m_container.size() - 1,x);
992 init_velocity(m_container.size() - 1);
1002 void population::set_v(
const size_type &idx,
const decision_vector &v)
1004 if (idx >= size()) {
1005 pagmo_throw(index_error,
"invalid individual position");
1008 pagmo_throw(value_error,
"velocity vector is not compatible with problem");
1011 m_container[idx].cur_v = v;
1018 const problem::base &population::problem()
const
1027 const population::champion_type &population::champion()
const
1029 if (!m_champion.
x.size()) {
1030 pagmo_assert(!size());
1031 pagmo_throw(value_error,
"champion has not been determined yet");
1042 return m_container.size();
1050 void population::clear()
1052 m_container.clear();
1054 m_dom_count.clear();
1055 m_crowding_d.clear();
1056 m_pareto_rank.clear();
1057 m_champion = champion_type();
1066 return m_container.begin();
1075 return m_container.end();
1096 std::pair<std::vector<population::size_type>,
unsigned int> population::race(
const size_type n_final,
const unsigned int min_trials,
const unsigned int max_count,
double delta,
const std::vector<size_type>& active_set,
const bool race_best,
const bool screen_output)
const
1098 unsigned int seed = m_urng();
1099 util::racing::race_pop m_race_pop(*
this, seed);
1115 for (
size_type i = 0; i < m_container.size(); ++i) {
1116 if (m_prob->compare_fc(ind.best_f,ind.best_c,
1117 m_container[i].best_f,m_container[i].best_c))
1135 std::ostream &
operator<<(std::ostream &s,
const population &pop)
1137 s << pop.human_readable();
1150 std::ostream &
operator<<(std::ostream &s,
const population::individual_type &ind)
1152 s << ind.human_readable();
1165 std::ostream &
operator<<(std::ostream &s,
const population::champion_type &champ)
1167 s << champ.human_readable();
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
size_type get_domination_count(const size_type &) const
Get domination count.
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base problem.
population & operator=(const population &)
Assignment operator.
std::vector< double > decision_vector
Decision vector type.
The sum of the constraint violation is used as objective function of the transformed problem...
fitness_vector cur_f
Current fitness vector.
std::ostream & operator<<(std::ostream &s, const archipelago &a)
Overload stream operator for pagmo::archipelago.
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.
Individuals stored in the population.
fitness_vector compute_ideal() const
Compute and return the ideal objective vector.
population(const problem::base &, int=0, const boost::uint32_t &seed=getSeed())
Constructor from problem::base and number of individuals.
Fixed number of function evaluations.
size_type get_dimension() const
Return global dimension.
decision_vector x
Decision vector.
fitness_vector f
Fitness vector.
const std::vector< size_type > & get_domination_list(const size_type &) const
Get domination list.
std::vector< double > fitness_vector
Fitness vector type.
double get_crowding_d(const size_type &) const
Get Crowding Distance.
std::vector< double > constraint_vector
Constraint vector type.
container_type::const_iterator const_iterator
Const iterator.
constraint_vector c
Constraint vector.
container_type::size_type size_type
Population size type.
double mean_velocity() const
Computes the mean curent velocity of all individuals in the population.
fitness_vector compute_nadir() const
Compute and return the nadir objective vector.
size_type get_pareto_rank(const size_type &) const
Get Pareto rank.
f_size_type get_f_dimension() const
Return fitness dimension.
void reinit()
Re-initialise all individuals.
std::vector< std::vector< size_type > > compute_pareto_fronts() const
Computes and returns the population Pareto fronts.