HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Travelling salesman using brute-force and heuristics

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
salesmanforceheuristicsandtravellingusingbrute

Problem

I have implemented both a brute-force and a heuristic algorithm to solve the travelling salesman problem.

```
import doctest
from itertools import permutations

def distance(point1, point2):
"""
Returns the Euclidean distance of two points in the Cartesian Plane.

>>> distance([3,4],[0,0])
5.0
>>> distance([3,6],[10,6])
7.0
"""
return ((point1[0] - point2[0])2 + (point1[1] - point2[1])2) ** 0.5

def total_distance(points):
"""
Returns the length of the path passing throught
all the points in the given order.

>>> total_distance([[1,2],[4,6]])
5.0
>>> total_distance([[3,6],[7,6],[12,6]])
9.0
"""
return sum([distance(point, points[index + 1]) for index, point in enumerate(points[:-1])])

def travelling_salesman(points, start=None):
"""
Finds the shortest route to visit all the cities by bruteforce.
Time complexity is O(N!), so never use on long lists.

>>> travelling_salesman([[0,0],[10,0],[6,0]])
([0, 0], [6, 0], [10, 0])
>>> travelling_salesman([[0,0],[6,0],[2,3],[3,7],[0.5,9],[3,5],[9,1]])
([0, 0], [6, 0], [9, 1], [2, 3], [3, 5], [3, 7], [0.5, 9])
"""
if start is None:
start = points[0]
return min([perm for perm in permutations(points) if perm[0] == start], key=total_distance)

def optimized_travelling_salesman(points, start=None):
"""
As solving the problem in the brute force way is too slow,
this function implements a simple heuristic: always
go to the nearest city.

Even if this algoritmh is extremely simple, it works pretty well
giving a solution only about 25% longer than the optimal one (cit. Wikipedia),
and runs very fast in O(N^2) time complexity.

>>> optimized_travelling_salesman([[i,j] for i in range(5) for j in range(5)])
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [1, 4], [1, 3], [1, 2], [1, 1], [1, 0], [2, 0], [2, 1], [2, 2], [2, 3], [2, 4], [3, 4], [3, 3], [3, 2], [3, 1], [3, 0], [4, 0], [4, 1], [4,

Solution

I enjoyed the first look at the code as it's very clean, you have
extensive docstrings and great, expressive function names. Now you know
the deal with PEP8, but except for the one 200 character long line I
don't think it matters much really.

There're a few typo with the wrong spelling "algoritmh".

The coordinates should be immutable 2-tuples. The reason being the
safety of immutable data-structures. YMMV, but that makes it really
obvious that those are coordinates as well.

optimized_travelling_salesman should make a defensive copy of
points, or you should otherwise indicate that it's destructive on that
argument.

Instead of if start is None: start = points[0] you could also use
start = start or points[0] to save some space while still being
relatively readable.

For the algorithms the only thing I'd is not to use square root if you
don't have to. You can basically create a distance_squared and use that
instead of distance because the relationship
between a smaller and bigger distance will stay the same regardless.
That doesn't apply for the final output of course. Edit: And, as mentioned below by @JanneKarila, you can't use that for the brute-force version.

Context

StackExchange Code Review Q#81865, answer score: 9

Revisions (0)

No revisions yet.