Interactive companion · Chapter 6 · Tabu search

Tabu Search Lab

Local search with a memory. Tabu search moves to the best neighbor it is allowed to visit, even uphill, and forbids recent moves for a while so it can walk out of local optima.

Based on Chapter 6, “Tabu search,” in Alaa Khamis, Optimization Algorithms: AI techniques for design, planning, and control problems, Manning Publications, 2024 (ISBN 978-1633438835).

Tabu search on Himmelblau’s function. Dashed circles mark recently visited points, which are tabu.

Part 1 · Sections 6.1 and 6.2

From local search to tabu search

Local search moves only when a neighbor improves the current solution, so it stops at the first local optimum. Tabu search (TS) adds memory: it accepts the best neighbor even when it is worse, and forbids moves back to recently visited solutions.

Sections 6.1 and 6.2 of the book build this idea from a resort-restaurant analogy and weigh the pros and cons of TS.

Escaping local optima

Both searches start at the same point. Local search stops at the first valley; tabu search keeps going and marks each visited position tabu for T iterations (red bars). Click the landscape to choose a new start, then Step or Run.

Local search vs. tabu search

Minimize f(x)

Part 2 · Section 6.2

The tabu search algorithm

Algorithm 6.1: Local search Input: an initial feasible solution s while termination criteria not met generate a neighbor s′ by local moves if s′ is better than s then s ← s′
Algorithm 6.2: Tabu search Input: an initial feasible solution s while termination criteria not met choose the best s′ ∈ N(s) − T(s) + A(s) # neighbors, minus tabu moves, plus moves # allowed by the aspiration criterion memorize s′ if it improves the best known solution s ← s′ # even if s′ is worse update the tabu list T(s) and aspiration A(s)

Each iteration builds a candidate list of moves, evaluates them, discards tabu ones unless they pass the aspiration criterion, and makes the best admissible move, even a worsening one.

Figure 6.1 in Section 6.2 walks through this loop, with stopping rules and a small TSP neighborhood example.

Part 3 · Section 6.2.1

Memory structures

Recency (short-term) memory forbids recent moves for a number of iterations, the tabu tenure. Frequency (long-term) memory counts how often each move is made and penalizes frequent ones to diversify the search.

Section 6.2.1 links these memories to models of human memory and compares static, dynamic, adaptive and reactive tenure rules (Figure 6.7).

The tabu structure in action

Order seven laminate sheets for maximum strength (Listing C.5); each move swaps two sheets. Step through the search and watch the triangle: tenures fill the upper half, swap counts the lower half.

Recency and frequency memory

Maximize strength · 21 swap neighbors
Order
Upper triangle (red): iterations a swap stays tabu. Lower triangle: how many times the swap has been made. Read swap (i, j) at row i, column j above the diagonal and at row j, column i below it.

Aspiration criteria and the tabu tenure

An aspiration criterion lifts the tabu status of a move that would beat the best solution found so far. The tenure matters most: too short risks cycling, too long risks stagnation (try the experiment in Part 9).

Figure 6.6 and Section 6.2.1 explain the tenure trade-off and list every TS parameter you can tune or adapt during a run.

Part 4 · Section 6.3

Constraint satisfaction: n-queens

Place n queens so that none attack each other. As a permutation, only diagonal collisions remain to minimize; a move swaps two queens’ columns and that swap becomes tabu. Step from the book’s board or a random one.

Section 6.3 carries out the first iterations by hand on Figure 6.8 and solves larger boards with Listing 6.1.

n-queens with tabu search

Minimize collisions
Columns C

Listing 6.1 uses a different neighborhood (single-queen moves) from the swap moves above.

Part 5 · Binary problems

A 0/1 knapsack problem

Pack seven items into a 50 kg knapsack. A solution is a bit string, and f below rewards filling the knapsack exactly while packing high utility (minimize):

f = f₁ − f₂,   f₁ = |Σwi − 50| (+ 50 if overloaded),   f₂ = Σui

A move flips one item, which then becomes tabu.

Knapsack with tabu search

Minimize f

Part 6 · Graph problems

Connecting factory units with cables

Connect five factory units at minimum cable cost (a minimum spanning tree). A move swaps one tree edge for another; the edge just added is tabu to remove for T = 2 iterations. Press Step to follow each swap.

Edge-swap tabu search

Minimize cable cost

Part 7 · Assignment problems

The quadratic assignment problem

Place n objects on n sites to minimize total flow × distance (the NUG5 instance; matrices at right):

cost(p) = Σi Σj fpipj dij

A move exchanges two sites’ objects; returning an object to a site it just left is tabu for a while. Step and watch the tabu matrix.

QAP with tabu search

Minimize flow × distance

Tabu matrix: red cells show how long an object may not return to a site.

Part 8 · Section 6.4

Continuous functions

Here a candidate is tabu if it falls within a tabu radius of a recent point. Pick a function (Himmelblau, Mishra’s Bird or Schwefel) and Run.

Section 6.4 solves Himmelblau’s function with the book’s optalgotools solver in Listing 6.2, and Listing C.4 tackles the deceptive Schwefel function.

Continuous tabu search lab

Minimize f(x, y)

Current value (faint) and best value per iteration.

Part 9 · Section 6.5

Routing: the Berlin52 TSP

Find the shortest tour through 52 Berlin locations (optimum 7,542). A 2-opt move reverses a segment; removed edges become tabu. Run it, then try the swap neighborhood.

Section 6.5 solves Berlin52 with Google OR-Tools in Listing 6.3 and with the generic solver, and Listing 6.4 routes a delivery semi-truck.

Berlin52 tabu search lab

Minimize tour length

Current (faint) and best tour length per iteration.

Effect of the tabu tenure

Run 2-opt tabu search four times per tenure and compare the best tours. Look for cycling at short tenures and stagnation at long ones.

Tenure experiment

Berlin52 · 4 runs per tenure

Mean best tour length (line) and each run (dots) against the tabu tenure. The dashed line is the optimum, 7,542.

Part 10 · Section 6.6

Assembly line balancing

Assign tasks to workstations so no station exceeds the cycle time CT and precedence is respected. SALBP-1 minimizes the number of stations; balance is measured by the smoothing index:

SI = √( Σi=1..NS (WLmax − WLi)² / NS )

A solution is a task sequence; a move swaps two tasks. Step through the 6-task example below.

Section 6.6 defines the SALBP and TSALBP variants (Table 6.1) and works this example by hand with Listing 6.5.

Precedence diagram (Figure 6.22).

Hand iterations, automated

6 tasks · CT = 4 · tenure 3
Sequence

Benchmark lab

Pick a SALBP benchmark and Run: tabu search minimizes stations first, then the smoothing index.

SALBP-1 benchmarks

Minimize stations, then SI

Best number of stations + SI/CT per iteration (lower is better).

Part 11 · Section 6.5 and appendix C

More applications

Delivery semi-truck routing

Route a truck through 18 stores in the Greater Toronto Area.

Listing 6.4

Schwefel function

A deceptive multimodal test function.

Listing C.4

Composite laminate design

The problem behind the Part 3 demo.

Listing C.5

Assembly line balancing

Another SALBP solved with tabu search.

Listing C.6

Part 12 · Code

Python in Google Colab

Open the book’s notebooks in Colab, or the companion notebook with the from-scratch code below.

Notebooks

From-scratch implementations

# Tabu search for the n-queens problem (Chapter 6, Section 6.3)
# A solution is a permutation: queens[i] is the column of the queen in row i, so rows and columns never clash
# and only diagonal collisions remain. The neighborhood swaps the columns of two queens.
import numpy as np


def collisions(q):
    n = len(q)
    return sum(abs(q[i] - q[j]) == j - i for i in range(n) for j in range(i + 1, n))


def swap(q, i, j):
    q = list(q)
    q[i], q[j] = q[j], q[i]
    return q


# The book's starting board (Figure 6.8): Q1..Q7 in columns 4, 5, 3, 6, 7, 1, 2
book = [4, 5, 3, 6, 7, 1, 2]
print("initial collisions:", collisions(book))                       # 4
for i, j in [(1, 7), (2, 3), (2, 6), (5, 6), (1, 5)]:
    print(f"swap Q{i}, Q{j}: delta = {collisions(swap(book, i - 1, j - 1)) - collisions(book)}")


def tabu_search(n=7, tenure=3, max_iter=500, aspiration=True, init=None, seed=0):
    rng = np.random.default_rng(seed)
    q = list(init) if init is not None else list(rng.permutation(n))
    tabu = np.zeros((n, n), int)            # tabu[i, j]: last iteration at which the swap (i, j) is tabu-active
    best, best_val = q, collisions(q)
    for it in range(1, max_iter + 1):
        if best_val == 0:
            break
        cands = []
        for i in range(n):
            for j in range(i + 1, n):
                v = collisions(swap(q, i, j))
                is_tabu = tabu[i, j] >= it
                if not is_tabu or (aspiration and v < best_val):       # aspiration: better than the best so far
                    cands.append((v, rng.random(), i, j))
        if not cands:
            continue
        v, _, i, j = min(cands)                 # best admissible move, ties broken at random
        q = swap(q, i, j)
        tabu[i, j] = it + tenure
        if v < best_val:
            best, best_val = q, v
    return best, best_val, it


sol, val, it = tabu_search(init=[c - 1 for c in book])
print("7-queens from the book's board:", [c + 1 for c in sol], "collisions:", val, "iterations:", it)
sol, val, it = tabu_search(n=20, tenure=5, seed=1)
print("20-queens:", [c + 1 for c in sol], "collisions:", val, "iterations:", it)

Open the companion notebook in Colab, or paste a tab’s code into any notebook.

Part 13 · Summary

What to remember

Local search + memory

Tabu search moves to the best admissible neighbor, even uphill.

Tabu list and tenure

Too short a tenure risks cycling; too long risks stagnation.

Aspiration

A tabu move is allowed if it beats the best solution so far.

Balance

Recency memory intensifies; frequency memory diversifies.

References: F. Glover, “Tabu search and adaptive memory programming: advances, applications and challenges,” 1997. F. Glover, M. Laguna and R. Martí, “Principles of tabu search.” R. Battiti and G. Tecchiolli, “The reactive tabu search,” 1994. E. Taillard, “Robust taboo search for the quadratic assignment problem,” 1991. A. Khamis, Optimization Algorithms: AI techniques for design, planning, and control problems, Manning, 2024, Chapter 6.

Part 14 · Quiz

Check your understanding

Two quick questions on Chapter 6. Pick an answer to check it.

Q1. Every neighbor of the current solution is worse, and the only improving move is tabu but would give a solution better than the best found so far. What does tabu search do?

Q2. In the tenure experiment on Berlin52, what typically goes wrong when the tabu tenure is very long?

For more exercises with full solutions, see Appendix C, “Exercises and solutions,” in Optimization Algorithms. The coding solutions are also on GitHub (Chapter 6).