Source code for mrinufft.trajectories.maths.tsp_solver

"""Solver for the Travelling Salesman Problem."""

import numpy as np


[docs] def solve_tsp_with_2opt(locations, improvement_threshold=1e-8): """Solve the TSP problem using a 2-opt approach. A sub-optimal solution to the Travelling Salesman Problem (TSP) is provided using the 2-opt approach in O(n²) where chunks of an initially random route are reversed, and selected if the total distance is reduced. As a result the route solution does not cross its own path in 2D. Parameters ---------- locations : array_like An array of N points with shape (N, D) with D the space dimension. improvement_threshold: float Threshold used as progress criterion to stop the optimization process. Returns ------- array_like The new positions order of shape (N,). """ route = np.arange(locations.shape[0]) distances = np.linalg.norm(locations[None] - locations[:, None], axis=-1) route_length = np.sum(distances[0]) improvement_factor = 1 while improvement_factor >= improvement_threshold: old_route_length = route_length for i in range(1, len(route) - 2): # Check new distance by reversing chunks between i and j for j in range(i + 1, len(route) - 1): # Compute new route distance variation delta_length = ( distances[route[i - 1], route[j]] + distances[route[i], route[j + 1]] - distances[route[i - 1], route[i]] - distances[route[j], route[j + 1]] ) if delta_length < 0: # Reverse route chunk route = np.concatenate( [route[:i], route[i : j + 1][::-1], route[j + 1 :]] ) route_length += delta_length improvement_factor = abs(1 - route_length / old_route_length) return route