1
|
|
|
# encoding=utf8 |
2
|
|
|
import logging |
3
|
|
|
|
4
|
|
|
from numpy import apply_along_axis, zeros, argsort, concatenate, array, exp, cos, pi |
5
|
|
|
|
6
|
|
|
from NiaPy.algorithms.algorithm import Algorithm |
7
|
|
|
|
8
|
|
|
logging.basicConfig() |
9
|
|
|
logger = logging.getLogger('NiaPy.algorithms.basic') |
10
|
|
|
logger.setLevel('INFO') |
11
|
|
|
|
12
|
|
|
__all__ = ['MothFlameOptimizer'] |
13
|
|
|
|
14
|
|
|
class MothFlameOptimizer(Algorithm): |
15
|
|
|
r"""MothFlameOptimizer of Moth flame optimizer. |
16
|
|
|
|
17
|
|
|
Algorithm: |
18
|
|
|
Moth flame optimizer |
19
|
|
|
|
20
|
|
|
Date: |
21
|
|
|
2018 |
22
|
|
|
|
23
|
|
|
Author: |
24
|
|
|
Kivanc Guckiran and Klemen Berkovič |
25
|
|
|
|
26
|
|
|
License: |
27
|
|
|
MIT |
28
|
|
|
|
29
|
|
|
Reference paper: |
30
|
|
|
Mirjalili, Seyedali. "Moth-flame optimization algorithm: A novel nature-inspired heuristic paradigm." Knowledge-Based Systems 89 (2015): 228-249. |
31
|
|
|
|
32
|
|
|
Attributes: |
33
|
|
|
Name (List[str]): List of strings representing algorithm name. |
34
|
|
|
|
35
|
|
|
See Also: |
36
|
|
|
* :class:`NiaPy.algorithms.algorithm.Algorithm` |
37
|
|
|
""" |
38
|
|
|
Name = ['MothFlameOptimizer', 'MFO'] |
39
|
|
|
|
40
|
|
|
@staticmethod |
41
|
|
|
def algorithmInfo(): |
42
|
|
|
r"""Get basic information of algorithm. |
43
|
|
|
|
44
|
|
|
Returns: |
45
|
|
|
str: Basic information. |
46
|
|
|
|
47
|
|
|
See Also: |
48
|
|
|
* :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
49
|
|
|
""" |
50
|
|
|
return r"""Mirjalili, Seyedali. "Moth-flame optimization algorithm: A novel nature-inspired heuristic paradigm." Knowledge-Based Systems 89 (2015): 228-249.""" |
51
|
|
|
|
52
|
|
|
@staticmethod |
53
|
|
|
def typeParameters(): |
54
|
|
|
r"""Get dictionary with functions for checking values of parameters. |
55
|
|
|
|
56
|
|
|
Returns: |
57
|
|
|
Dict[str, Callable]: TODO |
58
|
|
|
|
59
|
|
|
See Also: |
60
|
|
|
* :func:`NiaPy.algorithms.algorithm.Algorithm.typeParameters` |
61
|
|
|
""" |
62
|
|
|
return Algorithm.typeParameters() |
63
|
|
|
|
64
|
|
|
def setParameters(self, NP=25, **ukwargs): |
65
|
|
|
r"""Set the algorithm parameters. |
66
|
|
|
|
67
|
|
|
Arguments: |
68
|
|
|
NP (int): Number of individuals in population |
69
|
|
|
|
70
|
|
|
See Also: |
71
|
|
|
* :func:`NiaPy.algorithms.algorithm.Algorithm.setParameters` |
72
|
|
|
""" |
73
|
|
|
Algorithm.setParameters(self, NP=NP, **ukwargs) |
74
|
|
|
|
75
|
|
|
def initPopulation(self, task): |
76
|
|
|
r"""Initialize starting population. |
77
|
|
|
|
78
|
|
|
Args: |
79
|
|
|
task (Task): Optimization task |
80
|
|
|
|
81
|
|
|
Returns: |
82
|
|
|
Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]: |
83
|
|
|
1. Initialized population |
84
|
|
|
2. Initialized population function/fitness values |
85
|
|
|
3. Additional arguments: |
86
|
|
|
* best_flames (numpy.ndarray): Best individuals |
87
|
|
|
* best_flame_fitness (numpy.ndarray): Best individuals fitness/function values |
88
|
|
|
* previous_population (numpy.ndarray): Previous population |
89
|
|
|
* previous_fitness (numpy.ndarray[float]): Previous population fitness/function values |
90
|
|
|
|
91
|
|
|
See Also: |
92
|
|
|
* :func:`NiaPy.algorithms.algorithm.Algorithm.initPopulation` |
93
|
|
|
""" |
94
|
|
|
moth_pos, moth_fitness, d = Algorithm.initPopulation(self, task) |
95
|
|
|
# Create best population |
96
|
|
|
indexes = argsort(moth_fitness) |
97
|
|
|
best_flames, best_flame_fitness = moth_pos[indexes], moth_fitness[indexes] |
98
|
|
|
# Init previous population |
99
|
|
|
previous_population, previous_fitness = zeros((self.NP, task.D)), zeros(self.NP) |
100
|
|
|
d.update({'best_flames': best_flames, 'best_flame_fitness': best_flame_fitness, 'previous_population': previous_population, 'previous_fitness': previous_fitness}) |
101
|
|
|
return moth_pos, moth_fitness, d |
102
|
|
|
|
103
|
|
|
def runIteration(self, task, moth_pos, moth_fitness, xb, fxb, best_flames, best_flame_fitness, previous_population, previous_fitness, **dparams): |
104
|
|
|
r"""Core function of MothFlameOptimizer algorithm. |
105
|
|
|
|
106
|
|
|
Args: |
107
|
|
|
task (Task): Optimization task. |
108
|
|
|
moth_pos (numpy.ndarray): Current population. |
109
|
|
|
moth_fitness (numpy.ndarray): Current population fitness/function values. |
110
|
|
|
xb (numpy.ndarray): Current population best individual. |
111
|
|
|
fxb (float): Current best individual |
112
|
|
|
best_flames (numpy.ndarray): Best found individuals |
113
|
|
|
best_flame_fitness (numpy.ndarray): Best found individuals fitness/function values |
114
|
|
|
previous_population (numpy.ndarray): Previous population |
115
|
|
|
previous_fitness (numpy.ndarray): Previous population fitness/function values |
116
|
|
|
**dparams (Dict[str, Any]): Additional parameters |
117
|
|
|
|
118
|
|
|
Returns: |
119
|
|
|
Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]: |
120
|
|
|
1. New population. |
121
|
|
|
2. New population fitness/function values. |
122
|
|
|
3. New global best solution |
123
|
|
|
4. New global best fitness/objective value |
124
|
|
|
5. Additional arguments: |
125
|
|
|
* best_flames (numpy.ndarray): Best individuals. |
126
|
|
|
* best_flame_fitness (numpy.ndarray): Best individuals fitness/function values. |
127
|
|
|
* previous_population (numpy.ndarray): Previous population. |
128
|
|
|
* previous_fitness (numpy.ndarray): Previous population fitness/function values. |
129
|
|
|
""" |
130
|
|
|
# Previous positions |
131
|
|
|
previous_population, previous_fitness = moth_pos, moth_fitness |
132
|
|
|
# Create sorted population |
133
|
|
|
indexes = argsort(moth_fitness) |
134
|
|
|
sorted_population = moth_pos[indexes] |
135
|
|
|
# Some parameters |
136
|
|
|
flame_no, a = round(self.NP - task.Iters * ((self.NP - 1) / task.nGEN)), -1 + task.Iters * ((-1) / task.nGEN) |
137
|
|
|
for i in range(self.NP): |
138
|
|
|
for j in range(task.D): |
139
|
|
|
distance_to_flame, b, t = abs(sorted_population[i, j] - moth_pos[i, j]), 1, (a - 1) * self.rand() + 1 |
140
|
|
|
if i <= flame_no: moth_pos[i, j] = distance_to_flame * exp(b * t) * cos(2 * pi * t) + sorted_population[i, j] |
141
|
|
|
else: moth_pos[i, j] = distance_to_flame * exp(b * t) * cos(2 * pi * t) + sorted_population[flame_no, j] |
142
|
|
|
moth_pos = apply_along_axis(task.repair, 1, moth_pos, self.Rand) |
143
|
|
|
moth_fitness = apply_along_axis(task.eval, 1, moth_pos) |
144
|
|
|
xb, fxb = self.getBest(moth_pos, moth_fitness, xb, fxb) |
145
|
|
|
double_population, double_fitness = concatenate((previous_population, best_flames), axis=0), concatenate((previous_fitness, best_flame_fitness), axis=0) |
146
|
|
|
indexes = argsort(double_fitness) |
147
|
|
|
double_sorted_fitness, double_sorted_population = double_fitness[indexes], double_population[indexes] |
148
|
|
|
for newIdx in range(2 * self.NP): double_sorted_population[newIdx] = array(double_population[indexes[newIdx], :]) |
149
|
|
|
best_flame_fitness, best_flames = double_sorted_fitness[:self.NP], double_sorted_population[:self.NP] |
150
|
|
|
return moth_pos, moth_fitness, xb, fxb, {'best_flames': best_flames, 'best_flame_fitness': best_flame_fitness, 'previous_population': previous_population, 'previous_fitness': previous_fitness} |
151
|
|
|
|
152
|
|
|
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3 |
153
|
|
|
|