Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Lecture 11: Traveling Salesman Problem

Open In Colab

The third classical problem of this lecture is the traveling salesman problem (TSP): find the shortest tour along a number of cities. As for the shortest path and maximum flow problems, we define the problem and give an example, solve the example with an ILO approach, and then look for a dedicated algorithm. This time the story ends differently. The ILO model needs a huge number of constraints, and the only exact algorithm we find tries all tours, which takes far too long for large instances. No exact algorithm with a polynomial running time is known for the TSP. The next notebook, Complexity and Heuristics, explains what that means and why, and continues with this example using a heuristic.

Learning outcomes

On completion of this notebook, you will be able to:

  • formulate the TSP as an ILO model and explain why subtour elimination constraints are needed;

  • follow how a small TSP is solved in pulp by adding subtour elimination constraints only when they are needed;

  • explain why trying all tours is not practical for large instances.

The Traveling Salesman Problem

What is the shortest tour that visits each city once and returns to the city it started from? This question, the traveling salesman problem, comes up whenever a vehicle or a person makes a round trip: a delivery van that delivers orders and returns to the warehouse, an order picker who collects the items of an order in a warehouse, or a machine that drills holes in a circuit board. It is also part of many larger planning problems, such as vehicle routing with several vans.

Given are nn nodes (cities) and a distance dijd_{ij} between every pair of nodes ii and jj. The goal is to find the shortest tour that visits all nodes and returns to the start node. Where to start does not matter: a tour is a cycle, so it returns to its start anyway. If two cities are not directly connected, we set their distance very large. If the shortest route between two cities passes through a third city, use the length of that route as dijd_{ij}: the shortest distances between all pairs follow from Dijkstra’s algorithm.

As an example, take the network of Figure 1, where all edges can be used in both directions. The tour A → B → D → F → E → C → A has length 2+3+5+2+6+1=192 + 3 + 5 + 2 + 6 + 1 = 19. Is there a shorter one?

Source
<Figure size 900x480 with 1 Axes>

Figure 1:Example network with distances along the edges, and in red the tour A → B → D → F → E → C → A of length 19.

ILO Approach

Model

Decision Variables

xij=1x_{ij} = 1 if the tour goes from ii directly to jj, and 0 otherwise, for i,j=1,…,ni, j = 1, \dots, n with i≠ji \ne j.

Objective

Minimize the length of the tour, ∑i≠jdijxij\sum_{i \ne j} d_{ij} x_{ij}.

Constraints

The tour arrives in every city exactly once and leaves every city exactly once:

∑i≠jxij=1,for all j∑i≠jxji=1,for all j.\begin{aligned} & \sum_{i \ne j} x_{ij} = 1, \quad \text{for all } j \\ & \sum_{i \ne j} x_{ji} = 1, \quad \text{for all } j. \end{aligned}

These constraints are not enough. In Figure 2, every node is entered once and left once, but the red edges form two separate tours, A → B → C → A and D → E → F → D, instead of one tour along all nodes. Such separate tours are called subtours. Their total length is 5+8=135 + 8 = 13, so a model with only the constraints above would happily return them.

<Figure size 900x480 with 1 Axes>

Figure 2:Two subtours (red), A → B → C → A and D → E → F → D. Every node is entered and left exactly once, but this is not one tour.

To prevent subtours, look at a set SS of nodes and count how many times the tour goes directly from a node in SS to another node in SS. A subtour along the nodes of SS alone does this ∣S∣|S| times, where ∣S∣|S| is the number of nodes in SS: a tour along zz nodes has zz edges. One tour along all nodes, on the other hand, has to leave SS at some point, and then uses at most ∣S∣−1|S| - 1 edges inside SS. So we add the subtour elimination constraints

∑i,j∈S, i≠jxij≤∣S∣−1,for all node sets S with 2≤∣S∣≤n−1.\sum_{i,j \in S,\ i \ne j} x_{ij} \le |S| - 1, \quad \text{for all node sets } S \text{ with } 2 \le |S| \le n - 1.

In Figure 2, the set S={A,B,C}S = \{\text{A}, \text{B}, \text{C}\} has xAB+xBC+xCA=3>∣S∣−1=2x_{AB} + x_{BC} + x_{CA} = 3 > |S| - 1 = 2, so these subtours are no longer feasible.

Complete ILO Model

min⁡∑i≠jdijxijs.t.∑i≠jxij=1,for all j∑i≠jxji=1,for all j∑i,j∈S, i≠jxij≤∣S∣−1,for all S with 2≤∣S∣≤n−1xij∈{0,1},for all i≠j.\begin{aligned} \min \quad & \sum_{i \ne j} d_{ij} x_{ij} \\ \text{s.t.} \quad & \sum_{i \ne j} x_{ij} = 1, \quad \text{for all } j \\ & \sum_{i \ne j} x_{ji} = 1, \quad \text{for all } j \\ & \sum_{i,j \in S,\ i \ne j} x_{ij} \le |S| - 1, \quad \text{for all } S \text{ with } 2 \le |S| \le n - 1 \\ & x_{ij} \in \{0, 1\}, \quad \text{for all } i \ne j. \end{aligned}

The price is the number of constraints: a set of nn nodes has 2n2^n subsets, so there are about 2n2^n subtour elimination constraints. For 50 cities that is 250≈10152^{50} \approx 10^{15} constraints, far too many to write down.

Model for the Example

The 10 edges of Figure 1 can each be used in both directions, which gives 20 variables; pairs of nodes without an edge get no variable. With the two directions of each edge grouped, the model is

min⁡2(xAB+xBA)+(xAC+xCA)+2(xBC+xCB)+3(xBD+xDB)+2(xBE+xEB)+3(xCD+xDC)+6(xCE+xEC)+(xDE+xED)+5(xDF+xFD)+2(xEF+xFE)s.t.xBA+xCA=1(arrive in A)xAB+xAC=1(leave A)⋮(the same for B to F)xAB+xBA+xAC+xCA+xBC+xCB≤2(S={A,B,C})⋮(one for each S with 2≤∣S∣≤5)xij∈{0,1},for all 20 variables.\begin{aligned} \min \quad & 2(x_{AB} + x_{BA}) + (x_{AC} + x_{CA}) + 2(x_{BC} + x_{CB}) + 3(x_{BD} + x_{DB}) + 2(x_{BE} + x_{EB}) \\ & + 3(x_{CD} + x_{DC}) + 6(x_{CE} + x_{EC}) + (x_{DE} + x_{ED}) + 5(x_{DF} + x_{FD}) + 2(x_{EF} + x_{FE}) \\ \text{s.t.} \quad & x_{BA} + x_{CA} = 1 & \text{(arrive in A)} \\ & x_{AB} + x_{AC} = 1 & \text{(leave A)} \\ & \quad \vdots & \text{(the same for B to F)} \\ & x_{AB} + x_{BA} + x_{AC} + x_{CA} + x_{BC} + x_{CB} \le 2 & (S = \{\text{A}, \text{B}, \text{C}\}) \\ & \quad \vdots & \text{(one for each } S \text{ with } 2 \le |S| \le 5) \\ & x_{ij} \in \{0, 1\}, \quad \text{for all 20 variables.} \end{aligned}

With 6 nodes there are 26−6−2=562^6 - 6 - 2 = 56 sets SS with 2≤∣S∣≤52 \le |S| \le 5, so 56 subtour elimination constraints.

Solving the Example in pulp

In practice, the subtour elimination constraints are added only when they are needed, as so-called lazy constraints: solve the model without them, and follow the solution from the start node A until it returns to A. If that tour visits all nodes, it is the optimal tour. If not, it is a subtour: add the subtour elimination constraint for its nodes, and solve again. Usually only a small fraction of all subtour elimination constraints is ever added.

In the code, distance holds each edge once; arc_length adds the reverse direction, so there is a variable for each of the 20 arcs. The function follow_tour follows the solution from node to node. A solver computes with floating-point numbers, so a binary variable can come out as, say, 0.9999999 instead of exactly 1. That is why the code tests var.value() > 0.5 and not var.value() == 1. As for the algorithms in this lecture, you do not have to be able to write this code yourself, but you should be able to follow what each line does and why.

length 12.0: ['A', 'C']
length 13.0: ['A', 'B', 'C']
length 13.0: ['A', 'B', 'D', 'C']
length 15.0: ['A', 'B', 'E', 'F', 'D', 'C']

In the first solution, the tour from A is A → C → A: going to a neighbor and straight back also enters and leaves every node once. The constraint for S={A,C}S = \{\text{A}, \text{C}\} is xAC+xCA≤1x_{AC} + x_{CA} \le 1. The second solution contains the subtour A → B → C → A of Figure 2, and the third the subtour A → B → D → C → A. After adding their constraints too, the solver finds one tour of length 15. Only 3 of the 56 subtour elimination constraints were needed. Each time, only the subtour through A gets a constraint; adding one for every subtour in the solution at once usually saves solves. For instances with thousands of cities, specialized solvers use this approach together with many other tricks, but the solution time can still grow very quickly with the number of cities.

Algorithm: Trying All Tours

Is there a dedicated algorithm for the TSP, as Dijkstra’s algorithm is for the shortest path problem? A simple exact algorithm, called brute force, tries every tour:

  • Start: best length =∞= \infty.

  • For every tour:

    1. Calculate the total distance of the tour.

    2. If it is shorter than the best length so far, it becomes the new best tour.

Fix the start node; then the tour can visit the other n−1n - 1 nodes in any order. That gives (n−1)!=(n−1)⋅(n−2)⋯2⋅1(n - 1)! = (n - 1) \cdot (n - 2) \cdots 2 \cdot 1 possible tours. For the example with n=6n = 6, that is 5!=1205! = 120 tours, which a computer checks in no time:

checked 120 tours
shortest tour: A -> B -> E -> F -> D -> C -> A length 15

The running time of this algorithm grows like n!n!, and that grows extremely fast. For 20 cities there are 19!≈1.2⋅101719! \approx 1.2 \cdot 10^{17} tours. Even at a billion tours per second, checking them all takes almost four years, and every extra city multiplies that time by the number of cities. This is not practical for reasonably sized instances.

Can we do better? Unlike for the shortest path and maximum flow problems, no exact algorithm with a polynomial running time is known for the TSP: not via the ILO model, and not via any dedicated algorithm. The next notebook, Complexity and Heuristics, explains what polynomial running time means, why there probably is no such algorithm for the TSP, and then solves this example with a heuristic.

References

  • Koole, G. (2019). An Introduction to Business Analytics. Chapter 7, “Combinatorial Optimization” (traveling salesman problem).