Skip to content

Commit bbacd17

Browse files
authored
Added graphs/travelling_salesman_problem.py
1 parent 6c92c5a commit bbacd17

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

graphs/travelling_salesman_problem.py

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"""
2+
Author:- Sanjay Muthu <https://github.com/XenoBytesX>
3+
4+
The Problem:
5+
In the travelling salesman problem you have to find the path
6+
in which a salesman can start from a source node and visit all the other nodes
7+
ONCE and return to the source node in the shortest possible way
8+
9+
Complexity:
10+
There are n! permutations of all the nodes in the graph and
11+
for each permutation we have to go through all the nodes
12+
which will take O(n) time per permutation.
13+
So the total time complexity will be O(n * n!).
14+
15+
Time Complexity:- O(n * n!)
16+
17+
It takes O(n) space to store the list of nodes.
18+
19+
Space Complexity:- O(n)
20+
21+
Wiki page:- <https://en.wikipedia.org/wiki/Travelling_salesman_problem>
22+
"""
23+
24+
from itertools import permutations
25+
26+
27+
def floyd_warshall(graph, v):
28+
dist = graph
29+
for k in range(v):
30+
for i in range(v):
31+
for j in range(v):
32+
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
33+
return dist
34+
35+
36+
def travelling_salesman_problem(graph, v):
37+
"""
38+
Returns the shortest path that a salesman can take to visit all the nodes
39+
in the graph and return to the source node
40+
41+
The graph in the below testcase looks something like this:-
42+
2
43+
_________________________
44+
| |
45+
2 ^ 6 ^
46+
(0) <------------> (1) (2)<------>(3)
47+
^ ^
48+
| 3 |
49+
|_______________________________|
50+
51+
>>> graph = []
52+
>>> graph.append([0, 2, 3, float('inf')])
53+
>>> graph.append([2, 0, float('inf'), 2])
54+
>>> graph.append([3, float('inf'), 0, 6])
55+
>>> graph.append([float('inf'), 2, 6, 0])
56+
>>> travelling_salesman_problem(graph, 4)
57+
13
58+
"""
59+
60+
# See graphs_floyd_warshall.py for implementation
61+
shortest_distance_matrix = floyd_warshall(graph, v)
62+
nodes = list(range(v))
63+
64+
min_distance = float("inf")
65+
66+
# Go through all the permutations of the nodes to find out
67+
# which of the order of nodes lead to the shortest distance
68+
# Permutations(nodes) returns a list of all permutations of the list
69+
# Permutations are all the possible ways to arrange the elements of the list
70+
for permutation in permutations(nodes):
71+
current_dist = 0
72+
current_node = 0
73+
74+
# Find the distance of the current permutation by going through all the nodes
75+
# in order and add the distance between the nodes to the current_dist
76+
for node in permutation:
77+
current_dist += shortest_distance_matrix[current_node][node]
78+
current_node = node
79+
80+
# Add the distance to come back to the source node
81+
current_dist += shortest_distance_matrix[current_node][0]
82+
83+
# If the current distance is less than the minimum distance found so far,
84+
# update the minimum distance
85+
# print(permutation, current_dist)
86+
min_distance = min(min_distance, current_dist)
87+
88+
# NOTE: We are assuming 0 is the source node here.
89+
90+
return min_distance
91+
92+
93+
if __name__ == "__main__":
94+
import doctest
95+
96+
doctest.testmod()

0 commit comments

Comments
 (0)