Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the NSGA-III algorithm #569

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ set(PAGMO_SRC_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/src/algorithms/moead.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/algorithms/moead_gen.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/algorithms/nsga2.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/algorithms/nsga3.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/algorithms/gaco.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/algorithms/de1220.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/algorithms/gwo.cpp"
Expand Down Expand Up @@ -277,6 +278,7 @@ set(PAGMO_SRC_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/src/utils/hv_algos/hv_hv2d.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/utils/hv_algos/hv_hv3d.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/utils/hv_algos/hv_hvwfg.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/utils/reference_point.cpp"
# Detail.
"${CMAKE_CURRENT_SOURCE_DIR}/src/detail/base_sr_policy.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/detail/bfe_impl.cpp"
Expand Down
67 changes: 67 additions & 0 deletions include/pagmo/algorithms/nsga3.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#ifndef PAGMO_ALGORITHMS_NSGA3_HPP
#define PAGMO_ALGORITHMS_NSGA3_HPP

#include <string>
#include <tuple>
#include <vector>

#include <pagmo/rng.hpp> // random_device, random_engine_type
#include <pagmo/detail/visibility.hpp> // PAGMO_DLL_PUBLIC
#include <pagmo/population.hpp> // population
#include <pagmo/utils/reference_point.hpp> // ReferencePoint


namespace pagmo{

class PAGMO_DLL_PUBLIC nsga3{
public:
typedef struct{
std::vector<std::vector<double>> v_extreme;
std::vector<double> v_ideal;
std::vector<double> v_nadir;
} NSGA3Memory;
// Log line format: (gen, fevals, ideal_point)
typedef std::tuple<unsigned, unsigned long long, vector_double> log_line_type;
typedef std::vector<log_line_type> log_type;
// Defaults from IEEE ToEC Vol.18 Iss.4 Aug, 2014
nsga3(unsigned gen = 1u, double cr = 1.0, double eta_c = 30.0,
double mut = 0.10, double eta_mut = 20.0, size_t divisions = 12u,
unsigned seed = pagmo::random_device::next(), bool use_memory = false);
std::string get_name() const{ return "NSGA-III:"; }
population evolve(population) const;
std::vector<size_t> selection(population &, size_t) const;
std::vector<ReferencePoint> generate_uniform_reference_points(size_t nobjs, size_t divisions) const;
std::vector<std::vector<double>> translate_objectives(population) const;
std::vector<std::vector<double>> find_extreme_points(population, std::vector<std::vector<pop_size_t>> &, std::vector<std::vector<double>> &) const;
std::vector<double> find_intercepts(population, std::vector<std::vector<double>> &) const;
std::vector<std::vector<double>> normalize_objectives(std::vector<std::vector<double>> &, std::vector<double> &) const;
const log_type &get_log() const { return m_log; }
void set_verbosity(unsigned level) { m_verbosity = level; }
unsigned get_verbosity() const { return m_verbosity; }
void set_seed(unsigned seed) { reng.seed(seed); seed = seed; }
unsigned get_seed() const { return seed; }
bool has_memory() const {return use_memory; }
private:
unsigned ngen;
double cr; // crossover
double eta_c; // eta crossover
double mut; // mutation
double eta_mut; // eta mutation
size_t divisions; // Reference Point hyperplane subdivisions
unsigned seed; // Seed for PRNG initialisation
bool use_memory; // Preserve extremes, ideal, nadir across generations
mutable NSGA3Memory memory{};
mutable detail::random_engine_type reng; // Defaults to std::mt19937
mutable log_type m_log;
unsigned m_verbosity;
mutable std::vector<ReferencePoint> refpoints;
// Serialisation support
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive &, unsigned int);
};

} // namespace pagmo

PAGMO_S11N_ALGORITHM_EXPORT_KEY(pagmo::nsga3)
#endif
19 changes: 19 additions & 0 deletions include/pagmo/utils/multi_objective.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ see https://www.gnu.org/licenses/. */

#include <pagmo/detail/visibility.hpp>
#include <pagmo/exceptions.hpp>
#include <pagmo/rng.hpp>
#include <pagmo/types.hpp>
#include <pagmo/utils/discrepancy.hpp>
#include <pagmo/utils/generic.hpp>
Expand Down Expand Up @@ -215,6 +216,24 @@ inline std::vector<vector_double> decomposition_weights(vector_double::size_type
PAGMO_DLL_PUBLIC vector_double decompose_objectives(const vector_double &, const vector_double &, const vector_double &,
const std::string &);

// Gaussian Elimination
PAGMO_DLL_PUBLIC vector_double gaussian_elimination(std::vector<std::vector<double>>, const vector_double &);

// Achievement Scalarization Function
PAGMO_DLL_PUBLIC double achievement(const vector_double &, const vector_double &);

// Perpendicular distance to reference point vectors
PAGMO_DLL_PUBLIC double perpendicular_distance(const std::vector<double> &, const std::vector<double> &);

/* Choose single random element from vector container */
template <class T>
PAGMO_DLL_PUBLIC
T choose_random_element(const std::vector<T> &container){
std::vector<T> choice;
std::sample(container.begin(), container.end(), std::back_inserter(choice), 1, std::mt19937{random_device::next()});
return choice[0];
}

} // namespace pagmo

#endif
63 changes: 63 additions & 0 deletions include/pagmo/utils/reference_point.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Defines a ReferencePoint type used by the NSGA-III algorithm
*
*/

#ifndef PAGMO_UTILS_REFERENCE_POINT
#define PAGMO_UTILS_REFERENCE_POINT

#include <iostream>
#include <optional>
#include <string>
#include <sstream>
#include <vector>

#include <pagmo/detail/visibility.hpp> // PAGMO_DLL_PUBLIC
#include <pagmo/population.hpp> // pop_size_t


namespace pagmo{

class PAGMO_DLL_PUBLIC ReferencePoint{
public:
ReferencePoint(size_t nobj);
~ReferencePoint();
size_t dim() const;
double& operator[](int);
friend PAGMO_DLL_PUBLIC std::ostream& operator<<(std::ostream& ostr, const ReferencePoint& rp);
void increment_members(){ ++nmembers; }
void decrement_members(){ --nmembers; }
size_t member_count() const{ return nmembers; }
void add_candidate(size_t, double);
void remove_candidate(size_t index);
size_t candidate_count() const{ return candidates.size(); }
std::vector<double> get_coeffs(){ return coeffs; }
std::optional<size_t> nearest_candidate() const;
std::optional<size_t> random_candidate() const;
std::optional<size_t> select_member() const;
protected:
std::vector<double> coeffs{0};
size_t nmembers{0};
std::vector<std::pair<size_t, double>> candidates;
};

std::vector<ReferencePoint> generate_reference_point_level(
ReferencePoint& rp,
size_t remain,
size_t level,
size_t total
);

void associate_with_reference_points(
std::vector<ReferencePoint> &, // Reference points
std::vector<std::vector<double>>, // Normalized objectives
std::vector<std::vector<pop_size_t>> // NDS Fronts
);

size_t identify_niche_point(std::vector<ReferencePoint> &);

size_t n_choose_k(unsigned, unsigned);

} // namespace pagmo

#endif
Loading
Loading