Source code for surrogate.selection.selNSGA2

# Copyright 2016 Quan Pan
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
# Author: Quan Pan <>
# License: Apache License, Version 2.0
# Create: 2016-12-02

from itertools import chain
from operator import attrgetter

from .utils import assignCrowdingDist
from ..sorting import sorNondominated, sorLogNondominated

[docs]def selNSGA2(individuals, k, nd='standard'): """Apply NSGA-II selection operator on the *individuals*. Usually, the size of *individuals* will be larger than *k* because any individual present in *individuals* will appear in the returned list at most once. Having the size of *individuals* equals to *k* will have no effect other than sorting the population according to their front rank. The list returned contains references to the input *individuals*. For more details on the NSGA-II operator see [Deb2002]_. :param individuals: A list of individuals to select from. :param k: The number of individuals to select. :param nd: Specify the non-dominated algorithm to use: 'standard' or 'log'. :returns: A list of selected individuals. .. [Deb2002] Deb, Pratab, Agarwal, and Meyarivan, "A fast elitist non-dominated sorting genetic algorithm for multi-objective optimization: NSGA-II", 2002. """ if nd == 'standard': pareto_fronts = sorNondominated(individuals, k) elif nd == 'log': pareto_fronts = sorLogNondominated(individuals, k) else: raise Exception('selNSGA2: The choice of non-dominated sorting ' 'method "{0}" is invalid.'.format(nd)) for front in pareto_fronts: assignCrowdingDist(front) chosen = list(chain(*pareto_fronts[:-1])) k = k - len(chosen) if k > 0: sorted_front = sorted(pareto_fronts[-1], key=attrgetter("fitness.crowding_dist"), reverse=True) chosen.extend(sorted_front[:k]) return chosen