1 /* Copyright 2017-2021 PaGMO development team 2 3 This file is part of the PaGMO library. 4 5 The PaGMO library is free software; you can redistribute it and/or modify 6 it under the terms of either: 7 8 * the GNU Lesser General Public License as published by the Free 9 Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 or 13 14 * the GNU General Public License as published by the Free Software 15 Foundation; either version 3 of the License, or (at your option) any 16 later version. 17 18 or both in parallel, as here. 19 20 The PaGMO library is distributed in the hope that it will be useful, but 21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 23 for more details. 24 25 You should have received copies of the GNU General Public License and the 26 GNU Lesser General Public License along with the PaGMO library. If not, 27 see https://www.gnu.org/licenses/. */ 28 29 #ifndef PAGMO_POPULATION_HPP 30 #define PAGMO_POPULATION_HPP 31 32 #include <cassert> 33 #include <iostream> 34 #include <string> 35 #include <type_traits> 36 #include <utility> 37 #include <vector> 38 39 #include <pagmo/bfe.hpp> 40 #include <pagmo/detail/island_fwd.hpp> 41 #include <pagmo/detail/support_xeus_cling.hpp> 42 #include <pagmo/detail/visibility.hpp> 43 #include <pagmo/problem.hpp> 44 #include <pagmo/rng.hpp> 45 #include <pagmo/s11n.hpp> 46 #include <pagmo/type_traits.hpp> 47 #include <pagmo/types.hpp> 48 49 namespace pagmo 50 { 51 /// Population class. 52 /** 53 * \image html pop_no_text.png 54 * 55 * This class represents a population of individuals, i.e., potential 56 * candidate solutions to a given problem. In pagmo an 57 * individual is determined by: 58 * - a unique ID used to track it across generations and migrations, 59 * - a chromosome (a decision vector), 60 * - the fitness of the chromosome as evaluated by a pagmo::problem, 61 * and thus including objectives, equality constraints and inequality 62 * constraints if present. 63 * 64 * A special mechanism is implemented to track the best individual that has ever 65 * been part of the population. Such an individual is called *champion* and its 66 * decision vector and fitness vector are automatically kept updated. The *champion* is 67 * not necessarily an individual currently in the population. The *champion* is 68 * only defined and accessible via the population interface if the pagmo::problem 69 * currently contained in the pagmo::population is single objective. 70 * 71 * \verbatim embed:rst:leading-asterisk 72 * .. warning:: 73 * 74 * A moved-from :cpp:class:`pagmo::population` is destructible and assignable. Any other operation will result 75 * in undefined behaviour. 76 * 77 * \endverbatim 78 */ 79 class PAGMO_DLL_PUBLIC population 80 { 81 // Make friends with island for direct 82 // access to the population's members during 83 // evolution. 84 friend class PAGMO_DLL_PUBLIC island; 85 86 public: 87 /// The size type of the population. 88 typedef pop_size_t size_type; 89 // Default constructor 90 population(); 91 92 private: 93 void prob_ctor_impl(size_type); 94 // Enable the generic ctor only if T is not a population (after removing 95 // const/reference qualifiers). 96 template <typename T> 97 using generic_ctor_enabler 98 = enable_if_t<detail::conjunction<detail::negation<std::is_same<population, uncvref_t<T>>>, 99 std::is_constructible<problem, T &&>>::value, 100 int>; 101 102 public: 103 /// Constructor from a problem. 104 /** 105 * \verbatim embed:rst:leading-asterisk 106 * .. note:: 107 * 108 * This constructor is enabled only if, after the removal of cv/reference qualifiers, 109 * ``T`` is not :cpp:class:`pagmo::population`, and if :cpp:class:`pagmo::problem` is constructible from ``T``. 110 * 111 * \endverbatim 112 * 113 * Constructs a population with \p pop_size individuals associated 114 * to the problem \p x and setting the population random seed 115 * to \p seed. The input problem \p x can be either a pagmo::problem or a user-defined problem 116 * (UDP). 117 * 118 * @param x the problem the population refers to. 119 * @param pop_size population size (i.e. number of individuals therein). 120 * @param seed seed of the random number generator used, for example, to 121 * create new random individuals within the bounds. 122 * 123 * @throws unspecified any exception thrown by random_decision_vector(), push_back(), or by the 124 * invoked constructor of pagmo::problem. 125 */ 126 template <typename T, generic_ctor_enabler<T> = 0> population(T && x,size_type pop_size=0u,unsigned seed=pagmo::random_device::next ())127 explicit population(T &&x, size_type pop_size = 0u, unsigned seed = pagmo::random_device::next()) 128 : m_prob(std::forward<T>(x)), m_e(seed), m_seed(seed) 129 { 130 prob_ctor_impl(pop_size); 131 } 132 133 private: 134 // Implementation of the ctor from bfe. Distinguish the two cases 135 // in which bfe or a udbfe were provided. 136 void constructor_from_bfe_impl(const bfe &, size_type, const std::true_type &); 137 template <typename U> constructor_from_bfe_impl(U && b,size_type pop_size,const std::false_type &)138 void constructor_from_bfe_impl(U &&b, size_type pop_size, const std::false_type &) 139 { 140 constructor_from_bfe_impl(bfe(std::forward<U>(b)), pop_size, std::true_type{}); 141 } 142 143 public: 144 /// Constructor from a problem and a batch fitness evaluator. 145 /** 146 * \verbatim embed:rst:leading-asterisk 147 * .. note:: 148 * 149 * This constructor is enabled only if :cpp:class:`pagmo::problem` is constructible from ``T``, 150 * and :cpp:class:`pagmo::bfe` is constructible from ``U``. 151 * 152 * Constructs a population with *pop_size* individuals associated 153 * to the problem *x* and setting the population random seed 154 * to *seed*. The input problem *x* can be either a :cpp:class:`pagmo::problem` or a user-defined problem 155 * (UDP). The fitnesses of the individuals will be evaluated with the input 156 * :cpp:class:`pagmo::bfe` or UDBFE *b*. 157 * 158 * \endverbatim 159 * 160 * @param x the problem the population refers to. 161 * @param b the (user-defined) batch fitness evaluator that will be used to evaluate the fitnesses of the 162 * individuals. 163 * @param pop_size population size (i.e. number of individuals therein). 164 * @param seed seed of the random number generator used, for example, to 165 * create new random individuals within the bounds. 166 * 167 * @throws unspecified any exception thrown by batch_random_decision_vector(), the public API of the (user-defined) 168 * batch fitness evaluator, push_back(), or by the invoked constructor of pagmo::problem. 169 */ 170 template < 171 typename T, typename U, 172 enable_if_t<detail::conjunction<std::is_constructible<problem, T &&>, std::is_constructible<bfe, U &&>>::value, 173 int> = 0> population(T && x,U && b,size_type pop_size=0u,unsigned seed=pagmo::random_device::next ())174 explicit population(T &&x, U &&b, size_type pop_size = 0u, unsigned seed = pagmo::random_device::next()) 175 : m_prob(std::forward<T>(x)), m_e(seed), m_seed(seed) 176 { 177 constructor_from_bfe_impl(std::forward<U>(b), pop_size, std::is_same<uncvref_t<U>, bfe>{}); 178 } 179 180 // Copy constructor. 181 population(const population &); 182 // Move constructor. 183 population(population &&) noexcept; 184 // Copy assignment operator. 185 population &operator=(const population &); 186 // Move assignment operator. 187 population &operator=(population &&) noexcept; 188 // Destructor. 189 ~population(); 190 191 private: 192 // Internal implementation of push_back(). 193 template <typename T, typename U> 194 void push_back_impl(T &&, U &&); 195 // Short routine to update the champion. Does nothing if the problem is MO 196 PAGMO_DLL_LOCAL void update_champion(vector_double, vector_double); 197 198 public: 199 // Adds one decision vector (chromosome) to the population. 200 void push_back(const vector_double &); 201 // Adds one decision vector (chromosome) to the population (move overload). 202 void push_back(vector_double &&); 203 // Adds one decision vector/fitness vector to the population. 204 void push_back(const vector_double &, const vector_double &); 205 // Adds one decision vector/fitness vector to the population (move overload). 206 void push_back(vector_double &&, vector_double &&); 207 208 // Creates a random decision vector 209 vector_double random_decision_vector() const; 210 211 // Index of the best individual 212 size_type best_idx() const; 213 // Index of the best individual (accounting for a vector tolerance) 214 size_type best_idx(const vector_double &) const; 215 // Index of the best individual (accounting for a scalar tolerance) 216 size_type best_idx(double) const; 217 218 // Index of the worst individual 219 size_type worst_idx() const; 220 // Index of the worst individual (accounting for a vector tolerance) 221 size_type worst_idx(const vector_double &) const; 222 // Index of the worst individual (accounting for a scalar tolerance) 223 size_type worst_idx(double) const; 224 225 // Champion decision vector 226 vector_double champion_x() const; 227 // Champion fitness 228 vector_double champion_f() const; 229 230 /// Number of individuals in the population 231 /** 232 * @return the number of individuals in the population 233 */ size() const234 size_type size() const 235 { 236 assert(m_f.size() == m_ID.size()); 237 assert(m_x.size() == m_ID.size()); 238 return m_ID.size(); 239 } 240 241 // Sets the \f$i\f$-th individual decision vector, and fitness 242 void set_xf(size_type, const vector_double &, const vector_double &); 243 // Sets the \f$i\f$-th individual's chromosome 244 void set_x(size_type, const vector_double &); 245 246 /// Const getter for the pagmo::problem. 247 /** 248 * @return a const reference to the internal pagmo::problem. 249 */ get_problem() const250 const problem &get_problem() const 251 { 252 return m_prob; 253 } 254 255 /// Getter for the pagmo::problem. 256 /** 257 * \verbatim embed:rst:leading-asterisk 258 * .. warning:: 259 * 260 * The ability to extract a mutable reference to the problem is provided solely in order to 261 * allow calling non-const methods on the problem. Assigning the population's problem via a reference 262 * returned by this method is undefined behaviour. 263 * 264 * \endverbatim 265 * 266 * @return a reference to the internal pagmo::problem. 267 */ get_problem()268 problem &get_problem() 269 { 270 return m_prob; 271 } 272 273 /// Const getter for the fitness vectors. 274 /** 275 * @return a const reference to the vector of fitness vectors. 276 */ get_f() const277 const std::vector<vector_double> &get_f() const 278 { 279 return m_f; 280 } 281 282 /// Const getter for the decision vectors. 283 /** 284 * @return a const reference to the vector of decision vectors. 285 */ get_x() const286 const std::vector<vector_double> &get_x() const 287 { 288 return m_x; 289 } 290 291 /// Const getter for the individual IDs. 292 /** 293 * @return a const reference to the vector of individual IDs. 294 */ get_ID() const295 const std::vector<unsigned long long> &get_ID() const 296 { 297 return m_ID; 298 } 299 300 /// Getter for the seed of the population random engine. 301 /** 302 * @return the seed of the population's random engine. 303 */ get_seed() const304 unsigned get_seed() const 305 { 306 return m_seed; 307 } 308 309 private: 310 friend class boost::serialization::access; 311 // Save to archive. 312 template <typename Archive> save(Archive & ar,unsigned) const313 void save(Archive &ar, unsigned) const 314 { 315 detail::to_archive(ar, m_prob, m_ID, m_x, m_f, m_champion_x, m_champion_f, m_e, m_seed); 316 } 317 // Load from archive. 318 template <typename Archive> load(Archive & ar,unsigned)319 void load(Archive &ar, unsigned) 320 { 321 try { 322 detail::from_archive(ar, m_prob, m_ID, m_x, m_f, m_champion_x, m_champion_f, m_e, m_seed); 323 // LCOV_EXCL_START 324 } catch (...) { 325 *this = population{}; 326 throw; 327 } 328 // LCOV_EXCL_STOP 329 } 330 BOOST_SERIALIZATION_SPLIT_MEMBER() 331 332 void clear(); 333 334 // Problem. 335 problem m_prob; 336 // ID of the various decision vectors 337 std::vector<unsigned long long> m_ID; 338 // Decision vectors. 339 std::vector<vector_double> m_x; 340 // Fitness vectors. 341 std::vector<vector_double> m_f; 342 // The Champion chromosome 343 vector_double m_champion_x; 344 // The Champion fitness 345 vector_double m_champion_f; 346 // Random engine. 347 mutable detail::random_engine_type m_e; 348 // Seed. 349 unsigned m_seed; 350 }; 351 352 // Streaming operator for the class pagmo::population. 353 PAGMO_DLL_PUBLIC std::ostream &operator<<(std::ostream &, const population &); 354 355 } // namespace pagmo 356 357 // Add some repr support for CLING 358 PAGMO_IMPLEMENT_XEUS_CLING_REPR(population) 359 360 #endif 361