Source code for desdeo_emo.selection.IOPIS_NSGAIII

from desdeo_emo.selection.NSGAIII_select import NSGAIII_select
import numpy as np
#from pygmo import fast_non_dominated_sorting as nds
from desdeo_tools.utilities import fast_non_dominated_sort
from typing import List
from desdeo_emo.population.Population import Population
from desdeo_emo.utilities.ReferenceVectors import ReferenceVectors


[docs]class IOPIS_NSGAIII_select(NSGAIII_select): def __init__( self, scalarization_nethods, pop: Population, n_survive: int = None, selection_type: str = None, ): self.scalarization_methods = scalarization_nethods self.worst_fitness: np.ndarray = -np.full( (1, len(scalarization_nethods)), np.inf ) self.extreme_points: np.ndarray = None if n_survive is None: self.n_survive: int = pop.pop_size self.ideal: np.ndarray = np.full((1, len(scalarization_nethods)), np.inf)
[docs] def do( self, pop: Population, vectors: ReferenceVectors, reference_point: np.ndarray ) -> List[int]: """Select individuals for mating for NSGA-III. Parameters ---------- pop : Population The current population. vectors : ReferenceVectors Class instance containing reference vectors. Returns ------- List[int] List of indices of the selected individuals """ ref_dirs = vectors.values_planar fitness = np.asarray( [ scalar(pop.fitness, reference_point) for scalar in self.scalarization_methods ] ).T # Calculating fronts and ranks # fronts, dl, dc, rank = nds(fitness) fronts = fast_non_dominated_sort(fitness) fronts = [np.where(fronts[i])[0] for i in range(len(fronts))] non_dominated = fronts[0] fmin = np.amin(fitness, axis=0) self.ideal = np.amin(np.vstack((self.ideal, fmin)), axis=0) # Calculating worst points self.worst_fitness = np.amax(np.vstack((self.worst_fitness, fitness)), axis=0) worst_of_population = np.amax(fitness, axis=0) worst_of_front = np.max(fitness[non_dominated, :], axis=0) self.extreme_points = self.get_extreme_points_c( fitness[non_dominated, :], self.ideal, extreme_points=self.extreme_points ) nadir_point = self.get_nadir_point( self.extreme_points, self.ideal, self.worst_fitness, worst_of_population, worst_of_front, ) # Finding individuals in first 'n' fronts selection = np.asarray([], dtype=int) for front_id in range(len(fronts)): if len(np.concatenate(fronts[: front_id + 1])) < self.n_survive: continue else: fronts = fronts[: front_id + 1] selection = np.concatenate(fronts) break F = fitness[selection] last_front = fronts[-1] # Selecting individuals from the last acceptable front. if len(selection) > self.n_survive: niche_of_individuals, dist_to_niche = self.associate_to_niches( F, ref_dirs, self.ideal, nadir_point ) # if there is only one front if len(fronts) == 1: n_remaining = self.n_survive until_last_front = np.array([], dtype=np.int) niche_count = np.zeros(len(ref_dirs), dtype=np.int) # if some individuals already survived else: until_last_front = np.concatenate(fronts[:-1]) id_until_last_front = list(range(len(until_last_front))) niche_count = self.calc_niche_count( len(ref_dirs), niche_of_individuals[id_until_last_front] ) n_remaining = self.n_survive - len(until_last_front) last_front_selection_id = list(range(len(until_last_front), len(selection))) if np.any(selection[last_front_selection_id] != last_front): print("error!!!") selected_from_last_front = self.niching( fitness[last_front, :], n_remaining, niche_count, niche_of_individuals[last_front_selection_id], dist_to_niche[last_front_selection_id], ) final_selection = np.concatenate( (until_last_front, last_front[selected_from_last_front]) ) if self.extreme_points is None: print("Error") if final_selection is None: print("Error") else: final_selection = selection return final_selection.astype(int)