Heuristics and Local Search
Imagine you must route a fleet of delivery trucks through 500 cities. A customer wants a decent schedule by tomorrow morning. No known algorithm can guarantee the optimal route in time. The problem is NP-hard. Even the best Approximation Algorithms may guarantee only a weak bound on quality. Yet real logistics companies solve problems like this every day. They get excellent answers. The trick is to stop demanding a proof of near-optimality. Instead, search intelligently through the space of solutions. Improve a candidate a little at a time. Keep going until further improvement seems impossible. This is the world of local search and metaheuristics. Some methods build a solution top-down with guaranteed structure. You saw this in Coping with NP-Hardness and in A 2-Approximation for Vertex Cover. Local search instead starts anywhere. It often begins at a random or greedily constructed solution. Then it repeatedly moves to a "neighboring" solution that looks better. The central danger is also the central subtlety. The search can get trapped at a local optimum. This is a point that beats every neighbor but is far from the global best. The algorithms in this article — hill climbing, simulated annealing, tabu search — are different strategies for escaping that trap. This comes at the cost of giving up any worst-case performance guarantee. This trade is not a failure of rigor. It is a deliberate and well-understood engineering decision. Approximation algorithms give you a certificate — "this solution is never worse than twice optimal." But they often require problem-specific structure that many real problems lack. Or their guaranteed ratio is too weak to be useful in practice. Local search and its randomized cousins give up the certificate entirely. In exchange, they apply to almost any problem with a notion of "neighboring solutions." Empirically they often outperform approximation algorithms by a wide margin on real instances. This holds even though nobody can prove how good they will be in advance. This article builds the theory of neighborhood search precisely. It covers what a local optimum is, and why hill climbing gets stuck. It explains how simulated annealing uses randomness and a cooling schedule. This lets it escape shallow traps while still (probabilistically) settling into good solutions. We prove the key structural facts. We show when a local optimum is provably a global optimum (convex/matroid-like structure). We also show why, absent such structure, no fixed neighborhood can avoid bad local optima in the worst case. We end with a careful worked trace on the Traveling Salesman Problem. We include a taxonomy of the classic bugs. Finally, we trace the historical arc from Metropolis's 1953 physics simulation to the AI systems of today.
- Local search explores a space of complete candidate solutions, moving to better neighbors until none exists — a local optimum.
- Hill climbing (greedy local search) is fast but has no guarantee: it can get stuck arbitrarily far from optimal.
- Simulated annealing accepts worsening moves with probability , controlled by a temperature that decreases over time, to escape shallow local optima.
- These methods have no worst-case approximation guarantee — unlike the algorithms in A 2-Approximation for Vertex Cover — but often perform excellently in practice.
- The choice of neighborhood structure (2-opt, swap, flip) determines both solution quality and how easy it is to get stuck.
- Restarts, tabu lists, and adaptive cooling schedules are practical tools for balancing exploration against convergence speed.
Local search trades a provable worst-case guarantee for the ability to iteratively improve any solution to any problem using only a notion of "neighboring" candidates — and metaheuristics like simulated annealing add controlled randomness so the search can escape local optima instead of freezing at the first one it finds.
The idea
A local search algorithm operates on a solution space (all feasible candidate solutions to a problem instance) equipped with a neighborhood function , where is the set of solutions "close to" under some small, well-defined perturbation — flipping one bit, swapping two elements, reversing a tour segment. Given a cost function that we want to minimize (or maximize), the algorithm maintains a current solution and repeatedly tries to replace it with a better neighbor in . A solution is a local optimum with respect to if for every — no single move from the neighborhood improves it. This is emphatically not the same as a global optimum, which beats every solution in all of . The gap between the two is the entire subject of this article: local optima can be arbitrarily bad relative to the global optimum, and how bad depends intricately on the choice of . A neighborhood that is "too small" (few candidates to move to) makes search fast but traps you easily; a neighborhood that is "too large" (e.g., all of ) makes every step as hard as solving the whole problem again.
Hill climbing (also called steepest descent, iterative improvement, or greedy local search) is the baseline strategy: from the current solution, look at all neighbors, move to the best one that improves on the current cost, and stop when no neighbor improves. It is simple, fast per step, and always makes progress — but it is a strictly greedy rule with no lookahead, so it commits irrevocably to whichever local optimum it first reaches. Metaheuristics are general-purpose strategies layered on top of a basic local search to help it escape local optima: simulated annealing injects randomness governed by a temperature parameter; tabu search forbids revisiting recently seen solutions to force exploration; random restarts simply rerun hill climbing from many different starting points and keep the best result. None of these methods carry a worst-case approximation ratio — this is the price paid for generality, in contrast to the guaranteed-ratio algorithms studied under Coping with NP-Hardness.
How it works
Hill climbing is the essential skeleton on which everything else is built. ``` HILL-CLIMB(instance, initial-solution s, neighborhood N, cost f) current ← s repeat best-neighbor ← argmin_{s' in N(current)} f(s') if f(best-neighbor) >= f(current) return current // local optimum reached current ← best-neighbor until false ``` This is first-improvement or best-improvement hill climbing depending on whether we scan `N(current)` for the first improving move or the single best one; both terminate at a local optimum, and both can be led astray by an unlucky neighborhood shape.
Simulated annealing modifies this loop in exactly one way: instead of requiring an improving move, it proposes a random neighbor and accepts it with a probability that depends on how much worse it is and on a temperature that decreases over the run. Early on (high ), almost any move is accepted, so the search wanders broadly and can climb out of shallow basins. Late in the run (low ), only improving moves (or negligibly worsening ones) are accepted, so the process settles like hill climbing into whatever basin it currently occupies. ``` SIMULATED-ANNEALING(instance, initial-solution s, neighborhood N, cost f, initial-temp T0, cooling-schedule cool, max-iters) current ← s best ← s T ← T0 for iter ← 1 to max-iters s' ← RANDOM-NEIGHBOR(current, N) Δ ← f(s') − f(current) if Δ < 0 // s' strictly better current ← s' else with probability exp(−Δ / T): current ← s' // accept a worsening move if f(current) < f(best) best ← current T ← cool(T, iter) // e.g. T ← α·T, 0 < α < 1 return best ``` Two design choices govern behavior entirely: 1. The neighborhood . For the Traveling Salesman Problem, a classic choice is 2-opt: pick two edges of the tour, remove them, and reconnect the tour the only other way that keeps it a single cycle (equivalently, reverse a contiguous segment). For graph partitioning, a neighborhood might be "swap one vertex between the two sides." For SAT, it might be "flip one variable's truth value" (this specific case is the basis of the WalkSAT family of heuristics). 2. The cooling schedule. A geometric schedule with close to but below 1 (e.g., –) is standard. Cool too fast and the algorithm behaves like plain hill climbing (freezes into the first local optimum found); cool too slow and it wastes time wandering without converging. The figure below shows the core geometric picture: a one-dimensional cost landscape with a shallow local optimum next to a deep global optimum, and the difference between how hill climbing and simulated annealing behave on it.
Complexity & correctness
Per-step cost. For hill climbing, one iteration inspects neighbors and evaluates on each; if can be updated incrementally (e.g., a 2-opt move changes tour length by a computable delta rather than recomputing the whole tour), one step costs time. The number of iterations until reaching a local optimum is bounded above by the number of distinct achievable cost values on the improvement path, which in the worst case can be exponential in the instance size — there exist crafted instances (e.g., certain "PLS-complete" problems, formalized in the complexity class Polynomial Local Search) where any sequence of improving moves under a natural neighborhood takes exponentially many steps to reach a local optimum. In practice, though, hill climbing on structured instances (TSP with 2-opt, graph coloring, MAX-SAT) tends to converge in a low-degree polynomial number of steps.
Simulated annealing complexity. One iteration is or if only a single random neighbor is sampled (the usual implementation). Total running time is evaluated moves — a parameter you choose, not a function of instance difficulty, which is exactly the point: you trade guaranteed quality for bounded, controllable runtime.
No worst-case approximation guarantee — and why this is unavoidable. For an arbitrary NP-hard optimization problem with an arbitrary neighborhood, one can construct instances where every local optimum is arbitrarily far from the global optimum. Consider MAX-CUT with the "flip one vertex" neighborhood: it is known that local optima under this neighborhood can be a factor of worse than the global maximum in the worst case, and richer problems admit far worse gaps under natural neighborhoods. This is not a defect of a particular heuristic; it is a statement about the neighborhood structure itself, and it explains why local search papers report empirical performance rather than proved ratios — contrast this with the certificate-carrying guarantee proved in A 2-Approximation for Vertex Cover.
When is a local optimum provably global? This is the positive side of the theory, and it is worth stating precisely, because it explains why local search works so well on some problems and fails on others. Claim. If the cost function is convex over a convex solution space , and the neighborhood contains all points within any sufficiently small ball around (a "local" neighborhood in the calculus sense), then every local minimum is a global minimum. Proof sketch. Suppose is a local minimum but not global, so there exists with . Consider the segment for , which lies in by convexity. Convexity of gives
For small enough, lies in any neighborhood of that includes a small ball, so has a neighbor of strictly lower cost — contradicting local optimality. This is exactly the fact that makes gradient descent reliable on convex functions and explains the special role of matroid structures and other combinatorial analogues of convexity (e.g., local search on a matroid's independent sets with an exchange neighborhood provably finds the global optimum for linear objectives — the theoretical backbone of the Greedy Algorithms and Matroids family of results). The moment or loses this convex-like structure — as almost every interesting NP-hard combinatorial problem does — the guarantee evaporates, and we are left with heuristics.
Why simulated annealing "should" work (informally). Model the search as a Markov chain over where the transition probability from to a proposed neighbor is . At fixed temperature , this chain is a Metropolis–Hastings chain whose stationary distribution is the Boltzmann distribution
As , concentrates all its probability mass on the global minima of . This gives the theoretical justification for annealing: if is decreased slowly enough (a logarithmic schedule suffices under classical results on Markov chain mixing), the process converges in probability to a global optimum as the number of steps grows. This is a genuine asymptotic guarantee — but the required schedule is so slow that it is impractical, which is exactly why every real implementation uses a much faster geometric cooling schedule that sacrifices the asymptotic guarantee for a usable running time. The theory tells you why annealing has a chance of working; the practice reminds you that the "correct" schedule is too slow to use.
Worked example
Consider a tiny Traveling Salesman Problem instance with five cities placed as coordinates, and the 2-opt neighborhood (reverse a segment of the tour). Distances are Euclidean, rounded to one decimal.
| City | x | y |
|---|---|---|
| A | 0 | 0 |
| B | 1 | 5 |
| C | 5 | 5 |
| D | 5 | 0 |
| E | 2 | 2 |
Start with the arbitrary tour .
Step 1 — evaluate the initial tour.
| Edge | Length |
|---|---|
| A–B | |
| B–D | |
| D–C | |
| C–E | |
| E–A | |
| Total | 23.57 |
Step 2 — hill climbing with 2-opt. Try reversing the segment between B and C (edges A–B and D–C removed, replaced by A–D and B–C), giving tour :
| Edge | Length |
|---|---|
| A–D | |
| D–B | |
| B–C | |
| C–E | |
| E–A | |
| Total | 22.47 |
This is an improvement (); hill climbing accepts it. From here, checking all remaining 2-opt moves on this new tour reveals no further strict improvement — for instance reversing B–C to test gives edges –, –, –, –, –, total — actually better. So hill climbing continues, accepts this move, reaching total .
Step 3 — genuine local optimum. Suppose after exhausting all 2-opt moves from , no reversal improves the total (this is the case here, since the tour visits the four "outer" cities B, C, D in an order consistent with their convex-hull positions and threads E in the only improving slot). Hill climbing halts, returning tour length 20.99. For this small instance, exhaustive checking confirms this is in fact the global optimum — but the point of this example is not that hill climbing always finds it; it is that hill climbing stops as soon as it can't improve, whether or not that point is global.
Step 4 — where simulated annealing differs. Suppose the initial tour had instead been trapped at a different local optimum, such as with total length 26.1 (worse), and every single 2-opt reversal from that tour happens to increase cost (a plausible configuration on slightly perturbed coordinates). Plain hill climbing would halt at 26.1 forever. Simulated annealing, at moderate temperature, would sometimes accept a worsening 2-opt move — say one that raises cost by — with probability . At , this acceptance probability is , so roughly half the time the search escapes this configuration into a different basin, from which it may find the deeper 20.99 optimum. As cools toward 0 over subsequent iterations, such escapes become rare and the search settles — ideally into the better basin it has by then discovered. This is the entire qualitative story of the method: identical neighborhood, identical cost function, but a controlled willingness to accept short-term losses in exchange for long-term gains — a willingness that shrinks over time.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Cooling too fast | Geometric factor too small (e.g., ) collapses in a handful of steps, degenerating to plain hill climbing | Use and tune against instance size; monitor acceptance rate, not just final cost |
| Neighborhood too small | Few or brittle moves (e.g., only adjacent-swap) can't reach better basins at all, regardless of temperature | Use richer neighborhoods (2-opt/3-opt for TSP) or combine several move types |
| Neighborhood too large | Evaluating all of each step (e.g., all pairs for 3-opt) makes each iteration itself intractable | Sample neighbors randomly instead of enumerating; use incremental cost deltas |
| Ignoring incremental cost updates | Recomputing from scratch each step turns an delta into an or worse recomputation | Maintain cost incrementally: track directly from the move's local structure |
| Treating "no improvement in steps" as proof of global optimality | Local search never certifies anything; a plateau or slow region can look like convergence | Run multiple restarts / seeds and compare best found; never report a single run's result as "the answer" |
| Forgetting acceptance is stochastic and must use a real random source | Deterministic pseudo-randomness with a bad seed can make "simulated annealing" behave identically to hill climbing every run | Seed properly, verify the acceptance rate empirically matches at test temperatures |
Pioneers & history
Local search and simulated annealing sit at the intersection of statistical physics, operations research, and theoretical computer science. The key conceptual leap — using a physical analogy (slow cooling of metal, "annealing," which allows atoms to settle into a low-energy crystal lattice rather than a defect-ridden glassy state) to design a general optimization algorithm — came from a 1983 paper by Kirkpatrick, Gelatt, and Vecchi, building directly on a 1953 Monte Carlo sampling algorithm due to Nicholas Metropolis and collaborators.
Origins · 1 minNicholas Metropolis and how this was discovered
Metropolis co-authored the 1953 paper "Equation of State Calculations by Fast Computing Machines," introducing what is now called the Metropolis algorithm: a Markov chain Monte Carlo method for sampling from a probability distribution proportional to , originally used to simulate the equilibrium states of physical particle systems on the MANIAC computer. Three decades later, this exact acceptance rule — accept an improving move always, accept a worsening move with probability — became the beating heart of simulated annealing when reinterpreted as an optimization procedure rather than a physical simulation.
Where this matters
Local search and its metaheuristic descendants are the workhorses of applied combinatorial optimization precisely because so few real problems have clean polynomial-time exact algorithms or tight approximation guarantees. Chip placement and routing in VLSI design uses simulated-annealing-style local search to minimize wire length and congestion across billions of components. Airline crew scheduling and vehicle routing systems use large-neighborhood local search (often called "large neighborhood search" or LNS) to handle scheduling constraints that defy clean combinatorial structure. Modern SAT solvers include local-search components (WalkSAT and its descendants) as a complement to systematic backtracking search, especially effective on randomly generated or loosely constrained instances. Training neural networks is, at its core, local search over a continuous, extremely non-convex landscape — stochastic gradient descent with momentum and learning-rate schedules is a close cousin of simulated annealing, trading a decaying "temperature" (learning rate) for the ability to escape shallow local minima in loss landscapes. Protein structure prediction, hyperparameter tuning, and job-shop scheduling all lean on the same family of ideas. As you move next into Online Algorithms and Competitive Analysis, you will meet a different response to the same underlying tension — problems where you cannot even see the whole input in advance — but the guiding lesson from local search persists: when no algorithm can certify optimality, the right question shifts from "can I prove this is good?" to "how do I systematically search for good, and how do I know empirically when to stop?"
Ask the tutor: Why does a slow logarithmic cooling schedule guarantee convergence to the global optimum in simulated annealing, while the geometric schedules used in practice do not?
What exactly is the difference between local search and an approximation algorithm?
An approximation algorithm is designed with a specific structural argument that guarantees its output is within a proven factor of optimal — for example the -approximation for vertex cover guarantees the output is never more than twice the optimal cover size, for every input. Local search makes no such promise: it simply improves a candidate solution using neighbor moves until none help, and the quality of what it finds depends entirely on the instance and the starting point. In practice local search often outperforms weak approximation guarantees on typical inputs, but it offers no certificate, so the two approaches serve different needs — provable safety versus practical performance.
Why does simulated annealing sometimes accept a worse solution on purpose?
Because accepting only improving moves (as in plain hill climbing) means the search can never leave a local optimum's basin of attraction — once you are at the bottom of a shallow valley, every neighbor looks worse, and you are stuck forever even if a much deeper valley exists nearby. Simulated annealing occasionally accepts a worsening move, with probability , precisely so the search can climb over a small barrier and discover better regions of the solution space. As the temperature cools, this willingness fades, and the process behaves increasingly like ordinary hill climbing, ideally now anchored in a better basin than it started in.
How should I choose the neighborhood function for a new problem?
The neighborhood should be small enough to evaluate quickly (ideally with an incremental cost update in or rather than recomputing the objective from scratch), but rich enough that good solutions are reachable via short sequences of moves from typical starting points. For sequencing problems like TSP, 2-opt and 3-opt (reversing or re-threading segments) are standard; for assignment problems, pairwise swaps between two items' positions are common; for SAT-like problems, single-variable flips are typical. There is no universal recipe — the right neighborhood is problem-specific, and it is common to test several and compare empirical performance, since the same cost function can behave very differently under different move sets.
Does simulated annealing have any theoretical guarantee at all?
Yes, but a fragile one. If temperature is decreased according to a sufficiently slow schedule (classically, on the order of ), the Markov chain's distribution converges to concentrate on global optima as the number of steps goes to infinity — this follows from properties of the Metropolis-Hastings chain's stationary Boltzmann distribution as . In practice, this schedule is far too slow to be usable, so real implementations use much faster geometric cooling that sacrifices this asymptotic guarantee entirely in exchange for a runnable algorithm. So the "guarantee" exists in theory but is essentially never the one actually used in practice.
How is this related to gradient descent in machine learning?
Gradient descent is local search on a continuous solution space, where the neighborhood is implicitly "a small step in the direction of steepest descent" rather than an explicit discrete move set. On convex loss surfaces, this matches the correctness argument given here: every local minimum is global, so gradient descent (with a suitable step size) reliably finds the optimum. On the highly non-convex loss landscapes of deep neural networks, this guarantee disappears, and stochastic gradient descent behaves much more like simulated annealing — mini-batch noise plays a role similar to the temperature parameter, letting the optimizer bounce out of some shallow local minima, with learning-rate schedules acting as a cooling schedule.
Can local search be combined with exact algorithms rather than replacing them?
Yes, and this is common in practice. Many production solvers use local search or metaheuristics to quickly find a good feasible solution, then use it as a strong starting bound (an incumbent) inside an exact branch-and-bound or branch-and-cut search, dramatically pruning the exact search tree. Conversely, exact methods can solve small sub-instances exactly and stitch results together with local search moves at the boundary — this hybrid style, "large neighborhood search," repeatedly re-solves a small exact sub-problem embedded inside a large local-search loop, and is standard in modern vehicle routing and scheduling solvers.
Why doesn't a local search algorithm just use the whole solution space as its neighborhood, to guarantee reaching the global optimum in one step?
Because evaluating "the best solution in all of " is exactly the original NP-hard optimization problem restated — if you could compute directly you would not need local search at all. The entire premise of local search is to substitute a small, cheaply searchable neighborhood for the full solution space, so that each step is fast even though this means giving up any guarantee that the sequence of steps reaches the true global optimum.