|
| 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) |
0 commit comments