Design routes for a homogeneous fleet serving ~500 transport requests
(≈1000 tasks): each request is a pickup node and a delivery node that
must be served by the same vehicle, pickup first, under vehicle
capacity and hard two-sided time windows at every node. The objective is
the ranking scalarisation locked for this task:
Cost = 10000 × (number of routes) + total euclidean distance — one
vehicle saved outweighs any distance detour. At this scale the best
results anyone has are still being improved by professional teams with
months of compute; pairing constraints break
classic VRP neighbourhoods (2-opt, Or-opt mostly produce infeasible
moves), so pair-aware removal/reinsertion operators are the core of every
strong method. Your solver is graded on unseen instances drawn from the
same generator families (clustered / random / mixed geometry × tight /
loose windows) — a memorised record solution is useless there.
Hard Constraints
Implement solve(instance_path: str, time_budget_s: int) ->
list[list[int]] in /app/methods/main/solver.py; keep the entry point
importable (module-level solve).
Return a list of routes; each route is a list of customer ids
(1..n-1), without the depot — the verifier closes every route at
the depot (node 0). Every customer appears exactly once across all
routes; at most vehicles routes.
Feasibility, re-checked by the sealed verifier: for each pair, pickup
and delivery in the same route, pickup strictly before delivery;
running load within [0, capacity] at every step; service at node i
starts at max(arrival_i, earliest_i) and must satisfy
start_i ≤ latest_i (waiting is free); each route returns to the depot
no later than latest_0. Travel time = exact euclidean distance,
service times as given.
Any violation on an instance scores 100.0 (the baseline) on that
instance — the verifier does not repair your output.
time_budget_s (60) is the per-instance wall-clock budget your solver
should respect; the verifier kills the child process on a safety net
well above it. No other resource is limited — a full validation costs
under 0.1 s, iterate freely.
Do not read, probe, or special-case anything outside /app; the hidden
instances and anchors are not in your environment.
A solver that ignores time_budget_s is killed by the safety net and scores 100 on that instance.
What You Have
/app/pdptw.py — the full public evaluator, cross-validated
byte-equivalent in verdict and cost (to 1e-6 relative) against an
independent decimal-128 reference checker on a large corpus of external
solution files: check_and_cost (feasibility + cost), check_route,
weak_solution, score. What it reports is what you are graded on.
/app/data/ — four visible 1000-task instances (JSON): V1
(clustered geometry), V2 (random), V3 (mixed), and V4 — a
generated instance from the same generator the hidden set uses
(random geometry, tight windows).
/app/methods/main/solver.py — the weak baseline (greedy insertion of
pickup-delivery blocks + adjacent-swap improvement). It defines
score = 100 on every instance. Start from it or replace it.
What You Submit
The whole /app/methods directory; the graded artifact is
methods/main/solver.py with the solve contract above. Anything else
you write under /app stays local; only methods/ is exported.
How It Is Judged
The sealed verifier re-runs your solve on six hidden instances
(private generator draws, one per family: clustered/random/mixed ×
tight/loose windows, ≈1000 tasks each), re-validates every route with
its own trusted evaluator and re-computes
Cost = 10000 × routes + distance in a separate process.
Per instance: score = 100 × Cost / Cost(weak baseline), lower is
better; infeasible output scores 100. The task score is the mean over
the hidden instances.
Lower normalised score is better. The scoring anchors are sealed in the
verifier; no submission can reach a score of 1.0.
Metric
mean normalised cost over the six hidden PDPTW instances · lower is better
100 x (10000*routes + distance) / weak-baseline cost per instance; an infeasible route set scores 100 there
anchor
held-out
reward
B
weak greedy-insertion baseline
100.00
0.00
R
REFERENCE, the author's own LNS
87.5368
0.30
normalisation
m >= B or m <= 0
0
B > m >= R
0.3 * (ln B - ln m) / (ln B - ln R)
m < R
1 - 0.7 / y, y = 1 + (ln R - ln m) / (ln B - ln R)
m = this run's held-out metric · B = weak greedy-insertion baseline · R = REFERENCE, the author's own LNS
The six case scores are averaged first, then mapped once. No upper anchor: past REFERENCE a soft cap rises toward 1.0 and never reaches it.
Rollouts
185 minwall clock
$60.53spend
101.4Mtokens
63versions, 32 kept
keptrevertedno scoreturning point
v0Inherited baseline: greedy adjacent-block insertion with adjacent swaps1000 min · $0.14
v1Independent feasible pickup/delivery positions; precomputed distance matrixPlace the pickup and the delivery each at their own best feasible slot instead of as one adjacent block.75.04932 min · $0.29
v2Transactional whole-route removal, constrained-first/regret reinsertion74.73473 min · $0.47
v3Forward-time/backward-latest feasibility; insertion scan cubic to quadratic72.3595 min · $0.65
v4Deterministic multistart over temporal, span, geometric orders, 12 shuffles72.78837 min · $0.94
v5Bounded tabu pair-ejection chains after failed route elimination71.909710 min · $1.33
v7Global ALNS: whole-route plus related/random pair destroy, cached regretDestroy and rebuild across the whole solution at once, instead of repacking one isolated route pool at a time.70.836416 min · $2.38
v15Classical distance-regret as seed-0/1 starts; dropped fixed span/angular69.899443 min · $7.51
v16Classical distance-regret in one of every four ALNS recreations69.882146 min · $8.10
v17Fixed-seed noise in regret construction, 12 mode/noise/seed combinationsV1/V2 route counts50 min · $8.89
v18Exact ternary-state DP resequencing when insertion blocks elimination69.909254 min · $9.75
v19ALNS operator weights 40/40/20 over destroy sizes 10, 36 and 28V3/V4 at 30 s only60 min · $11.26
v20Incumbent-protected ALNS extended through the final 8% ejection reserve69.84561 min · $11.77
v21After 120 stagnant tries, 3-route/48-request and 5-route/64-request rebuildsV1-V4 routes at 60 s69 min · $13.58
v22Doubled the late 5-route neighborhood, dropped forced 3-route trialsV3 distance at 60 s75 min · $15.21
v23Long-haul gate: mean direct ride above 20% of the coordinate-box diagonalV4 only76 min · $15.76
v24Stagnated long-haul search forces size-10 trials and one fewer routeV4 only79 min · $16.46
v25Exact bipartite component recombination across multistart partitionsconstruction only82 min · $17.56
v26One in six ALNS recreations inserts by minimum downstream schedule delayRebuild occasionally to preserve schedule slack rather than distance, leaving room for the next route removal.69.499284 min · $18.08
v27Slack-preserving recreation frequency raised from one in six to one in threeV3 routes at 30 s86 min · $18.89
v28One in three slack frequency only on related-removal, constrained-first triesV3 routes at 30 s88 min · $19.48
v29Slack-preserving cycle offset moved from attempt mod 6 = 2 to 0V3 routes at 30 s88 min · $19.90
v30Slack-preserving cycle offset moved to attempt mod 6 = 4V3 routes at 30 s89 min · $20.15
v31Slack scoring becomes distance plus 3x downstream delayV3 at 30 and 60 s90 min · $20.57
v32Downstream-delay weight reduced to 1V3 routes at 30 s91 min · $20.82
v33Downstream-delay weight raised to 10V3 routes at 30 s92 min · $21.07
v34Perturbation by shortest pickup-to-delivery segment, then delay, distanceV3 routes at 30 s97 min · $23.04
v35Maximise the minimum residual margin over prefix, segment, delivery, suffixV3 routes at 30 s99 min · $23.59
v36On service-heavy data, pool six related routes and force five replacementsV1 routes at 60 s100 min · $24.06
v37Numeric demand/window/service arrays in the hot feasibility loopsV3/V4 at 30/60 s103 min · $25.11
v38Cached forward/load/backward route profiles in construction and recreationV3 at 30 and 60 s107 min · $26.54
v39Route-profile caching extended to direct elimination scansV3 routes at 30 s109 min · $27.30
v40Late-neighborhood stagnation trigger raised from 120 to 240 attemptsV3 at 30 and 60 s112 min · $28.37
v41Trigger by 7 s since the last vehicle gain instead of 240 attemptsV3 routes at 30 s120 min · $31.08
v42Wall-time stagnation trigger shortened to 6 sV3 routes at 30 s120 min · $31.38
v43Classical-regret ALNS frequency raised to one half on long-haul instancesV4 only128 min · $34.20
v44Slack-preserving insertion disabled on long-haul instancesV4 only131 min · $35.41
v45Shortest-route targeting on every second attempt instead of every thirdV3 60 s, V4 30 s137 min · $37.68
v46Every-second shortest-route targeting only off the long-haul pathV2 distance at 60 s138 min · $38.00
v47That targeting gated to non-long-haul data with window width above 20V1-V4 routes at 60 s141 min · $39.14
v48Classical-regret ALNS disabled on tight-window, non-long-haul instancesV2 at 60 s only143 min · $40.22
v49Sparse slack-preserving insertion disabled on tight-window data as wellV2 routes at 30 s144 min · $40.77
v50Shaw-related extra removals on every long-haul ALNS attemptV4 only146 min · $41.54
v51Shaw time-relatedness weight 0.25 to 1.0 on long-haul data onlyV4 only149 min · $42.84
v52After 240 stagnant long-haul attempts, double size-36/two-source trialsV4 at 60 s only152 min · $44.17
v53Dropped the dead route_dists recomputation and unused validator stateV3/V4 at 30/60 s154 min · $45.22
v54Removed the unreachable legacy ejection-chain branch and its final call69.2642162 min · $48.47
v55Worst-distance-contribution removals on a quarter of late large trialsV3 routes at 30 s168 min · $50.91
v56Below a 3 s budget, skip regret multistarts and keep fixed construction1 s edge test only169 min · $51.67
v57High- and low-demand regret starts added on every instanceV3/V4 at 30 s only170 min · $52.33
v58High-demand start gated to wide-window, low-demand start to long-haulV3/V4 at 60 s only172 min · $52.97
v59Five-start portfolio replaced by fixed fallback plus per-regime regretV3/V4 at 30 s only176 min · $54.90
v60Demand seeds dropped, only fixed fallback and winning legacy regret keptV3/V4 at 30 s only177 min · $55.55
v61Delivery-earliest regret start added for long-haul instances onlyV4 at 30 and 60 s179 min · $56.45
v62Slack-preserving insertion throughout elimination on wide-window dataV3 routes at 30 s183 min · $59.85
63 snapshots, 185 min, $60.53. v0-v20 cost $11.77 and carried 100 -> 69.85; the last 42 versions cost $48.76 for 0.58 more.