Source code for niapy.algorithms.basic.abc

# encoding=utf8
import copy
import logging

import numpy as np

from niapy.algorithms.algorithm import Algorithm, Individual, default_individual_init

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

__all__ = ['ArtificialBeeColonyAlgorithm']


class SolutionABC(Individual):
    r"""Representation of solution for Artificial Bee Colony Algorithm.

    Date:
        2018

    Author:
        Klemen Berkovič

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

    """

    pass


[docs]class ArtificialBeeColonyAlgorithm(Algorithm): r"""Implementation of Artificial Bee Colony algorithm. Algorithm: Artificial Bee Colony algorithm Date: 2018 Author: Uros Mlakar and Klemen Berkovič License: MIT Reference paper: Karaboga, D., and Bahriye B. "A powerful and efficient algorithm for numerical function optimization: artificial bee colony (ABC) algorithm." Journal of global optimization 39.3 (2007): 459-471. Arguments Name (List[str]): List containing strings that represent algorithm names limit (Union[float, numpy.ndarray[float]]): Maximum number of cycles without improvement. See Also: * :class:`niapy.algorithms.Algorithm` """ Name = ['ArtificialBeeColonyAlgorithm', 'ABC']
[docs] @staticmethod def info(): r"""Get algorithms information. Returns: str: Algorithm information. See Also: * :func:`niapy.algorithms.Algorithm.info` """ return r"""Karaboga, D., and Bahriye B. "A powerful and efficient algorithm for numerical function optimization: artificial bee colony (ABC) algorithm." Journal of global optimization 39.3 (2007): 459-471."""
[docs] def __init__(self, population_size=10, limit=100, *args, **kwargs): """Initialize ArtificialBeeColonyAlgorithm. Args: population_size (Optional[int]): Population size. limit (Optional[int]): Maximum number of cycles without improvement. See Also: :func:`niapy.algorithms.Algorithm.__init__` """ super().__init__(population_size, initialization_function=default_individual_init, individual_type=SolutionABC, *args, **kwargs) self.limit = limit self.food_number = self.population_size // 2
[docs] def set_parameters(self, population_size=10, limit=100, **kwargs): r"""Set the parameters of Artificial Bee Colony Algorithm. Args: population_size(Optional[int]): Population size. limit (Optional[int]): Maximum number of cycles without improvement. See Also: * :func:`niapy.algorithms.Algorithm.set_parameters` """ super().set_parameters(population_size=population_size, initialization_function=default_individual_init, individual_type=SolutionABC, **kwargs) self.food_number = self.population_size // 2 self.limit = limit
[docs] def get_parameters(self): """Get parameters.""" params = super().get_parameters() params.update({ 'limit': self.limit }) return params
[docs] def calculate_probabilities(self, foods): r"""Calculate the probes. Args: foods (numpy.ndarray): Current population. Returns: numpy.ndarray: Probabilities. """ probs = np.asarray([1.0 / (foods[i].f + 0.01) for i in range(self.food_number)]) return probs / np.sum(probs)
[docs] def init_population(self, task): r"""Initialize the starting population. Args: task (Task): Optimization task Returns: Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]: 1. New population 2. New population fitness/function values 3. Additional arguments: * trials (numpy.ndarray): Number of cycles without improvement. See Also: * :func:`niapy.algorithms.Algorithm.init_population` """ foods, fpop, _ = super().init_population(task) trials = np.zeros(self.food_number, dtype=np.int32) return foods, fpop, {'trials': trials}
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params): r"""Core function of the algorithm. Args: task (Task): Optimization task population (numpy.ndarray): Current population population_fitness (numpy.ndarray[float]): Function/fitness values of current population best_x (numpy.ndarray): Current best individual best_fitness (float): Current best individual fitness/function value params (Dict[str, Any]): Additional parameters Returns: Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]: 1. New population 2. New population fitness/function values 3. New global best solution 4. New global best fitness/objective value 5. Additional arguments: * trials (numpy.ndarray): Number of cycles without improvement. """ trials = params.pop('trials') for i in range(self.food_number): new_solution = copy.deepcopy(population[i]) param2change = int(self.random() * task.dimension) neighbor = int(self.food_number * self.random()) new_solution.x[param2change] = population[i].x[param2change] + self.uniform(-1, 1) * ( population[i].x[param2change] - population[neighbor].x[param2change]) new_solution.evaluate(task, rng=self.rng) if new_solution.f < population[i].f: population[i] = new_solution trials[i] = 0 if new_solution.f < best_fitness: best_x = new_solution.x.copy() best_fitness = new_solution.f else: trials[i] += 1 probabilities, t, s = self.calculate_probabilities(population), 0, 0 while t < self.food_number: if self.random() < probabilities[s]: t += 1 solution = copy.deepcopy(population[s]) param2change = int(self.random() * task.dimension) neighbor = int(self.food_number * self.random()) while neighbor == s: neighbor = int(self.food_number * self.random()) solution.x[param2change] = population[s].x[param2change] + self.uniform(-1, 1) * ( population[s].x[param2change] - population[neighbor].x[param2change]) solution.evaluate(task, rng=self.rng) if solution.f < population[s].f: population[s] = solution trials[s] = 0 if solution.f < best_fitness: best_x = solution.x.copy() best_fitness = solution.f else: trials[s] += 1 s += 1 if s == self.food_number: s = 0 mi = np.argmax(trials) if trials[mi] >= self.limit: population[mi], trials[mi] = SolutionABC(task=task, rng=self.rng), 0 if population[mi].f < best_fitness: best_x, best_fitness = population[mi].x.copy(), population[mi].f return population, np.asarray([f.f for f in population]), best_x, best_fitness, {'trials': trials}