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 21 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5ac6ccb
Add initial NSGA3 type and test; Fix cec2014 uninitializeds
pmslavin Dec 12, 2023
8ed1622
Add initial ReferencePoint and uniform distribution
pmslavin Dec 14, 2023
d450b8c
ReferencePoint updates and tests
pmslavin Dec 15, 2023
571f5a2
WIP: Add Gaussian elim; translation; ASF; Extreme points
pmslavin Feb 22, 2024
0c564a6
WIP: Find intercepts; Normalize objectives complete
pmslavin Feb 28, 2024
33d266f
WIP: Adds Association and Selection
pmslavin Mar 5, 2024
2949777
WIP: Begin Offspring generation
pmslavin Mar 6, 2024
10d994e
WIP: Offspring generation; Serialisation
pmslavin Mar 7, 2024
f8379c2
RP selection optional; Choice template; Logging; Ctor validation
pmslavin Mar 12, 2024
e331054
Fall back to nadir for duplicate ext and neg intercept
pmslavin Mar 12, 2024
7851a07
Add inter-gen memory; Fix reng seeding
pmslavin Mar 14, 2024
a27bc59
Set seed for global random_device in instance ctor
pmslavin Mar 15, 2024
d569896
Validate problem characteristics
pmslavin Mar 18, 2024
a1b475c
Fix intercepts fallback-without-memory case
pmslavin Mar 22, 2024
ca66f44
Match existing alg.verbosity behaviour; Update tests
pmslavin Mar 28, 2024
4667ff5
Merge branch 'esa:master' into nsga3
pmslavin Apr 4, 2024
d378b23
Merge remote-tracking branch 'upstream/master' into nsga3
pmslavin Dec 23, 2024
8b7dc43
Unshadow members; Explicit casts; Tidy tests
pmslavin Dec 31, 2024
9c81524
Avoid float-as-bool conversion warning
pmslavin Jan 2, 2025
272fd6c
Add nsga3 ctor arguments test
pmslavin Jan 12, 2025
3b32e2c
Fix uninitialised m_verbosity
pmslavin Jan 12, 2025
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 @@ -259,6 +259,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 @@ -293,6 +294,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) { m_reng.seed(seed); m_seed = seed; }
unsigned get_seed() const { return m_seed; }
bool has_memory() const {return m_use_memory; }
private:
unsigned m_gen;
double m_cr; // crossover
double m_eta_c; // eta crossover
double m_mut; // mutation
double m_eta_mut; // eta mutation
size_t m_divisions; // Reference Point hyperplane subdivisions
unsigned m_seed; // Seed for PRNG initialisation
bool m_use_memory; // Preserve extremes, ideal, nadir across generations
mutable NSGA3Memory m_memory{};
mutable detail::random_engine_type m_reng; // Defaults to std::mt19937
mutable log_type m_log;
unsigned m_verbosity {0};
mutable std::vector<ReferencePoint> m_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
18 changes: 18 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,23 @@ 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>
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);
size_t dim() const;
//double& operator[](int);
double& operator[](size_t);
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(size_t, size_t);

} // namespace pagmo

#endif
Loading
Loading