This project implements a simple parser for the TSPLIB-95 format for traveling salesman problems (TSPs), as well as methods for calculating the length of tours and paths. In addition, two simple and similar heuristics have been implemented: the nearest neighbor algorithm and the furthest insertion algorithm.
Work is organized into five modules:
tspparse.py
. Parses.tsp
files of typeTSP
. Currently, this parser works only on the subset of.tsp
files included in the directory./tspfiles
, and has not been tested on other TSP instances in the TSPLIB library. The final destination for all parsed information is adict
object whose keys areTSPLIB 95
keywords. The cities are stored in the dictionary under the key “~cities~.”city.py
. Datatypes for geographical coordinates (classGeoCoord
), cities represented as geographical points (classGeoCity
), and cities represented as Euclidean coordinates on the plane (classEuc_2D
). This file also contains thedistance
function, which operates on objects of classesEuc_2D
andGeoCity
.algorithms.py
. Simple algorithms and heuristics for calculating tours. The functioncalc_in_order_tour
calculates the length of the tour[1,2,3,...,n,1]
for a TSP problem of dimensionn
. Also implemented in this module are the nearest neighbor and furthest insertion heuristics, respectively namedcalc_nearest_neighbor_tour
andcalc_furthest_neighbor_tour
.argparser.py
. Parses command line arguments tomain.py
with theargparse
module. Command line arguments include-f
if the furthest insertion tour is requested,-n
if the nearest neighbor tour is requested, and-i
if the in-order tour length is requested.main.py
. Iterate through directories and files in order to find the.tsp
files and print the information requested through the command line arguments.
The file main.py
is intended for use as a command-line program. To
get an idea of the interface, examine the help text:
python3 main.py --help
usage: main.py [-h] [-n] [-f] [-i] [-p] PATH [PATH ...] Parse TSP files and calculate paths using simple algorithms. positional arguments: PATH Path to directory or .tsp file. If PATH is a directory, run on all .tsp files in the directory. optional arguments: -h, --help show this help message and exit -n, --nearest calculate distance traveled by nearest neighbor heuristic -f, --furthest calculate distance traveled by furthest insertion heuristic -i, --in-order calculate the distance traveled by the in-order-tour [1..n,1] -p, --print-tours print explicit tours
Running main.py
on the entire director of TSP files (./tspfiles
)
is easy and pain-free:
python3 main.py -nfi tspfiles
TSP Problem: a280 PATH: tspfiles/a280.tsp IN-ORDER TOUR LENGTH: 2808 NEAREST NEIGHBOR LENGTH: 3157 FURTHEST NEIGHBOR LENGTH: 50172 TSP Problem: ali535 PATH: tspfiles/ali535.tsp IN-ORDER TOUR LENGTH: 3369702 NEAREST NEIGHBOR LENGTH: 253307 FURTHEST NEIGHBOR LENGTH: 4643454 TSP Problem: berlin52 PATH: tspfiles/berlin52.tsp IN-ORDER TOUR LENGTH: 22205 NEAREST NEIGHBOR LENGTH: 8980 FURTHEST NEIGHBOR LENGTH: 37742 TSP Problem: burma14 PATH: tspfiles/burma14.tsp IN-ORDER TOUR LENGTH: 4562 NEAREST NEIGHBOR LENGTH: 4048 FURTHEST NEIGHBOR LENGTH: 8854 TSP Problem: gr137 PATH: tspfiles/gr137.tsp IN-ORDER TOUR LENGTH: 97113 NEAREST NEIGHBOR LENGTH: 94124 FURTHEST NEIGHBOR LENGTH: 924837 TSP Problem: gr202 PATH: tspfiles/gr202.tsp IN-ORDER TOUR LENGTH: 58162 NEAREST NEIGHBOR LENGTH: 48524 FURTHEST NEIGHBOR LENGTH: 356085 TSP Problem: gr229 PATH: tspfiles/gr229.tsp IN-ORDER TOUR LENGTH: 179722 NEAREST NEIGHBOR LENGTH: 165928 FURTHEST NEIGHBOR LENGTH: 1959746 TSP Problem: gr431 PATH: tspfiles/gr431.tsp IN-ORDER TOUR LENGTH: 232979 NEAREST NEIGHBOR LENGTH: 212555 FURTHEST NEIGHBOR LENGTH: 3464792 TSP Problem: gr666 PATH: tspfiles/gr666.tsp IN-ORDER TOUR LENGTH: 423633 NEAREST NEIGHBOR LENGTH: 367163 FURTHEST NEIGHBOR LENGTH: 6956638 TSP Problem: gr96 PATH: tspfiles/gr96.tsp IN-ORDER TOUR LENGTH: 81015 NEAREST NEIGHBOR LENGTH: 70915 FURTHEST NEIGHBOR LENGTH: 530251 TSP Problem: pr226 PATH: tspfiles/pr226.tsp IN-ORDER TOUR LENGTH: 110417 NEAREST NEIGHBOR LENGTH: 94683 FURTHEST NEIGHBOR LENGTH: 2514865 TSP Problem: u574 PATH: tspfiles/u574.tsp IN-ORDER TOUR LENGTH: 40197 NEAREST NEIGHBOR LENGTH: 50459 FURTHEST NEIGHBOR LENGTH: 990585 TSP Problem: ulysses16.tsp PATH: tspfiles/ulysses16.tsp IN-ORDER TOUR LENGTH: 9665 NEAREST NEIGHBOR LENGTH: 9988 FURTHEST NEIGHBOR LENGTH: 15911 TSP Problem: ulysses22.tsp PATH: tspfiles/ulysses22.tsp IN-ORDER TOUR LENGTH: 12198 NEAREST NEIGHBOR LENGTH: 10586 FURTHEST NEIGHBOR LENGTH: 21520
Calculation of Euclidean 2-D distances does not match up with other
implementations of TSP programs. The culprit is most likely the
rounding function used in the euc_2d_distance
function found in
the city
module. As per the TSPLIB ‘95 documentation, distances
should be “round[ed] to the nearest integer (in most cases)” (6). In
my reading of the TSPLIB ‘95 documentation, it is implied that the
rounding convention used should exactly replicate the C-language nint
function.
Nevertheless, getting Euclidean distances to match up with a previous
implementation I wrote in Haskell has proven difficult. Both the
Haskell round
function and Numpy’s around
function should
theoretically have the same behavior (that is, round as you learned in
grade school, except for floats falling exactly equidistant from two
integers – in that case, round to the nearest even integer). However,
rounding errors persist in one or both of the implementations. The
effect is more pronounced on TSPs with large dimension.
For example, consider the following table of in-order tour lengths calculated by this Python implementation and a previous Haskell implementation:
Problem | Python | Haskell | Percent diff. (rel. to Python) |
---|---|---|---|
/ | < | < | < |
ali535 | 3369702 | 3370175 | -1.40368495e-4 |
gr666 | 423633 | 423529 | 2.45495511e-4 |
This Python implementation both overshoots and undershoots the Haskell implementation’s calculations. As usual, the discrepancy between the two versions probably originates with the particular choices each language implementation makes with respect to floating point numbers. Making these TSP implementations match would require further study into each language’s choices for floating point representations, but this project is mostly a toy, so that endeavor is ill-advised.
- implement the Lin-Kernighan algorithm for improving tours through programmatic permutation of city sequences
- test and patch the parser so that it operates on the full range of TSP instances provided by TSPLIB ‘95