You inherit a weak but legal ride-pooling dispatch pipeline and must improve
its solve() so that it routes a robotaxi fleet through paired
pickup-delivery requests with two-sided time windows and a maximum ride
time per passenger — the dial-a-ride problem. Small and mid-size instances of this
family are solvable to proven optimality, so your distance to the true
optimum is a measurable fact. Your submitted
solve() is re-run per instance on a set of sealed hidden instances, and
the lower your mean normalised cost, the better.
Hard Constraints
An instance is a self-contained JSON file: fleet size m, capacity Q,
max route duration T, max ride time L, a depot, and n requests with
pickup/delivery coordinates, service times, load, and time windows
(outbound requests constrain the delivery window, inbound ones the
pickup — the usual dial-a-ride convention). Travel time = travel cost =
Euclidean distance. Node numbering for solutions: pickup of request i
(0-based) is i+1, its delivery is n+i+1; depot 0 is implicit at
both route ends.
Implement solve(instance_path: str, time_budget_s: float) -> list[dict]
in methods/main/solver.py, returning at most m routes, each
{"sequence": [nodes...], "schedule": [service start times...]}. It is
called once per instance and must return within time_budget_s (the
verifier uses 60 s per instance).
The sealed verifier re-checks the RETURNED schedules against every
constraint: pairing on one vehicle, pickup before delivery, capacity
along the route, time windows (waiting is allowed:
B_next ≥ B_prev + service + travel), per-passenger ride time
B_delivery − (B_pickup + service) ≤ L, route duration
return − departure ≤ T, and the depot window. Any violation on an
instance scores 100.0 (the baseline) for that instance — there is no
repair on the grader side.
You may only change your solver code — not the evaluator, the
instances, or the scoring. Determinism is recommended (seed your RNG) so
your local scores reproduce.
What You Have
methods/main/solver.py — the weak baseline you edit in place: greedy
cheapest insertion in time-window order, no improvement moves at all.
darp.py — the exact public evaluator used for scoring: instance loader,
the full constraint validator (check_solution), the
eight-step route scheduler (route_schedule) that
turns a visit sequence into a feasible schedule (delaying departures and
pickups via forward slack to tame ride times) — the same routine the
verifier's trusted copy uses — plus seq_cost, the weak baseline
(weak_solution) used as the normalisation denominator, and score().
data/ — 4 visible instances: a2_16, a4_32 (small instances solvable to proven
optimality — you can see
exactly how far from the true optimum you are) plus V1, V2 (samples
from the hidden-set generator, so the visible set spans the hidden
distribution).
selfcheck.py — runs your current solve() on the visible instances and
prints the mean normalised score (QUICK=5 python selfcheck.py for fast
rounds).
What You Submit
Your edited methods/main/solver.py (plus any helper modules under
methods/). The verifier re-runs solve() per hidden instance and
re-validates + re-scores the returned solutions; only the
solve(path, budget) -> list[dict] contract above is relied upon.
How It Is Judged
The sealed verifier calls your solve() on each hidden instance (unseen
members of the same generator family as V1/V2: the same geometry
with varied request counts, fleet sizes, ride-time caps and window widths),
then recomputes
with its own trusted validator. The hidden mean is your score; lower is
better, and your reward rises as it drops. On the visible
instances the proven optima sit roughly 7–10 % below the weak baseline for
the small sizes and further below it as instances grow — every percent you
close is measurable against ground truth, not against a movable record.
Metric
mean normalised cost over the five sealed hidden instances · lower is better
100 x cost / weak-baseline cost per instance, re-validated by the grader; any violation scores that instance 100
anchor
held-out
reward
B
greedy-insertion baseline
100.00
0.00
R
REFERENCE anchor
94.84
0.30
S
SOTA anchor
89.7814
0.60
normalisation
m >= B or m <= 0
0
B > m >= R
0.3 * (ln B - ln m) / (ln B - ln R)
R > m >= S
0.3 + 0.3 * (ln R - ln m) / (ln R - ln S)
m < S
1 - 0.4 / y, y = 1 + (ln S - ln m) / (ln R - ln S)
m = this run's held-out metric · B = greedy-insertion baseline · R = REFERENCE anchor · S = SOTA anchor
Log interpolation in both bands. The five per-case scores are averaged first, then mapped once; past SOTA a soft cap nears 1.0, unreached.
Rollouts
200 minwall clock
$18.34spend
24.5Mtokens
10versions, 10 kept
keptrevertedno scoreturning point
v0Inherited greedy cheapest-insertion baseline, unchanged1003 min · $0.52
v1_preFull rewrite: exact difference-constraint scheduler, regret-2 insertion, LNS with SAReplace the heuristic 8-step scheduler with an exact fixpoint, then build regret-2 insertion and ruin-and-recreate on top.89.18816 min · $2.55
v2Request bank + penalty objective so repair never dead-ends; window removal operator89.5416 min · $2.55
v3O(1) necessary-condition screening in insertion, verified by exhaustive enumerationReject most candidate insertions by valid relaxation bounds instead of scheduling them. LNS iterations in 9 s: 67 to 1184, n=80.89.13322 min · $3.37
v4ALNS adaptive operator weights, kill-route removal, re-heat on stallonly ALL b=10: 86.36395 min · $9.39
v5SA temperature 0.1 -> 1.0 from 3-seed sweeps; time fraction 0.92 -> 0.94Settled the one parameter that mattered against ground truth: a4_32 sticks at 486.57 at 0.1, reaches the optimum 485.50 at 1.0.not re-measured127 min · $11.77
v6Set-partitioning recombination tested and rejected; wall-clock guard in repair88.628156 min · $13.84
v7Feasibility monotone under route growth, so infeasible cache entries never retried88.628176 min · $15.79
v8Focused repair tested and rejected; behaviour identical to v788.628194 min · $17.25
v9Entry point wrapped so any exception still returns the greedy construction88.628196 min · $17.90
All ten snapshots stayed on the line; swap search, ejection insertion, recombination and focused repair were measured and removed inside a version.
v1Multi-start insertion, relocate/exchange/2-opt* LS, ALNS, tightening schedulerSchedule sequences by complete window tightening instead of the eight-step check, then search on top.89.985
v2Feasible relocate tabu accepting worsening moves; faster TW-filtered insertionLet the descent accept worsening feasible relocations; a2_16 and a4_32 land on their proven optima 294.25 and 485.50.88.922
v4Earliest-schedule fast path, budget-independent construction cap, 20 s prefixMake a 60 s run replay the 20 s search first so extra time can only extend it: hold-out V2 82.16 to 81.45.88.746
v5solve() never raises; ejection fallback when a construction order finds none88.746
The tuning trio froze at v2, so v4 and v5 move only hold-out V2; their means are 60 s numbers while v1 and v2 were measured at 20 s.
v1Inherited greedy cheapest-insertion baseline, unchanged1001 min · $0.24
v2Deterministic best-improvement paired-request relocation, within and across routes93.8862 min · $0.45
v3Complete-request identity swaps alternating with relocation descent93.0643 min · $0.62
v4Seeded multi-request ruin/recreate, 2-6 requests, monotone incumbent acceptanceStop descending one solution: tear out a related 2-6 request set and rebuild. Every later version runs inside this loop.91.5895 min · $0.80
v5Simulated-annealing acceptance with 30-stale restart instead of monotone LNS91.7488 min · $1.12
v6Dynamic regret-2 repair on a quarter of LNS iterations92.3789 min · $1.28
v7Intra-route swap/reversal and zero-load-cut inter-route 2-opt-star polish91.13510 min · $1.47
v8Exhaustive cross-route two-request exchange with optimized reinsertion91.411 min · $1.64
v9Destroy size diversified per iteration, maximum ruin raised from 6 to 1091.412 min · $1.87
v10Construction reordered by pickup-window midpoint, atomic fallback to reference order89.70515 min · $2.28
v11Structural descent delayed behind a 48%-budget monotone LNS phase89.30921 min · $3.08
v12Pre-structural LNS allocation cut from 48% to 30% of budget89.29722 min · $3.25
v13Exact O(1) six-edge insertion delta replaces full route-cost recomputation89.29724 min · $3.63
v14Cooler post-structural annealing with restart every fourth iteration89.29726 min · $4.02
v15Relocation lookahead on every fifth near-incumbent repair89.29727 min · $4.32
v16Best-improvement relocation of contiguous load-balanced blocks at zero-load cuts89.29729 min · $4.66
v17Post-structural LNS replaced by an annealed feasible random walk89.29732 min · $5.18
v18Post-structural LNS replaced by strict-best randomized multistart constructionsSearch stopped paying, so build many randomized chronology-blend starts instead and polish each to a local optimum.89.18436 min · $5.81
v19Multistart RNG reseeded at the phase boundary, decoupled from phase-one LNS88.96439 min · $6.52
v20Phase-one monotone LNS allocation reduced from 30% to 20%repeats 89.158 / 89.30141 min · $6.93
v21Insertion hot loop delta-prunes before building candidates; neighbourhood unchanged88.96142 min · $7.38
v22Precomputed distance matrix indexed directly in the exact insertion delta88.96143 min · $7.77
v23Multistart insertion-noise cycle widened from [0,1,2] to [0,2,5,10]88.96152 min · $9.91
v24Full randomized construction alternated with whole-route ruin and reinsertion89.29754 min · $10.22
v25Final 30% of budget given to whole-route ruin/reinsert with strict-best polish89.29755 min · $10.61
v26Budget-scaled phases: multistart capped, remainder to one/two whole-route ruinReal budgets get a phase QUICK=5 never sees: cap multistart by n, spend the rest on whole-route ruin. V2 at 60 s: 82.11 to 81.63.88.96160 min · $11.78
v27Three-route ruin every sixth long-horizon rebuild88.96165 min · $13.18
v28Periodic dynamic regret-2 repair inside whole-route ruin88.96167 min · $13.89
v29Width-3 restricted candidate list on every fifth rebuild; IndexError at 60 s88.96168 min · $14.97
v30RCL helper corrected to the shared insertion tuple contract88.96170 min · $15.58
v31Bellman-Ford least schedule replaces the public eight-step feasibility call88.96181 min · $18.14
v32Scheduler-filtered Or-opt relocation of segments of length 1-688.96183 min · $18.70
v33Annealed whole-route rebuild excursions after 15 s of monotone route ruin88.96186 min · $19.78
v34Random, contiguous-time and Shaw destroy of 7-15 requests after 15 s ruin88.96189 min · $20.52
v35Fallback to public weak_solution and trusted validation of the final output88.96190 min · $21.04
v36Guarded balanced pickup-order seed with route-size penalty 4, used within 5%88.961111 min · $27.56
v37Balanced-seed route-size penalty raised from 4 to 12, chosen by a 0-30 sweep88.961117 min · $29.87
v38Balanced-seed guard tightened from 105% of primary cost to primary cost88.961121 min · $31.40
The QUICK=5 mean froze at 88.961 from v21 on; every version after v26 was decided on targeted 60-second V2 runs, ending at panel mean 88.628.
v0Inherited greedy cheapest-insertion baseline, unchanged1001 min · $0.24
v1Cached deterministic complete-request relocation, cross-route and within-route94.892 min · $0.51
v2Multi-request ruin plus regret-2 repair, relocation polish after each acceptFrom one-request moves to ruin-and-recreate: tear out a related set, rebuild with regret-2. Every later version lives in this loop90.9694 min · $0.71
v3Bounded beam repair keeping several non-cheapest placements per removed request90.9617 min · $0.97
v4Second construction ordered by each request's critical latest pickup bound90.2199 min · $1.18
v5Search the original basin before trying the critical-latest construction90.24410 min · $1.38
v6Ruin/repair refactored into a reusable phase, applied to the alternate basin90.24412 min · $1.61
v7Alternate-basin phase extended to 94% of the quick budget90.24412 min · $1.76
v8Replay the strongest deterministic ruin sampling stream in the alternate basin90.24414 min · $2.02
v9Exact improving relocation of contiguous zero-load route fragments, then polishA neighbourhood, not a parameter: a contiguous zero-load stretch holds whole requests, so it lifts out and reinserts exactly.89.71915 min · $2.35
v10Atomic zero-load fragment swaps inside every block-polish call90.12317 min · $2.59
v11Block swaps isolated to a final phase to preserve the v9 trajectory89.71918 min · $2.78
v12Long-budget tail split between beam repair and SA over repaired local optimaAnnealing over repaired local optima in a long budget's tail: invisible at QUICK=5, worth 1.4 on V2 at 60 s, the grader's budget.89.71921 min · $3.25
v13Annealing destroy diversified with worst-detour and same-route-chain removal89.71930 min · $4.60
v14Exhaustive reordering of atomic zero-load chains up to five requests89.71932 min · $4.97
v15Extra pickup-earliest, delivery-earliest and midpoint constructions above 15 s89.71935 min · $5.61
v16Exact necessary-condition screening before the eight-step scheduler89.71938 min · $6.08
v17Independent deterministic RNG stream for the annealing phase89.71941 min · $6.75
v18Beam phase capped at 15 s to give annealing ten more seconds89.71943 min · $7.28
v19v12's annealing RNG restored while keeping the shorter beam89.71948 min · $8.15
v20Beam capped at 9 s, effectively skipping it after the alternate basin89.71950 min · $8.56
v21Now-unreachable beam-repair code and its insertion helper removed89.71952 min · $9.11
v22Annealing ruin size enlarged from 3-8 to 3-10 requests89.71953 min · $9.48
v23Annealing ruin size shrunk from 3-8 to 3-6 requests89.71955 min · $9.85
v24Annealing temperature lowered from 2.5-0.3% to 1.1-0.1% of incumbent cost89.71956 min · $10.23
v25Regret-3 instead of regret-2 repair during annealing89.71958 min · $10.73
v26Time-capped parallel regret construction from an empty fleet above 30 s89.71959 min · $11.15
v27Four-second phase of exact two-request reinsertion in both repair orders89.71962 min · $11.91
v1ALNS with lower-bound insertion pruning, four destroy and three repair operatorsReject over 95% of candidate routes by a lower-bound feasibility test, then spend the budget on destroy and repair.89.52213 min · $0.29
v2Deadline checked inside the local-search inner loops to hold the 60 s budget89.52215 min · $0.40
v3Adaptive EMA operator weights tested and reverted; uniform weighting kept90.10124 min · $0.57
Three snapshots in 25 minutes; the QUICK=5 mean never left 91.803, so both keeps rest on the 60 s visible mean, where a4_32 misses its optimum.