Skip to content

Commit 1dca028

Browse files
committed
Merge branch 'master' of github.com:rsarai/swarm-algorithms
2 parents 67acdb8 + 0d81629 commit 1dca028

12 files changed

+412
-258
lines changed

.gitignore

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py,cover
51+
.hypothesis/
52+
.pytest_cache/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
target/
76+
77+
# Jupyter Notebook
78+
.ipynb_checkpoints
79+
80+
# IPython
81+
profile_default/
82+
ipython_config.py
83+
84+
# pyenv
85+
.python-version
86+
87+
# pipenv
88+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91+
# install all needed dependencies.
92+
#Pipfile.lock
93+
94+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
95+
__pypackages__/
96+
97+
# Celery stuff
98+
celerybeat-schedule
99+
celerybeat.pid
100+
101+
# SageMath parsed files
102+
*.sage.py
103+
104+
# Environments
105+
.env
106+
.venv
107+
env/
108+
venv/
109+
ENV/
110+
env.bak/
111+
venv.bak/
112+
113+
# Spyder project settings
114+
.spyderproject
115+
.spyproject
116+
117+
# Rope project settings
118+
.ropeproject
119+
120+
# mkdocs documentation
121+
/site
122+
123+
# mypy
124+
.mypy_cache/
125+
.dmypy.json
126+
dmypy.json
127+
128+
# Pyre type checker
129+
.pyre/

fish_school_search.py

+99-110
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import copy
2+
import numpy as np
23
import functools
34
import random
45
import math
@@ -7,120 +8,108 @@
78
from particle import Fish
89
from parameters import num_of_individuos, dimensions, iterations_number
910

11+
# np.random.seed(42)
1012

1113
class FSS():
1214

13-
def __init__(self, function_wrapper):
14-
self.function = function_wrapper
15+
def __init__(self, objective_function):
16+
self.function = objective_function
17+
self.dimensions = dimensions
18+
self.iterations_number = iterations_number
19+
self.num_of_individuos = num_of_individuos
20+
self.cluster = []
21+
self.global_best = float('inf')
22+
self.global_best_position = []
23+
24+
# Params
25+
self.total_weight = 1 * self.num_of_individuos
26+
self.initial_step_ind = 0.1
27+
self.final_step_ind = 0.0001
28+
self.step_ind = self.initial_step_ind * (objective_function.upper_bound - objective_function.lower_bound)
29+
self.initial_step_vol = 0.01
30+
self.final_step_vol = 0.001
31+
self.step_vol = self.initial_step_vol * (objective_function.upper_bound - objective_function.lower_bound)
32+
self.list_global_best_values = []
1533

1634
def search(self):
17-
bests = []
18-
maximum_weight_value = 1000
19-
individual_step_dacay = 0.00005
20-
self._initialize_particles()
21-
22-
for iterations in range(iterations_number):
23-
24-
# individual_movement
25-
fitness_variations = []
26-
for fish in self.population:
27-
new_position = fish.individual_movement()
28-
new_fish = Fish(fish.function_wrapper, new_position, fish.weights)
29-
new_fish.aply_function_on_current_position()
30-
fish.aply_function_on_current_position()
31-
32-
if new_fish.fitness < fish.fitness:
33-
new_fish.previous_position = fish.current_position
34-
fish = new_fish
35-
else:
36-
fish.previous_position = fish.current_position
37-
38-
fitness_variations.append(abs(new_fish.fitness - fish.fitness))
39-
40-
# feed fishes
41-
max_variation = max(fitness_variations)
42-
for fish in self.population:
43-
new_weight = fish.weights + (fish.fitness / max_variation)
44-
fish.previous_weight = fish.weights
45-
fish.weights = new_weight
46-
if fish.weights > maximum_weight_value:
47-
fish.weights = maximum_weight_value
48-
49-
# calculates vector of instintict moviments
50-
distance_variations_sum = [0 for i in range(0, dimensions)]
51-
fitness_variations_sum = sum(fitness_variations)
52-
for fish in self.population:
53-
54-
for i in range(0, dimensions):
55-
distance_variations = abs(fish.current_position[i] - fish.previous_position[i])
56-
distance_variations_sum[i] = distance_variations_sum[i] + (distance_variations * fitness_variations[i])
57-
58-
instintive_movement_array = []
59-
for i in range(0, dimensions):
60-
if fitness_variations_sum != 0:
61-
instintive_movement_array.append(distance_variations_sum[i]/fitness_variations_sum)
62-
else:
63-
instintive_movement_array.append(0)
64-
65-
# executes instintive moviments
66-
for fish in self.population:
67-
for i in range(0, dimensions):
68-
fish.current_position[i] = fish.current_position[i] + instintive_movement_array[i]
69-
70-
# calculates the baricenter
71-
weights_sum = 0
72-
for fish in self.population:
73-
weights_sum += fish.weights
74-
75-
weights_sum_times_position = 0
76-
for fish in self.population:
77-
for i in range(0, dimensions):
78-
weights_sum_times_position = weights_sum_times_position + (fish.current_position[i] * fish.weights)
79-
80-
baricenter = [weights_sum_times_position / weights_sum for i in range(0, dimensions)]
81-
82-
# executes volitive moviment
83-
for fish in self.population:
84-
distance_to_baricenter = np.linalg.norm([fish.current_position, baricenter])
85-
86-
volational_array = []
87-
difference_to_baricenter = []
88-
weight_variation_sum = 0
89-
for i in range(0, dimensions):
90-
volational_array.append(2 * fish.current_position[i])
91-
difference_to_baricenter.append(fish.current_position[i] - baricenter[i])
92-
weight_variation_sum = weight_variation_sum + abs(fish.weights - fish.previous_weight)
93-
94-
sign = functools.partial(math.copysign, 1)
95-
for i in range(0, dimensions):
96-
fish.current_position[i] = fish.current_position[i] + -sign(weight_variation_sum) * volational_array[i] * random.random() * difference_to_baricenter[i] / distance_to_baricenter
97-
98-
for fish in self.population:
99-
for i in range(0, dimensions):
100-
fish.current_position[i] -= individual_step_dacay
101-
102-
for fish in self.population:
103-
fish.aply_function_on_current_position()
104-
105-
bests.append(min([fish.fitness for fish in self.population]))
106-
return bests
107-
108-
109-
def _initialize_particles(self):
110-
self.population = []
111-
for i in range(num_of_individuos):
112-
random_position = [self._get_random_number() for index in range(dimensions)]
113-
fish = Fish(self.function, random_position, random.uniform(300, 600))
114-
self.population.append(fish)
115-
116-
def _euclidian_distance(self, particle_i, particle_j):
117-
total = 0
118-
for i in range(dimensions):
119-
distance = (particle_i[i] - particle_j[i])**2
120-
total += distance
121-
return math.sqrt(total)
35+
self._initialize_cluster()
36+
37+
for i in range(self.iterations_number):
38+
self.evaluate_cluster()
39+
self.updates_optimal_solution()
40+
41+
self.apply_individual_movement()
42+
self.evaluate_cluster()
43+
self.updates_optimal_solution()
44+
45+
self.apply_feeding()
46+
47+
self.apply_instintive_collective_movement()
48+
self.apply_collective_volitive_movement()
49+
50+
self.update_step(i)
51+
self.update_total_weight()
52+
53+
self.evaluate_cluster()
54+
self.updates_optimal_solution()
55+
self.list_global_best_values.append(self.global_best)
56+
print("iter: {} = cost: {}".format(i, self.global_best))
57+
58+
def update_total_weight(self):
59+
self.total_weight = sum([fish.weight for fish in self.cluster])
60+
61+
def _initialize_cluster(self):
62+
self.cluster = []
63+
for _ in range(self.num_of_individuos):
64+
fish = Fish(
65+
positions=[self._get_random_number() for _ in range(dimensions)],
66+
objective_function=self.function
67+
)
68+
self.cluster.append(fish)
69+
70+
def evaluate_cluster(self):
71+
for fish in self.cluster:
72+
fish.evaluate()
73+
74+
def updates_optimal_solution(self):
75+
for fish in self.cluster:
76+
if fish.fitness < self.global_best:
77+
self.global_best = fish.fitness
78+
self.global_best_position = list(fish.current_position)
79+
80+
def apply_individual_movement(self):
81+
for fish in self.cluster:
82+
fish.update_position_individual_movement(self.step_ind)
83+
84+
def apply_feeding(self):
85+
max_delta_fitness = max([fish.delta_fitness for fish in self.cluster])
86+
for fish in self.cluster:
87+
fish.feed(max_delta_fitness)
88+
89+
def apply_instintive_collective_movement(self):
90+
sum_delta_fitness = sum([fish.delta_fitness for fish in self.cluster])
91+
92+
for fish in self.cluster:
93+
fish.update_position_collective_movement(sum_delta_fitness)
94+
95+
def _calculate_barycenter(self):
96+
sum_weights = sum([fish.weight for fish in self.cluster])
97+
sum_position_and_weights = [[x * fish.weight for x in fish.current_position] for fish in self.cluster]
98+
sum_position_and_weights = np.sum(sum_position_and_weights, 0)
99+
return [s / sum_weights for s in sum_position_and_weights]
100+
101+
def apply_collective_volitive_movement(self):
102+
barycenter = self._calculate_barycenter()
103+
current_total_weight = sum([fish.weight for fish in self.cluster])
104+
search_operator = -1 if current_total_weight > self.total_weight else 1
105+
for fish in self.cluster:
106+
fish.update_position_volitive_movement(barycenter, self.step_vol, search_operator)
107+
108+
def update_step(self, current_i):
109+
self.step_ind = self.initial_step_ind - current_i * float(
110+
self.initial_step_ind - self.final_step_ind) / iterations_number
111+
self.step_vol = self.initial_step_vol - current_i * float(
112+
self.initial_step_vol - self.final_step_vol) / iterations_number
122113

123114
def _get_random_number(self):
124-
return (
125-
self.function.lower_bound + random.uniform(0, 1) * (self.function.upper_bound - self.function.lower_bound)
126-
)
115+
return np.random.uniform(self.function.lower_bound, self.function.upper_bound)

0 commit comments

Comments
 (0)