# encoding=utf8
import logging
import numpy as np
from niapy.algorithms.algorithm import Algorithm
from niapy.util.distances import euclidean
import niapy.util.repair as repair
logging.basicConfig()
logger = logging.getLogger('niapy.algorithms.basic')
logger.setLevel('INFO')
__all__ = ['FireworksAlgorithm', 'EnhancedFireworksAlgorithm', 'DynamicFireworksAlgorithm',
'DynamicFireworksAlgorithmGauss', 'BareBonesFireworksAlgorithm']
[docs]class BareBonesFireworksAlgorithm(Algorithm):
r"""Implementation of Bare Bones Fireworks Algorithm.
Algorithm:
Bare Bones Fireworks Algorithm
Date:
2018
Authors:
Klemen Berkovič
License:
MIT
Reference URL:
https://www.sciencedirect.com/science/article/pii/S1568494617306609
Reference paper:
Junzhi Li, Ying Tan, The bare bones fireworks algorithm: A minimalist global optimizer, Applied Soft Computing, Volume 62, 2018, Pages 454-462, ISSN 1568-4946, https://doi.org/10.1016/j.asoc.2017.10.046.
Attributes:
Name (List[str]): List of strings representing algorithm names
num_sparks (int): Number of sparks
amplification_coefficient (float): amplification coefficient
reduction_coefficient (float): reduction coefficient
"""
Name = ['BareBonesFireworksAlgorithm', 'BBFWA']
[docs] @staticmethod
def info():
r"""Get default information of algorithm.
Returns:
str: Basic information.
See Also:
* :func:`niapy.algorithms.Algorithm.info`
"""
return r"""Junzhi Li, Ying Tan, The bare bones fireworks algorithm: A minimalist global optimizer, Applied Soft Computing, Volume 62, 2018, Pages 454-462, ISSN 1568-4946, https://doi.org/10.1016/j.asoc.2017.10.046."""
[docs] def __init__(self, num_sparks=10, amplification_coefficient=1.5, reduction_coefficient=0.5, *args, **kwargs):
r"""Initialize BareBonesFireworksAlgorithm.
Args:
num_sparks (int): Number of sparks :math:`\in[1, \infty)`.
amplification_coefficient (float): Amplification coefficient :math:`\in [1, \infty)`.
reduction_coefficient (float): Reduction coefficient :math:`\in (0, 1)`.
"""
kwargs.pop('population_size', None)
super().__init__(1, *args, **kwargs)
self.num_sparks = num_sparks
self.amplification_coefficient = amplification_coefficient
self.reduction_coefficient = reduction_coefficient
[docs] def set_parameters(self, num_sparks=10, amplification_coefficient=1.5, reduction_coefficient=0.5, **kwargs):
r"""Set the arguments of an algorithm.
Args:
num_sparks (int): Number of sparks :math:`\in [1, \infty)`.
amplification_coefficient (float): Amplification coefficient :math:`\in [1, \infty)`.
reduction_coefficient (float): Reduction coefficient :math:`\in (0, 1)`.
"""
kwargs.pop('population_size', None)
super().set_parameters(population_size=1, **kwargs)
self.num_sparks = num_sparks
self.amplification_coefficient = amplification_coefficient
self.reduction_coefficient = reduction_coefficient
[docs] def get_parameters(self):
r"""Get parameters of the algorithm.
Returns:
Dict[str, Any]: Algorithm parameters.
"""
params = super().get_parameters()
params.pop('population_size', None)
params.update({
'num_sparks': self.num_sparks,
'amplification_coefficient': self.amplification_coefficient,
'reduction_coefficient': self.reduction_coefficient
})
return params
[docs] def init_population(self, task):
r"""Initialize starting population.
Args:
task (Task): Optimization task.
Returns:
Tuple[numpy.ndarray, float, Dict[str, Any]]:
1. Initial solution.
2. Initial solution function/fitness value.
3. Additional arguments:
* A (numpy.ndarray): Starting amplitude or search range.
"""
x, x_fit, d = super().init_population(task)
d.update({'amplitude': task.range})
return x, x_fit, d
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params):
r"""Core function of Bare Bones Fireworks Algorithm.
Args:
task (Task): Optimization task.
population (numpy.ndarray): Current solution.
population_fitness (float): Current solution fitness/function value.
best_x (numpy.ndarray): Current best solution.
best_fitness (float): Current best solution fitness/function value.
params (Dict[str, Any]): Additional parameters.
Returns:
Tuple[numpy.ndarray, float, numpy.ndarray, float, Dict[str, Any]]:
1. New solution.
2. New solution fitness/function value.
3. New global best solution.
4. New global best solutions fitness/objective value.
5. Additional arguments:
* amplitude (numpy.ndarray): Search range.
"""
amplitude = params.pop('amplitude')
sparks = self.uniform(population - amplitude, population + amplitude, (self.num_sparks, task.dimension))
sparks = np.apply_along_axis(task.repair, 1, sparks, self.rng)
sparks_fitness = np.apply_along_axis(task.eval, 1, sparks)
best_index = np.argmin(sparks_fitness)
if sparks_fitness[best_index] < population_fitness:
population = sparks[best_index]
population_fitness = sparks_fitness[best_index]
amplitude = self.amplification_coefficient * amplitude
else:
amplitude = self.reduction_coefficient * amplitude
return population, population_fitness, population.copy(), population_fitness, {'amplitude': amplitude}
[docs]class FireworksAlgorithm(Algorithm):
r"""Implementation of fireworks algorithm.
Algorithm:
Fireworks Algorithm
Date:
2018
Authors:
Klemen Berkovič
License:
MIT
Reference URL:
https://www.springer.com/gp/book/9783662463529
Reference paper:
Tan, Ying. "Fireworks algorithm." Heidelberg, Germany: Springer 10 (2015): 978-3
Attributes:
Name (List[str]): List of strings representing algorithm names.
"""
Name = ['FireworksAlgorithm', 'FWA']
[docs] @staticmethod
def info():
r"""Get default information of algorithm.
Returns:
str: Basic information.
See Also:
* :func:`niapy.algorithms.Algorithm.info`
"""
return r"""Tan, Ying. "Fireworks algorithm." Heidelberg, Germany: Springer 10 (2015): 978-3."""
[docs] def __init__(self, population_size=5, num_sparks=50, a=0.04, b=0.8, max_amplitude=40, num_gaussian=5, *args, **kwargs):
"""Initialize FWA.
Args:
population_size (int): Number of Fireworks
num_sparks (int): Number of sparks
a (float): Limitation of sparks
b (float): Limitation of sparks
max_amplitude (float): Initial amplitude.
num_gaussian (int): Number of sparks to apply gaussian mutation to.
"""
super().__init__(population_size, *args, **kwargs)
self.num_sparks = num_sparks
self.a = a
self.b = b
self.max_amplitude = max_amplitude
self.num_gaussian = num_gaussian
self.epsilon = np.finfo(float).eps
[docs] def set_parameters(self, population_size=5, num_sparks=50, a=0.04, b=0.8, max_amplitude=40, num_gaussian=5,
**kwargs):
r"""Set the arguments of an algorithm.
Args:
population_size (int): Number of Fireworks
num_sparks (int): Number of sparks
a (float): Limitation of sparks
b (float): Limitation of sparks
max_amplitude (float): Initial amplitude.
num_gaussian (int): Number of sparks to apply gaussian mutation to.
"""
super().set_parameters(population_size=population_size, **kwargs)
self.num_sparks = num_sparks
self.a = a
self.b = b
self.max_amplitude = max_amplitude
self.num_gaussian = num_gaussian
self.epsilon = np.finfo(float).eps
[docs] def get_parameters(self):
r"""Get parameters of the algorithm.
Returns:
Dict[str, Any]: Algorithm parameters.
"""
params = super().get_parameters()
params.update({
'num_sparks': self.num_sparks,
'a': self.a,
'b': self.b,
'max_amplitude': self.max_amplitude,
'num_gaussian': self.num_gaussian
})
return params
[docs] def sparks_num(self, population_fitness):
r"""Calculate number of sparks.
Args:
population_fitness (numpy.ndarray): Population fitness values.
Returns:
numpy.ndarray: Number of sparks that for all fireworks.
"""
worst_fitness = np.amax(population_fitness)
sparks_num = self.num_sparks * (worst_fitness - population_fitness + self.epsilon)
sparks_num /= np.sum(worst_fitness - population_fitness) + self.epsilon
cond = [sparks_num < self.a * self.num_sparks, (sparks_num > self.b * self.num_sparks) * (self.a < self.b < 1)]
choices = [round(self.a * self.num_sparks), round(self.b * self.num_sparks)]
return np.select(cond, choices, default=np.round(sparks_num)).astype(int)
[docs] def explosion_amplitudes(self, population_fitness, task=None):
r"""Calculate explosion amplitude.
Args:
population_fitness (numpy.ndarray): Population fitness values.
task (Optional[Task]): Optimization task (Unused in this version of the algorithm).
Returns:
numpy.ndarray: Explosion amplitude of sparks.
"""
best_fitness = np.amin(population_fitness)
amplitudes = self.max_amplitude * (population_fitness - best_fitness + self.epsilon)
amplitudes /= np.sum(population_fitness - best_fitness) + self.epsilon
return amplitudes
[docs] def explosion_spark(self, x, amplitude, task):
r"""Explode a spark.
Args:
x (numpy.ndarray): Individuals creating spark.
amplitude (float): Amplitude of spark.
task (Task): Optimization task.
Returns:
numpy.ndarray: Sparks exploded in with specified amplitude.
"""
z = self.rng.choice(task.dimension, self.rng.integers(task.dimension), replace=False)
x[z] = x[z] + amplitude * self.uniform(-1, 1)
return self.mapping(x, task)
[docs] def gaussian_spark(self, x, task, best_x=None):
r"""Create gaussian spark.
Args:
x (numpy.ndarray): Individual creating a spark.
task (Task): Optimization task.
best_x (numpy.ndarray): Current best individual. Unused in this version of the algorithm.
Returns:
numpy.ndarray: Spark exploded based on gaussian amplitude.
"""
z = self.rng.choice(task.dimension, self.rng.integers(task.dimension), replace=False)
x[z] = x[z] * self.normal(1, 1)
return self.mapping(x, task)
[docs] def mapping(self, x, task):
r"""Fix value to bounds.
Args:
x (numpy.ndarray): Individual to fix.
task (Task): Optimization task.
Returns:
numpy.ndarray: Individual in search range.
"""
return repair.reflect(x, task.lower, task.upper)
[docs] def selection(self, population, population_fitness, sparks, task):
r"""Generate new generation of individuals.
Args:
population (numpy.ndarray): Current population.
population_fitness (numpy.ndarray[float]): Currents population fitness/function values.
sparks (numpy.ndarray): New population.
task (Task): Optimization task.
Returns:
Tuple[numpy.ndarray, numpy.ndarray[float], numpy.ndarray, float]:
1. New population.
2. New populations fitness/function values.
3. New global best individual.
4. New global best fitness.
"""
sparks_fitness = np.apply_along_axis(task.eval, 1, sparks)
best_index = np.argmin(sparks_fitness)
best_x = sparks[best_index].copy()
best_fitness = sparks_fitness[best_index]
all_sparks = np.delete(sparks, best_index, axis=0)
fitness = np.delete(sparks_fitness, best_index)
distances = np.sum(euclidean(all_sparks[:, np.newaxis, :], all_sparks[np.newaxis, :, :]), axis=0)
probabilities = distances / np.sum(distances)
selected_indices = self.rng.choice(len(all_sparks), self.population_size - 1, replace=False, p=probabilities)
population[0] = best_x
population[1:] = all_sparks[selected_indices]
population_fitness[0] = best_fitness
population_fitness[1:] = fitness[selected_indices]
return population, population_fitness, best_x, best_fitness
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params):
r"""Core function of Fireworks algorithm.
Args:
task (Task): Optimization task.
population (numpy.ndarray): Current population.
population_fitness (numpy.ndarray[float]): Current populations function/fitness values.
best_x (numpy.ndarray): Global best individual.
best_fitness (float): Global best individuals fitness/function value.
**params (Dict[str, Any)]: Additional arguments
Returns:
Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
1. Initialized population.
2. Initialized populations function/fitness values.
3. New global best solution.
4. New global best solutions fitness/objective value.
5. Additional arguments:
* Ah (numpy.ndarray): Initialized amplitudes.
See Also:
* :func:`FireworksAlgorithm.sparks_num`.
* :func:`FireworksAlgorithm.explosion_amplitudes`
* :func:`FireworksAlgorithm.explosion_spark`
* :func:`FireworksAlgorithm.gaussian_spark`
* :func:`FireworksAlgorithm.selection`
"""
sparks_num = self.sparks_num(population_fitness)
amplitudes = self.explosion_amplitudes(population_fitness, task=task)
all_sparks = population.copy()
for i in range(self.population_size):
si = sparks_num[i]
ai = amplitudes[i]
sparks_i = np.empty((si, task.dimension))
for s in range(si):
sparks_i[s] = population[i]
sparks_i[s] = self.explosion_spark(sparks_i[s], ai, task)
all_sparks = np.concatenate((all_sparks, sparks_i), axis=0)
gaussian_idx = self.rng.choice(len(all_sparks), self.num_gaussian, replace=False)
gaussian_sparks = np.array(all_sparks[gaussian_idx])
for i in range(self.num_gaussian):
gaussian_sparks[i] = self.gaussian_spark(gaussian_sparks[i], task, best_x=best_x)
all_sparks = np.concatenate((all_sparks, gaussian_sparks), axis=0)
population, population_fitness, best_x, best_fitness = self.selection(population, population_fitness,
all_sparks, task)
return population, population_fitness, best_x, best_fitness, {}
[docs]class EnhancedFireworksAlgorithm(FireworksAlgorithm):
r"""Implementation of enhanced fireworks algorithm.
Algorithm:
Enhanced Fireworks Algorithm
Date:
2018
Authors:
Klemen Berkovič
License:
MIT
Reference URL:
https://ieeexplore.ieee.org/document/6557813/
Reference paper:
S. Zheng, A. Janecek and Y. Tan, "Enhanced Fireworks Algorithm," 2013 IEEE Congress on Evolutionary Computation, Cancun, 2013, pp. 2069-2077. doi: 10.1109/CEC.2013.6557813
Attributes:
Name (List[str]): List of strings representing algorithm names.
amplitude_init (float): Initial amplitude of sparks.
amplitude_final (float): Maximal amplitude of sparks.
"""
Name = ['EnhancedFireworksAlgorithm', 'EFWA']
[docs] @staticmethod
def info():
r"""Get default information of algorithm.
Returns:
str: Basic information.
See Also:
* :func:`niapy.algorithms.Algorithm.info`
"""
return r"""S. Zheng, A. Janecek and Y. Tan, "Enhanced Fireworks Algorithm," 2013 IEEE Congress on Evolutionary Computation, Cancun, 2013, pp. 2069-2077. doi: 10.1109/CEC.2013.6557813"""
[docs] def __init__(self, amplitude_init=0.2, amplitude_final=0.01, *args, **kwargs):
"""Initialize EFWA.
Args:
amplitude_init (float): Initial amplitude.
amplitude_final (float): Final amplitude.
See Also:
* :func:`FireworksAlgorithm.__init__`
"""
super().__init__(*args, **kwargs)
self.amplitude_init = amplitude_init
self.amplitude_final = amplitude_final
[docs] def set_parameters(self, amplitude_init=0.2, amplitude_final=0.01, **kwargs):
r"""Set EnhancedFireworksAlgorithm algorithms core parameters.
Args:
amplitude_init (float): Initial amplitude.
amplitude_final (float): Final amplitude.
See Also:
* :func:`FireworksAlgorithm.set_parameters`
"""
super().set_parameters(**kwargs)
self.amplitude_init = amplitude_init
self.amplitude_final = amplitude_final
[docs] def get_parameters(self):
r"""Get parameters of the algorithm.
Returns:
Dict[str, Any]: Algorithm parameters.
"""
params = super().get_parameters()
params.update({
'amplitude_init': self.amplitude_init,
'amplitude_final': self.amplitude_final
})
return params
[docs] def explosion_amplitudes(self, population_fitness, task=None):
r"""Calculate explosion amplitude.
Args:
population_fitness (numpy.ndarray):
task (Task): Optimization task.
Returns:
numpy.ndarray: New amplitude.
"""
amplitudes = super().explosion_amplitudes(population_fitness, task)
a_min = self.amplitude_init - np.sqrt(task.evals * (2 * task.max_evals - task.evals)) * (self.amplitude_init - self.amplitude_final) / task.max_evals
amplitudes[amplitudes < a_min] = a_min
return amplitudes
[docs] def mapping(self, x, task):
r"""Fix value to bounds.
Args:
x (numpy.ndarray): Individual to fix.
task (Task): Optimization task.
Returns:
numpy.ndarray: Individual in search range.
"""
return repair.rand(x, task.lower, task.upper, rng=self.rng)
[docs] def explosion_spark(self, x, amplitude, task):
r"""Explode a spark.
Args:
x (numpy.ndarray): Individuals creating spark.
amplitude (float): Amplitude of spark.
task (Task): Optimization task.
Returns:
numpy.ndarray: Sparks exploded in with specified amplitude.
"""
z = self.rng.choice(task.dimension, self.rng.integers(task.dimension), replace=False)
if isinstance(amplitude, np.ndarray):
x[z] = x[z] + amplitude[z] * self.uniform(-1, 1, len(z))
else:
x[z] = x[z] + amplitude * self.uniform(-1, 1, len(z))
return self.mapping(x, task)
[docs] def gaussian_spark(self, x, task, best_x=None):
r"""Create new individual.
Args:
x (numpy.ndarray):
task (Task): Optimization task.
best_x (numpy.ndarray): Current global best individual.
Returns:
numpy.ndarray: New individual generated by gaussian noise.
"""
z = self.rng.choice(task.dimension, self.rng.integers(task.dimension), replace=False)
e = self.standard_normal()
x[z] = x[z] + (best_x[z] - x[z]) * e
return self.mapping(x, task)
[docs] def selection(self, population, population_fitness, sparks, task):
r"""Generate new population.
Args:
population (numpy.ndarray): Current population.
population_fitness (numpy.ndarray[float]): Current populations fitness/function values.
sparks (numpy.ndarray): New population.
task (Task): Optimization task.
Returns:
Tuple[numpy.ndarray, numpy.ndarray[float], numpy.ndarray, float]:
1. New population.
2. New populations fitness/function values.
3. New global best individual.
4. New global best fitness.
"""
sparks_fitness = np.apply_along_axis(task.eval, 1, sparks)
ib = np.argmin(sparks_fitness)
best_x = sparks[ib].copy()
best_fitness = sparks_fitness[ib]
if sparks_fitness[ib] < population_fitness[0]:
population[0], population_fitness[0] = best_x, best_fitness
for i in range(1, self.population_size):
r = self.integers(len(sparks))
if sparks_fitness[r] < population_fitness[i]:
population[i], population_fitness[i] = sparks[r], sparks_fitness[r]
return population, population_fitness, best_x, best_fitness
[docs]class DynamicFireworksAlgorithmGauss(EnhancedFireworksAlgorithm):
r"""Implementation of dynamic fireworks algorithm.
Algorithm:
Dynamic Fireworks Algorithm
Date:
2018
Authors:
Klemen Berkovič
License:
MIT
Reference URL:
http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6900485&isnumber=6900223
Reference paper:
S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485
Attributes:
Name (List[str]): List of strings representing algorithm names.
amplitude_cf (Union[float, int]): Amplitude of the core firework.
amplification_coeff (Union[float, int]): Amplification coefficient.
reduction_coeff (Union[float, int]): Reduction coefficient.
"""
Name = ['DynamicFireworksAlgorithmGauss', 'dynFWAG']
[docs] @staticmethod
def info():
r"""Get default information of algorithm.
Returns:
str: Basic information.
See Also:
* :func:`niapy.algorithms.Algorithm.info`
"""
return r"""S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485"""
[docs] def __init__(self, amplification_coeff=1.2, reduction_coeff=0.9, *args, **kwargs):
"""Initialize dynFWAG.
Args:
amplification_coeff (Union[int, float]): Amplification coefficient.
reduction_coeff (Union[int, float]): Reduction coefficient.
See Also:
* :func:`FireworksAlgorithm.__init__`
"""
super().__init__(*args, **kwargs)
self.amplification_coeff = amplification_coeff
self.reduction_coeff = reduction_coeff
[docs] def set_parameters(self, amplification_coeff=1.2, reduction_coeff=0.9, **kwargs):
r"""Set core arguments of DynamicFireworksAlgorithmGauss.
Args:
amplification_coeff (Union[int, float]): Amplification coefficient.
reduction_coeff (Union[int, float]): Reduction coefficient.
See Also:
* :func:`FireworksAlgorithm.set_parameters`
"""
super().set_parameters(**kwargs)
self.amplification_coeff = amplification_coeff
self.reduction_coeff = reduction_coeff
[docs] def get_parameters(self):
r"""Get parameters of the algorithm.
Returns:
Dict[str, Any]: Algorithm parameters.
"""
params = super().get_parameters()
params.update({
'amplification_coeff': self.amplification_coeff,
'reduction_coeff': self.reduction_coeff
})
return params
[docs] def update_cf(self, xnb, xcb, xcb_f, xb, xb_f, amplitude_cf, task):
r"""Update the core firework.
Args:
xnb: Sparks generated by core fireworks.
xcb: Current generations best spark.
xcb_f: Current generations best fitness.
xb: Global best individual.
xb_f: Global best fitness.
amplitude_cf: Amplitude of the core firework.
task (Task): Optimization task.
Returns:
Tuple[numpy.ndarray, float, numpy.ndarray]:
1. New core firework.
2. New core firework's fitness.
3. New core firework amplitude.
"""
xnb_f = np.apply_along_axis(task.eval, 1, xnb)
ib_f = np.argmin(xnb_f)
if xnb_f[ib_f] <= xb_f:
xb, xb_f = xnb[ib_f], xnb_f[ib_f]
if xb_f >= xcb_f:
xb, xb_f, amplitude_cf = xcb, xcb_f, amplitude_cf * self.amplification_coeff
else:
amplitude_cf = amplitude_cf * self.reduction_coeff
return xb, xb_f, amplitude_cf
[docs] def explosion_amplitudes(self, population_fitness, task=None):
"""Calculate explosion amplitude for other fireworks."""
return FireworksAlgorithm.explosion_amplitudes(self, population_fitness)
[docs] def init_population(self, task):
r"""Initialize population.
Args:
task (Task): Optimization task.
Returns:
Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
1. Initialized population.
2. Initialized population function/fitness values.
3. Additional arguments:
* amplitude_cf (numpy.ndarray): Initial amplitude of the core firework.
"""
fireworks, fitness, _ = super().init_population(task)
amplitude_cf = task.range
return fireworks, fitness, {'amplitude_cf': amplitude_cf}
[docs] def selection(self, population, population_fitness, sparks, task):
"""Select fireworks for the next generation."""
sparks_fitness = np.apply_along_axis(task.eval, 1, sparks)
ib = np.argmin(sparks_fitness)
for i, f in enumerate(population_fitness):
r = self.integers(len(sparks))
if sparks_fitness[r] < f:
population[i], population_fitness[i] = sparks[r], sparks_fitness[r]
population[0], population_fitness[0] = sparks[ib], sparks_fitness[ib]
return population, population_fitness
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params):
r"""Core function of DynamicFireworksAlgorithmGauss algorithm.
Args:
task (Task): Optimization task.
population (numpy.ndarray): Current population.
population_fitness (numpy.ndarray): Current populations function/fitness values.
best_x (numpy.ndarray): Global best individual.
best_fitness (float): Global best fitness/function value.
**params (Dict[str, Any]): Additional arguments.
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 solutions fitness/objective value.
5. Additional arguments:
* amplitude_cf (numpy.ndarray): Amplitude of the core firework.
"""
amplitude_cf = params.pop('amplitude_cf')
sparks_num = self.sparks_num(population_fitness)
amplitudes = self.explosion_amplitudes(population_fitness)
cf_sparks_num = self.num_sparks * (np.amax(population_fitness) - best_fitness + self.epsilon) /\
(np.sum(np.amax(population_fitness - best_fitness)) + self.epsilon)
if cf_sparks_num < self.a * self.num_sparks:
cf_sparks_num = round(self.a * self.num_sparks)
elif cf_sparks_num > self.b * self.num_sparks and self.a < self.b < 1:
cf_sparks_num = round(self.b * self.num_sparks)
else:
cf_sparks_num = round(cf_sparks_num)
all_sparks = population.copy()
for i in range(self.population_size):
si = sparks_num[i]
ai = amplitudes[i]
sparks_i = np.empty((si, task.dimension))
for s in range(si):
sparks_i[s] = population[i]
sparks_i[s] = self.explosion_spark(sparks_i[s], ai, task)
all_sparks = np.concatenate((all_sparks, sparks_i), axis=0)
gaussian_idx = self.rng.choice(len(all_sparks), self.num_gaussian, replace=False)
gaussian_sparks = np.array(all_sparks[gaussian_idx])
for i in range(self.num_gaussian):
gaussian_sparks[i] = self.gaussian_spark(gaussian_sparks[i], task, best_x=best_x)
all_sparks = np.concatenate((all_sparks, gaussian_sparks), axis=0)
cf_sparks = np.empty((cf_sparks_num, task.dimension))
for s in range(cf_sparks_num):
cf_sparks[s] = best_x
cf_sparks[s] = self.explosion_spark(cf_sparks[s], amplitude_cf, task)
population, population_fitness = self.selection(population, population_fitness, all_sparks, task)
best_x, best_fitness, amplitude_cf = self.update_cf(cf_sparks, population[0], population_fitness[0], best_x, best_fitness, amplitude_cf, task)
return population, population_fitness, best_x, best_fitness, {'amplitude_cf': amplitude_cf}
[docs]class DynamicFireworksAlgorithm(DynamicFireworksAlgorithmGauss):
r"""Implementation of dynamic fireworks algorithm.
Algorithm:
Dynamic Fireworks Algorithm
Date:
2018
Authors:
Klemen Berkovič
License:
MIT
Reference URL:
http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6900485&isnumber=6900223
Reference paper:
S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485
Attributes:
Name (List[str]): List of strings representing algorithm name.
See Also:
* :class:`niapy.algorithms.basic.DynamicFireworksAlgorithmGauss`
"""
Name = ['DynamicFireworksAlgorithm', 'dynFWA']
[docs] @staticmethod
def info():
r"""Get default information of algorithm.
Returns:
str: Basic information.
See Also:
* :func:`niapy.algorithms.Algorithm.info`
"""
return r"""S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485"""
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params):
r"""Co50re function of Dynamic Fireworks Algorithm.
Args:
task (Task): Optimization task
population (numpy.ndarray): Current population
population_fitness (numpy.ndarray[float]): Current population fitness/function values
best_x (numpy.ndarray): Current best solution
best_fitness (float): Current best solution's fitness/function value
**params:
Returns:
Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
1. New population.
2. New population function/fitness values.
3. New global best solution.
4. New global best fitness.
5. Additional arguments.
"""
amplitude_cf = params.pop('amplitude_cf')
sparks_num = self.sparks_num(population_fitness)
amplitudes = self.explosion_amplitudes(population_fitness)
cf_sparks_num = self.num_sparks * (np.amax(population_fitness) - best_fitness + self.epsilon) / \
(np.sum(np.amax(population_fitness - best_fitness)) + self.epsilon)
if cf_sparks_num < self.a * self.num_sparks:
cf_sparks_num = round(self.a * self.num_sparks)
elif cf_sparks_num > self.b * self.num_sparks and self.a < self.b < 1:
cf_sparks_num = round(self.b * self.num_sparks)
else:
cf_sparks_num = round(cf_sparks_num)
all_sparks = population.copy()
for i in range(self.population_size):
si = sparks_num[i]
ai = amplitudes[i]
sparks_i = np.empty((si, task.dimension))
for s in range(si):
sparks_i[s] = population[i]
sparks_i[s] = self.explosion_spark(sparks_i[s], ai, task)
all_sparks = np.concatenate((all_sparks, sparks_i), axis=0)
cf_sparks = np.empty((cf_sparks_num, task.dimension))
for s in range(cf_sparks_num):
cf_sparks[s] = best_x
cf_sparks[s] = self.explosion_spark(cf_sparks[s], amplitude_cf, task)
population, population_fitness = self.selection(population, population_fitness, all_sparks, task)
best_x, best_fitness, amplitude_cf = self.update_cf(cf_sparks, population[0], population_fitness[0], best_x,
best_fitness, amplitude_cf, task)
return population, population_fitness, best_x, best_fitness, {'amplitude_cf': amplitude_cf}