From 30929de41c9a3e8fd540b1d45705ba9e7438cf9d Mon Sep 17 00:00:00 2001 From: Anton <antoshkvir@gmail.com> Date: Wed, 11 Dec 2024 01:24:45 +0200 Subject: [PATCH 1/2] Implementing last changes --- examples/aco_tsp/aco_tsp/model.py | 44 ++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/examples/aco_tsp/aco_tsp/model.py b/examples/aco_tsp/aco_tsp/model.py index 0b08ba93..905431bd 100644 --- a/examples/aco_tsp/aco_tsp/model.py +++ b/examples/aco_tsp/aco_tsp/model.py @@ -83,18 +83,20 @@ class AntTSP(CellAgent): An agent """ - def __init__(self, model, alpha: float = 1.0, beta: float = 5.0): + def __init__(self, model, alpha: float = 1.0, beta: float = 5.0, random_move_prob: float = 0.1, max_distance: float = None): """ Customize the agent """ super().__init__(model) self.alpha = alpha self.beta = beta + self.random_move_prob = random_move_prob # Ймовірність випадкового переміщення self._cities_visited = [] self._traveled_distance = 0 self.tsp_solution = [] self.tsp_distance = 0 self.graph = self.model.grid.G + self.max_distance = max_distance if max_distance is not None else float("inf") def calculate_pheromone_delta(self, q: float = 100): results = {} @@ -112,23 +114,25 @@ def move_to(self, cell) -> None: ]["distance"] super().move_to(cell) + # Зміна логіки вибору наступного міста мурахою + # У класі `AntTSP`, змінено метод `decide_next_city`, щоб додати нову логіку: враховувати довжину вже пройденого мурахою маршруту. def decide_next_city(self): - # Random - # new_city = self.random.choice(list(self.model.all_cities - set(self.cities_visited))) - # Choose closest city not yet visited neighbors = self.cell.neighborhood candidates = [n for n in neighbors if n not in self._cities_visited] if len(candidates) == 0: return self.cell - # p_ij(t) = 1/Z*[(tau_ij)**alpha * (1/distance)**beta] + # p_ij(t) = 1/Z*[(tau_ij)**alpha * (1/distance)**beta * (1 + adjustment_factor)] results = [] for city in candidates: + adjustment_factor = 1 - ( + self._traveled_distance / self.model.grid.G[self.cell.coordinate][city.coordinate]["distance"]) val = ( - (self.graph[self.cell.coordinate][city.coordinate]["pheromone"]) - ** self.alpha - * (self.graph[self.cell.coordinate][city.coordinate]["visibility"]) - ** self.beta + (self.graph[self.cell.coordinate][city.coordinate]["pheromone"]) + ** self.alpha + * (self.graph[self.cell.coordinate][city.coordinate]["visibility"]) + ** self.beta + * (1 + adjustment_factor) ) results.append(val) @@ -137,17 +141,17 @@ def decide_next_city(self): results /= norm new_city = self.random.choices(candidates, weights=results)[0] - return new_city + # У методі `step` мурахи завершують подорож при досягненні ліміту def step(self): """ Modify this method to change what an individual agent will do during each step. Can include logic based on neighbors states. """ - for _ in range(self.model.num_cities - 1): - # Pick a random city that isn't in the list of cities visited + if self._traveled_distance >= self.max_distance: + break # Завершується маршрут, якщо досягнуто ліміту new_city = self.decide_next_city() self.move_to(new_city) @@ -173,6 +177,7 @@ def __init__( max_steps: int = int(1e6), ant_alpha: float = 1.0, ant_beta: float = 5.0, + local_decay: float = 0.1, # Новий параметр для локального випаровування ): super().__init__() self.num_agents = num_agents @@ -181,6 +186,7 @@ def __init__( self.all_cities = set(range(self.num_cities)) self.max_steps = max_steps self.grid = Network(tsp_graph.g, random=self.random) + self.local_decay = local_decay # Збереження параметра локального випаровування for _ in range(self.num_agents): agent = AntTSP(model=self, alpha=ant_alpha, beta=ant_beta) @@ -213,20 +219,22 @@ def __init__( self.running = True - def update_pheromone(self, q: float = 100, ro: float = 0.5): - # tau_ij(t+1) = (1-ro)*tau_ij(t) + delta_tau_ij(t) - # delta_tau_ij(t) = sum_k^M {Q/L^k} * I[i,j \in T^k] + def update_pheromone(self, q: float = 100): + ro = max(0.1, 0.5 - (self.num_steps / self.max_steps) * 0.4) # Динамічне ro delta_tau_ij = {} for k, agent in enumerate(self.agents): delta_tau_ij[k] = agent.calculate_pheromone_delta(q) - for i, j in self.grid.G.edges(): - # Evaporate tau_ij = (1 - ro) * self.grid.G[i][j]["pheromone"] - # Add ant's contribution for k, delta_tau_ij_k in delta_tau_ij.items(): tau_ij += delta_tau_ij_k.get((i, j), 0.0) + # Збільшення часу випаровування феромону на шляхах, якими пройшло більше мурах + num_ants_on_edge = sum( + 1 for agent in self.agents if (i, j) in zip(agent.tsp_solution[:-1], agent.tsp_solution[1:])) + if num_ants_on_edge > 0: + tau_ij *= (1 + 0.1 * num_ants_on_edge) # Додатковий коефіцієнт для популярних шляхів + self.grid.G[i][j]["pheromone"] = tau_ij def step(self): From 37c46e15973309213b52b1c48af8883987820cf7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:37:19 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/aco_tsp/aco_tsp/model.py | 32 ++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/examples/aco_tsp/aco_tsp/model.py b/examples/aco_tsp/aco_tsp/model.py index 905431bd..f3bba5a7 100644 --- a/examples/aco_tsp/aco_tsp/model.py +++ b/examples/aco_tsp/aco_tsp/model.py @@ -83,7 +83,14 @@ class AntTSP(CellAgent): An agent """ - def __init__(self, model, alpha: float = 1.0, beta: float = 5.0, random_move_prob: float = 0.1, max_distance: float = None): + def __init__( + self, + model, + alpha: float = 1.0, + beta: float = 5.0, + random_move_prob: float = 0.1, + max_distance: float = None, + ): """ Customize the agent """ @@ -126,13 +133,15 @@ def decide_next_city(self): results = [] for city in candidates: adjustment_factor = 1 - ( - self._traveled_distance / self.model.grid.G[self.cell.coordinate][city.coordinate]["distance"]) + self._traveled_distance + / self.model.grid.G[self.cell.coordinate][city.coordinate]["distance"] + ) val = ( - (self.graph[self.cell.coordinate][city.coordinate]["pheromone"]) - ** self.alpha - * (self.graph[self.cell.coordinate][city.coordinate]["visibility"]) - ** self.beta - * (1 + adjustment_factor) + (self.graph[self.cell.coordinate][city.coordinate]["pheromone"]) + ** self.alpha + * (self.graph[self.cell.coordinate][city.coordinate]["visibility"]) + ** self.beta + * (1 + adjustment_factor) ) results.append(val) @@ -231,9 +240,14 @@ def update_pheromone(self, q: float = 100): # Збільшення часу випаровування феромону на шляхах, якими пройшло більше мурах num_ants_on_edge = sum( - 1 for agent in self.agents if (i, j) in zip(agent.tsp_solution[:-1], agent.tsp_solution[1:])) + 1 + for agent in self.agents + if (i, j) in zip(agent.tsp_solution[:-1], agent.tsp_solution[1:]) + ) if num_ants_on_edge > 0: - tau_ij *= (1 + 0.1 * num_ants_on_edge) # Додатковий коефіцієнт для популярних шляхів + tau_ij *= ( + 1 + 0.1 * num_ants_on_edge + ) # Додатковий коефіцієнт для популярних шляхів self.grid.G[i][j]["pheromone"] = tau_ij