-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparticle.py
236 lines (191 loc) · 9.17 KB
/
particle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
import numpy as np
import random
import copy
import random
from parameters import dimensions, iterations_number
from enum import Enum
# np.random.seed(42)
# random.seed(42)
class Particle():
def __init__(self, function_wrapper, positions):
self.function_wrapper = function_wrapper
self.current_position = positions
self.best_particle = self.current_position
self.fitness = 1.0
def aply_function_on_current_position(self):
self.fitness = self.function_wrapper.calculate_fitness(self.current_position)
def clone_particle(self):
clone_object = copy.copy(self)
clone_object.current_position = copy.deepcopy(self.current_position)
clone_object.fitness = copy.deepcopy(self.fitness)
return clone_object
class Fish():
def __init__(self, objective_function, positions):
self.fitness_function = objective_function
self.current_position = positions
self.weight = iterations_number / 2.0
self.fitness = np.inf
self.delta_fitness = 0
self.delta_position = []
def evaluate(self):
new_fitness = self.fitness_function.calculate_fitness(self.current_position)
self.fitness = new_fitness
def update_position_individual_movement(self, step_ind):
new_positions = []
for pos in self.current_position:
new = pos + (step_ind * np.random.uniform(-1, 1))
if new > self.fitness_function.upper_bound:
new = self.fitness_function.upper_bound
elif new < self.fitness_function.lower_bound:
new = self.fitness_function.lower_bound
new_positions.append(new)
assert len(new_positions) == len(self.current_position)
new_fitness = self.fitness_function.calculate_fitness(new_positions)
if new_fitness < self.fitness:
self.delta_fitness = abs(new_fitness - self.fitness)
self.fitness = new_fitness
self.delta_position = [x - y for x, y in zip(new_positions, self.current_position)]
self.current_position = list(new_positions)
else:
self.delta_position = [0] * dimensions
self.delta_fitness = 0
def feed(self, max_delta_fitness):
if max_delta_fitness != 0:
self.weight = self.weight + (self.delta_fitness / max_delta_fitness)
else:
self.weight = 1
def update_position_collective_movement(self, sum_delta_fitness):
collective_instinct = []
for i, _ in enumerate(self.delta_position):
collective_instinct.append(self.delta_position[i] * self.delta_fitness)
if sum_delta_fitness != 0:
collective_instinct = [val / sum_delta_fitness for val in collective_instinct]
new_positions = []
for i, _ in enumerate(self.current_position):
new = self.current_position[i] + collective_instinct[i]
if new > self.fitness_function.upper_bound:
new = self.fitness_function.upper_bound
elif new < self.fitness_function.lower_bound:
new = self.fitness_function.lower_bound
new_positions.append(new)
assert len(new_positions) == len(self.current_position)
self.current_position = list(new_positions)
def update_position_volitive_movement(self, barycenter, step_vol, search_operator):
new_positions = []
for i, pos in enumerate(self.current_position):
new = pos + (((pos - barycenter[i]) * step_vol * np.random.uniform(0, 1)) * search_operator)
if new > self.fitness_function.upper_bound:
new = self.fitness_function.upper_bound
elif new < self.fitness_function.lower_bound:
new = self.fitness_function.lower_bound
new_positions.append(new)
# volitive_step = [x - y for x, y in zip(self.current_position,barycenter)] / np.linalg.norm([self.current_position, barycenter])
# volitive_step = np.random.uniform(0, 1) * step_vol * volitive_step * search_operator
# new_positions = [x + y for x, y in zip(self.current_position, volitive_step)]
assert len(new_positions) == len(self.current_position)
self.current_position = list(new_positions)
class BeeJob(Enum):
EMPLOYED = 1
ONLOOKERS = 2
SCOUT = 3
class Bee():
def __init__(self, objective_function, positions, bee_type, food_source):
self.objective_function = objective_function
self.current_position = positions
self.fitness = self._calculate_fitness(positions)
self.bee_type = bee_type
self.dimensions = len(positions)
self.failures = 0
self.food_source = food_source
def evaluate(self):
self.fitness = self._calculate_fitness(self.current_position)
def employed_bees_explore_new_food_source(self):
if self.bee_type != BeeJob.EMPLOYED:
return
new_position = list(self.current_position)
position2change = random.randint(0, self.dimensions - 1)
random_index = self._get_random_number(position2change)
new_pos = self.current_position[position2change] + random.uniform(-1, 1) * (self.current_position[position2change] - self.current_position[random_index])
if new_pos > self.objective_function.upper_bound:
new_pos = self.objective_function.upper_bound
if new_pos < self.objective_function.lower_bound:
new_pos = self.objective_function.lower_bound
new_position[position2change] = new_pos
new_fitness = self._calculate_fitness(new_position)
if self.fitness < new_fitness:
self.failures += 1
return
self.current_position = new_position
self.fitness = new_fitness
def set_new_food_source_for_onlooker_bee(self, source_position, food_source):
new_position = list(self.current_position)
position2change = random.randint(0, self.dimensions - 1)
random_index = self._get_random_number(position2change)
new_pos = self.current_position[position2change] + random.uniform(-1, 1) * (self.current_position[position2change] - source_position[random_index])
if new_pos > self.objective_function.upper_bound:
new_pos = self.objective_function.upper_bound
if new_pos < self.objective_function.lower_bound:
new_pos = self.objective_function.lower_bound
new_position[position2change] = new_pos
new_fitness = self._calculate_fitness(new_position)
if self.fitness < new_fitness:
return
self.current_position = new_position
self.food_source = food_source
self.fitness = new_fitness
def _calculate_fitness(self, new_position):
return self.objective_function.calculate_fitness(new_position)
def _get_random_number(self, excluded_index):
random_index = random.randint(0, self.dimensions - 1)
while random_index == excluded_index:
random_index = random.randint(0, self.dimensions - 1)
return random_index
def set_position(self, new_positions):
self.current_position = list(new_positions)
class Ant():
def __init__(self, current_town):
self.current_town = current_town
self.tabu_list = [current_town]
self.pheromones_delta = []
self.total_cost = 0
def move_next_city_to_construct_tour(self, graph, alpha, beta):
assert len(self.tabu_list) == len(set(self.tabu_list))
denominator = 0
for j in range(len(graph.cities)):
if j in self.tabu_list:
continue
denominator += (
(graph.pheromones[self.current_town][j] ** alpha) *
((1 / graph.distance_matrix[self.current_town][j]) ** beta)
)
probabilities = []
for j in range(len(graph.cities)):
if j in self.tabu_list:
probabilities.append(0)
continue
if denominator == 0:
probabilities.append(1 / len(graph.cities))
else:
probabilities.append(
(
(graph.pheromones[self.current_town][j] ** alpha) *
((1 / graph.distance_matrix[self.current_town][j]) ** beta)
) / denominator
)
next_town = random.choices(
population=list(range(0, len(graph.cities))),
weights=probabilities
)[0]
self.total_cost += graph.distance_matrix[self.current_town][next_town]
self.current_town = next_town
self.tabu_list.append(next_town)
assert len(self.tabu_list) == len(set(self.tabu_list))
def update_pheromone_trails(self, graph):
self.pheromones_delta = [[0 for _ in range(len(self.tabu_list))] for _ in range(len(self.tabu_list))]
for i in range(len(self.tabu_list) - 1):
step = self.tabu_list[i]
next_step = self.tabu_list[i + 1]
self.pheromones_delta[step][next_step] = 1 / graph.distance_matrix[step][next_step]
# self.pheromones_delta[step][next_step] = 1 / self.total_cost
def complet_tour_cost(self, graph):
self.total_cost += graph.distance_matrix[self.current_town][self.tabu_list[0]]