# encoding=utf8
import logging
import numpy as np
from niapy.algorithms.algorithm import Algorithm
logging.basicConfig()
logger = logging.getLogger('niapy.algorithms.basic.SineCosineAlgorithm')
logger.setLevel('INFO')
__all__ = ['SineCosineAlgorithm']
[docs]class SineCosineAlgorithm(Algorithm):
r"""Implementation of sine cosine algorithm.
Algorithm:
Sine Cosine Algorithm
Date:
2018
Authors:
Klemen Berkovič
License:
MIT
Reference URL:
https://www.sciencedirect.com/science/article/pii/S0950705115005043
Reference paper:
Seyedali Mirjalili, SCA: A Sine Cosine Algorithm for solving optimization problems, Knowledge-Based Systems, Volume 96, 2016, Pages 120-133, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2015.12.022.
Attributes:
Name (List[str]): List of string representing algorithm names.
a (float): Parameter for control in :math:`r_1` value
r_min (float): Minimum value for :math:`r_3` value
r_max (float): Maximum value for :math:`r_3` value
See Also:
* :class:`niapy.algorithms.Algorithm`
"""
Name = ['SineCosineAlgorithm', 'SCA']
[docs] @staticmethod
def info():
r"""Get basic information of algorithm.
Returns:
str: Basic information of algorithm.
See Also:
* :func:`niapy.algorithms.Algorithm.info`
"""
return r"""Seyedali Mirjalili, SCA: A Sine Cosine Algorithm for solving optimization problems, Knowledge-Based Systems, Volume 96, 2016, Pages 120-133, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2015.12.022."""
[docs] def __init__(self, population_size=25, a=3, r_min=0, r_max=2, *args, **kwargs):
"""Initialize SineCosineAlgorithm.
Args:
population_size (Optional[int]): Number of individual in population
a (Optional[float]): Parameter for control in :math:`r_1` value
r_min (Optional[float]): Minimum value for :math:`r_3` value
r_max (Optional[float]): Maximum value for :math:`r_3` value
See Also:
* :func:`niapy.algorithms.algorithm.Algorithm.__init__`
"""
super().__init__(population_size, *args, **kwargs)
self.a = a
self.r_min = r_min
self.r_max = r_max
[docs] def set_parameters(self, population_size=25, a=3, r_min=0, r_max=2, **kwargs):
r"""Set the arguments of an algorithm.
Args:
population_size (Optional[int]): Number of individual in population
a (Optional[float]): Parameter for control in :math:`r_1` value
r_min (Optional[float]): Minimum value for :math:`r_3` value
r_max (Optional[float]): Maximum value for :math:`r_3` value
See Also:
* :func:`niapy.algorithms.algorithm.Algorithm.set_parameters`
"""
super().set_parameters(population_size=population_size, **kwargs)
self.a = a
self.r_min = r_min
self.r_max = r_max
[docs] def get_parameters(self):
r"""Get algorithm parameters values.
Returns:
Dict[str, Any]:
See Also:
* :func:`niapy.algorithms.algorithm.Algorithm.get_parameters`
"""
d = super().get_parameters()
d.update({
'a': self.a,
'r_min': self.r_min,
'r_max': self.r_max
})
return d
[docs] def next_position(self, x, best_x, r1, r2, r3, r4, task):
r"""Move individual to new position in search space.
Args:
x (numpy.ndarray): Individual represented with components.
best_x (numpy.ndarray): Best individual represented with components.
r1 (float): Number dependent on algorithm iteration/generations.
r2 (float): Random number in range of 0 and 2 * PI.
r3 (float): Random number in range [r_min, r_max].
r4 (float): Random number in range [0, 1].
task (Task): Optimization task.
Returns:
numpy.ndarray: New individual that is moved based on individual ``x``.
"""
return task.repair(x + r1 * (np.sin(r2) if r4 < 0.5 else np.cos(r2)) * np.fabs(r3 * best_x - x), rng=self.rng)
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params):
r"""Core function of Sine Cosine Algorithm.
Args:
task (Task): Optimization task.
population (numpy.ndarray): Current population individuals.
population_fitness (numpy.ndarray[float]): Current population individuals function/fitness values.
best_x (numpy.ndarray): Current best solution to optimization task.
best_fitness (float): Current best function/fitness value.
params (Dict[str, Any]): Additional parameters.
Returns:
Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
1. New population.
2. New populations fitness/function values.
3. New global best solution.
4. New global best fitness/objective value.
5. Additional arguments.
"""
r1 = self.a - (task.iters + 1) * (self.a / (task.iters + 1))
r2 = self.uniform(0, 2 * np.pi)
r3 = self.uniform(self.r_min, self.r_max)
r4 = self.random()
population = np.apply_along_axis(self.next_position, 1, population, best_x, r1, r2, r3, r4, task)
population_fitness = np.apply_along_axis(task.eval, 1, population)
best_x, best_fitness = self.get_best(population, population_fitness, best_x, best_fitness)
return population, population_fitness, best_x, best_fitness, {}