Tasks/Earth & Energy/Power Grid

Repair a feeder's phase and impedance records from smart-meter archives

Repair phase labels and impedances on a distribution feeder

feeder_phase_impedance_inversion Earth & Energy Power Grid
instruction.mdthis is what the agent is given

You are an AI agent assisting a distribution planning engineer at a mid-size utility with a solar interconnection queue. Before any hosting-capacity or voltage-drop study can be signed off, the feeder model has to be calibrated: the GIS says which phase each customer is on, which conductor each segment uses, and where the regulator tap sits — and all three are wrong at well-documented rates, because crews re-phase laterals after storms, re-conductor spans without closing the paperwork, and move taps in the field. All you have per feeder is two to three days of 15-minute AMI data from most (not all) customers — voltage magnitude only — plus head SCADA and billing averages. A model calibrated too optimistically overstates hosting capacity and customers get voltage complaints; too pessimistically and interconnections are refused for no reason. You inherit the utility's current first-pass script; your job is to build the calibration method the utility will run fleet-wide — it is re-run, unchanged, on feeders whose actual wiring you never see.

Hard Constraints

  • Submit a method: methods/main/solver.py defining exactly calibrate(record) -> dict with keys "phase" (list of one int in 0/1/2 per customer), "code" (list of one conductor class per segment, from the record's catalog), "scale" (list of one positive impedance multiplier per segment), and "tap_steps" (number, in regulator steps). Optionally add "z_rx": a list of [R1_ohm, X1_ohm] per segment, which then overrides code/scale in the impedance part of the score. A pure function of one feeder record.
  • record is a dict with the feeder's network records and its AMI monitoring window — the same schema as the practice records, minus the truth field. Field-by-field documentation: data/practice/DATA_CARD.md.
  • Each call runs in a fresh process under a 300-second wall-clock budget (measured outside your process, with a 15 s grace and a hard kill at 330 s); over-budget, crashed or malformed outputs are scored as the worst case for that feeder.
  • Evaluation budget as a whole: the evaluation runs your method once per assessment feeder, serially, inside a 10800-second wall-clock cap for the entire scoring pass, on 2 CPUs and 512 MB of memory. The assessment fleet is 16 feeders — 1.33× the 12 practice feeders you have — and its members are on average larger (more customers and more segments) than the practice ones. Budget your per-feeder cost accordingly: 16 feeders that each burn the full 300 s do fit, but nothing beyond that does.
  • CPU only, no network. Runtime: Python 3 with numpy, scipy and the OpenDSS engine (import opendssdirect); you may run as many forward power-flow solves as the budget allows. Your own container has 2 CPUs / 1024 MB. /dev/shm is only 64 MiB on both sides, so a multiprocessing / joblib design that passes large arrays through POSIX shared memory will create the segment successfully and then die with SIGBUS on the first write — size any such buffer accordingly. BLAS/OpenMP thread counts are pinned to the same constant on both sides, so a timing you measure with selfcheck.py transfers to the evaluation.
  • Only files under methods/ are collected and re-run: keep everything calibrate() imports inside methods/main/. Do not modify data/, selfcheck.py or run_solver.py.
  • Return plain python types (ints/floats/lists); numpy arrays are fine for z_rx rows, but every value must be finite and code entries must come from the record's catalog. A malformed return is scored as the worst case for that feeder.

What You Have

  • data/practice/instances.json — 12 practice feeders with complete as-operated truth (actual per-customer phases, per-segment conductor classes and impedance multipliers, actual tap), documented in data/practice/DATA_CARD.md. This is your only labeled data; study it in full.
  • data/assessment/records.json — the 16 assessment feeders your method will actually be judged on: same monitoring protocol, no truth. They are unseen feeders drawn from the same population as the practice fleet (a subset weighted toward its hard end: the largest networks and longest segments the population produces).
  • methods/main/solver.py — the inherited starting method: voltage- trace similarity grouping for metered phases, records-as-shipped impedances, and a tap estimate from the average voltage offset of an OpenDSS replay (methods/main/dss_forward.py is its forward engine; python3 methods/main/dss_forward.py runs a round-trip demo). It carries a real signal but is far from what the records support; its level is also the floor you must clearly beat before the evaluation awards any credit.
  • python3 selfcheck.py — free and unlimited: scores your current methods/main/solver.py on the practice fleet against its truth and prints per-feeder component scores and the mean.

What You Submit

Leave your best methods/main/solver.py (plus any helper files it needs inside methods/main/) in place. There is no submit step and no feedback from the assessment fleet: whatever sits in methods/main/ at the end is what the evaluation re-runs.

How It Is Judged

The evaluation re-runs your calibrate() once per assessment feeder, on records byte-identical to data/assessment/records.json, and compares your output to the sealed as-operated truth. Per feeder it computes a score in [0, 1] (HIGHER is better): 0.45 × phase score (label accuracy over metered customers, rescaled so that copying the shipped GIS labels scores 0 and perfect labeling scores 1) + 0.40 × impedance score (how much your cumulative substation-to-customer positive-sequence R and X — the quantity a voltage-drop study consumes — improves on the records as shipped, measured by log-error norm and clipped to [0, 1]) + 0.15 × tap score (1 − |tap step error| / 4, clipped). Returning the records as shipped scores exactly 0 — selfcheck.py computes the identical per-feeder score on practice. Feeder scores are averaged within each assessment group (f00f07 and f08f15), then across the two groups. Your reward rises monotonically with that sealed mean; at or below the shipped starting method's level it is zero.

Metric

mean per-feeder calibration score over the 16 sealed feeders · higher is better

0.45*phase + 0.40*impedance + 0.15*tap per feeder, averaged inside each group then across the two groups

anchorvisible setheld-outreward
Bshipped first-pass script0.4330.5383910.00
Rreference solution0.47410.5776860.30
Sexpert solution (sota)0.73590.7621590.60
Uperfect recovery (structural)1.01.01.00
normalisation
m <= B0
B < m <= R0.3 * (m - B) / (R - B)
R < m <= S0.3 + 0.3 * (m - R) / (S - R)
S < m <= U0.6 + 0.4 * (m - S) / (U - S)
m > U1

m = this run's held-out metric  ·  B = shipped first-pass script  ·  R = reference solution  ·  S = expert solution (sota)  ·  U = perfect recovery (structural)

Linear in the raw metric: it is already a bounded [0,1] composite. Feeder scores are averaged first, then the fleet mean is mapped once.

Rollouts

166 minwall clock
$33.47spend
47.2Mtokens
28versions, 20 kept
0.4 0.5 0.6 0.7 0.8 0.9 $0 $7.5 $15 $22 $30 cumulative spend on the run practice-fleet mean self-check score, higher is better expert solution · visible · 0.7359 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 v25 v26 v27 v28 v29 v30 v31
keptrevertedno scoreturning point
  1. v0Inherited starter: spectral voltage grouping, shipped impedances, mean-offset tap0.4331 min · $0.21
  2. v1Leave-one-out median phase prototypes with a correlation-margin GIS prior0.5088 min · $0.87
  3. v2OpenDSS finite-difference line inverse, R/X shrinkage via z_rx, joint tap fitStop shipping the recorded impedances: invert path R and X from the replay residual, the 0.40 component the starter scored 0 on.0.624124 min · $2.85
  4. v3Ensemble robust and spectral traces with a greedy pairwise physics candidateGet phases from physics, not trace similarity: propose swaps that cut the replay residual and select on the full window.0.742940 min · $5.27
  5. v4Linearized screening of adjacent conductor substitutions under a sparse prior0.778750 min · $7.59
  6. v5Beam width 3 instead of greedy width 1 for pairwise physics phasesphase scores only56 min · $8.51
  7. v6Second finite-difference relinearization after discrete conductor selectionimpedance only56 min · $8.75
  8. v7Two-day out-of-time code ranking, averaged 50/50 with the full-window model0.789666 min · $10.53
  9. v8Round the joint tap to the regulator step grid and clip to nameplate rangeprojected 0.790570 min · $11.36
  10. v9Physics-trace hybrid; within noise sigma prefer the candidate fixing more labelsBreak replay ties by label parsimony: among candidates inside the noise sigma, take the one correcting more metered phases.0.838980 min · $13.56
  11. v10Metered-only hybrid that resets unmetered phase compensationprojected 0.853782 min · $14.21
  12. v11Use the two-day conductor model directly instead of averaging with the MAP0.863188 min · $15.68
  13. v12Cap near-tie phase candidates at the 14% population error target0.8631101 min · $19.70
  14. v13Make the phase-count cap a near-tie guard only, not a hard bound0.8631102 min · $20.12
  15. v14Signed continuous-scale outliers as extra adjacent-code proposalsimpedance only104 min · $20.62
  16. v15Sweep the shared feeder-scale prior from 0 to 1x the local ridgeimpedance only104 min · $20.92
  17. v16Screen every catalog class, charging 2 noise variances per extra step0.8631106 min · $21.65
  18. v17Allow a third conductor change behind a +15 noise-variance hurdle0.8631107 min · $22.26
  19. v18Infer missing-customer load shape from head_p by quadratic loss correctionimpedance only109 min · $22.77
  20. v19End-to-end re-verification of the broadened search and third-change path0.8631116 min · $23.24
  21. v20Reconcile unmetered profiles to head_p using simulated feeder lossesimpedance only125 min · $24.62
  22. v25Weak N(1, 0.10^2) feeder-mean multiplier prior on the day-CV selectorimpedance unchanged132 min · $25.89
  23. v26Tempered local multiplier prior added to break close conductor CV ties0.8659139 min · $27.33
  24. v27Freeze the two-span base inside the guarded third-change loop0.8659151 min · $30.10
  25. v28Greedy extension to five changes, +15 variances per span beyond twopractice unchanged154 min · $30.66
  26. v29Metered-only hybrid plus one separately inferred unmetered phase0.8659161 min · $32.38
  27. v30Bonus for conductor pairs sharing a replacement class, swept 1-25 variancesimpedance only165 min · $33.15
  28. v31Final audit: practice re-run plus all 16 assessment contracts checked0.8659166 min · $33.39

v0-v11 reached 0.8631 in 88 minutes for $15.68; the remaining 16 versions added 0.0028 on practice and cost $17.79.

On the hidden set

held-out metricreward
shipped first-pass script0.5383910.00
reference solution0.5776860.30
expert solution (sota)0.7621590.60
perfect recovery (structural)1.01.00
this run0.6913640.4849