Source code for pymoo.core.survival

from abc import abstractmethod

import numpy as np

from pymoo.core.population import Population
from pymoo.util import default_random_state


# ---------------------------------------------------------------------------------------------------------
# Survival
# ---------------------------------------------------------------------------------------------------------


[docs] class Survival: def __init__(self, filter_infeasible=True): super().__init__() self.filter_infeasible = filter_infeasible @default_random_state def do(self, problem, pop, *args, n_survive=None, random_state=None, return_indices=False, **kwargs): # make sure the population has at least one individual if len(pop) == 0: return pop if n_survive is None: n_survive = len(pop) n_survive = min(n_survive, len(pop)) # if the split should be done beforehand if self.filter_infeasible and problem.has_constraints(): # split feasible and infeasible solutions feas, infeas = split_by_feasibility(pop, sort_infeas_by_cv=True) if len(feas) == 0: survivors = Population() else: survivors = self._do(problem, pop[feas], *args, n_survive=min(len(feas), n_survive), random_state=random_state, **kwargs) # calculate how many individuals are still remaining to be filled up with infeasible ones n_remaining = n_survive - len(survivors) # if infeasible solutions needs to be added if n_remaining > 0: survivors = Population.merge(survivors, pop[infeas[:n_remaining]]) else: survivors = self._do(problem, pop, *args, n_survive=n_survive, random_state=random_state, **kwargs) if return_indices: H = {} for k, ind in enumerate(pop): H[ind] = k return [H[survivor] for survivor in survivors] else: return survivors @abstractmethod def _do(self, problem, pop, *args, n_survive=None, random_state=None, **kwargs): pass
class ToReplacement(Survival): def __init__(self, survival): super().__init__(False) self.survival = survival def _do(self, problem, pop, off, random_state=None, **kwargs): merged = Population.merge(pop, off) I = self.survival.do(problem, merged, n_survive=len(merged), return_indices=True, random_state=random_state, **kwargs) merged.set("__rank__", I) for k in range(len(pop)): if off[k].get("__rank__") < pop[k].get("__rank__"): pop[k] = off[k] return pop def split_by_feasibility(pop, sort_infeas_by_cv=True, sort_feas_by_obj=False, return_pop=False): F, CV, b = pop.get("F", "CV", "FEAS") feasible = np.where(b)[0] infeasible = np.where(~b)[0] if sort_infeas_by_cv: infeasible = infeasible[np.argsort(CV[infeasible, 0])] if sort_feas_by_obj: feasible = feasible[np.argsort(F[feasible, 0])] if not return_pop: return feasible, infeasible else: return feasible, infeasible, pop[feasible], pop[infeasible]