Skip to content

Commit 41693bd

Browse files
committed
Adds firefly algorithm
1 parent b44b0c6 commit 41693bd

9 files changed

+164
-0
lines changed
3.63 KB
Binary file not shown.

__pycache__/functions.cpython-35.pyc

2.19 KB
Binary file not shown.

__pycache__/parameters.cpython-35.pyc

270 Bytes
Binary file not shown.

__pycache__/particle.cpython-35.pyc

1017 Bytes
Binary file not shown.

firefly_algorithm.py

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

functions.py

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import math
2+
3+
from abc import ABCMeta, abstractmethod
4+
5+
6+
class AFunction:
7+
__metaclass__ = ABCMeta
8+
9+
upper_bound = 100
10+
lower_bound = -100
11+
12+
@abstractmethod
13+
def calculate_fitness(self, position):
14+
pass
15+
16+
17+
class Sphere(AFunction):
18+
19+
def __init__(self):
20+
AFunction.upper_bound = 100
21+
AFunction.lower_bound = -100
22+
23+
def calculate_fitness(self, position_list):
24+
solution = 0
25+
for position in position_list:
26+
solution += position ** 2
27+
return solution
28+
29+
30+
class Rastrigin(AFunction):
31+
32+
def __init__(self):
33+
AFunction.upper_bound = 5.12
34+
AFunction.lower_bound = -5.12
35+
36+
def calculate_fitness(self, position_list):
37+
solution = 0
38+
for position in position_list:
39+
solution += (position ** 2 + 10 - 10 * math.cos(2 * math.pi * position))
40+
return solution
41+
42+
43+
class Rosenbrocks(AFunction):
44+
45+
def __init__(self):
46+
AFunction.upper_bound = 30
47+
AFunction.lower_bound = -30
48+
49+
def calculate_fitness(self, position_list):
50+
solution = 0
51+
for i in range(0, len(position_list) - 1):
52+
solution += (100 * ((position_list[i] ** 2 - position_list[i + 1]) ** 2) + ((position_list[i] - 1) ** 2))
53+
return solution

main.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from firefly_algorithm import Firefly
2+
from functions import Sphere, Rastrigin
3+
4+
5+
def main():
6+
f = Firefly(Rastrigin())
7+
f.search()
8+
9+
10+
main()

parameters.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
iterations_number = 10000
2+
num_of_individuos = 30
3+
probability_of_recombination = 0.6
4+
dimensions = 30

particle.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import copy
2+
3+
4+
class Particle():
5+
6+
def __init__(self, function_wrapper, positions):
7+
self.function_wrapper = function_wrapper
8+
self.current_position = positions
9+
self.best_particle = self.current_position
10+
self.fitness = 1.0
11+
12+
def aply_function_on_current_position(self):
13+
self.fitness = self.function_wrapper.calculate_fitness(self.current_position)
14+
15+
def clone_particle(self):
16+
clone_object = copy.copy(self)
17+
clone_object.current_position = copy.deepcopy(self.current_position)
18+
clone_object.fitness = copy.deepcopy(self.fitness)
19+
return clone_object

0 commit comments

Comments
 (0)