import math, random def distance(city1, city2): return math.sqrt((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2) def total_distance(cities): return sum([distance(cities[i - 1], cities[i]) for i in range(len(cities))]) class SimulatedAnnealing: def __init__(self, cities, temperature=10000, cooling_rate=0.9999, temperature_ok=0.001): self.cities = cities self.temperature = temperature self.cooling_rate = cooling_rate self.temperature_ok = temperature_ok def run(self): current_solution = self.cities.copy() best_solution = self.cities.copy() while self.temperature > self.temperature_ok: new_solution = current_solution.copy() # Swap two cities in the route i = random.randint(0, len(new_solution) - 1) j = random.randint(0, len(new_solution) - 1) new_solution[i], new_solution[j] = new_solution[j], new_solution[i] # Calculate the acceptance probability current_energy = total_distance(current_solution) new_energy = total_distance(new_solution) delta = new_energy - current_energy if delta < 0 or random.random() < math.exp(-delta / self.temperature): current_solution = new_solution if total_distance(current_solution) < total_distance(best_solution): best_solution = current_solution # Cool down self.temperature *= self.cooling_rate return best_solution