Source code for pymoo.algorithms.moo.gde3

"""GDE3 multi-objective differential evolution algorithm and its crowding-metric variants."""

from typing import Optional, Tuple, Union

from pymoo.algorithms.moo.nsde import NSDE
from pymoo.core.population import Population
from pymoo.operators.survival.rank_and_crowding import RankAndCrowding
from pymoo.util.dominator import get_relation


# =========================================================================================================
# GDE3
# =========================================================================================================


[docs] class GDE3(NSDE): def __init__( self, pop_size: int = 100, variant: str = "DE/rand/1/bin", CR: float = 0.5, F: Optional[Union[float, Tuple[float, float]]] = None, gamma: float = 1e-4, **kwargs, ): """GDE3 (Generalized Differential Evolution 3) extends DE to multi-objective problems. Each trial vector competes one-to-one with its parent: if the trial dominates, it replaces the parent; if the parent dominates, it is kept; otherwise both enter a combined pool that is trimmed to pop_size via the survival operator. Derived classes GDE3MNN, GDE32NN, GDE3PCD use alternative crowding metrics. Reference: Kukkonen & Lampinen (2005). GDE3: The third evolution step of generalized differential evolution. IEEE CEC 2005. Args: pop_size: Population size. Defaults to 100. variant: DE strategy: "DE/selection/n/crossover". Defaults to 'DE/rand/1/bin'. CR: Crossover rate in [0, 1]. Defaults to 0.5. F: Scale factor(s). Defaults to randomized in (0, 1). gamma: Jitter deviation. Defaults to 1e-4. de_repair: Donor vector repair. Defaults to 'bounce-back'. survival: Survival operator applied when pool > pop_size. Defaults to RankAndCrowding(). **kwargs: Additional keyword arguments forwarded to the NSDE base class. """ super().__init__( pop_size=pop_size, variant=variant, CR=CR, F=F, gamma=gamma, **kwargs ) def _advance(self, infills=None, **kwargs): assert infills is not None, ( "This algorithm uses the AskAndTell interface; 'infills' must be provided." ) survivors = [] for k in range(len(self.pop)): off, parent = infills[k], self.pop[k] rel = get_relation(parent, off) if rel == 0: survivors.extend([parent, off]) elif rel == -1: survivors.append(off) else: survivors.append(parent) survivors = Population.create(*survivors) self.pop = self.survival.do( self.problem, survivors, n_survive=self.n_offsprings, random_state=self.random_state, )
class GDE3MNN(GDE3): """GDE3 with MNN crowding metric — recommended for many-objective problems.""" def __init__( self, pop_size=100, variant="DE/rand/1/bin", CR=0.5, F=None, gamma=1e-4, **kwargs, ): super().__init__( pop_size, variant, CR, F, gamma, survival=RankAndCrowding(crowding_func="mnn"), **kwargs, ) class GDE32NN(GDE3): """GDE3 with 2NN crowding metric — recommended for many-objective problems.""" def __init__( self, pop_size=100, variant="DE/rand/1/bin", CR=0.5, F=None, gamma=1e-4, **kwargs, ): super().__init__( pop_size, variant, CR, F, gamma, survival=RankAndCrowding(crowding_func="2nn"), **kwargs, ) class GDE3PCD(GDE3): """GDE3 with PCD crowding metric — recommended for bi-objective problems.""" def __init__( self, pop_size=100, variant="DE/rand/1/bin", CR=0.5, F=None, gamma=1e-4, **kwargs, ): super().__init__( pop_size, variant, CR, F, gamma, survival=RankAndCrowding(crowding_func="pcd"), **kwargs, )