Nondominated sorting genetic algorithm III (NSGA-III)#
-
class nsga3#
Nondominated Sorting genetic algorithm III (NSGA-III).
NSGA-III is a many-objective evolutionary algorithm. It keeps the non-dominated sorting of NSGA-II but replaces the crowding distance, whose ability to discriminate degrades quickly as the number of objectives grows, with a set of structured reference directions. At every generation the objectives are adaptively normalized, each individual is associated with the reference direction whose ray it lies closest to, and the individuals which fill the least crowded directions are preferred. Diversity is therefore maintained explicitly rather than as a by-product of a density estimate, which is what allows the algorithm to scale to a large number of objectives.
The version implemented in pagmo can be applied to box-bounded, unconstrained, deterministic multiple-objective optimization. Like nsga2 it also deals with integer chromosomes, treating the last
nixentries of the decision vector as integers.Reference directions. The directions are placed on the unit simplex by the systematic approach of Das and Dennis: with
divisionsdivisions along each objective, an \(M\)-objective problem receives \(H = \binom{M + p - 1}{p}\) directions. That count grows quickly with \(M\), so Deb and Jain add a second, inner layer for many-objective problems: a Das and Dennis layer built withdivisions_innerdivisions whose every coordinate is then mapped through\[ c \rightarrow \frac{c + 1/M}{2}, \]which shrinks it by one half about the centroid of the simplex while keeping it on that simplex. Settingdivisions_innerto zero uses the outer layer alone. The two layers are concatenated deterministically, outer first, and a direction of the inner layer coinciding with one already present is dropped. The settings of Table I of the original paper are reproduced by:Objectives
divisions
divisions_inner
Directions
Population
3
12
0
91
92
5
6
0
210
212
8
3
2
156
156
10
3
2
275
276
15
2
1
135
136
A configuration whose direction count is too large to be built is rejected before anything is allocated, rather than exhausting memory: eight objectives with
divisionsset to 8, for instance, would already need 5040 directions, which is the situation the inner layer exists to avoid.Population requirements. The population size must be at least 5, as for nsga2, and it must be at least as large as the number of reference directions. Equality is explicitly permitted: the eight-objective row of Table I above uses a population of exactly 156 for 156 directions.
Memory. Section IV-C of the original paper takes the ideal point over the selected sets of every generation so far, and builds the normalizing hyperplane from the extreme points ever found since the start of the run, while Algorithm 2 is written in terms of the current generation alone. Both behaviours are available: with
use_memoryset to true the ideal point and the extreme points are retained across generations, and with it left false they are recomputed from scratch every generation. The retained extreme points are stored in the original objective coordinates, so that they remain meaningful as the ideal point moves.Deviations from Deb and Jain. The following are deliberate and are the only ones:
Mating selection is selectable through
random_mating. The default, true, is the behaviour of the original paper, whose Section IV-F states that no explicit selection operator is used and that parents are picked at random. Setting it to false instead holds the binary tournament on non-domination rank and crowding distance which is the pagmo convention established by nsga2; that is a materially different mechanism and is not what the paper describes. The tournament can help noticeably on multimodal problems, where the absence of any selection pressure at mating slows convergence: on DTLZ1 with three objectives it reached a p-distance below 0.08 across four seeds, against up to 1.08 for the random pairing. On the unimodal DTLZ2 the two are indistinguishable.use_memorydefaults to false, which follows Algorithm 2 literally rather than the running quantities of Section IV-C.The default mutation probability is a constant, whereas Table II of the paper recommends \(1/n\) for a chromosome of length \(n\); that value depends on the problem and so cannot be a default. Passing it explicitly is advisable.
This implementation is based on the work of Paul Slavin in pagmo2 pull request #569.
See: Deb, K., & Jain, H. (2014). An Evolutionary Many-Objective Optimization Algorithm Using Reference-Point-Based Nondominated Sorting Approach, Part I: Solving Problems With Box Constraints. IEEE Transactions on Evolutionary Computation, 18(4), 577-601. https://doi.org/10.1109/TEVC.2013.2281535
Public Types
-
typedef std::tuple<unsigned, unsigned long long, vector_double> log_line_type#
Single entry of the log (gen, fevals, ideal_point).
-
typedef std::vector<log_line_type> log_type#
The log.
Public Functions
-
nsga3(unsigned gen = 1u, double cr = 1.0, double eta_c = 30.0, double mut = 0.10, double eta_mut = 20.0, std::size_t divisions = 12u, std::size_t divisions_inner = 0u, bool random_mating = true, unsigned seed = pagmo::random_device::next(), bool use_memory = false)#
Constructor.
Constructs the NSGA-III user defined algorithm. The defaults for the genetic operators are those of Table II of Deb and Jain, and the default reference direction set is the single layer with 12 divisions of their Table I, which gives 91 directions for a three-objective problem.
- Parameters:
gen – number of generations to evolve.
cr – crossover probability.
eta_c – distribution index for crossover.
mut – mutation probability.
eta_mut – distribution index for mutation.
divisions – number of divisions of the outer layer of reference directions along each objective.
divisions_inner – number of divisions of the inner layer of reference directions; zero disables the inner layer.
random_mating – if true, mating parents are picked at random as in Section IV-F of the original paper; if false, they are picked by binary tournament on non-domination rank and crowding distance, as in nsga2.
seed – seed used by the internal random number generator (default is random).
use_memory – if true, the ideal point and the extreme points are retained across generations, as described in Section IV-C of the original paper.
- Throws:
std::invalid_argument – if
crormutis not finite or not in \([0,1]\), ifeta_coreta_mutis not finite or not in \([1,100]\), ifdivisionsis zero, or ifdivisions_innerexceedsdivisions.
-
population evolve(population) const#
Algorithm evolve method.
Evolves the population for the requested number of generations.
- Parameters:
pop – population to be evolved
- Throws:
std::invalid_argument – if the problem is stochastic, constrained, single objective or has equal lower and upper bounds; if the population size is smaller than 5 or is smaller than the number of reference directions; or if a configured batch fitness evaluator returns a fitness vector of unexpected size.
unspecified – any exception thrown by the reference direction construction, in particular if the requested number of directions is too large to be built.
- Returns:
evolved population
-
inline void set_seed(unsigned seed)#
Sets the seed.
- Parameters:
seed – the seed controlling the algorithm stochastic behaviour
-
inline unsigned get_seed() const#
Gets the seed.
- Returns:
the seed controlling the algorithm stochastic behaviour
-
inline void set_verbosity(unsigned level)#
Sets the algorithm verbosity.
Sets the verbosity level of the screen output and of the log returned by get_log().
levelcan be:0: no verbosity
>0: will print and log one line each
levelgenerations.
Example (verbosity 1):
Gen is the generation number, Fevals the number of function evaluations used. The ideal point of the current population follows, cropped to its 5th component.Gen: Fevals: ideal1: ideal2: ideal3: 1 0 0.113086 0.153994 0.0682423 2 92 0.113086 0.153994 0.0682423 3 184 0.0866138 0.107934 0.0682423 4 276 0.0866138 0.0917604 0.0682423 5 368 0.0361252 0.0917604 0.0577711
- Parameters:
level – verbosity level
-
inline unsigned get_verbosity() const#
Gets the verbosity level.
- Returns:
the verbosity level
-
void set_bfe(const bfe &b)#
Sets the batch function evaluation scheme.
- Parameters:
b – batch function evaluation object
-
inline std::string get_name() const#
Algorithm name.
Returns the name of the algorithm.
- Returns:
std::stringcontaining the algorithm name
-
std::string get_extra_info() const#
Extra info.
Returns extra information on the algorithm.
- Returns:
an
std::stringcontaining extra info on the algorithm
-
inline const log_type &get_log() const#
Get log.
A log containing relevant quantities monitoring the last call to evolve. Each element of the returned
std::vectoris a nsga3::log_line_type containing: Gen, Fevals, ideal_point as described in nsga3::set_verbosity- Returns:
an
std::vectorof nsga3::log_line_type containing the logged values Gen, Fevals, ideal_point