From bbacd170346915c059dc45002f4840c6d11c9eba Mon Sep 17 00:00:00 2001 From: Sanjay Muthu Date: Tue, 4 Feb 2025 21:37:33 +0530 Subject: [PATCH] Added graphs/travelling_salesman_problem.py --- graphs/travelling_salesman_problem.py | 96 +++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 graphs/travelling_salesman_problem.py diff --git a/graphs/travelling_salesman_problem.py b/graphs/travelling_salesman_problem.py new file mode 100644 index 000000000000..62094491a28f --- /dev/null +++ b/graphs/travelling_salesman_problem.py @@ -0,0 +1,96 @@ +""" +Author:- Sanjay Muthu + +The Problem: + In the travelling salesman problem you have to find the path + in which a salesman can start from a source node and visit all the other nodes + ONCE and return to the source node in the shortest possible way + +Complexity: + There are n! permutations of all the nodes in the graph and + for each permutation we have to go through all the nodes + which will take O(n) time per permutation. + So the total time complexity will be O(n * n!). + + Time Complexity:- O(n * n!) + + It takes O(n) space to store the list of nodes. + + Space Complexity:- O(n) + +Wiki page:- +""" + +from itertools import permutations + + +def floyd_warshall(graph, v): + dist = graph + for k in range(v): + for i in range(v): + for j in range(v): + dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]) + return dist + + +def travelling_salesman_problem(graph, v): + """ + Returns the shortest path that a salesman can take to visit all the nodes + in the graph and return to the source node + + The graph in the below testcase looks something like this:- + 2 + _________________________ + | | + 2 ^ 6 ^ + (0) <------------> (1) (2)<------>(3) + ^ ^ + | 3 | + |_______________________________| + + >>> graph = [] + >>> graph.append([0, 2, 3, float('inf')]) + >>> graph.append([2, 0, float('inf'), 2]) + >>> graph.append([3, float('inf'), 0, 6]) + >>> graph.append([float('inf'), 2, 6, 0]) + >>> travelling_salesman_problem(graph, 4) + 13 + """ + + # See graphs_floyd_warshall.py for implementation + shortest_distance_matrix = floyd_warshall(graph, v) + nodes = list(range(v)) + + min_distance = float("inf") + + # Go through all the permutations of the nodes to find out + # which of the order of nodes lead to the shortest distance + # Permutations(nodes) returns a list of all permutations of the list + # Permutations are all the possible ways to arrange the elements of the list + for permutation in permutations(nodes): + current_dist = 0 + current_node = 0 + + # Find the distance of the current permutation by going through all the nodes + # in order and add the distance between the nodes to the current_dist + for node in permutation: + current_dist += shortest_distance_matrix[current_node][node] + current_node = node + + # Add the distance to come back to the source node + current_dist += shortest_distance_matrix[current_node][0] + + # If the current distance is less than the minimum distance found so far, + # update the minimum distance + # print(permutation, current_dist) + min_distance = min(min_distance, current_dist) + + # NOTE: We are assuming 0 is the source node here. + + return min_distance + + +if __name__ == "__main__": + import doctest + + doctest.testmod()