Source code for niapy.algorithms.basic.ca

# encoding=utf8
import logging

import numpy as np

from niapy.algorithms.algorithm import Algorithm, Individual
from niapy.util import objects_to_array

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

__all__ = ['CamelAlgorithm']


class Camel(Individual):
    r"""Implementation of population individual that is a camel for Camel algorithm.

    Algorithm:
        Camel algorithm

    Date:
        2018

    Authors:
        Klemen Berkovič

    License:
        MIT

    Attributes:
        endurance (float): Camel endurance.
        supply (float): Camel supply.
        x_past (numpy.ndarray): Camel's past position.
        f_past (float): Camel's past function/fitness value.
        steps (int): Age of camel.

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

    """

    def __init__(self, endurance_init=None, supply_init=None, **kwargs):
        r"""Initialize the Camel.

        Args:
            endurance_init (Optional[float]): Starting endurance of Camel.
            supply_init (Optional[float]): Stating supply of Camel.

        See Also:
            * :func:`niapy.algorithms.Individual.__init__`

        """
        super().__init__(**kwargs)
        self.endurance = endurance_init
        self.endurance_past = endurance_init
        self.supply = supply_init
        self.supply_past = supply_init
        self.x_past = self.x
        self.f_past = self.f
        self.temperature = None
        self.steps = 0

    def next_temperature(self, min_temperature, max_temperature, rng):
        r"""Apply nextT function on Camel.

        Args:
            min_temperature (float): Minimum temperature.
            max_temperature (float): Maximum temperature.
            rng (numpy.random.Generator): Random number generator.

        """
        self.temperature = rng.uniform(min_temperature, max_temperature)

    def next_supply(self, burden_factor, max_iters):
        r"""Apply nextS on Camel.

        Args:
            burden_factor (float): Burden factor.
            max_iters (int): Number of Camel Algorithm iterations/generations.

        """
        self.supply = self.supply_past * (1 - burden_factor * self.steps / max_iters)

    def next_endurance(self, max_temperature, max_iters):
        r"""Apply function nextE on function on Camel.

        Args:
            max_iters (int): Number of Camel Algorithm iterations/generations
            max_temperature (float): Maximum temperature of environment

        """
        self.endurance = self.endurance_past * (1 - self.temperature / max_temperature) * (1 - self.steps / max_iters)

    def next_x(self, cb, endurance_init, supply_init, task, rng):
        r"""Apply function next_x on Camel.

        This method/function move this Camel to new position in search space.

        Args:
            cb (numpy.ndarray): Best Camel in population.
            endurance_init (float): Starting endurance of camel.
            supply_init (float): Starting supply of camel.
            task (Task): Optimization task.
            rng (numpy.random.Generator): Random number generator.

        """
        delta = rng.uniform(-1, 1)
        self.x = self.x_past + delta * (1 - (self.endurance / endurance_init)) * np.exp(
            1 - self.supply / supply_init) * (
                         cb - self.x_past)
        if not task.is_feasible(self.x):
            self.x = self.x_past
        else:
            self.f = task.eval(self.x)

    def next(self):
        r"""Save new position of Camel to old position."""
        self.x_past = self.x.copy()
        self.f_past = self.f
        self.endurance_past = self.endurance
        self.supply_past = self.supply
        self.steps += 1
        return self

    def refill(self, supply=None, endurance=None):
        r"""Apply this function to Camel.

        Args:
            supply (float): New value of Camel supply.
            endurance (float): New value of Camel endurance.

        """
        self.supply = supply
        self.endurance = endurance


[docs]class CamelAlgorithm(Algorithm): r"""Implementation of Camel traveling behavior. Algorithm: Camel algorithm Date: 2018 Authors: Klemen Berkovič License: MIT Reference URL: https://www.iasj.net/iasj?func=fulltext&aId=118375 Reference paper: Ali, Ramzy. (2016). Novel Optimization Algorithm Inspired by Camel Traveling Behavior. Iraq J. Electrical and Electronic Engineering. 12. 167-177. Attributes: Name (List[str]): List of strings representing name of the algorithm. population_size (Optional[int]): Population size :math:`\in [1, \infty)`. burden_factor (Optional[float]): Burden factor :math:`\in [0, 1]`. death_rate (Optional[float]): Dying rate :math:`\in [0, 1]`. visibility (Optional[float]): View range of camel. supply_init (Optional[float]): Initial supply :math:`\in (0, \infty)`. endurance_init (Optional[float]): Initial endurance :math:`\in (0, \infty)`. min_temperature (Optional[float]): Minimum temperature, must be true :math:`$T_{min} < T_{max}`. max_temperature (Optional[float]): Maximum temperature, must be true :math:`T_{min} < T_{max}`. See Also: * :class:`niapy.algorithms.Algorithm` """ Name = ['CamelAlgorithm', 'CA']
[docs] @staticmethod def info(): r"""Get information about algorithm. Returns: str: Algorithm information See Also: * :func:`niapy.algorithms.Algorithm.info` """ return r'''Ali, Ramzy. (2016). Novel Optimization Algorithm Inspired by Camel Traveling Behavior. Iraq J. Electrical and Electronic Engineering. 12. 167-177.'''
[docs] def __init__(self, population_size=50, burden_factor=0.25, death_rate=0.5, visibility=0.5, supply_init=10, endurance_init=10, min_temperature=-10, max_temperature=10, *args, **kwargs): r"""Initialize CamelAlgorithm. Args: population_size (Optional[int]): Population size :math:`\in [1, \infty)`. burden_factor (Optional[float]): Burden factor :math:`\in [0, 1]`. death_rate (Optional[float]): Dying rate :math:`\in [0, 1]`. visibility (Optional[float]): View range of camel. supply_init (Optional[float]): Initial supply :math:`\in (0, \infty)`. endurance_init (Optional[float]): Initial endurance :math:`\in (0, \infty)`. min_temperature (Optional[float]): Minimum temperature, must be true :math:`$T_{min} < T_{max}`. max_temperature (Optional[float]): Maximum temperature, must be true :math:`T_{min} < T_{max}`. See Also: * :func:`niapy.algorithms.Algorithm.__init__` """ super().__init__(population_size, individual_type=kwargs.pop('individual_type', Camel), initialization_function=kwargs.pop('initialization_function', self.init_pop), *args, **kwargs) self.burden_factor = burden_factor self.death_rate = death_rate self.visibility = visibility self.supply_init = supply_init self.endurance_init = endurance_init self.min_temperature = min_temperature self.max_temperature = max_temperature
[docs] def set_parameters(self, population_size=50, burden_factor=0.25, death_rate=0.5, visibility=0.5, supply_init=10, endurance_init=10, min_temperature=-10, max_temperature=10, **kwargs): r"""Set the arguments of an algorithm. Args: population_size (Optional[int]): Population size :math:`\in [1, \infty)`. burden_factor (Optional[float]): Burden factor :math:`\in [0, 1]`. death_rate (Optional[float]): Dying rate :math:`\in [0, 1]`. visibility (Optional[float]): View range of camel. supply_init (Optional[float]): Initial supply :math:`\in (0, \infty)`. endurance_init (Optional[float]): Initial endurance :math:`\in (0, \infty)`. min_temperature (Optional[float]): Minimum temperature, must be true :math:`$T_{min} < T_{max}`. max_temperature (Optional[float]): Maximum temperature, must be true :math:`T_{min} < T_{max}`. See Also: * :func:`niapy.algorithms.Algorithm.set_parameters` """ super().set_parameters(population_size=population_size, individual_type=Camel, initialization_function=kwargs.pop('initialization_function', self.init_pop), **kwargs) self.burden_factor = burden_factor self.death_rate = death_rate self.visibility = visibility self.supply_init = supply_init self.endurance_init = endurance_init self.min_temperature = min_temperature self.max_temperature = max_temperature
[docs] def get_parameters(self): r"""Get parameters of the algorithm. Returns: Dict[str, Any]: Algorithm Parameters. """ d = super().get_parameters() d.update({ 'burden_factor': self.burden_factor, 'death_rate': self.death_rate, 'visibility': self.visibility, 'supply_init': self.supply_init, 'endurance_init': self.endurance_init, 'min_temperature': self.min_temperature, 'max_temperature': self.max_temperature }) return d
[docs] def init_pop(self, task, population_size, rng, individual_type, **_kwargs): r"""Initialize starting population. Args: task (Task): Optimization task. population_size (int): Number of camels in population. rng (numpy.random.Generator): Random number generator. individual_type (Type[Individual]): Individual type. Returns: Tuple[numpy.ndarray[Camel], numpy.ndarray[float]]: 1. Initialize population of camels. 2. Initialized populations function/fitness values. """ caravan = objects_to_array( [individual_type(endurance_init=self.endurance_init, supply_init=self.supply_init, task=task, rng=rng, e=True) for _ in range(population_size)]) return caravan, np.asarray([c.f for c in caravan])
[docs] def walk(self, camel, best_x, task): r"""Move the camel in search space. Args: camel (Camel): Camel that we want to move. best_x (numpy.ndarray): Global best coordinates. task (Task): Optimization task. Returns: Camel: Camel that moved in the search space. """ camel.next_temperature(self.min_temperature, self.max_temperature, self.rng) camel.next_supply(self.burden_factor, task.max_iters) camel.next_endurance(self.max_temperature, task.max_iters) camel.next_x(best_x, self.endurance_init, self.supply_init, task, self.rng) return camel
[docs] def oasis(self, c): r"""Apply oasis function to camel. Args: c (Camel): Camel to apply oasis on. Returns: Camel: Camel with applied oasis on. """ if self.random() > (1 - self.visibility) and c.f < c.f_past: c.refill(self.supply_init, self.endurance_init) return c
[docs] def life_cycle(self, camel, task): r"""Apply life cycle to Camel. Args: camel (Camel): Camel to apply life cycle. task (Task): Optimization task. Returns: Camel: Camel with life cycle applied to it. """ if camel.f_past < self.death_rate * camel.f: return Camel(self.endurance_init, self.supply_init, rng=self.rng, task=task) else: return camel.next()
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params): r"""Core function of Camel Algorithm. Args: task (Task): Optimization task. population (numpy.ndarray[Camel]): Current population of Camels. population_fitness (numpy.ndarray[float]): Current population fitness/function values. best_x (numpy.ndarray): Current best Camel. best_fitness (float): Current best Camel fitness/function value. **params (Dict[str, Any]): Additional arguments. Returns: Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, dict]: 1. New population 2. New population function/fitness value 3. New global best solution 4. New global best fitness/objective value 5. Additional arguments """ new_caravan = objects_to_array([self.walk(c, best_x, task) for c in population]) new_caravan = objects_to_array([self.oasis(c) for c in new_caravan]) new_caravan = objects_to_array([self.life_cycle(c, task) for c in new_caravan]) new_caravan_fitness = np.asarray([c.f for c in new_caravan]) best_x, best_fitness = self.get_best(new_caravan, new_caravan_fitness, best_x, best_fitness) return new_caravan, new_caravan_fitness, best_x, best_fitness, {}