The recursive-fold-algorithm (RFA) is a recursive algorithm for the metric travelling-salesman-problem (TSP). The objective of the TSP is to find a round trip through a number of cities/locations (more generally referred to as nodes). The round trip should be as short as possible. The TSP is a very hard problem with difficult computational properties (TSP belongs to the NP-hard problem class).
Recursive algorithms naturally split a problem into a series of smaller steps that are easier to solve individually. As such, they're often very elegant.
RFA exploits the fact that the TSP can be trivially solved if there are only 3 nodes, because only a single round trip route exists for 3 nodes. The solution is self-evident:
This trivial case is the recursion anchor for the algorithm.
But how to deal with larger problem sizes? The answer is to fold nodes. Folding means that two nodes that are in close proximity to each other are fused into an artifical new node. This new node gets placed in the middle between the two original nodes. By remembering the original nodes it is also possible to reverse such a folding operation later on (referred to as unfolding). Of course, folded nodes can be folded again themselves (recursively).
Once only 3 nodes remain, a preliminary solution (route) can be constructed. Again, this is self-evident:
The key to RFA is that the nodes are now unfolded step by step. Each unfolding removes a node and replaces it with two new nodes. These new nodes can be inserted into the preliminary route in two alternative orders only. In the following picture the artificial node in the bottom-right corner (blue) is unfolded:
It is obvious that the new nodes (red) can only be inserted in two different orders. It is also easy to determine which of these orders gives the shorter route (the green one).
The complete process can be described as follows:
- Folding: Pick a node and fold it with a neighboring node. Repeat folding nodes until the number of nodes has been reduced to 3.
- Recursion anchor: Create a preliminary round trip route through the 3 remaining nodes.
- Unfolding: Unfold the nodes until the original nodes have been restored. At each unfolding step, insert the new nodes in the preliminary route. Choose the insertion order that gives the shorter route length.
FoldingStrategyRandomWithNearestNeighbor
(default): A very simple yet highly efficient method which randomly picks a node and folds it with the nearest-neighbor.FoldingStrategyOutsideIn
: The node furthest from the center point is folded with its nearest-neighbor. The center point is only calculated once at the beginning.
UnfoldingStrategyBreadthFirst
: The list of folded nodes is processed repeatedly. During each iteration, only the nodes with the maximum depth are unfolded.UnfoldingStrategyBreadthFirstWithLocal2Opt
(default): Same as UnfoldingStrategyBreadthFirst, but after each unfolding step, a local 2-opt optimization around the inserted nodes is performed.
The scripts require
- Python 3, for example 3.13 is working.
- PyPI packages
rtree
,shapely
, andtabulate
The easiest way is to use pipenv
. A Pipfile
is included in the project. You can simply download the code and run pipenv install
in the top-level
project folder. Then switch to the project's Python environment by executing pipenv shell
. You can now execute the main script RFA_demo.py
as described
in the below Usage section.
The main script is RFA_demo.py and it features multiple commandline arguments. There is only one obligatory argument, namely the mode, which may be demo
or benchmark
.
The following command runs a simple demonstration based on 100 randomly generated nodes with a random number generator seed of 17:
$ python RFA_demo.py demo -n 100 -s 17
Total costs: 4075
Runtime: 0.016s
The following command runs a benchmark using a subset of the TSPLIB instances (see TSPLIB/ folder):
$ python RFA_demo.py benchmark --tsplib all -s 17
...
Instance Costs of optimal route Costs of RFA route Cost factor Runtime
---------- ------------------------ -------------------- ------------- ---------
a280 2579 2917 113.11% 0.057s
berlin52 7542 8403 111.42% 0.007s
bier127 118282 127078 107.44% 0.024s
brd14051 469385 521991 111.21% 45.724s
ch150 6528 7034 107.75% 0.029s
d18512 645238 718894 111.42% 78.015s
eil51 426 448 105.16% 0.010s
pla33810 66048945 77860165 117.88% 234.044s
pla7397 23260728 26821014 115.31% 11.737s
pla85900 142382641 165332217 116.12% 1583.811s
pr1002 259045 288473 111.36% 0.431s
pr107 44303 44982 101.53% 0.018s
pr439 107217 118868 110.87% 0.114s
pr76 108159 116356 107.58% 0.012s
rat783 8806 9520 108.11% 0.268s
rat99 1211 1263 104.29% 0.017s
sw24978 855597 959275 112.12% 147.175s
usa13509 19982859 22639652 113.30% 44.453s
You may download and execute the RFA_demo scripts.