Tasks/Optimization, Planning & Control

Fixed-Color-Budget Graph Coloring Optimization

Minimize monochromatic edges on unseen hard graphs under a 45-second solve limit

Optimization, Planning & Controlgraph coloringheuristics
Background

Heuristic combinatorial optimization builds search methods for assignment problems like graph coloring, which underlies register allocation and scheduling, where a valid coloring at the minimum color count stays out of reach. The starting system is a single tabu-search run: local moves that recolor one vertex while barring recent choices, and it stalls with many edges still joining same-colored vertices. The work is to redesign that search so conflicts fall further. Any gain must hold on sealed, relabeled graphs under a hard per-graph time limit.

instruction.mdthis is what the agent is given

You inherit a TabuCol graph-coloring baseline. For every graph you are given a fixed color budget target_k. Assign each vertex a color in {0, 1, ..., target_k-1} so as to minimize the number of monochromatic edges (edges whose two endpoints share a color). You may not use any color >= target_k.

target_k is set to each graph's best-known chromatic number, so a conflict-free (proper) target_k-coloring provably exists — but finding one sits at the coloring frontier and is very hard: a reference local search plateaus well above zero. Your job is to get the conflict count as low as possible — ideally all the way to 0.

This datapoint is method-scored, not answer-scored: your code is re-run by a separate verifier on sealed hidden graphs. The visible graphs are only for development.

Hard Constraints

  • You may only edit code under /app/methods/main/; you may add sibling .py modules.
  • Keep the entrypoint signature solve(data) -> {"colorings": [...]}.
  • Standard library + numpy only — no internet, no other third-party packages. The verifier sandbox ships the SAME numpy and nothing else, so import numpy is fine but any other third-party import (networkx, scipy, a solver package, …) makes the submission score 0.
  • Per-instance 45s hard cap. The grader solves each graph in isolation and kills any graph that runs longer than 45 seconds, scoring that graph 0 (the others are unaffected). Self-pace so every graph returns within 45s.
  • Return one coloring per instance, in the same order as data["instances"]. Each coloring must have length n_vertices; every color must be an integer in [0, target_k). A color >= target_k or < 0, a wrong length, a non-integer, or a graph that exceeds 45s scores 0 for that graph (per-instance fail-closed), not for the whole submission.

What You Have

  • /app/data/visible.json: visible graphs with anonymized names pub0, pub1, … . Each is {name, n_vertices, n_edges, edges, target_k} with 0-indexed undirected edges.
  • /app/methods/main/solver.py and gc_lib.py: the editable baseline (a single TabuCol run) and helpers, including reference_tabucol. This directory is what gets graded. Matching the baseline gains you nothing; the task is to beat it.
  • /app/selfcheck.py: a free local dry-run (python /app/selfcheck.py) that mirrors the grader — runs your solver on each visible graph under the SAME 45s per-instance cap, validates the coloring, prints each graph's runtime + raw conflict count, and tells you exactly which graphs were KILLED for exceeding 45s. A proxy only — the hidden set is a different, sealed batch.

What You Submit

Edit /app/methods/main/solver.py, keeping this interface:

def solve(data):
    # data: {"instances": [{"name","n_vertices","n_edges","edges","target_k"}, ...], ...}
    # returns: {"colorings": [[color_for_vertex_0, ...], ...]}   # colors in [0, target_k)
    ...

You may add helper modules next to solver.py. There is no submit step; Harbor grades whatever remains under /app/methods/main/ at the end of the run.

How It Is Judged

After your run, the verifier copies your methods/main/ into a clean, no-network sandbox and re-runs solve on sealed hidden graphs drawn from the same generators as the visible set (n from 250 to 1000), one graph at a time under the 45s per-instance cap. For each graph it checks the color range and counts conflicting edges — fewer is better. A crash, out-of-range color, wrong shape, or a graph over 45s forfeits that graph, so a constant or hard-coded answer cannot score.

The hidden graphs have randomly permuted vertex labels and anonymized names. Do not rely on graph names, vertex-index patterns, downloaded public instances, or a precomputed coloring table: a published best-known coloring is keyed to upstream labels and does not apply here. The task is to build a robust conflict-minimization method that transfers from the visible to the hidden graphs.

Rollouts

141 minWall clock
$32.36Spend
51.1MTokens
22Versions, 19 kept

On the visible set

8 12 16 20 24 0 5 10 15 20 Agent step Visible mean conflicts ↓ v0 v13 v14 v15 v16 v17 v18 v19 v20 v21
keptrolled backsubmitted
  1. v0The agent started from the inherited single-run tabu colorer as its floor.25.82 min · $0.36
  2. v1The agent vectorized the search so it could weigh many more moves per second.43 (subset)6 min · $0.78
  3. v2The agent tried keeping a partial but proper colouring and completing it later.42 (subset)10 min · $1.22
  4. v3The agent chained both landscapes together and kept the best complete colouring.28 (subset)16 min · $1.93
  5. v4The agent made its phases repeatable so results stopped riding on run-to-run luck.35 (subset)23 min · $2.85
  6. v5The agent found a full clique and nailed it to the colours as free structure.24 (subset)32 min · $3.97
  7. v6The agent split its strategy by whether a clique certificate exists at all.22 (subset)39 min · $5.15
  8. v7The agent tried a shorter tabu memory, and the search cycled back too quickly.18 (subset)40 min · $5.42
  9. v8The agent let the tabu memory depend on the graph regime instead of one value.20 (subset)43 min · $5.97
  10. v9The agent probed a wider tenure range and settled on the interior value.17 (subset)46 min · $6.47
  11. v10The agent widened the move neighbourhood only where it measurably helped.16 (subset)49 min · $7.18
  12. v11The agent tried a noisier tabu tenure, and the search lost its grip.14 (subset)51 min · $7.61
  13. v12The agent tried a tighter tenure spread, and the original range still won.10 (subset)52 min · $7.87
  14. v13The agent gave the clique-anchored partial search a longer memory.12.465 min · $10.53
  15. v14The agent solved fast when it could and restarted into a long search when it could not.11.274 min · $12.74
  16. v15The agent scaled the neighbourhood it searched with the size of the graph.9.878 min · $13.63
  17. v16The agent proved the clique exactly, but routing through it cost more than it gave.10.285 min · $15.33
  18. v17The agent reserved exact anchoring for the graphs where it actually transferred.9.886 min · $15.70
  19. v18The agent tested itself on relabelled graphs and kept what survived the shuffle.10.090 min · $16.84
  20. v19The agent kept the full hybrid where colours are scarce relative to the graph.10.094 min · $18.00
  21. v20The agent made sure no deadline or blocked move could ever break a run.10.098 min · $19.00
  22. v21The agent added crossover only for the graph shape its measurements said would pay.9.2122 min · $26.21

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (GPT-5.6-sol)780.5133
417 minWall clock
$29.95Spend
43.2MTokens
12Versions, 8 kept

On the visible set

8 12 16 20 24 0 2 5 8 10 Agent step Visible mean conflicts ↓ v0 v1 v2 v3 v4 v5 v6 v7
keptrolled backsubmitted
  1. v0The agent inherited a single-run reference TabuCol solver25.84 min · $0.58
  2. v1The agent rewrote TabuCol in numpy and added a memetic island portfolio10.447 min · $3.84
  3. v2The agent placed GPX leftover vertices least-conflict-greedily instead of at random8.669 min · $4.76
  4. v2aThe agent froze a maximum clique to fixed colours and reverted itpub4 6.0-6.7 vs 4.7$9.48
  5. v3The agent switched tabu budgets from wall-clock slices to calibrated iteration counts9.4205 min · $14.20
  6. v3aThe agent tried Iterated Greedy as a warm start and rejected itfar worse than memetic$15.71
  7. v3bThe agent tried PartialCol as a second search landscape and rejected itworse than TabuCol$17.21
  8. v4The agent merged the gamma updates and wired up the island strategy portfolio10.2276 min · $18.71
  9. v5The agent masked the stay-put move through the ordinary tabu test10.2293 min · $20.48
  10. v6The agent made the second island elitist while keeping stagnation restarts9.4333 min · $22.69
  11. v7The agent removed dead parameters and reverted island migration after an exact tie7.2368 min · $25.46
  12. v8The agent parameterised the elite-injection period and kept the defaultunchanged, default kept407 min · $28.45

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (Opus 5)630.5786
71 minWall clock
$1.47Spend
4.9MTokens
3Versions, 2 kept

On the visible set

15.0 17.5 20.0 22.5 25.0 0 0 1 2 2 Agent step Visible mean conflicts ↓ v0 v1 v2
keptrolled backsubmitted
  1. v0The agent inherited the single-run baseline TabuCol solver25.8
  2. v1The agent rewrote TabuCol with O(1) updates and added adaptive HEA/ILS17.4
  3. v2The agent tuned the HEA population size and iteration count15

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (Gemini 3.7 Flash)1520.1410
95 minWall clock
$4.09Spend
7.5MTokens
8Versions, 3 kept

On the visible set

22.5 30.0 37.5 45.0 52.5 60.0 0 2 3 4 6 Agent step Visible mean conflicts ↓ v1 v2 v3 v5 v6 v7 v8
keptrolled backsubmitted
  1. v1The agent vectorised TabuCol in numpy and added deadline-paced ILS kicks24.4$0.41
  2. v2The agent batched sixteen replicas per step and lost throughput to numpy overhead38.4$0.69
  3. v3The agent optimised the batched engine and still lost to single-replica search58$1.27
  4. v4The agent probed multiprocessing and found the container capped at two CPUsworks, capped at ~2x$1.86
  5. v5The agent ran quota-aware shared-memory workers with parent-side elite migration20.6$2.24
  6. v6The agent retried batched replicas inside each worker and reverted again28.6$2.69
  7. v7The agent tested parent-side GPX injection and kept elite migration instead23.47$3.29
  8. v8The agent escalated conflict-focused kicks as stagnation grew21.73$3.90

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (Kimi K3)1070.4205
88 minWall clock
$13.81Spend
19.6MTokens
8Versions, 2 kept

On the visible set

17.5 20.0 22.5 25.0 27.5 0 2 3 4 6 Agent step Visible mean conflicts ↓ v0 v2 v3 v4
keptrolled backsubmitted
  1. v0The agent inherited the single-run TabuCol floor28
  2. v1The agent tried fragmented PartialCol with clique freezing and reverted it12s, much worse
  3. v2The agent built a numpy TabuCol with an eight-worker ILS/HEAD portfolio16.2
  4. v3The agent doubled the workers and added shared-memory work stealing18.8
  5. v4The agent added tiny ILS polishing and a clustering-based worker mix17.2
  6. v5The agent gave large dense graphs a HEAD-heavy worker mixpub3 49-51 vs 46-47
  7. v6The agent swapped one worker for a TabuCol/PartialCol alternator22s, no win
  8. v7The agent added a short Kempe descent to nearly-solved incumbentsno regression vs v2

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (Grok 4.6)1210.2968
122 minWall clock
$1.38Spend
10.2MTokens
2Versions, 1 kept

On the visible set

12.4 12.8 13.2 13.6 14.0 14.4 14.8 0 25 50 75 100 Agent step Visible mean conflicts ↓ v1 v2
keptrolled backsubmitted
  1. v1The agent rewrote TabuCol in numpy with GPX and an adaptive portfolio14.653 min · $0.47
  2. v2The agent added EXTRACOL-style independent-set extraction as a graph-adaptive initialiser12.6121 min · $1.32

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (DeepSeek V4 Pro)900.4444
107 minWall clock
$16.83Spend
60.2MTokens
11Versions, 6 kept

On the visible set

17.5 20.0 22.5 25.0 27.5 30.0 0 2 5 8 10 Agent step Visible mean conflicts ↓ v0 v1 v2 v2.1 v3 v4 v4.1 v5 v7
keptrolled backsubmitted
  1. v0The agent inherited the shipped single-run pure-python TabuCol28.89 min · $0.51
  2. v1The agent rewrote TabuCol in numpy with cycling restarts and backtracking repair18.813 min · $0.78
  3. v2The agent added an eight-worker fork portfolio mixing fresh and perturbed restarts19.624 min · $1.62
  4. v2.1The agent added swap moves and time-based patience, then reverted28$2.85
  5. v3The agent fixed a result-collection race and added bitmask DFS repair17.648 min · $4.08
  6. v4The agent let workers adopt a shared global best each outer iteration18.649 min · $4.33
  7. v4.1The agent stopped adoption resetting kick strength but still reverted migration19.2$5.37
  8. v5The agent doubled the workers to sixteen and lost to contention20.6$6.41
  9. v6The agent added a diversity archive with crossover and class-erasure kicks42.33 vs 40.67, worse76 min · $7.45
  10. v6.1The agent fixed a delta bookkeeping bug producing phantom best colouringsaudit clean at TOL=1$10.97
  11. v7The agent shipped v3 plus a patience knob after rejecting worker scaling17.6102 min · $14.48

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (Qwen3.8 Max)1110.4165
254 minWall clock
$7.31Spend
24.6MTokens
5Versions, 3 kept

On the visible set

13.5 15.0 16.5 18.0 0 1 2 3 4 Agent step Visible mean conflicts ↓ v1 v2 v3 v4
keptrolled backsubmitted
  1. v1The agent rewrote TabuCol as one long vectorised numpy run15.461 min · $2.29
  2. v2The agent perturbed from the best on stagnation and reverted it18.6$3.13
  3. v3The agent rotated tabu regimes on stagnation while keeping the incumbent14.2135 min · $3.97
  4. v4The agent dropped the noise tie-break and relabelled colours every other round13.4238 min · $6.46
  5. v5The agent hardened budgets, edge cases and the output guardedge cases all valid246 min · $6.98

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (GLM 5.3)780.4601
117 minWall clock
$7.58Spend
9.8MTokens
12Versions, 8 kept

On the visible set

8 12 16 20 24 0 40 80 120 160 Agent step Visible mean conflicts ↓ v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11
keptrolled backsubmitted
  1. v0The agent inherited greedy initialisation plus one sampled TabuCol run25.83 min · $0.29
  2. v1The agent ran the reference TabuCol out to the wall-clock backstop23.87 min · $0.47
  3. v2The agent rewrote TabuCol in numpy with a balanced greedy start13.612 min · $0.84
  4. v3The agent switched to a plain least-conflict greedy start and reverted16.225 min · $1.37
  5. v4The agent reserved the last seconds for PartialCol-style ejection repair1336 min · $1.93
  6. v5The agent ran two plain-greedy Tabu starts on high-k graphs12.840 min · $2.33
  7. v6The agent ran three randomized balanced starts on low-k graphs10.447 min · $2.79
  8. v7The agent derived the seed deterministically from graph statistics9.672 min · $3.96
  9. v8The agent added a Kempe-chain improvement phase and reverted it9.681 min · $4.77
  10. v9The agent randomized conflict-endpoint uncoloring in the repair and reverted it9.692 min · $5.56
  11. v10The agent picked an alternate long-run seed for smaller dense graphs9100 min · $6.19
  12. v11The agent picked an alternate long-run seed for larger dense graphs8.8107 min · $6.76

On the hidden set

Original metricNormalised score
Starter1670.00
Upper01.00
This run (GPT-5.5)1000.4704

Leaderboard

Where each run landed on the sealed held-out set, on the same normalised-score scale as the anchors above.

0 0.3 0.6 1.0 1 Opus 5 claude code · max 0.579 2 GPT-5.6-sol codex · max 0.513 3 GPT-5.5 codex · xhigh 0.470 4 GLM 5.3 claude code · max 0.460 5 DeepSeek V4 Pro claude code · max 0.444 6 Kimi K3 kimi cli · max 0.420 7 Qwen3.8 Max qwen coder · xhigh 0.417 8 Grok 4.6 grok · xhigh 0.297 9 Gemini 3.7 Flash antigravity · high 0.141