pyVolutionary 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. pyvolutionary/__init__.py +44 -0
  2. pyvolutionary/abstract.py +325 -0
  3. pyvolutionary/african_vulture/__init__.py +2 -0
  4. pyvolutionary/african_vulture/african_vulture_optimization.py +87 -0
  5. pyvolutionary/african_vulture/models.py +41 -0
  6. pyvolutionary/ant_colony/__init__.py +2 -0
  7. pyvolutionary/ant_colony/ant_colony_optimization.py +80 -0
  8. pyvolutionary/ant_colony/models.py +25 -0
  9. pyvolutionary/aquila/__init__.py +2 -0
  10. pyvolutionary/aquila/aquila_optimization.py +75 -0
  11. pyvolutionary/aquila/models.py +9 -0
  12. pyvolutionary/bacterial_foraging/__init__.py +2 -0
  13. pyvolutionary/bacterial_foraging/bacterial_foraging_optimization.py +152 -0
  14. pyvolutionary/bacterial_foraging/models.py +63 -0
  15. pyvolutionary/bat/__init__.py +2 -0
  16. pyvolutionary/bat/bat_optimization.py +66 -0
  17. pyvolutionary/bat/models.py +66 -0
  18. pyvolutionary/bee_colony/__init__.py +2 -0
  19. pyvolutionary/bee_colony/bee_colony_optimization.py +116 -0
  20. pyvolutionary/bee_colony/models.py +22 -0
  21. pyvolutionary/camel_caravan/__init__.py +2 -0
  22. pyvolutionary/camel_caravan/camel_caravan_optimization.py +96 -0
  23. pyvolutionary/camel_caravan/models.py +61 -0
  24. pyvolutionary/coral_reef/__init__.py +2 -0
  25. pyvolutionary/coral_reef/coral_reef_optimization.py +133 -0
  26. pyvolutionary/coral_reef/models.py +81 -0
  27. pyvolutionary/coyotes/__init__.py +2 -0
  28. pyvolutionary/coyotes/coyotes_optimization.py +96 -0
  29. pyvolutionary/coyotes/models.py +22 -0
  30. pyvolutionary/earthworms/__init__.py +2 -0
  31. pyvolutionary/earthworms/earthworms_optimization.py +124 -0
  32. pyvolutionary/earthworms/models.py +62 -0
  33. pyvolutionary/electromagnetic_field/__init__.py +2 -0
  34. pyvolutionary/electromagnetic_field/electromagnetic_field_optimization.py +58 -0
  35. pyvolutionary/electromagnetic_field/models.py +45 -0
  36. pyvolutionary/elephant_herd/__init__.py +2 -0
  37. pyvolutionary/elephant_herd/elephant_herd_optimization.py +56 -0
  38. pyvolutionary/elephant_herd/models.py +38 -0
  39. pyvolutionary/enums.py +39 -0
  40. pyvolutionary/firefly_swarm/__init__.py +2 -0
  41. pyvolutionary/firefly_swarm/firefly_swarm_optimization.py +76 -0
  42. pyvolutionary/firefly_swarm/models.py +37 -0
  43. pyvolutionary/fireworks/__init__.py +2 -0
  44. pyvolutionary/fireworks/fireworks_optimization.py +96 -0
  45. pyvolutionary/fireworks/models.py +41 -0
  46. pyvolutionary/fish_school_search/__init__.py +2 -0
  47. pyvolutionary/fish_school_search/fish_school_search_optimization.py +142 -0
  48. pyvolutionary/fish_school_search/models.py +27 -0
  49. pyvolutionary/flower_pollination_algorithm/__init__.py +2 -0
  50. pyvolutionary/flower_pollination_algorithm/flower_pollination_algorithm_optimization.py +46 -0
  51. pyvolutionary/flower_pollination_algorithm/models.py +29 -0
  52. pyvolutionary/forest_algorithm/__init__.py +2 -0
  53. pyvolutionary/forest_algorithm/forest_optimization_algorithm.py +121 -0
  54. pyvolutionary/forest_algorithm/models.py +53 -0
  55. pyvolutionary/fox/__init__.py +2 -0
  56. pyvolutionary/fox/fox_optimization.py +43 -0
  57. pyvolutionary/fox/models.py +29 -0
  58. pyvolutionary/genetic_algorithm/__init__.py +2 -0
  59. pyvolutionary/genetic_algorithm/genetic_algorithm_optimization.py +167 -0
  60. pyvolutionary/genetic_algorithm/models.py +21 -0
  61. pyvolutionary/grasshopper/__init__.py +2 -0
  62. pyvolutionary/grasshopper/grasshopper_optimization_algorithm.py +73 -0
  63. pyvolutionary/grasshopper/models.py +29 -0
  64. pyvolutionary/grey_wolf/__init__.py +2 -0
  65. pyvolutionary/grey_wolf/grey_wolf_optimization.py +62 -0
  66. pyvolutionary/grey_wolf/models.py +9 -0
  67. pyvolutionary/harmony_search/__init__.py +2 -0
  68. pyvolutionary/harmony_search/harmony_search_optimization.py +64 -0
  69. pyvolutionary/harmony_search/models.py +29 -0
  70. pyvolutionary/helpers.py +290 -0
  71. pyvolutionary/imperialist_competitive/__init__.py +2 -0
  72. pyvolutionary/imperialist_competitive/classes.py +119 -0
  73. pyvolutionary/imperialist_competitive/imperialist_competitive_optimization.py +198 -0
  74. pyvolutionary/imperialist_competitive/models.py +47 -0
  75. pyvolutionary/invasive_weed/__init__.py +2 -0
  76. pyvolutionary/invasive_weed/invasive_weed_optimization.py +52 -0
  77. pyvolutionary/invasive_weed/models.py +51 -0
  78. pyvolutionary/krill_herd/__init__.py +2 -0
  79. pyvolutionary/krill_herd/krill_herd_optimization.py +179 -0
  80. pyvolutionary/krill_herd/models.py +62 -0
  81. pyvolutionary/levi_jaya_swarm/__init__.py +2 -0
  82. pyvolutionary/levi_jaya_swarm/levy_flight_jaya_swarm_optimization.py +40 -0
  83. pyvolutionary/levi_jaya_swarm/models.py +9 -0
  84. pyvolutionary/models.py +130 -0
  85. pyvolutionary/monarch_butterfly/__init__.py +2 -0
  86. pyvolutionary/monarch_butterfly/models.py +25 -0
  87. pyvolutionary/monarch_butterfly/monarch_butterfly_optimization.py +104 -0
  88. pyvolutionary/mountain_gazelle/__init__.py +2 -0
  89. pyvolutionary/mountain_gazelle/models.py +9 -0
  90. pyvolutionary/mountain_gazelle/mountain_gazelle_optimization.py +118 -0
  91. pyvolutionary/osprey/__init__.py +2 -0
  92. pyvolutionary/osprey/models.py +9 -0
  93. pyvolutionary/osprey/osprey_optimization.py +54 -0
  94. pyvolutionary/particle_swarm/__init__.py +2 -0
  95. pyvolutionary/particle_swarm/models.py +40 -0
  96. pyvolutionary/particle_swarm/particle_swarm_optimization.py +78 -0
  97. pyvolutionary/pathfinder_algorithm/__init__.py +2 -0
  98. pyvolutionary/pathfinder_algorithm/models.py +12 -0
  99. pyvolutionary/pathfinder_algorithm/pathfinder_algorithm_optimization.py +56 -0
  100. pyvolutionary/pelican/__init__.py +2 -0
  101. pyvolutionary/pelican/models.py +9 -0
  102. pyvolutionary/pelican/pelican_optimization.py +46 -0
  103. pyvolutionary/seagull/__init__.py +2 -0
  104. pyvolutionary/seagull/models.py +21 -0
  105. pyvolutionary/seagull/seagull_optimization.py +43 -0
  106. pyvolutionary/siberian_tiger/__init__.py +2 -0
  107. pyvolutionary/siberian_tiger/models.py +9 -0
  108. pyvolutionary/siberian_tiger/siberian_tiger_optimization.py +53 -0
  109. pyvolutionary/tasmanian_devil/__init__.py +2 -0
  110. pyvolutionary/tasmanian_devil/models.py +9 -0
  111. pyvolutionary/tasmanian_devil/tasmanian_devil_optimization.py +69 -0
  112. pyvolutionary/tests/fixtures.py +21 -0
  113. pyvolutionary/tests/test_african_vulture_optimization.py +34 -0
  114. pyvolutionary/tests/test_ant_colony_optimization.py +34 -0
  115. pyvolutionary/tests/test_aquila_optimization.py +27 -0
  116. pyvolutionary/tests/test_bacterial_foraging_optimization.py +37 -0
  117. pyvolutionary/tests/test_bat_optimization.py +34 -0
  118. pyvolutionary/tests/test_bee_colony_optimization.py +32 -0
  119. pyvolutionary/tests/test_camel_caravan_optimization.py +37 -0
  120. pyvolutionary/tests/test_coral_reef_optimization.py +39 -0
  121. pyvolutionary/tests/test_coyotes_optimization.py +32 -0
  122. pyvolutionary/tests/test_earthworms_optimization.py +37 -0
  123. pyvolutionary/tests/test_electromagnetic_field_optimization.py +35 -0
  124. pyvolutionary/tests/test_elephant_herd_optimization.py +34 -0
  125. pyvolutionary/tests/test_firefly_swarm_optimization.py +34 -0
  126. pyvolutionary/tests/test_fireworks_algorithm_optimization.py +36 -0
  127. pyvolutionary/tests/test_fish_school_search_optimization.py +37 -0
  128. pyvolutionary/tests/test_flower_pollination_algorithm_optimization.py +33 -0
  129. pyvolutionary/tests/test_forest_algorithm_optimization.py +36 -0
  130. pyvolutionary/tests/test_foxes_optimization.py +33 -0
  131. pyvolutionary/tests/test_genetic_algorithm_optimization.py +32 -0
  132. pyvolutionary/tests/test_grasshopper_optimization_algorithm.py +33 -0
  133. pyvolutionary/tests/test_grey_wolf_optimization.py +27 -0
  134. pyvolutionary/tests/test_harmony_search_optimization.py +33 -0
  135. pyvolutionary/tests/test_imperialist_competitive_optimization.py +40 -0
  136. pyvolutionary/tests/test_invasive_weed_optimization.py +34 -0
  137. pyvolutionary/tests/test_krill_herd_optimization.py +40 -0
  138. pyvolutionary/tests/test_levy_flight_jaya_swarm_optimization.py +33 -0
  139. pyvolutionary/tests/test_monarch_butterfly_optimization.py +33 -0
  140. pyvolutionary/tests/test_mountain_gazelle_optimization.py +27 -0
  141. pyvolutionary/tests/test_osprey_optimization.py +26 -0
  142. pyvolutionary/tests/test_particle_swarm_optimization.py +34 -0
  143. pyvolutionary/tests/test_pathfinder_algorithm_optimization.py +27 -0
  144. pyvolutionary/tests/test_pelican_optimization.py +27 -0
  145. pyvolutionary/tests/test_seagull_optimization.py +32 -0
  146. pyvolutionary/tests/test_siberian_tiger_optimization.py +27 -0
  147. pyvolutionary/tests/test_task_bounds.py +9 -0
  148. pyvolutionary/tests/test_tasmanian_devil_optimization.py +27 -0
  149. pyvolutionary/tests/test_utils.py +43 -0
  150. pyvolutionary/tests/test_virus_colony_search_optimization.py +33 -0
  151. pyvolutionary/tests/test_walrus_optimization.py +27 -0
  152. pyvolutionary/tests/test_whales_optimization.py +27 -0
  153. pyvolutionary/tests/test_wildebeest_herd_optimization.py +41 -0
  154. pyvolutionary/tests/test_zebra_optimization.py +27 -0
  155. pyvolutionary/utils.py +94 -0
  156. pyvolutionary/virus_colony_search/__init__.py +2 -0
  157. pyvolutionary/virus_colony_search/models.py +29 -0
  158. pyvolutionary/virus_colony_search/virus_colony_search_optimization.py +99 -0
  159. pyvolutionary/walrus/__init__.py +2 -0
  160. pyvolutionary/walrus/models.py +9 -0
  161. pyvolutionary/walrus/walrus_optimization.py +43 -0
  162. pyvolutionary/whales/__init__.py +2 -0
  163. pyvolutionary/whales/models.py +12 -0
  164. pyvolutionary/whales/whales_optimization.py +56 -0
  165. pyvolutionary/wildebeest_herd/__init__.py +2 -0
  166. pyvolutionary/wildebeest_herd/models.py +94 -0
  167. pyvolutionary/wildebeest_herd/wildebeest_herd_optimization.py +143 -0
  168. pyvolutionary/zebra/__init__.py +2 -0
  169. pyvolutionary/zebra/models.py +9 -0
  170. pyvolutionary/zebra/zebra_optimization.py +53 -0
  171. pyvolutionary-1.0.1.dist-info/METADATA +350 -0
  172. pyvolutionary-1.0.1.dist-info/RECORD +173 -0
  173. pyvolutionary-1.0.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,62 @@
1
+ from pydantic import field_validator, model_validator
2
+
3
+ from ..models import Agent, BaseOptimizationConfig
4
+
5
+
6
+ class Earthworm(Agent):
7
+ pass
8
+
9
+
10
+ class EarthwormsOptimizationConfig(BaseOptimizationConfig):
11
+ """
12
+ Configuration class of the Earthworms Optimization algorithm.
13
+ prob_mutate (float): [0, 1), probability of mutation of an earthworm.\n
14
+ prob_crossover (float): [0, 1), probability of crossover of an earthworm.\n
15
+ keep (int): [2, int(population_size/2)], number of earthworms to keep.\n
16
+ alpha (float): [0, 1), similarity factor.\n
17
+ beta (float): [0, 1), the initial proportional factor.\n
18
+ gamma (float): [0, 1), a sort cooling factor for beta.
19
+ """
20
+ prob_mutate: float
21
+ prob_crossover: float
22
+ keep: int
23
+ alpha: float
24
+ beta: float
25
+ gamma: float
26
+
27
+ @model_validator(mode="after")
28
+ def validate_keep(self) -> "EarthwormsOptimizationConfig":
29
+ if not 2 <= self.keep <= int(self.population_size / 2):
30
+ raise ValueError(f"keep must be a positive integer greater than 2 and lower than population_size / 2. "
31
+ f"Got {self.keep}")
32
+ return self
33
+
34
+ @field_validator("prob_mutate")
35
+ def correct_prob_mutate(cls, v):
36
+ if not 0 <= v < 1:
37
+ raise ValueError(f"\"prob_mutate\" must be a positive float lower than 1. Got {v}")
38
+ return v
39
+
40
+ @field_validator("prob_crossover")
41
+ def correct_prob_crossover(cls, v):
42
+ if not 0 <= v < 1:
43
+ raise ValueError(f"\"prob_crossover\" must be a positive float lower than 1. Got {v}")
44
+ return v
45
+
46
+ @field_validator("alpha")
47
+ def correct_alpha(cls, v):
48
+ if not 0 <= v < 1:
49
+ raise ValueError(f"\"alpha\" must be a positive float lower than 1. Got {v}")
50
+ return v
51
+
52
+ @field_validator("beta")
53
+ def correct_beta(cls, v):
54
+ if not 0 <= v < 1:
55
+ raise ValueError(f"\"beta\" must be a positive float lower than 1. Got {v}")
56
+ return v
57
+
58
+ @field_validator("gamma")
59
+ def correct_gamma(cls, v):
60
+ if not 0 <= v < 1:
61
+ raise ValueError(f"\"gamma\" must be a positive float lower than 1. Got {v}")
62
+ return v
@@ -0,0 +1,2 @@
1
+ from .models import Electromagnet, ElectromagneticFieldOptimizationConfig
2
+ from .electromagnetic_field_optimization import ElectromagneticFieldOptimization
@@ -0,0 +1,58 @@
1
+ import numpy as np
2
+
3
+ from ..helpers import parse_obj_doc # type: ignore
4
+ from ..abstract import OptimizationAbstract
5
+ from .models import Electromagnet, ElectromagneticFieldOptimizationConfig
6
+
7
+
8
+ class ElectromagneticFieldOptimization(OptimizationAbstract):
9
+ """
10
+ Implementation of the Electromagnetic Field Optimization (EFO) algorithm.
11
+
12
+ Args:
13
+ config (ElectromagneticFieldOptimizationConfig): an instance of ElectromagneticFieldOptimizationConfig class.
14
+ {parse_obj_doc(ElectromagneticFieldOptimizationConfig)}
15
+
16
+ Bibliography
17
+ ----------
18
+ [1] Abedinpourshotorban, H., Shamsuddin, S.M., Beheshti, Z. and Jawawi, D.N., 2016. Electromagnetic field
19
+ optimization: a physics-inspired metaheuristic optimization algorithm. Swarm and Evolutionary Computation, 26,
20
+ pp.8-22.
21
+ """
22
+ def __init__(self, config: ElectromagneticFieldOptimizationConfig, debug: bool | None = False):
23
+ super().__init__(config, debug)
24
+ self.__phi = (1 + np.sqrt(5)) / 2 # golden ratio
25
+
26
+ def optimization_step(self):
27
+ pop_size = self._config.population_size
28
+ n_field = int(pop_size * (1 - self._config.n_field))
29
+ n_field1 = int(pop_size * self._config.p_field + 1)
30
+ p_field = int(pop_size * self._config.p_field)
31
+ ps_rate = self._config.ps_rate
32
+
33
+ phi = self.__phi
34
+ r_rate = self._config.r_rate
35
+ n_dims = self._task.space_dimension
36
+
37
+ best_pos = np.array(self._best_agent.position)
38
+ for idx, electromagnet in enumerate(self._population):
39
+ if np.random.random() < ps_rate:
40
+ r_idx1 = np.random.randint(0, p_field) # top
41
+ r_idx2 = np.random.randint(n_field, pop_size) # bottom
42
+ r_idx3 = np.random.randint(n_field1, n_field) # middle
43
+
44
+ pos_new = np.array(self._population[r_idx1].position) + phi * np.random.random() * (
45
+ best_pos - np.array(self._population[r_idx3].position)
46
+ ) + np.random.random() * (best_pos - np.array(self._population[r_idx2].position))
47
+ else:
48
+ pos_new = self._init_position()
49
+
50
+ # replacement of one electromagnet of generated particle with a random number
51
+ # (only for some generated particles) to bring diversity to the population
52
+ if np.random.random() < r_rate:
53
+ pos_new[np.random.randint(0, n_dims)] = self._uniform_coordinates(np.random.randint(0, n_dims))
54
+
55
+ # checking whether the generated number is inside boundary or not
56
+ agent = self._init_agent(self._correct_position(pos_new))
57
+
58
+ self._population[idx] = self._greedy_select_agent(electromagnet, agent)
@@ -0,0 +1,45 @@
1
+ from pydantic import field_validator
2
+
3
+ from ..models import Agent, BaseOptimizationConfig
4
+
5
+
6
+ class Electromagnet(Agent):
7
+ pass
8
+
9
+
10
+ class ElectromagneticFieldOptimizationConfig(BaseOptimizationConfig):
11
+ """
12
+ Configuration class for the Electromagnetic Field Optimization algorithm.
13
+ r_rate (float): [0.1, 0.6], like mutation parameter in GA but for one variable.\n
14
+ ps_rate (float): [0.5, 0.95], like crossover parameter in GA.\n
15
+ p_field (float): [0.05, 0.3], portion of population, positive field.\n
16
+ n_field (float): [0.3, 0.7], portion of population, negative field.
17
+ """
18
+ r_rate: float
19
+ ps_rate: float
20
+ p_field: float
21
+ n_field: float
22
+
23
+ @field_validator("r_rate")
24
+ def r_rate_validator(cls, v):
25
+ if not 0.1 <= v <= 0.6:
26
+ raise ValueError("r_rate must be between 0.1 and 0.6")
27
+ return v
28
+
29
+ @field_validator("ps_rate")
30
+ def ps_rate_validator(cls, v):
31
+ if not 0.5 <= v <= 0.95:
32
+ raise ValueError("ps_rate must be between 0.5 and 0.95")
33
+ return v
34
+
35
+ @field_validator("p_field")
36
+ def p_field_validator(cls, v):
37
+ if not 0.05 <= v <= 0.3:
38
+ raise ValueError("p_field must be between 0.05 and 0.3")
39
+ return v
40
+
41
+ @field_validator("n_field")
42
+ def n_field_validator(cls, v):
43
+ if not 0.3 <= v <= 0.7:
44
+ raise ValueError("n_field must be between 0.3 and 0.7")
45
+ return v
@@ -0,0 +1,2 @@
1
+ from .models import Elephant, ElephantHerdOptimizationConfig
2
+ from .elephant_herd_optimization import ElephantHerdOptimization
@@ -0,0 +1,56 @@
1
+ import numpy as np
2
+
3
+ from ..helpers import (
4
+ generate_group_population,
5
+ sort_by_cost,
6
+ parse_obj_doc, # type: ignore
7
+ )
8
+ from ..abstract import OptimizationAbstract
9
+ from .models import Elephant, ElephantHerdOptimizationConfig
10
+
11
+
12
+ class ElephantHerdOptimization(OptimizationAbstract):
13
+ """
14
+ Implementation of the Elephant Herd Optimization algorithm.
15
+
16
+ Args:
17
+ config (ElephantHerdOptimizationConfig): an instance of ElephantHerdOptimizationConfig class.
18
+ {parse_obj_doc(ElephantHerdOptimizationConfig)}
19
+
20
+ Bibliography
21
+ ----------
22
+ [1] Wang, G.G., Deb, S. and Coelho, L.D.S., 2015, December. Elephant herding optimization.
23
+ In 2015 3rd international symposium on computational and business intelligence (ISCBI) (pp. 1-5). IEEE.
24
+ """
25
+ def __init__(self, config: ElephantHerdOptimizationConfig, debug: bool | None = False):
26
+ super().__init__(config, debug)
27
+ self.__n_individuals: int = int(self._config.population_size / self._config.n_clans)
28
+ self.__groups: list[list[Elephant]] = []
29
+
30
+ def _init_population(self):
31
+ super()._init_population()
32
+ self.__groups = generate_group_population(self._population, self._config.n_clans, self.__n_individuals)
33
+
34
+ def optimization_step(self):
35
+ n_individuals = self.__n_individuals
36
+
37
+ for idx in range(0, self._config.population_size):
38
+ clan_idx = int(idx / n_individuals)
39
+ pos_group = [np.array(elephant.position) for elephant in self.__groups[clan_idx]]
40
+
41
+ # pos_clan_idx == 0 means the best in clan, because all clans are sorted based on cost
42
+ pos_clan_idx = int(idx % n_individuals)
43
+ pos_new = self._config.beta * np.mean(pos_group, axis=0) if pos_clan_idx == 0 else (
44
+ pos_group[pos_clan_idx] + self._config.alpha * np.random.random() * (
45
+ pos_group[0] - pos_group[pos_clan_idx]
46
+ )
47
+ )
48
+ self._population[idx] = self._greedy_select_agent(self._population[idx], self._init_agent(pos_new))
49
+
50
+ self.__groups = generate_group_population(self._population, self._config.n_clans, n_individuals)
51
+
52
+ # Separating operator
53
+ for idx in range(0, self._config.n_clans):
54
+ sort_by_cost(self.__groups[idx])
55
+ self.__groups[idx][-1] = self._init_agent()
56
+ self._population = [elephant for pack in self.__groups for elephant in pack]
@@ -0,0 +1,38 @@
1
+ from pydantic import field_validator, model_validator
2
+
3
+ from ..models import Agent, BaseOptimizationConfig
4
+
5
+
6
+ class Elephant(Agent):
7
+ pass
8
+
9
+
10
+ class ElephantHerdOptimizationConfig(BaseOptimizationConfig):
11
+ """
12
+ Configuration class of the Earthworms Optimization algorithm.
13
+ alpha (float): (0, 3), a factor that determines the influence of the best in each clan.\n
14
+ beta (float): (0, 1), a factor that determines the influence of the x_center.\n
15
+ n_clans (int): [2, int(population_size/5)], the number of clans.
16
+ """
17
+ alpha: float
18
+ beta: float
19
+ n_clans: int
20
+
21
+ @model_validator(mode="after")
22
+ def validate_n_clans(self) -> "ElephantHerdOptimizationConfig":
23
+ if not 2 <= self.n_clans <= int(self.population_size / 5):
24
+ raise ValueError(f"n_clans must be a positive integer greater than 2 and lower than population_size / 5. "
25
+ f"Got {self.n_clans}")
26
+ return self
27
+
28
+ @field_validator("alpha")
29
+ def correct_alpha(cls, v):
30
+ if not 0 < v < 3:
31
+ raise ValueError(f"\"alpha\" must be a positive float lower than 3. Got {v}")
32
+ return v
33
+
34
+ @field_validator("beta")
35
+ def correct_beta(cls, v):
36
+ if not 0 < v < 1:
37
+ raise ValueError(f"\"beta\" must be a positive float lower than 1. Got {v}")
38
+ return v
pyvolutionary/enums.py ADDED
@@ -0,0 +1,39 @@
1
+ from enum import Enum as BaseEnum, EnumMeta
2
+
3
+
4
+ class MetaEnum(EnumMeta):
5
+ """
6
+ Enables the use of the `in` operator for enums.
7
+ For example:
8
+ if el not in Elements:
9
+ raise ValueError("invalid element")
10
+ """
11
+
12
+ def __contains__(cls, item):
13
+ try:
14
+ cls(item) # pylint: disable=E1120
15
+ except ValueError:
16
+ return False
17
+ return True
18
+
19
+
20
+ class Enum(BaseEnum, metaclass=MetaEnum):
21
+ def __str__(self):
22
+ return self.value
23
+
24
+
25
+ class TaskType(Enum):
26
+ """
27
+ The type of task that the user wants to perform.
28
+ """
29
+ MIN = "min"
30
+ MAX = "max"
31
+
32
+
33
+ class ModeSolver(Enum):
34
+ """
35
+ The mode of the solver.
36
+ """
37
+ SERIAL = "serial"
38
+ THREAD = "thread"
39
+ PROCESS = "process"
@@ -0,0 +1,2 @@
1
+ from .models import Firefly, FireflySwarmOptimizationConfig
2
+ from .firefly_swarm_optimization import FireflySwarmOptimization
@@ -0,0 +1,76 @@
1
+ import numpy as np
2
+
3
+ from ..helpers import (
4
+ best_agent,
5
+ distance,
6
+ parse_obj_doc, # type: ignore
7
+ )
8
+ from ..abstract import OptimizationAbstract
9
+ from .models import Firefly, FireflySwarmOptimizationConfig
10
+
11
+
12
+ class FireflySwarmOptimization(OptimizationAbstract):
13
+ """
14
+ Implementation of the Firefly Swarm Optimization algorithm.
15
+
16
+ Args:
17
+ config (FireflySwarmOptimizationConfig): an instance of FireflySwarmOptimizationConfig class.
18
+ {parse_obj_doc(FireflySwarmOptimizationConfig)}
19
+
20
+ Bibliography
21
+ ----------
22
+ [1] Yang, Xin-She. "Firefly algorithms for multimodal optimization". International symposium on stochastic algorithms.
23
+ Springer, Berlin, Heidelberg, 2009.
24
+ [2] Yang, Xin-She. "Firefly algorithm, stochastic test functions and design optimization." International Journal of
25
+ Bio-Inspired Computation 2.2 (2010): 78-84. https://doi.org/10.1504/IJBIC.2010.032124
26
+ [3] Yang, Xin-She. "Firefly algorithm, Levy flights and global optimization." Research and development in intelligent
27
+ systems XXVI. Springer, London, 2010. 209-218. https://doi.org/10.1007/978-1-84996-153-4_15
28
+ """
29
+
30
+ def __init__(self, config: FireflySwarmOptimizationConfig, debug: bool | None = False):
31
+ super().__init__(config, debug)
32
+
33
+ def __update_alpha__(self):
34
+ """
35
+ Update alpha parameter. This parameter is used to control the randomness of the movement of the fireflies.
36
+ """
37
+ delta = 1.0 - (10.0 ** -4.0 / 0.9) ** (1.0 / self._cycles)
38
+ self._config.alpha *= (1 - delta) * self._config.alpha
39
+
40
+ def __update_population__(self):
41
+ """
42
+ Update the population of fireflies. This method is called at each iteration of the algorithm. It updates the
43
+ position of each firefly based on the position of the other fireflies. The fireflies with the best fitness
44
+ values will attract the other fireflies and the fireflies with the worst fitness values will be attracted by the
45
+ other fireflies. The fireflies with the best fitness values will move towards the fireflies with the worst
46
+ fitness values. The fireflies with the worst fitness values will move away from the fireflies with the best
47
+ fitness values.
48
+ """
49
+ alpha = self._config.alpha
50
+ beta_min = self._config.beta_min
51
+ gamma = self._config.gamma
52
+
53
+ n_dims = self._task.space_dimension
54
+ pop_size = self._config.population_size
55
+ for idx in range(0, self._config.population_size):
56
+ position = self._population[idx].position
57
+ cost = self._population[idx].cost
58
+ weighted_pos = [np.array(position) + beta_min * np.exp(
59
+ -gamma * distance(position, firefly.position) / np.sqrt(n_dims)
60
+ ) * np.matmul(
61
+ np.array(firefly.position) - np.array(position), np.random.uniform(0, 1, (n_dims, n_dims))
62
+ ) + alpha * np.random.uniform(0, 1, n_dims)
63
+ for firefly in self._population[idx+1:] if firefly.cost < cost]
64
+
65
+ new_agents = (
66
+ [self._init_agent(position) for position in weighted_pos] +
67
+ [self._init_agent() for _ in range(0, pop_size - len(weighted_pos) + 1)]
68
+ )
69
+ self._population[idx] = best_agent(new_agents)
70
+
71
+ def optimization_step(self):
72
+ # update alpha
73
+ self.__update_alpha__()
74
+
75
+ # replace old population
76
+ self.__update_population__()
@@ -0,0 +1,37 @@
1
+ from pydantic import field_validator
2
+
3
+ from ..models import Agent, BaseOptimizationConfig
4
+
5
+
6
+ class Firefly(Agent):
7
+ pass
8
+
9
+
10
+ class FireflySwarmOptimizationConfig(BaseOptimizationConfig):
11
+ """
12
+ Configuration class of the Firefly Swarm Optimization algorithm.
13
+ alpha (float): [0, 1), the attractiveness constant of the fireflies.\n
14
+ beta_min (float): [0, 1), the minimum value of the attractiveness constant of the fireflies.\n
15
+ gamma (float): [0, 1), the light absorption coefficient.
16
+ """
17
+ alpha: float
18
+ beta_min: float
19
+ gamma: float
20
+
21
+ @field_validator("alpha")
22
+ def correct_alpha(cls, v):
23
+ if not 0 <= v < 1:
24
+ raise ValueError(f"\"alpha\" must be a positive float lower than 1. Got {v}")
25
+ return v
26
+
27
+ @field_validator("beta_min")
28
+ def correct_beta_min(cls, v):
29
+ if not 0 <= v < 1:
30
+ raise ValueError(f"\"beta_min\" must be a positive float lower than 1. Got {v}")
31
+ return v
32
+
33
+ @field_validator("gamma")
34
+ def correct_gamma(cls, v):
35
+ if not 0 <= v < 1:
36
+ raise ValueError(f"\"gamma\" must be a positive float lower than 1. Got {v}")
37
+ return v
@@ -0,0 +1,2 @@
1
+ from .models import Firework, FireworksOptimizationConfig
2
+ from .fireworks_optimization import FireworksOptimization
@@ -0,0 +1,96 @@
1
+ from typing import Final
2
+ import numpy as np
3
+
4
+ from ..helpers import parse_obj_doc # type: ignore
5
+ from ..abstract import OptimizationAbstract
6
+ from .models import Firework, FireworksOptimizationConfig
7
+
8
+
9
+ class FireworksOptimization(OptimizationAbstract):
10
+ """
11
+ Implementation of the Fireworks Algorithm Optimization algorithm.
12
+
13
+ Args:
14
+ config (FireworksOptimizationConfig): an instance of FireworksAlgorithmOptimizationConfig class.
15
+ {parse_obj_doc(FireworksOptimizationConfig)}
16
+
17
+ Bibliography
18
+ ----------
19
+ [1] Yang, X. S. (2010). Fireworks algorithm for optimization. International Journal of Bio-Inspired Computation,
20
+ 2(4), 78–84. https://doi.org/10.1504/IJBIC.2010.037285
21
+ [2] Yang, X. S. (2010). Fireworks Algorithm: A Novel Swarm Intelligence Optimization Method. In Nature Inspired
22
+ Cooperative Strategies for Optimization (pp. 355–364). Springer Berlin Heidelberg.
23
+ https://doi.org/10.1007/978-3-642-12538-6_35
24
+ [3] Yang, X. S. (2012). Fireworks Algorithm for Optimization. In Nature-Inspired Optimization Algorithms
25
+ (pp. 355–364). Elsevier. https://doi.org/10.1016/B978-0-12-416743-8.00016-2
26
+ [4] Yang, X. S. (2013). Fireworks Algorithm: Recent Advances and Applications. In Studies in Computational
27
+ Intelligence (Vol. 476, pp. 355–364). Springer Berlin Heidelberg. https://doi.org/10.1007/978-3-642-31688-4_17
28
+ [5] Yang, X. S. (2014). Fireworks Algorithm: A Novel Swarm Intelligence Optimization Method. In Nature-Inspired
29
+ Computation in Engineering (pp. 355–364). Springer Berlin Heidelberg. https://doi.org/10.1007/978-3-642-39829-2_35
30
+ [6] Yang, X. S. (2015). Fireworks Algorithm: A Survey. International Journal of Swarm Intelligence Research,
31
+ 5(1), 1–18. https://doi.org/10.4018/IJSIR.2015010101
32
+ """
33
+ EPS: Final[float] = np.finfo(float).eps
34
+
35
+ def __init__(self, config: FireworksOptimizationConfig, debug: bool | None = False):
36
+ super().__init__(config, debug)
37
+
38
+ def __explode__(self) -> list[Firework]:
39
+ """
40
+ This method performs the explosion of the fireworks. It generates new fireworks by exploding the current ones.
41
+ Gaussian sparks are generated by each firework. The number of sparks is proportional to the cost of the
42
+ firework. The amplitude of the explosion is proportional to the cost of the firework. The new fireworks are
43
+ generated by adding the amplitude to the position of the firework. The new fireworks are then corrected to
44
+ be within the bounds of the search space. The new fireworks are then added to the population.
45
+ :return: the new population
46
+ :rtype: list[Firework]
47
+ """
48
+ costs = sorted([firework.cost for firework in self._population])
49
+
50
+ sparks_num = self._config.sparks_num
51
+ pop_size = self._config.population_size
52
+ explosion_amplitude = self._config.explosion_amplitude
53
+ a = self._config.a
54
+ b = self._config.b
55
+
56
+ n_dims = self._task.space_dimension
57
+
58
+ pop_new = []
59
+ for firework in self._population:
60
+ si = sparks_num * (costs[-1] - firework.cost + self.EPS) / (pop_size * costs[-1] - np.sum(costs) + self.EPS)
61
+ Ai = explosion_amplitude * (firework.cost - costs[0] + self.EPS) / (np.sum(costs) - costs[0] + self.EPS)
62
+
63
+ si_ = int(round(si) + 1)
64
+ if si < a * sparks_num:
65
+ si_ = int(round(a * sparks_num) + 1)
66
+ elif si > b * sparks_num:
67
+ si_ = int(round(b * sparks_num) + 1)
68
+
69
+ # generate Gaussian sparks
70
+ for j in range(0, si_):
71
+ pos_new = firework.position
72
+ list_idx = np.random.choice(range(0, n_dims), round(np.random.uniform() * n_dims), replace=False)
73
+ pos_new = [pos_new[i] + int(i in list_idx) * Ai * np.random.uniform(-1, 1) for i in range(0, n_dims)]
74
+ pop_new.append(Firework(**self._init_agent(pos_new).model_dump()))
75
+
76
+ return pop_new
77
+
78
+ def __evolve__(self, candidates: list[Firework]) -> list[Firework]:
79
+ sparks_num = self._config.sparks_num
80
+ pop_size = self._config.population_size
81
+ n_dims = self._task.space_dimension
82
+
83
+ for _ in range(0, sparks_num):
84
+ idx = np.random.randint(0, pop_size)
85
+ pos_new = self._population[idx].position
86
+ list_idx = np.random.choice(range(0, n_dims), round(np.random.uniform() * n_dims), replace=False)
87
+ # Gaussian explosion
88
+ pos_new = [pos_new[i] + int(i in list_idx) * np.random.normal(0, 1) for i in range(0, n_dims)]
89
+ candidates.append(Firework(**self._init_agent(pos_new).model_dump()))
90
+
91
+ return candidates
92
+
93
+ def optimization_step(self):
94
+ candidates = self.__evolve__(self.__explode__())
95
+ self._extend_and_trim_population(candidates)
96
+
@@ -0,0 +1,41 @@
1
+ from pydantic import model_validator, field_validator
2
+
3
+ from ..models import Agent, BaseOptimizationConfig
4
+
5
+
6
+ class Firework(Agent):
7
+ pass
8
+
9
+
10
+ class FireworksOptimizationConfig(BaseOptimizationConfig):
11
+ """
12
+ Configuration class of the Fireworks Algorithm.
13
+ sparks_num (int): number of sparks to be generated by each firework.\n
14
+ a (float): (0, 1), parameter to control the explosion amplitude.\n
15
+ b (float): (0, 1), parameter to control the explosion amplitude.\n
16
+ explosion_amplitude (int): maximum amplitude of the explosion.\n
17
+ gaussian_explosion_number (int): number of gaussian explosions (less than the population size).
18
+ """
19
+ sparks_num: int
20
+ a: float
21
+ b: float
22
+ explosion_amplitude: int
23
+ gaussian_explosion_number: int
24
+
25
+ @model_validator(mode="after")
26
+ def validate_gaussian_explosion_number(self) -> "FireworksOptimizationConfig":
27
+ if self.gaussian_explosion_number > self.population_size:
28
+ raise ValueError("\"gaussian_explosion_number\" must be less than or equal to population_size")
29
+ return self
30
+
31
+ @field_validator("a")
32
+ def correct_a(cls, v):
33
+ if not 0 < v < 1:
34
+ raise ValueError(f"\"a\" must be a positive float lower than 1. Got {v}")
35
+ return v
36
+
37
+ @field_validator("b")
38
+ def correct_b(cls, v):
39
+ if not 0 < v < 1:
40
+ raise ValueError(f"\"b\" must be a positive float lower than 1. Got {v}")
41
+ return v
@@ -0,0 +1,2 @@
1
+ from .models import Fish, FishSchoolSearchOptimizationConfig
2
+ from .fish_school_search_optimization import FishSchoolSearchOptimization