Source code for niapy.algorithms.modified.jde

# encoding=utf8
import logging

from niapy.algorithms.algorithm import Individual
from niapy.algorithms.basic.de import DifferentialEvolution, cross_best1, cross_rand1, cross_curr2best1, cross_best2, \
    cross_curr2rand1, multi_mutations
from niapy.util import objects_to_array

logging.basicConfig()
logger = logging.getLogger('niapy.algorithms.modified')
logger.setLevel('INFO')

__all__ = [
    'SolutionJDE',
    'SelfAdaptiveDifferentialEvolution',
    'MultiStrategySelfAdaptiveDifferentialEvolution',
]


class SolutionJDE(Individual):
    r"""Individual for jDE algorithm.

    Attributes:
        differential_weight (float): Scale factor.
        crossover_probability (float): Crossover probability.

    See Also:
        :class:`niapy.algorithms.Individual`

    """

    def __init__(self, differential_weight=2, crossover_probability=0.5, **kwargs):
        r"""Initialize SolutionJDE.

        Attributes:
            differential_weight (float): Scale factor.
            crossover_probability (float): Crossover probability.

        See Also:
            :func:`niapy.algorithm.Individual.__init__`

        """
        super().__init__(**kwargs)
        self.differential_weight = differential_weight
        self.crossover_probability = crossover_probability


[docs]class SelfAdaptiveDifferentialEvolution(DifferentialEvolution): r"""Implementation of Self-adaptive differential evolution algorithm. Algorithm: Self-adaptive differential evolution algorithm Date: 2018 Author: Uros Mlakar and Klemen Berkovič License: MIT Reference paper: Brest, J., Greiner, S., Boskovic, B., Mernik, M., Zumer, V. Self-adapting control parameters in differential evolution: A comparative study on numerical benchmark problems. IEEE transactions on evolutionary computation, 10(6), 646-657, 2006. Attributes: Name (List[str]): List of strings representing algorithm name f_lower (float): Scaling factor lower limit. f_upper (float): Scaling factor upper limit. tao1 (float): Change rate for differential_weight parameter update. tao2 (float): Change rate for crossover_probability parameter update. See Also: * :class:`niapy.algorithms.basic.DifferentialEvolution` """ Name = ['SelfAdaptiveDifferentialEvolution', 'jDE']
[docs] @staticmethod def info(): r"""Get algorithm information. Returns: str: Algorithm information. See Also: * :func:`niapy.algorithms.Algorithm.info` """ return r"""Brest, J., Greiner, S., Boskovic, B., Mernik, M., Zumer, V. Self-adapting control parameters in differential evolution: A comparative study on numerical benchmark problems. IEEE transactions on evolutionary computation, 10(6), 646-657, 2006."""
[docs] def __init__(self, f_lower=0.0, f_upper=1.0, tao1=0.4, tao2=0.2, *args, **kwargs): """Initialize SelfAdaptiveDifferentialEvolution. Args: f_lower (Optional[float]): Scaling factor lower limit. f_upper (Optional[float]): Scaling factor upper limit. tao1 (Optional[float]): Change rate for differential_weight parameter update. tao2 (Optional[float]): Change rate for crossover_probability parameter update. See Also: * :func:`niapy.algorithms.basic.DifferentialEvolution.__init__` """ super().__init__(individual_type=kwargs.pop('individual_type', SolutionJDE), *args, **kwargs) self.f_lower = f_lower self.f_upper = f_upper self.tao1 = tao1 self.tao2 = tao2
[docs] def set_parameters(self, f_lower=0.0, f_upper=1.0, tao1=0.4, tao2=0.2, **kwargs): r"""Set the parameters of an algorithm. Args: f_lower (Optional[float]): Scaling factor lower limit. f_upper (Optional[float]): Scaling factor upper limit. tao1 (Optional[float]): Change rate for differential_weight parameter update. tao2 (Optional[float]): Change rate for crossover_probability parameter update. See Also: * :func:`niapy.algorithms.basic.DifferentialEvolution.set_parameters` """ super().set_parameters(individual_type=kwargs.pop('individual_type', SolutionJDE), **kwargs) self.f_lower = f_lower self.f_upper = f_upper self.tao1 = tao1 self.tao2 = tao2
[docs] def get_parameters(self): r"""Get algorithm parameters. Returns: Dict[str, Any]: Algorithm parameters. """ d = DifferentialEvolution.get_parameters(self) d.update({ 'f_lower': self.f_lower, 'f_upper': self.f_upper, 'tao1': self.tao1, 'tao2': self.tao2 }) return d
[docs] def adaptive_gen(self, x): r"""Adaptive update scale factor in crossover probability. Args: x (IndividualJDE): Individual to apply function on. Returns: Individual: New individual with new parameters """ f = self.f_lower + self.random() * (self.f_upper - self.f_lower) if self.random() < self.tao1 else x.differential_weight cr = self.random() if self.random() < self.tao2 else x.crossover_probability return self.individual_type(x=x.x, differential_weight=f, crossover_probability=cr, e=False)
[docs] def evolve(self, pop, xb, task, **_kwargs): r"""Evolve current population. Args: pop (numpy.ndarray[Individual]): Current population. xb (Individual): Global best individual. task (Task): Optimization task. Returns: numpy.ndarray: New population. """ new_pop = objects_to_array([self.adaptive_gen(e) for e in pop]) for i, e in enumerate(new_pop): new_pop[i].x = self.strategy(new_pop, i, e.differential_weight, e.crossover_probability, rng=self.rng, x_b=xb) for e in new_pop: e.evaluate(task, rng=self.random) return new_pop
[docs]class MultiStrategySelfAdaptiveDifferentialEvolution(SelfAdaptiveDifferentialEvolution): r"""Implementation of self-adaptive differential evolution algorithm with multiple mutation strategies. Algorithm: Self-adaptive differential evolution algorithm with multiple mutation strategies Date: 2018 Author: Klemen Berkovič License: MIT Attributes: Name (List[str]): List of strings representing algorithm name See Also: * :class:`niapy.algorithms.modified.SelfAdaptiveDifferentialEvolution` """ Name = ['MultiStrategySelfAdaptiveDifferentialEvolution', 'MsjDE']
[docs] def __init__(self, strategies=(cross_curr2rand1, cross_curr2best1, cross_rand1, cross_best1, cross_best2), *args, **kwargs): """Initialize MultiStrategySelfAdaptiveDifferentialEvolution. Args: strategies (Optional[Iterable[Callable]]): Mutations strategies to use in algorithm. See Also: * :func:`niapy.algorithms.modified.SelfAdaptiveDifferentialEvolution.__init__` """ super().__init__(strategy=kwargs.pop('strategy', multi_mutations), *args, **kwargs) self.strategies = strategies
[docs] def set_parameters(self, strategies=(cross_curr2rand1, cross_curr2best1, cross_rand1, cross_best1, cross_best2), **kwargs): r"""Set core parameters of MultiStrategySelfAdaptiveDifferentialEvolution algorithm. Args: strategies (Optional[Iterable[Callable]]): Mutations strategies to use in algorithm. See Also: * :func:`niapy.algorithms.modified.SelfAdaptiveDifferentialEvolution.set_parameters` """ super().set_parameters(strategy=kwargs.pop('strategy', multi_mutations), **kwargs) self.strategies = strategies
[docs] def get_parameters(self): r"""Get parameters of the algorithm. Returns: Dict[str, Any]: Algorithm parameters. """ params = super().get_parameters() params.update({'strategies': self.strategies}) return params
[docs] def evolve(self, pop, xb, task, **kwargs): r"""Evolve population with the help multiple mutation strategies. Args: pop (numpy.ndarray[Individual]): Current population. xb (Individual): Current best individual. task (Task): Optimization task. Returns: numpy.ndarray[Individual]: New population of individuals. """ return objects_to_array( [self.strategy(pop, i, xb, self.differential_weight, self.crossover_probability, self.rng, task, self.individual_type, self.strategies) for i in range(len(pop))])