-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfirefly_algorithm.py
79 lines (58 loc) · 2.58 KB
/
firefly_algorithm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import random
import math
from particle import Particle
from parameters import num_of_individuos, dimensions, iterations_number
class Firefly():
def __init__(self, function_wrapper):
self.function = function_wrapper
def search(self):
bests = []
self._initialize_particles()
beta_inicial = 1
light_rate = random.random()
for iterations in range(iterations_number):
for particle in self.population:
particle.aply_function_on_current_position()
population_cp = [particle.clone_particle() for particle in self.population]
for particle_i in self.population:
self._remove_matching_element_from_fireflies_copy(population_cp, particle_i)
for particle_j in population_cp:
if particle_i.fitness < particle_j.fitness:
distance = self._euclidian_distance(particle_i, particle_j)
beta = beta_inicial * math.exp(-1 * distance**2)
for index in range(dimensions):
new_location = particle_i.current_position[index] * (1 - beta) \
+ particle_j.current_position[index] * beta \
+ (random.random() - 0.5)
new_location = self.__constrain_within_range(new_location, index)
particle_i.current_position[index] = new_location
bests.append(self._select_best_firefly_by_fitness(self.population).fitness)
return bests
def __constrain_within_range(self, new_location, index):
if new_location < self.function.lower_bound:
return self.function.lower_bound
elif new_location > self.function.upper_bound:
return self.function.upper_bound
else:
return new_location
def _select_best_firefly_by_fitness(self, population):
return min(population, key=lambda particle: particle.fitness)
def _euclidian_distance(self, particle_i, particle_j):
total = 0
for i in range(dimensions):
distance = (particle_i.current_position[i] - particle_j.current_position[i])**2
total += distance
return math.sqrt(total)
def _remove_matching_element_from_fireflies_copy(self, fireflies_copy, firefly):
matching_fireflies_copy_element = next((fireflies_copy_element for fireflies_copy_element in fireflies_copy if fireflies_copy_element.fitness == firefly.fitness), None)
fireflies_copy.remove(matching_fireflies_copy_element)
def _get_random_number(self):
return (
self.function.lower_bound + random.uniform(0, 1) * (self.function.upper_bound - self.function.lower_bound)
)
def _initialize_particles(self):
self.population = []
for i in range(num_of_individuos):
random_position = [self._get_random_number() for index in range(dimensions)]
particle = Particle(self.function, random_position)
self.population.append(particle)