Skip to content

Commit 0d81629

Browse files
authored
Merge pull request #2 from rsarai/update-fss
Update fss
2 parents b92db57 + 905ffd0 commit 0d81629

18 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/
-3.65 KB
Binary file not shown.

__pycache__/fish.cpython-35.pyc

-1.51 KB
Binary file not shown.
-4.01 KB
Binary file not shown.

__pycache__/functions.cpython-35.pyc

-2.19 KB
Binary file not shown.

__pycache__/parameters.cpython-35.pyc

-270 Bytes
Binary file not shown.

__pycache__/particle.cpython-35.pyc

-2.53 KB
Binary file not shown.

fish_school_search.py

+99-110
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,114 @@
11
import copy
2+
import numpy as np
23
import functools
34
import random
45
import math
56

67
from particle import Fish
78
from parameters import num_of_individuos, dimensions, iterations_number
89

10+
# np.random.seed(42)
911

1012
class FSS():
1113

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

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

122113
def _get_random_number(self):
123-
return (
124-
self.function.lower_bound + random.uniform(0, 1) * (self.function.upper_bound - self.function.lower_bound)
125-
)
114+
return np.random.uniform(self.function.lower_bound, self.function.upper_bound)

0 commit comments

Comments
 (0)