Capstone: Meridian's Bid Desk
In short: this section built four separate pieces of hard-problem machinery — brute force vs. verification, a reduction between two NP-hard problems, a provably-bounded approximation, and a search over an opponent who's also optimising. The bid desk is where the approximation piece earns its keep for real: a fixed, seeded benchmark of tender instances, scored two ways — the no-guarantee nearest-neighbour heuristic, and the MST-shortcut approximation with its proven ratio of at most 2. Measured honestly, one of them can break its informal expectations. The other, provably, cannot.
Run the benchmark, read what actually happened
At seed=7, fifteen trials, the MST approximation's worst ratio lands at
1.9535 — under the 2x ceiling, as the proof in lesson 3 said it must.
Run bid_desk_benchmark(7, 15) in full and the nearest-neighbour column
tells a different story: 2.0465, past 2x. Nothing about
nearest-neighbour is broken — it's a perfectly reasonable heuristic most of
the time — but nothing was ever proven about it either, and this benchmark
is where that absence shows up as a real number, not a footnote.
Why the same instances treat the two heuristics differently
Nearest-neighbour makes a locally greedy choice at every step and never
revisits it. On most seeded point sets that works out fine. But a handful of
points can be arranged — not maliciously, just by chance, as a seeded
random.Random instance sometimes will — so that an early "closest" choice
strands the walk far from where it still needs to go, with no mechanism to
notice or correct it. The MST-shortcut approximation has no such blind spot
because its guarantee doesn't come from being locally sensible — it comes
from the inequality shortcut tour ≤ 2 × MST weight, which holds
structurally, for every instance, not just typical ones.
nn_ratio, approx_ratio = 2.0465, 1.9535
print(nn_ratio <= 2.0, approx_ratio <= 2.0)Quick practice
def guarantee_held(ratios):
return max(ratios) <= 2.0
print(guarantee_held([1.2, 1.5, 2.0]), guarantee_held([1.2, 1.5, 2.01]))trials_run = 30
instances_skipped = 0 # none have MST weight 0 here
print(trials_run - instances_skipped)🎯 Your turn
Build bid_desk_benchmark(seed, trials). Generate trials seeded
instances with random.Random(seed) (4 to 9 stops, coordinates 0..30,
Manhattan distance between every pair). For each, compare the
nearest-neighbour heuristic and the MST-shortcut approximation against the
MST weight. Return
{"trials": ..., "nearest_neighbour_max_ratio": ..., "approximation_max_ratio": ..., "approximation_guarantee_held": ...}.
bid_desk_benchmark(42, 30)→approximation_guarantee_heldTrue.bid_desk_benchmark(7, 15)→ nearest-neighbour's ratio breaks past2.0; the approximation's doesn't.
Hint: reuse the MST, preorder-walk and nearest-neighbour pieces from lesson 3 — this lesson's job is running them at scale and reporting honestly, not inventing new algorithms.
Press ▶ Run, try the Live App chips, then ✓ Check. Green = this piece of Meridian is built. ✅
