From 013bb76e3323cc1ec6d86cf8213fc7bcd976fb4f Mon Sep 17 00:00:00 2001 From: Denis Suchkov <107809488+Den-is-me@users.noreply.github.com> Date: Tue, 5 Mar 2024 22:57:12 +0500 Subject: [PATCH] Fix bugs update_pheromones: fixed a bug. Previously, the method updated all pheromones with the same value, resulting in identical pheromones. visit_random_attraction: fixed a bug. Previously, the method chose from a range instead of from possible attractions, resulting in a chance to return to a previously visited attraction. visit_probabilistic_attraction: minor fix based on the correct probability function. roulette_wheel_selection: minor optimization. --- ch06-swarm_intelligence-ants/carnival_aco.py | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/ch06-swarm_intelligence-ants/carnival_aco.py b/ch06-swarm_intelligence-ants/carnival_aco.py index 278f172..9f005e7 100644 --- a/ch06-swarm_intelligence-ants/carnival_aco.py +++ b/ch06-swarm_intelligence-ants/carnival_aco.py @@ -22,7 +22,7 @@ # Set the probability of ants choosing a random attraction to visit (0.0 - 1.0) RANDOM_ATTRACTION_FACTOR = 0.0 # Set the weight for pheromones on path for selection -ALPHA = 4 +ALPHA = 5 # Set the weight for heuristic of path for selection BETA = 7 @@ -52,7 +52,7 @@ def visit_attraction(self, pheromone_trails): def visit_random_attraction(self): all_attractions = set(range(0, ATTRACTION_COUNT)) possible_attractions = all_attractions - set(self.visited_attractions) - return random.randint(0, len(possible_attractions) - 1) + return possible_attractions.pop() # Calculate probabilities of visiting adjacent unvisited attractions def visit_probabilistic_attraction(self, pheromone_trails): @@ -65,8 +65,8 @@ def visit_probabilistic_attraction(self, pheromone_trails): for attraction in possible_attractions: possible_indexes.append(attraction) pheromones_on_path = math.pow(pheromone_trails[current_attraction][attraction], ALPHA) - heuristic_for_path = math.pow(1 / attraction_distances[current_attraction][attraction], BETA) - probability = pheromones_on_path * heuristic_for_path + heuristic_for_path = math.pow(20/ attraction_distances[current_attraction][attraction], BETA) + probability = pheromones_on_path + heuristic_for_path possible_probabilities.append(probability) total_probabilities += probability possible_probabilities = [probability / total_probabilities for probability in possible_probabilities] @@ -84,8 +84,9 @@ def roulette_wheel_selection(probabilities): slices.append([possible_indexes[i], total, total + possible_probabilities[i]]) total += possible_probabilities[i] spin = random.random() - result = [s[0] for s in slices if s[1] < spin <= s[2]] - return result[0] + for s in slices: + if s[1] < spin <= s[2]: + return s[0] # Get the total distance travelled by this ant def get_distance_travelled(self): @@ -167,8 +168,13 @@ def update_pheromones(self, evaporation_rate): for x in range(0, ATTRACTION_COUNT): for y in range(0, ATTRACTION_COUNT): self.pheromone_trails[x][y] = self.pheromone_trails[x][y] * evaporation_rate - for ant in self.ant_colony: - self.pheromone_trails[x][y] += 1 / ant.get_distance_travelled() + + for ant in self.ant_colony: + distance = ant.get_distance_travelled() + for i in range(1, ATTRACTION_COUNT - 1): + x, y = ant.visited_attractions[i - 1], ant.visited_attractions[i] + self.pheromone_trails[x][y] += 1 / distance + self.pheromone_trails[y][x] += 1 / distance # Tie everything together - this is the main loop def solve(self, total_iterations, evaporation_rate):