Simulated Annealing — Cooling Schedule Caused Unrouted Nets
Production VLSI layout faced 15% wire-length over budget due to aggressive cooling frozen search.
20+ years shipping performance-critical code where algorithms decide the bill. Drawn from code that ran under real load.
- ✓Solid grasp of fundamentals
- ✓Comfortable reading code examples
- ✓Basic production concepts
- Simulated annealing (SA) escapes local optima by accepting worse moves with probability exp(-ΔE/T)
- Starts at high temperature (exploration) and slowly cools to greedy (exploitation)
- Cooling schedule is the critical knob: too fast traps you, too slow wastes compute
- Geometric cooling (T *= 0.995) is the workhorse in production — simple and effective
- Real-world cost: each temperature stage runs ~100 iterations, total ~10,000 evaluations for medium problems
- Production gotcha: SA needs a good initial temperature — set it so ~80% of moves are accepted at start
When you heat metal and let it cool slowly (annealing), atoms arrange into a low-energy crystalline structure — the global minimum. Simulated annealing applies this to optimisation: start hot (accept bad moves freely), cool slowly (accept bad moves less and less often), freeze (only accept improvements). The random acceptance at high temperature lets the algorithm escape local optima that trap pure hill-climbing.
| Chrome | Firefox | Safari | Edge |
|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ |
Simulated annealing (SA) was introduced by Kirkpatrick, Gelatt, and Vecchi in 1983 as a method for solving combinatorial optimisation problems. The key insight from statistical mechanics: systems in thermal equilibrium at temperature T have state energies distributed according to the Boltzmann distribution — higher energy states are possible but less probable, with probability proportional to exp(-ΔE/kT).
Applied to optimisation: at high temperature T, accept moves that make the objective worse with probability exp(-Δcost/T). As T decreases, only improvements are accepted. This controlled randomness escapes local optima that would trap pure greedy search.
Simulated Annealing as a Stochastic Search Engine
Simulated annealing is a probabilistic optimization algorithm that mimics the physical annealing process in metallurgy. It starts with a high "temperature" parameter, allowing the algorithm to accept worse solutions with a certain probability, then gradually cools to zero, at which point only improvements are accepted. The core mechanic is the Metropolis acceptance criterion: a worse solution is accepted with probability exp(-ΔE / T), where ΔE is the change in cost and T is the current temperature. This controlled randomness lets the search escape local optima early while converging to a near-global optimum later.
In practice, the cooling schedule—how T decreases over iterations—determines success. Common schedules include exponential cooling (T = T₀ * α^k, α ≈ 0.95–0.99) and logarithmic cooling (T = T₀ / log(k)), which guarantees convergence to the global optimum given infinite time. The algorithm has no memory, so each step depends only on the current state and temperature. Key properties: it is simple to implement, works on discrete and continuous spaces, and requires only a cost function and a neighbor generation mechanism.
Use simulated annealing when the search space is large, multimodal, and gradient-free—for example, VLSI routing, traveling salesman, or protein folding. It matters in production because it often finds good-enough solutions faster than exact methods (which are NP-hard) and more robustly than greedy hill-climbing. The trade-off: tuning the cooling schedule and initial temperature is art, not science, and a bad schedule can produce results worse than random.
Simulated Annealing Algorithm
Simulated annealing generalises gradient-free optimization. At each step, you generate a neighbour of the current solution. If the neighbour improves the cost (ΔE < 0), accept it always. If it worsens the cost, accept it with probability exp(-ΔE/T). This 'case acceptance' at high temperature lets you explore globally.
Here's a production-ready implementation in Python. It uses geometric cooling and tracks the best solution seen (not just the current one) because you can wander into a bad region and still remember the best discovered peak.
- At high T: you're a drunkard wandering the solution space — every move is possible
- At medium T: you're a tipsy climber — you mostly go uphill but sometimes take a detour
- At low T: you're a sober mountaineer — you only move to higher ground
- The cooling schedule dictates how long you stay in each state of sobriety
neighbour() must generate a small perturbation — like swapping two cities. A neighbour that's too large (random permutation) breaks SA's local structure and kills convergence.Cooling Schedules: Which One for Production?
The cooling schedule determines how fast the temperature falls. The four main types:
Geometric cooling: T ← T * α, where α ∈ (0.9, 0.999). Simple and efficient. α close to 0.999 gives near-logarithmic behaviour but with constant computational cost per step.
Logarithmic cooling: T = T₀ / log(1 + t). Theoretically guarantees convergence to global optimum (Hajek, 1988) but needs trillions of steps for complex problems — impractical.
Adaptive cooling: Adjust cooling rate based on the observed acceptance rate. Target ~50% acceptance at each temperature. If acceptance > 50%, cool faster; if < 20%, reheat slightly. More robust for unknown problem landscapes.
Exponential cooling (fast): T = T₀ * exp(-β t). Used when you need a quick answer — converges fast but may get stuck.