def solve(Ma, Mw): write_graph(Ma, Mw, [], 'tmp', int_weights=True) redirector_stdout = Redirector(fd=STDOUT) redirector_stderr = Redirector(fd=STDERR) redirector_stderr.start() redirector_stdout.start() solver = TSPSolver.from_tspfile('tmp') solution = solver.solve(verbose=False) redirector_stderr.stop() redirector_stdout.stop() return solution.tour if solution.found_tour else []
def solve(Ma, Mw): """ Invokes Concorde to solve a TSP instance Uses Python's Redirector library to prevent Concorde from printing unsufferably verbose messages """ STDOUT = 1 STDERR = 2 redirector_stdout = Redirector(fd=STDOUT) redirector_stderr = Redirector(fd=STDERR) # Write graph on a temporary file write_graph(Ma, Mw, filepath='tmp', int_weights=True) redirector_stderr.start() redirector_stdout.start() # Solve TSP on graph solver = TSPSolver.from_tspfile('tmp') # Get solution solution = solver.solve(verbose=False) redirector_stderr.stop() redirector_stdout.stop() """ Concorde solves only symmetric TSP instances. To circumvent this, we fill inexistent edges with large weights. Concretely, an inexistent edge is assigned with the strictest upper limit to the cost of an optimal tour, which is n (the number of nodes) times 1 (the maximum weight). If one of these edges is used in the optimal solution, we can deduce that no valid tour exists (as just one of these edges costs more than all the others combined). OBS. in this case the maximum weight 1 is multiplied by 'bins' because we are converting from floating point to integers """ if any([ Ma[i, j] == 0 for (i, j) in zip(list(solution.tour), list(solution.tour)[1:] + list(solution.tour)[:1]) ]): return None else: return list(solution.tour)