pyVolutionary 2.7.0__tar.gz → 2.7.1__tar.gz

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 (263) hide show
  1. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/PKG-INFO +1 -1
  2. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyproject.toml +1 -1
  3. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/abstract.py +16 -0
  4. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bee_colony/bee_colony_optimization.py +4 -0
  5. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/brain_storm/brain_storm_optimization.py +16 -15
  6. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/brain_storm/improved_brain_storm_optimization.py +12 -12
  7. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/chernobyl_disaster/chernobyl_disaster_optimization.py +4 -0
  8. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coral_reef/coral_reef_optimization.py +3 -0
  9. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coyotes/coyotes_optimization.py +4 -0
  10. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/dwarf_mongoose/dwarf_mongoose_optimization.py +4 -0
  11. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/earthworms/earthworms_optimization.py +4 -0
  12. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/electromagnetic_field/electromagnetic_field_optimization.py +15 -4
  13. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/elephant_herd/elephant_herd_optimization.py +8 -10
  14. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/energy_valley/energy_valley_optimization.py +4 -0
  15. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/firehawk/firehawk_optimization.py +2 -1
  16. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/flower_pollination_algorithm/flower_pollination_algorithm_optimization.py +4 -0
  17. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/forensic_based_investigation/forensic_based_investigation_optimization.py +4 -0
  18. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/forest_algorithm/forest_optimization_algorithm.py +3 -3
  19. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/gaining_sharing_knowledge_algorithm/gaining_sharing_knowledge_optimization.py +20 -6
  20. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/genetic_algorithm/genetic_algorithm_optimization.py +5 -4
  21. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/germinal_center/germinal_center_optimization.py +4 -0
  22. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/grey_wolf/grey_wolf_optimization.py +4 -0
  23. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/helpers.py +20 -0
  24. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/nuclear_reaction/nuclear_reaction_optimization.py +4 -0
  25. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/runge_kutta/runge_kutta_optimization.py +4 -0
  26. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/spotted_hyena/spotted_hyena_optimization.py +2 -1
  27. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/success_history_intelligent/success_history_intelligent_optimization.py +4 -0
  28. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/virus_colony_search/virus_colony_search_optimization.py +4 -0
  29. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/water_cycle/water_cycle_optimization.py +4 -0
  30. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/LICENSE +0 -0
  31. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/README.md +0 -0
  32. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/__init__.py +0 -0
  33. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/african_vulture/__init__.py +0 -0
  34. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/african_vulture/african_vulture_optimization.py +0 -0
  35. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/african_vulture/models.py +0 -0
  36. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ant_colony/__init__.py +0 -0
  37. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ant_colony/ant_colony_optimization.py +0 -0
  38. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ant_colony/models.py +0 -0
  39. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ant_lion/__init__.py +0 -0
  40. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ant_lion/ant_lion_optimization.py +0 -0
  41. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ant_lion/models.py +0 -0
  42. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/aquila/__init__.py +0 -0
  43. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/aquila/aquila_optimization.py +0 -0
  44. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/aquila/models.py +0 -0
  45. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/archimede/__init__.py +0 -0
  46. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/archimede/archimede_optimization.py +0 -0
  47. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/archimede/models.py +0 -0
  48. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bacterial_foraging/__init__.py +0 -0
  49. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bacterial_foraging/bacterial_foraging_optimization.py +0 -0
  50. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bacterial_foraging/models.py +0 -0
  51. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bat/__init__.py +0 -0
  52. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bat/bat_optimization.py +0 -0
  53. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bat/models.py +0 -0
  54. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/battle_royale/__init__.py +0 -0
  55. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/battle_royale/battle_royale_optimization.py +0 -0
  56. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/battle_royale/models.py +0 -0
  57. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bee_colony/__init__.py +0 -0
  58. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/bee_colony/models.py +0 -0
  59. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/biogeography_based/__init__.py +0 -0
  60. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/biogeography_based/biogeography_based_optimization.py +0 -0
  61. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/biogeography_based/models.py +0 -0
  62. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/brain_storm/__init__.py +0 -0
  63. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/brain_storm/models.py +0 -0
  64. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/brown_bear/__init__.py +0 -0
  65. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/brown_bear/brown_bear_optimization.py +0 -0
  66. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/brown_bear/models.py +0 -0
  67. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/camel_caravan/__init__.py +0 -0
  68. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/camel_caravan/camel_caravan_optimization.py +0 -0
  69. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/camel_caravan/models.py +0 -0
  70. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/cat_swarm/__init__.py +0 -0
  71. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/cat_swarm/cat_swarm_optimization.py +0 -0
  72. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/cat_swarm/models.py +0 -0
  73. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/chaos_game/__init__.py +0 -0
  74. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/chaos_game/chaos_game_optimization.py +0 -0
  75. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/chaos_game/models.py +0 -0
  76. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/chernobyl_disaster/__init__.py +0 -0
  77. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/chernobyl_disaster/models.py +0 -0
  78. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coati/__init__.py +0 -0
  79. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coati/coati_optimization.py +0 -0
  80. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coati/models.py +0 -0
  81. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coral_reef/__init__.py +0 -0
  82. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coral_reef/models.py +0 -0
  83. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coronavirus_herd_immunity/__init__.py +0 -0
  84. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coronavirus_herd_immunity/coronavirus_herd_immunity_optimization.py +0 -0
  85. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coronavirus_herd_immunity/models.py +0 -0
  86. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coyotes/__init__.py +0 -0
  87. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/coyotes/models.py +0 -0
  88. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/cuckoo_search/__init__.py +0 -0
  89. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/cuckoo_search/cuckoo_search_optimization.py +0 -0
  90. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/cuckoo_search/models.py +0 -0
  91. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/dragonfly/__init__.py +0 -0
  92. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/dragonfly/dragonfly_optimization.py +0 -0
  93. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/dragonfly/models.py +0 -0
  94. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/dwarf_mongoose/__init__.py +0 -0
  95. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/dwarf_mongoose/models.py +0 -0
  96. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/earthworms/__init__.py +0 -0
  97. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/earthworms/models.py +0 -0
  98. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/egret_swarm/__init__.py +0 -0
  99. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/egret_swarm/egret_swarm_optimization.py +0 -0
  100. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/egret_swarm/models.py +0 -0
  101. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/electromagnetic_field/__init__.py +0 -0
  102. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/electromagnetic_field/models.py +0 -0
  103. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/elephant_herd/__init__.py +0 -0
  104. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/elephant_herd/models.py +0 -0
  105. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/energy_valley/__init__.py +0 -0
  106. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/energy_valley/models.py +0 -0
  107. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/enums.py +0 -0
  108. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ficks_law/__init__.py +0 -0
  109. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ficks_law/ficks_law_optimization.py +0 -0
  110. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/ficks_law/models.py +0 -0
  111. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/firefly_swarm/__init__.py +0 -0
  112. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/firefly_swarm/firefly_swarm_optimization.py +0 -0
  113. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/firefly_swarm/models.py +0 -0
  114. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/firehawk/__init__.py +0 -0
  115. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/firehawk/models.py +0 -0
  116. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fireworks/__init__.py +0 -0
  117. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fireworks/fireworks_optimization.py +0 -0
  118. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fireworks/models.py +0 -0
  119. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fish_school_search/__init__.py +0 -0
  120. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fish_school_search/fish_school_search_optimization.py +0 -0
  121. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fish_school_search/models.py +0 -0
  122. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/flower_pollination_algorithm/__init__.py +0 -0
  123. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/flower_pollination_algorithm/models.py +0 -0
  124. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/forensic_based_investigation/__init__.py +0 -0
  125. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/forensic_based_investigation/models.py +0 -0
  126. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/forest_algorithm/__init__.py +0 -0
  127. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/forest_algorithm/models.py +0 -0
  128. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fox/__init__.py +0 -0
  129. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fox/fox_optimization.py +0 -0
  130. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/fox/models.py +0 -0
  131. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/gaining_sharing_knowledge_algorithm/__init__.py +0 -0
  132. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/gaining_sharing_knowledge_algorithm/models.py +0 -0
  133. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/genetic_algorithm/__init__.py +0 -0
  134. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/genetic_algorithm/classes.py +0 -0
  135. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/genetic_algorithm/models.py +0 -0
  136. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/germinal_center/__init__.py +0 -0
  137. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/germinal_center/models.py +0 -0
  138. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/giant_trevally/__init__.py +0 -0
  139. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/giant_trevally/giant_trevally_optimization.py +0 -0
  140. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/giant_trevally/models.py +0 -0
  141. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/giza_pyramid_construction/__init__.py +0 -0
  142. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/giza_pyramid_construction/giza_pyramid_construction_optimization.py +0 -0
  143. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/giza_pyramid_construction/models.py +0 -0
  144. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/golden_jackal/__init__.py +0 -0
  145. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/golden_jackal/golden_jackal_optimization.py +0 -0
  146. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/golden_jackal/models.py +0 -0
  147. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/grasshopper/__init__.py +0 -0
  148. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/grasshopper/grasshopper_optimization_algorithm.py +0 -0
  149. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/grasshopper/models.py +0 -0
  150. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/grey_wolf/__init__.py +0 -0
  151. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/grey_wolf/models.py +0 -0
  152. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/harmony_search/__init__.py +0 -0
  153. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/harmony_search/harmony_search_optimization.py +0 -0
  154. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/harmony_search/models.py +0 -0
  155. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/heap_based/__init__.py +0 -0
  156. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/heap_based/heap_based_optimization.py +0 -0
  157. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/heap_based/models.py +0 -0
  158. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/henry_gas_solubility/__init__.py +0 -0
  159. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/henry_gas_solubility/henry_gas_solubility_optimization.py +0 -0
  160. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/henry_gas_solubility/models.py +0 -0
  161. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/hunger_games_search/__init__.py +0 -0
  162. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/hunger_games_search/hunger_games_search_optimization.py +0 -0
  163. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/hunger_games_search/models.py +0 -0
  164. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/hypertuner.py +0 -0
  165. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/imperialist_competitive/__init__.py +0 -0
  166. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/imperialist_competitive/classes.py +0 -0
  167. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/imperialist_competitive/imperialist_competitive_optimization.py +0 -0
  168. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/imperialist_competitive/models.py +0 -0
  169. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/invasive_weed/__init__.py +0 -0
  170. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/invasive_weed/invasive_weed_optimization.py +0 -0
  171. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/invasive_weed/models.py +0 -0
  172. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/krill_herd/__init__.py +0 -0
  173. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/krill_herd/krill_herd_optimization.py +0 -0
  174. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/krill_herd/models.py +0 -0
  175. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/levi_jaya_swarm/__init__.py +0 -0
  176. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/levi_jaya_swarm/levy_flight_jaya_swarm_optimization.py +0 -0
  177. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/levi_jaya_swarm/models.py +0 -0
  178. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/marine_predators/__init__.py +0 -0
  179. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/marine_predators/marine_predators_optimization.py +0 -0
  180. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/marine_predators/models.py +0 -0
  181. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/models.py +0 -0
  182. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/monarch_butterfly/__init__.py +0 -0
  183. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/monarch_butterfly/models.py +0 -0
  184. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/monarch_butterfly/monarch_butterfly_optimization.py +0 -0
  185. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/moth_flame/__init__.py +0 -0
  186. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/moth_flame/models.py +0 -0
  187. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/moth_flame/moth_flame_optimization.py +0 -0
  188. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/mountain_gazelle/__init__.py +0 -0
  189. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/mountain_gazelle/models.py +0 -0
  190. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/mountain_gazelle/mountain_gazelle_optimization.py +0 -0
  191. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/multi_verse/__init__.py +0 -0
  192. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/multi_verse/models.py +0 -0
  193. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/multi_verse/multi_verse_optimization.py +0 -0
  194. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/multitask.py +0 -0
  195. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/nuclear_reaction/__init__.py +0 -0
  196. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/nuclear_reaction/models.py +0 -0
  197. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/osprey/__init__.py +0 -0
  198. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/osprey/models.py +0 -0
  199. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/osprey/osprey_optimization.py +0 -0
  200. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/particle_swarm/__init__.py +0 -0
  201. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/particle_swarm/models.py +0 -0
  202. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/particle_swarm/particle_swarm_optimization.py +0 -0
  203. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/pathfinder_algorithm/__init__.py +0 -0
  204. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/pathfinder_algorithm/models.py +0 -0
  205. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/pathfinder_algorithm/pathfinder_algorithm_optimization.py +0 -0
  206. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/pelican/__init__.py +0 -0
  207. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/pelican/models.py +0 -0
  208. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/pelican/pelican_optimization.py +0 -0
  209. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/runge_kutta/__init__.py +0 -0
  210. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/runge_kutta/models.py +0 -0
  211. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/salp_swarm/__init__.py +0 -0
  212. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/salp_swarm/models.py +0 -0
  213. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/salp_swarm/salp_swarm_optimization.py +0 -0
  214. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/seagull/__init__.py +0 -0
  215. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/seagull/models.py +0 -0
  216. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/seagull/seagull_optimization.py +0 -0
  217. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/serval/__init__.py +0 -0
  218. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/serval/models.py +0 -0
  219. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/serval/serval_optimization.py +0 -0
  220. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/siberian_tiger/__init__.py +0 -0
  221. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/siberian_tiger/models.py +0 -0
  222. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/siberian_tiger/siberian_tiger_optimization.py +0 -0
  223. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/sine_cosine_algorithm/__init__.py +0 -0
  224. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/sine_cosine_algorithm/classes.py +0 -0
  225. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/sine_cosine_algorithm/models.py +0 -0
  226. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/sine_cosine_algorithm/qle_sine_cosine_algorithm_optimization.py +0 -0
  227. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/sine_cosine_algorithm/sine_cosine_algorithm_optimization.py +0 -0
  228. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/spotted_hyena/__init__.py +0 -0
  229. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/spotted_hyena/models.py +0 -0
  230. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/success_history_intelligent/__init__.py +0 -0
  231. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/success_history_intelligent/models.py +0 -0
  232. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/swarm_hill_climbing/__init__.py +0 -0
  233. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/swarm_hill_climbing/models.py +0 -0
  234. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/swarm_hill_climbing/swarm_hill_climbing_optimization.py +0 -0
  235. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/tasmanian_devil/__init__.py +0 -0
  236. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/tasmanian_devil/models.py +0 -0
  237. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/tasmanian_devil/tasmanian_devil_optimization.py +0 -0
  238. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/tuna_swarm/__init__.py +0 -0
  239. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/tuna_swarm/models.py +0 -0
  240. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/tuna_swarm/tuna_swarm_optimization.py +0 -0
  241. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/utils.py +0 -0
  242. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/virus_colony_search/__init__.py +0 -0
  243. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/virus_colony_search/models.py +0 -0
  244. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/walrus/__init__.py +0 -0
  245. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/walrus/models.py +0 -0
  246. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/walrus/walrus_optimization.py +0 -0
  247. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/war_strategy/__init__.py +0 -0
  248. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/war_strategy/models.py +0 -0
  249. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/war_strategy/war_strategy_optimization.py +0 -0
  250. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/water_cycle/__init__.py +0 -0
  251. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/water_cycle/models.py +0 -0
  252. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/whales/__init__.py +0 -0
  253. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/whales/models.py +0 -0
  254. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/whales/whales_optimization.py +0 -0
  255. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/wildebeest_herd/__init__.py +0 -0
  256. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/wildebeest_herd/models.py +0 -0
  257. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/wildebeest_herd/wildebeest_herd_optimization.py +0 -0
  258. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/wind_driven/__init__.py +0 -0
  259. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/wind_driven/models.py +0 -0
  260. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/wind_driven/wind_driven_optimization.py +0 -0
  261. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/zebra/__init__.py +0 -0
  262. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/zebra/models.py +0 -0
  263. {pyvolutionary-2.7.0 → pyvolutionary-2.7.1}/pyvolutionary/zebra/zebra_optimization.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyVolutionary
3
- Version: 2.7.0
3
+ Version: 2.7.1
4
4
  Summary: pyVolutionary is a package collecting metaheuristic algorithms, available for free usage and able to solve a wide range of optimization problems.
5
5
  License: GPL-3.0-only
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pyVolutionary"
3
- version = "2.7.0"
3
+ version = "2.7.1"
4
4
  description = "pyVolutionary is a package collecting metaheuristic algorithms, available for free usage and able to solve a wide range of optimization problems."
5
5
  authors = ["Matteo Cacciola <matteo.cacciola@gmail.com>"]
6
6
  license = "GPL-3.0-only"
@@ -51,6 +51,15 @@ class OptimizationAbstract(ABC, Generic[T]):
51
51
  def before_initialization(self):
52
52
  pass
53
53
 
54
+ def _minimum_population_size(self) -> int:
55
+ """
56
+ The minimum size of the population the algorithm can work with (e.g. an algorithm guided by the three best
57
+ agents needs at least three agents). The algorithms needing more than two agents override it.
58
+ :return: the minimum population size
59
+ :rtype: int
60
+ """
61
+ return 2
62
+
54
63
  def after_initialization(self):
55
64
  pass
56
65
 
@@ -224,6 +233,13 @@ class OptimizationAbstract(ABC, Generic[T]):
224
233
  if not self._config:
225
234
  raise ValueError("Invalid configuration")
226
235
 
236
+ minimum_population_size = self._minimum_population_size()
237
+ if self._config.population_size < minimum_population_size:
238
+ raise ValueError(
239
+ f"{self.name} needs a population of at least {minimum_population_size} agents. "
240
+ f"Got {self._config.population_size}"
241
+ )
242
+
227
243
  np.random.seed(task.seed)
228
244
  random.seed(task.seed)
229
245
  evolution: list[Population] = []
@@ -34,6 +34,10 @@ class BeeColonyOptimization(OptimizationAbstract):
34
34
  def set_config_parameters(self, parameters: dict[str, Any]):
35
35
  self._config = BeeColonyOptimizationConfig(**parameters)
36
36
 
37
+ def _minimum_population_size(self) -> int:
38
+ # half of the colony are food sources, and a food source needs a partner
39
+ return 4
40
+
37
41
  def _init_population(self):
38
42
  # half of the colony are employed bees, each one bound to a food source: the population is made of the food
39
43
  # sources (the configuration is not altered, so that it can be reused for further optimizations)
@@ -4,6 +4,7 @@ import numpy as np
4
4
 
5
5
  from ..helpers import (
6
6
  find_centers,
7
+ split_in_clusters,
7
8
  parse_obj_doc, # type: ignore
8
9
  )
9
10
  from ..abstract import OptimizationAbstract
@@ -25,38 +26,37 @@ class BrainStormOptimization(OptimizationAbstract):
25
26
  """
26
27
  def __init__(self, config: BrainStormOptimizationConfig | None = None, debug: bool | None = False):
27
28
  super().__init__(config, debug)
28
- self.__m_solution: int | None = None
29
29
  self.__clusters: list[list[Person]] = []
30
30
  self.__centers: list[Person] = []
31
31
 
32
32
  def set_config_parameters(self, parameters: dict[str, Any]):
33
33
  self._config = BrainStormOptimizationConfig(**parameters)
34
34
 
35
- def before_initialization(self):
36
- self.__m_solution = int(self._config.population_size / self._config.m_clusters)
37
-
38
35
  def after_initialization(self):
39
- self.__clusters = self._generate_group_population(self._config.m_clusters, self.__m_solution, False)
36
+ # every agent belongs to a cluster, also when the population size is not a multiple of m_clusters
37
+ self.__clusters = split_in_clusters(self._population, self._config.m_clusters)
40
38
  self.__centers: list[Person] = find_centers(self.__clusters)
41
39
 
42
40
  def optimization_step(self):
43
41
  def evolve(idx: int) -> tuple[Person, int, int]:
44
- cluster_id = int(idx / m_solution)
45
- location_id = int(idx % m_solution)
42
+ cluster_id, location_id = locations[idx]
46
43
  if np.random.uniform() < p2: # p_6b
47
- rand_idx = np.random.randint(0, m_solution)
44
+ rand_idx = np.random.randint(0, len(self.__clusters[cluster_id]))
48
45
  pos_new = np.array(self.__clusters[cluster_id][rand_idx].position) + np.random.normal(0, 1, n_dims)
49
46
  if np.random.uniform() < p3: # p_6i
50
- cluster_id = np.random.randint(0, m_clusters)
51
- pos_new = np.array(self.__centers[cluster_id].position) + epsilon * np.random.normal(0, 1, n_dims)
47
+ # the new idea comes from the center of a random cluster, and competes with the agent idx
48
+ center_id = np.random.randint(0, m_clusters)
49
+ pos_new = np.array(self.__centers[center_id].position) + epsilon * np.random.normal(0, 1, n_dims)
52
50
  else:
53
51
  id1, id2 = np.random.choice(m_clusters, 2, replace=False)
54
52
  pos_new = 0.5 * (
55
53
  np.array(self.__centers[id1].position) + np.array(self.__centers[id2].position)
56
54
  ) + epsilon * np.random.normal(0, 1, n_dims)
57
55
  if np.random.uniform() >= p4:
58
- pos_rand_id1 = np.array(self.__clusters[id1][np.random.randint(0, m_solution)].position)
59
- pos_rand_id2 = np.array(self.__clusters[id2][np.random.randint(0, m_solution)].position)
56
+ cluster1 = self.__clusters[id1]
57
+ pos_rand_id1 = np.array(cluster1[np.random.randint(0, len(cluster1))].position)
58
+ cluster2 = self.__clusters[id2]
59
+ pos_rand_id2 = np.array(cluster2[np.random.randint(0, len(cluster2))].position)
60
60
  pos_new = 0.5 * (pos_rand_id1 + pos_rand_id2) + epsilon * np.random.normal(0, 1, n_dims)
61
61
  agent = Person(**self._init_agent(pos_new).__dict__)
62
62
  return agent, cluster_id, location_id
@@ -68,16 +68,17 @@ class BrainStormOptimization(OptimizationAbstract):
68
68
  epsilon = np.random.uniform() * (1 / (1 + np.exp(-x)))
69
69
 
70
70
  p1, p2, p3, p4 = self._config.p1, self._config.p2, self._config.p3, self._config.p4
71
- m_solution = self.__m_solution
71
+ # the (cluster, location) of each agent, cluster by cluster
72
+ locations = [(c_id, l_id) for c_id, cluster in enumerate(self.__clusters) for l_id in range(0, len(cluster))]
72
73
 
73
74
  n_dims = self._task.space_dimension
74
- m_clusters = self._config.m_clusters
75
+ m_clusters = len(self.__clusters)
75
76
 
76
77
  epsilon = 1. - 1. * epoch / epochs
77
78
  if np.random.uniform() < p1:
78
79
  self.__centers[np.random.randint(0, m_clusters)] = Person(**self._init_agent().__dict__)
79
80
 
80
- new_agents, cluster_ids, location_ids = zip(*[evolve(idx) for idx in range(0, self._config.population_size)])
81
+ new_agents, cluster_ids, location_ids = zip(*[evolve(idx) for idx in range(0, len(locations))])
81
82
  for cl_id, loc_id, new_agent in zip(cluster_ids, location_ids, new_agents):
82
83
  self.__clusters[cl_id][loc_id] = self._greedy_select_agent(self.__clusters[cl_id][loc_id], new_agent)
83
84
 
@@ -4,6 +4,7 @@ import numpy as np
4
4
 
5
5
  from ..helpers import (
6
6
  find_centers,
7
+ split_in_clusters,
7
8
  get_levy_flight_step,
8
9
  parse_obj_doc, # type: ignore
9
10
  )
@@ -26,24 +27,20 @@ class ImprovedBrainStormOptimization(OptimizationAbstract):
26
27
  """
27
28
  def __init__(self, config: ImprovedBrainStormOptimizationConfig | None = None, debug: bool | None = False):
28
29
  super().__init__(config, debug)
29
- self.__m_solution: int | None = None
30
30
  self.__clusters: list[list[Person]] = []
31
31
  self.__centers: list[Person] = []
32
32
 
33
33
  def set_config_parameters(self, parameters: dict[str, Any]):
34
34
  self._config = ImprovedBrainStormOptimizationConfig(**parameters)
35
35
 
36
- def before_initialization(self):
37
- self.__m_solution = int(self._config.population_size / self._config.m_clusters)
38
-
39
36
  def after_initialization(self):
40
- self.__clusters = self._generate_group_population(self._config.m_clusters, self.__m_solution, False)
37
+ # every agent belongs to a cluster, also when the population size is not a multiple of m_clusters
38
+ self.__clusters = split_in_clusters(self._population, self._config.m_clusters)
41
39
  self.__centers: list[Person] = find_centers(self.__clusters)
42
40
 
43
41
  def optimization_step(self):
44
42
  def evolve(idx: int) -> tuple[Person, int, int]:
45
- cluster_id = int(idx / m_solution)
46
- location_id = int(idx % m_solution)
43
+ cluster_id, location_id = locations[idx]
47
44
  if np.random.uniform() < p2: # p_6b
48
45
  temp_pos = np.array(self.__centers[cluster_id].position)
49
46
  offset = epsilon * np.random.normal(0, 1, n_dims)
@@ -57,25 +54,28 @@ class ImprovedBrainStormOptimization(OptimizationAbstract):
57
54
  np.array(self.__centers[id1].position) + np.array(self.__centers[id2].position)
58
55
  ) + epsilon * np.random.normal(0, 1, n_dims)
59
56
  if np.random.uniform() >= p4:
60
- pos_rand_id1 = np.array(self.__clusters[id1][np.random.randint(0, m_solution)].position)
61
- pos_rand_id2 = np.array(self.__clusters[id2][np.random.randint(0, m_solution)].position)
57
+ cluster1 = self.__clusters[id1]
58
+ pos_rand_id1 = np.array(cluster1[np.random.randint(0, len(cluster1))].position)
59
+ cluster2 = self.__clusters[id2]
60
+ pos_rand_id2 = np.array(cluster2[np.random.randint(0, len(cluster2))].position)
62
61
  pos_new = 0.5 * (pos_rand_id1 + pos_rand_id2) + epsilon * np.random.normal(0, 1, n_dims)
63
62
  agent = Person(**self._init_agent(pos_new).__dict__)
64
63
  return agent, cluster_id, location_id
65
64
 
66
65
  p1, p2, p3, p4 = self._config.p1, self._config.p2, self._config.p3, self._config.p4
67
- m_solution = self.__m_solution
66
+ # the (cluster, location) of each agent, cluster by cluster
67
+ locations = [(c_id, l_id) for c_id, cluster in enumerate(self.__clusters) for l_id in range(0, len(cluster))]
68
68
 
69
69
  n_dims = self._task.space_dimension
70
70
  epoch = self._current_cycle
71
71
  epochs = self._config.max_cycles
72
- m_clusters = self._config.m_clusters
72
+ m_clusters = len(self.__clusters)
73
73
 
74
74
  epsilon = 1. - 1. * epoch / epochs
75
75
  if np.random.uniform() < p1:
76
76
  self.__centers[np.random.randint(0, m_clusters)] = Person(**self._init_agent().__dict__)
77
77
 
78
- new_agents, cluster_ids, location_ids = zip(*[evolve(idx) for idx in range(0, self._config.population_size)])
78
+ new_agents, cluster_ids, location_ids = zip(*[evolve(idx) for idx in range(0, len(locations))])
79
79
  for cl_id, loc_id, new_agent in zip(cluster_ids, location_ids, new_agents):
80
80
  self.__clusters[cl_id][loc_id] = self._greedy_select_agent(self.__clusters[cl_id][loc_id], new_agent)
81
81
 
@@ -28,6 +28,10 @@ class ChernobylDisasterOptimization(OptimizationAbstract):
28
28
  def set_config_parameters(self, parameters: dict[str, Any]):
29
29
  self._config = ChernobylDisasterOptimizationConfig(**parameters)
30
30
 
31
+ def _minimum_population_size(self) -> int:
32
+ # the agents are guided by the three best ones
33
+ return 3
34
+
31
35
  def optimization_step(self):
32
36
  def evolve(radiation: SearchRadiation) -> SearchRadiation:
33
37
  pos = np.array(radiation.position)
@@ -68,6 +68,9 @@ class CoralReefOptimization(OptimizationAbstract):
68
68
  ))
69
69
 
70
70
  def multi_point_cross(pos1, pos2) -> list[float]:
71
+ if len(pos1) < 2:
72
+ # a single dimension can not be cut in two points: the larva takes it from one of the parents
73
+ return self._task.correct_solution(pos1 if np.random.random() < 0.5 else pos2)
71
74
  p1, p2 = np.random.choice(list(range(0, len(pos1))), 2, replace=False)
72
75
  start, end = min(p1, p2), max(p1, p2)
73
76
  return self._task.correct_solution(
@@ -32,6 +32,10 @@ class CoyotesOptimization(OptimizationAbstract):
32
32
  def set_config_parameters(self, parameters: dict[str, Any]):
33
33
  self._config = CoyotesOptimizationConfig(**parameters)
34
34
 
35
+ def _minimum_population_size(self) -> int:
36
+ # a pack holds num_coyotes coyotes
37
+ return max(self._config.num_coyotes, 3)
38
+
35
39
  def before_initialization(self):
36
40
  self.__n_packs = int(self._config.population_size / self._config.num_coyotes)
37
41
  self.__ps = 1. / self._task.space_dimension # Probability of selecting a dimension
@@ -28,6 +28,10 @@ class DwarfMongooseOptimization(OptimizationAbstract):
28
28
  def set_config_parameters(self, parameters: dict[str, Any]):
29
29
  self._config = DwarfMongooseOptimizationConfig(**parameters)
30
30
 
31
+ def _minimum_population_size(self) -> int:
32
+ # a mongoose forages with a partner different from itself and the alpha
33
+ return 3
34
+
31
35
  def _init_agent(self, position: list[float] | np.ndarray | None = None) -> DwarfMongoose:
32
36
  return DwarfMongoose(**super()._init_agent(position).__dict__)
33
37
 
@@ -31,6 +31,10 @@ class EarthwormsOptimization(OptimizationAbstract):
31
31
  def set_config_parameters(self, parameters: dict[str, Any]):
32
32
  self._config = EarthwormsOptimizationConfig(**parameters)
33
33
 
34
+ def _minimum_population_size(self) -> int:
35
+ # the best keep earthworms are kept at each cycle
36
+ return max(self._config.keep, 2)
37
+
34
38
  def before_initialization(self):
35
39
  self.__dyn_beta = self._config.beta
36
40
 
@@ -1,7 +1,10 @@
1
1
  from typing import Any
2
2
  import numpy as np
3
3
 
4
- from ..helpers import parse_obj_doc # type: ignore
4
+ from ..helpers import (
5
+ sort_by_cost,
6
+ parse_obj_doc, # type: ignore
7
+ )
5
8
  from ..abstract import OptimizationAbstract
6
9
  from .models import Electromagnet, ElectromagneticFieldOptimizationConfig
7
10
 
@@ -30,9 +33,9 @@ class ElectromagneticFieldOptimization(OptimizationAbstract):
30
33
  def optimization_step(self):
31
34
  def evolve(electromagnet: Electromagnet) -> Electromagnet:
32
35
  if np.random.random() < ps_rate:
33
- r_idx1 = np.random.randint(0, p_field) # top
34
- r_idx2 = np.random.randint(n_field, pop_size) # bottom
35
- r_idx3 = np.random.randint(n_field1, n_field) # middle
36
+ r_idx1 = random_index(0, p_field) # top
37
+ r_idx2 = random_index(n_field, pop_size) # bottom
38
+ r_idx3 = random_index(n_field1, n_field) # middle
36
39
 
37
40
  pos_new = np.array(self._population[r_idx1].position) + phi * np.random.random() * (
38
41
  best_position - np.array(self._population[r_idx3].position)
@@ -47,6 +50,14 @@ class ElectromagneticFieldOptimization(OptimizationAbstract):
47
50
  agent = Electromagnet(**self._init_agent(pos_new).__dict__)
48
51
  return self._greedy_select_agent(electromagnet, agent)
49
52
 
53
+ def random_index(low: int, high: int) -> int:
54
+ # a field may be empty with a small population: draw from the whole population then
55
+ return np.random.randint(low, high) if high > low else np.random.randint(0, pop_size)
56
+
57
+ # the fields are fractions of the population sorted by cost: positive (the best electromagnets), neutral and
58
+ # negative (the worst ones)
59
+ self._population = sort_by_cost(self._population)
60
+
50
61
  pop_size = self._config.population_size
51
62
  best_position = np.array(self._best_agent.position)
52
63
 
@@ -2,6 +2,7 @@ from typing import Any
2
2
  import numpy as np
3
3
 
4
4
  from ..helpers import (
5
+ split_in_clusters,
5
6
  sort_by_cost,
6
7
  parse_obj_doc, # type: ignore
7
8
  )
@@ -24,38 +25,35 @@ class ElephantHerdOptimization(OptimizationAbstract):
24
25
  """
25
26
  def __init__(self, config: ElephantHerdOptimizationConfig | None = None, debug: bool | None = False):
26
27
  super().__init__(config, debug)
27
- self.__n_individuals: int | None = None
28
28
  self.__groups: list[list[Elephant]] = []
29
29
 
30
30
  def set_config_parameters(self, parameters: dict[str, Any]):
31
31
  self._config = ElephantHerdOptimizationConfig(**parameters)
32
32
 
33
- def before_initialization(self):
34
- self.__n_individuals = int(self._config.population_size / self._config.n_clans)
35
-
36
33
  def after_initialization(self):
37
- self.__groups = self._generate_group_population(self._config.n_clans, self.__n_individuals)
34
+ # every elephant belongs to a clan, also when the population size is not a multiple of n_clans
35
+ self.__groups = split_in_clusters(self._population, self._config.n_clans)
38
36
 
39
37
  def optimization_step(self):
40
38
  def evolve(idx: int, elephant: Elephant) -> Elephant:
41
- clan_idx = int(idx / n_individuals)
39
+ clan_idx, pos_clan_idx = locations[idx]
42
40
  pos_group = [np.array(elephant.position) for elephant in self.__groups[clan_idx]]
43
41
  # pos_clan_idx == 0 means the best in clan, because all clans are sorted based on cost
44
- pos_clan_idx = int(idx % n_individuals)
45
42
  pos_new = beta * np.mean(pos_group, axis=0) if pos_clan_idx == 0 else (
46
43
  pos_group[pos_clan_idx] + alpha * np.random.random() * (pos_group[0] - pos_group[pos_clan_idx])
47
44
  )
48
45
  agent = Elephant(**self._init_agent(pos_new).__dict__)
49
46
  return self._greedy_select_agent(elephant, agent)
50
47
 
51
- n_individuals = self.__n_individuals
48
+ # the (clan, position in the clan) of each elephant, clan by clan
49
+ locations = [(c_id, l_id) for c_id, clan in enumerate(self.__groups) for l_id in range(0, len(clan))]
52
50
  alpha = self._config.alpha
53
51
  beta = self._config.beta
54
52
  self._population = [evolve(idx, elephant) for idx, elephant in enumerate(self._population)]
55
- self.__groups = self._generate_group_population(self._config.n_clans, self.__n_individuals)
53
+ self.__groups = split_in_clusters(self._population, self._config.n_clans)
56
54
 
57
55
  # Separating operator
58
- for idx in range(0, self._config.n_clans):
56
+ for idx in range(0, len(self.__groups)):
59
57
  self.__groups[idx] = sort_by_cost(self.__groups[idx])
60
58
  self.__groups[idx][-1] = self._init_agent()
61
59
  self._population = [elephant for pack in self.__groups for elephant in pack]
@@ -26,6 +26,10 @@ class EnergyValleyOptimization(OptimizationAbstract):
26
26
  def set_config_parameters(self, parameters: dict[str, Any]):
27
27
  self._config = EnergyValleyOptimizationConfig(**parameters)
28
28
 
29
+ def _minimum_population_size(self) -> int:
30
+ # a particle is compared with a team of its nearest particles
31
+ return 4
32
+
29
33
  def optimization_step(self):
30
34
  def evolve(idx: int, particle: Particle) -> list[Particle]:
31
35
  pos = np.array(particle.position)
@@ -32,7 +32,8 @@ class FireHawkOptimization(OptimizationAbstract):
32
32
  self._config = FireHawkOptimizationConfig(**parameters)
33
33
 
34
34
  def before_initialization(self):
35
- self.__hn = np.random.randint(1, np.ceil(self._config.population_size / 5))
35
+ # number of fire hawks: at least one (with a small population, ceil(population_size / 5) may be 1)
36
+ self.__hn = np.random.randint(1, max(np.ceil(self._config.population_size / 5), 2))
36
37
 
37
38
  def optimization_step(self):
38
39
  def get_groups() -> dict[int, list[FireHawk]]:
@@ -29,6 +29,10 @@ class FlowerPollinationAlgorithmOptimization(OptimizationAbstract):
29
29
  def set_config_parameters(self, parameters: dict[str, Any]):
30
30
  self._config = FlowerPollinationAlgorithmOptimizationConfig(**parameters)
31
31
 
32
+ def _minimum_population_size(self) -> int:
33
+ # the local pollination mixes two other flowers
34
+ return 3
35
+
32
36
  def optimization_step(self):
33
37
  def evolve(pollinator: Pollinator, idx: int) -> Pollinator:
34
38
  position = np.array(pollinator.position)
@@ -25,6 +25,10 @@ class ForensicBasedInvestigationOptimization(OptimizationAbstract):
25
25
  def set_config_parameters(self, parameters: dict[str, Any]):
26
26
  self._config = ForensicBasedInvestigationOptimizationConfig(**parameters)
27
27
 
28
+ def _minimum_population_size(self) -> int:
29
+ # a suspect is investigated through three other suspects
30
+ return 4
31
+
28
32
  def optimization_step(self):
29
33
  def investigation_a1(idx: int, detective: Detective) -> Detective:
30
34
  pos = detective.position
@@ -41,13 +41,13 @@ class ForestOptimizationAlgorithm(OptimizationAbstract):
41
41
  def optimization_step(self):
42
42
  def local_seeding(tree: Tree) -> Tree:
43
43
  position = np.array(tree.position, dtype=float)
44
- indices = np.random.choice(dims, local_seeding_changes, replace=False)
44
+ indices = np.random.choice(dims, min(local_seeding_changes, dims), replace=False)
45
45
  position[indices] += np.random.uniform(-self.__dx[indices], self.__dx[indices])
46
46
  return self._init_agent(position)
47
47
 
48
48
  def global_seeding(tree: Tree) -> Tree:
49
49
  position = np.array(tree.position, dtype=float)
50
- indices = np.random.choice(self._task.space_dimension, self._config.global_seeding_changes, replace=False)
50
+ indices = np.random.choice(dims, min(self._config.global_seeding_changes, dims), replace=False)
51
51
  position[indices] = self._task.uniform_coordinates(indices)
52
52
  return self._init_agent(position)
53
53
 
@@ -65,7 +65,7 @@ class ForestOptimizationAlgorithm(OptimizationAbstract):
65
65
 
66
66
  # identify and remove trees that exceeded their area limit
67
67
  self._population = sort_by_cost(self._population)
68
- dying_trees += self._population[area_limit + 1:]
68
+ dying_trees += self._population[area_limit:]
69
69
 
70
70
  self._population = self._population[:area_limit]
71
71
 
@@ -1,7 +1,10 @@
1
1
  from typing import Any
2
2
  import numpy as np
3
3
 
4
- from ..helpers import parse_obj_doc # type: ignore
4
+ from ..helpers import (
5
+ sort_by_cost,
6
+ parse_obj_doc, # type: ignore
7
+ )
5
8
  from ..abstract import OptimizationAbstract
6
9
  from .models import Knowledge, GainingSharingKnowledgeOptimizationConfig
7
10
 
@@ -40,8 +43,13 @@ class GainingSharingKnowledgeOptimization(OptimizationAbstract):
40
43
  # Other case it chooses i-1, i+1
41
44
  return idx - 1, idx + 1
42
45
 
46
+ def random_index(low: int, high: int, excluded: set[int]) -> int:
47
+ # a group may be empty with a small population: draw from the whole population then
48
+ candidates = list(set(range(low, high)) - excluded) or list(set(range(0, pop_size)) - excluded)
49
+ return np.random.choice(candidates) if candidates else np.random.randint(0, pop_size)
50
+
43
51
  def junior_gaining_sharing_knowledge(idx: int, agent: Knowledge) -> np.ndarray:
44
- rand_idx = np.random.choice(list(set(range(0, pop_size)) - {prevs[idx], idx, nexts[idx]}))
52
+ rand_idx = random_index(0, pop_size, {prevs[idx], idx, nexts[idx]})
45
53
  pos = np.array(agent.position)
46
54
  if np.random.uniform() > kr:
47
55
  return pos.copy()
@@ -57,9 +65,9 @@ class GainingSharingKnowledgeOptimization(OptimizationAbstract):
57
65
  pos = np.array(agent.position)
58
66
  if np.random.uniform() > kr:
59
67
  return pos.copy()
60
- rand_best = np.random.choice(list(set(range(0, id1)) - {idx}))
61
- rand_worst = np.random.choice(list(set(range(id2, pop_size)) - {idx}))
62
- rand_mid = np.random.choice(list(set(range(id1, id2)) - {idx}))
68
+ rand_best = random_index(0, id1, {idx})
69
+ rand_worst = random_index(id2, pop_size, {idx})
70
+ rand_mid = random_index(id1, id2, {idx})
63
71
  pos_rand_best = np.array(self._population[rand_best].position)
64
72
  pos_rand_worst = np.array(self._population[rand_worst].position)
65
73
  pos_rand_mid = np.array(self._population[rand_mid].position)
@@ -75,11 +83,17 @@ class GainingSharingKnowledgeOptimization(OptimizationAbstract):
75
83
  )
76
84
  return self._greedy_select_agent(agent, Knowledge(**self._init_agent(pos).__dict__))
77
85
 
86
+ # the knowledge is gained by rank: the population is sorted by cost (the best first)
87
+ self._population = sort_by_cost(self._population)
88
+
78
89
  p, kf, kr, kg = self._config.p, self._config.kf, self._config.kr, self._config.kg
79
90
  pop_size = self._config.population_size
80
91
  cycle_ratio = self._current_cycle / self._config.max_cycles
81
92
 
82
- prevs, nexts = zip(*[get_prev_next(i) for i in range(pop_size)])
93
+ # (with a very small population, the neighbours are kept inside the population)
94
+ prevs, nexts = zip(*[
95
+ tuple(min(max(n, 0), pop_size - 1) for n in get_prev_next(i)) for i in range(pop_size)
96
+ ])
83
97
  n_dims = self._task.space_dimension
84
98
  dd = int(n_dims * (1 - cycle_ratio) ** kg)
85
99
 
@@ -52,8 +52,8 @@ class GeneticAlgorithmOptimization(OptimizationAbstract):
52
52
  return self.__bit_genes[selection_ix].bitstring
53
53
 
54
54
  def crossover(idx: int) -> tuple[list[int], list[int]]:
55
- # get selected parents in pairs
56
- parent1, parent2 = selected[idx].copy(), selected[idx + 1].copy()
55
+ # get selected parents in pairs (with an odd population, the last parent mates with the first one)
56
+ parent1, parent2 = selected[idx].copy(), selected[(idx + 1) % len(selected)].copy()
57
57
  # children are copies of parents by default
58
58
  child1, child2 = parent1.copy(), parent2.copy()
59
59
  # check for recombination
@@ -62,7 +62,7 @@ class GeneticAlgorithmOptimization(OptimizationAbstract):
62
62
  pt = np.random.randint(1, len(parent1) - 2)
63
63
  # perform crossover
64
64
  child1 = parent1[:pt] + parent2[pt:]
65
- child2 = parent1[:pt] + parent2[pt:]
65
+ child2 = parent2[:pt] + parent1[pt:]
66
66
  return child1, child2
67
67
 
68
68
  px_over = self._config.px_over
@@ -82,7 +82,8 @@ class GeneticAlgorithmOptimization(OptimizationAbstract):
82
82
  c = np.array(child)
83
83
  children.append(np.where(np.random.rand(len(c)) < self.__p_mutation, 1 - c, c).tolist())
84
84
 
85
- # update population
85
+ # update population (with an odd population, the last pair generates one child more than needed)
86
+ children = children[:len(self.__bit_genes)]
86
87
  self.__bit_genes = [self.__bit_genes[idx].set_bit_string(child) for idx, child in enumerate(children)]
87
88
 
88
89
  lb, ub = self._task.get_bounds()
@@ -27,6 +27,10 @@ class GerminalCenterOptimization(OptimizationAbstract):
27
27
  def set_config_parameters(self, parameters: dict[str, Any]):
28
28
  self._config = GerminalCenterOptimizationConfig(**parameters)
29
29
 
30
+ def _minimum_population_size(self) -> int:
31
+ # the mutation mixes three cells
32
+ return 3
33
+
30
34
  def _init_agent(
31
35
  self, position: list[Any] | np.ndarray | None = None, cc: float | None = None, ls: float | None = None
32
36
  ) -> GerminalCenter:
@@ -32,6 +32,10 @@ class GreyWolfOptimization(OptimizationAbstract):
32
32
  def set_config_parameters(self, parameters: dict[str, Any]):
33
33
  self._config = GreyWolfOptimizationConfig(**parameters)
34
34
 
35
+ def _minimum_population_size(self) -> int:
36
+ # the pack is guided by the three best wolves (alpha, beta and delta)
37
+ return 3
38
+
35
39
  def after_initialization(self):
36
40
  self.__alpha_wolf, self.__beta_wolf, self.__gamma_wolf = best_agents(self._population, 3)
37
41
 
@@ -463,6 +463,26 @@ def get_pool_results(executors: list[parallel.Future]) -> list:
463
463
  return [executor.result() for executor in executors]
464
464
 
465
465
 
466
+ def split_in_clusters(population: list[T], n_clusters: int) -> list[list[T]]:
467
+ """
468
+ Split the population in (at most) n_clusters clusters of consecutive agents, whose sizes differ by one at most: all
469
+ the agents belong to a cluster, also when the size of the population is not a multiple of n_clusters (with equal
470
+ sizes, the clusters are the same as consecutive groups of population_size / n_clusters agents).
471
+ :param population: the population
472
+ :param n_clusters: the number of clusters
473
+ :return: the clusters (copies of the agents)
474
+ :rtype: list[list[T]]
475
+ """
476
+ n_clusters = max(1, min(n_clusters, len(population)))
477
+ size, residual = divmod(len(population), n_clusters)
478
+ clusters, start = [], 0
479
+ for idx in range(0, n_clusters):
480
+ end = start + size + (1 if idx < residual else 0)
481
+ clusters.append([agent.model_copy() for agent in population[start:end]])
482
+ start = end
483
+ return clusters
484
+
485
+
466
486
  def find_centers(pop_groups: list[list[T]]) -> list[T]:
467
487
  return [best_agent(pop_group).model_copy() for pop_group in pop_groups]
468
488
 
@@ -29,6 +29,10 @@ class NuclearReactionOptimization(OptimizationAbstract):
29
29
  def set_config_parameters(self, parameters: dict[str, Any]):
30
30
  self._config = NuclearReactionOptimizationConfig(**parameters)
31
31
 
32
+ def _minimum_population_size(self) -> int:
33
+ # the fission and the fusion involve two other nuclei
34
+ return 3
35
+
32
36
  def optimization_step(self):
33
37
  def nfi_phase(idx: int, reaction: NuclearReaction) -> NuclearReaction:
34
38
  position = np.array(reaction.position)
@@ -30,6 +30,10 @@ class RungeKuttaOptimization(OptimizationAbstract):
30
30
  def set_config_parameters(self, parameters: dict[str, Any]):
31
31
  self._config = RungeKuttaOptimizationConfig(**parameters)
32
32
 
33
+ def _minimum_population_size(self) -> int:
34
+ # the search mechanism uses three agents different from the current one
35
+ return 4
36
+
33
37
  def optimization_step(self):
34
38
  def evolve_runge_kutta(
35
39
  idx: int, agent: Agent
@@ -53,7 +53,8 @@ class SpottedHyenaOptimization(OptimizationAbstract):
53
53
  pos_new = np.array(g_best.position) - np.dot(E, D_h)
54
54
  new_agent = SpottedHyena(**self._init_agent(pos_new).__dict__)
55
55
  return self._greedy_select_agent(agent, new_agent)
56
- N = get_n()
56
+ # the circle can not be larger than the population
57
+ N = min(get_n(), pop_size)
57
58
  idx_list = np.random.choice(pop_size, N, replace=False).tolist()
58
59
  circle_list = [circle_list_item(idx_list[j], B, E) for j in range(0, N)]
59
60
  pos_new = np.mean(np.array(circle_list), axis=0)
@@ -30,6 +30,10 @@ class SuccessHistoryIntelligentOptimization(OptimizationAbstract):
30
30
  def set_config_parameters(self, parameters: dict[str, Any]):
31
31
  self._config = SuccessHistoryIntelligentOptimizationConfig(**parameters)
32
32
 
33
+ def _minimum_population_size(self) -> int:
34
+ # the agents are guided by the three best ones
35
+ return 3
36
+
33
37
  def before_initialization(self):
34
38
  # the coefficient decays during the run: reset it, so that the same instance can be used several times
35
39
  self.__a = 1.5
@@ -29,6 +29,10 @@ class VirusColonySearchOptimization(OptimizationAbstract):
29
29
  def set_config_parameters(self, parameters: dict[str, Any]):
30
30
  self._config = VirusColonySearchOptimizationConfig(**parameters)
31
31
 
32
+ def _minimum_population_size(self) -> int:
33
+ # the immune response involves two other viruses
34
+ return 3
35
+
32
36
  def before_initialization(self):
33
37
  self.__n_best = int(self._config.lamda * self._config.population_size)
34
38