{"data":{"kind":"file","path":"README.md","version_id":"n0dx6km4batwsfidaxr10vjx","entry":{"name":"README.md","path":"README.md","is_directory":false,"size":8214,"modified_at":"2026-07-07T19:02:36.409000","content_hash":"5248198e452bf904769d0a192f04559e1ed749973cfb6a337e2b407eecff539e"},"entries":[],"content":"# n1-contingency-dispatch\n\nN-1 security-constrained DC-OPF RL environment. Fourth rung of a power-systems vertical ([economic-dispatch](https://github.com/JWilksBooth/economic-dispatch) → [dcopf-grid-verifiers](https://github.com/JWilksBooth/dcopf-grid-verifiers) → [multiperiod-dispatch](https://github.com/JWilksBooth/multiperiod-dispatch) → this). The skill axis is **security**: the dispatch must survive the outage of *any* single non-islanding transmission line, with post-contingency flows within emergency ratings. The naive answer this environment defeats is precisely the previous congestion environment's *correct* answer — the ordinary DC-OPF optimum, which leans on fully-loaded corridors that have no margin left when a parallel line trips. Measured: **68% of instances make the plain OPF optimum insecure.**\n\n## Task\n\nGiven a meshed network (lines with reactance, normal rating, emergency rating), generators, and loads: output `{\"dispatch_mw\": [...]}` minimizing cost such that (1) the base case is feasible at normal ratings, and (2) for every single-line outage that leaves the network connected, the *same* dispatch remains feasible after DC power flow reroutes — every surviving line within its emergency rating (preventive SCOPF).\n\n## Ground truth validation\n\nTwo **independently formulated** solvers must agree — different variable spaces *and* different algorithms. Both legs still solve their LPs with scipy/HiGHS, so this is cross-implementation validation (different formulations, one solver engine), not independent-solver validation — stated plainly, the same standard the sibling LP-pair envs disclose:\n\n- **Primary:** monolithic security-constrained LP in angle space — variables `[P, θ⁰, θ¹…θᴷ]`, one angle block per contingency state (scipy/HiGHS).\n- **Cross-check:** injection-space solver using per-contingency **PTDF matrices** and iterative **constraint generation** (solve, find violated contingency constraints, add as cuts, repeat), written from scratch with no shared assembly code — its inner LPs are still solved by scipy/HiGHS.\n\n| Metric (200 instances, seeds 0–199) | Result |\n|---|---|\n| Objective mismatches (>0.1% rel and >$1/h abs) | **0 / 200** |\n| Worst relative objective gap | 1.4e-14 |\n| Constraint-generation non-convergence | 0 (test fails if >2%) |\n| Plain N-0 OPF optimum insecure (violates ≥1 contingency) | **135 / 200 (68%)** |\n| Median security premium (binding subset) | 5.2% |\n| Mean non-islanding contingencies per instance | ~9 |\n\n## Rewards (weighted rubric)\n\n| Reward | Weight | Description |\n|---|---|---|\n| `reward_format` | 0.10 | Parseable JSON, correct arity, finite values only |\n| `reward_base_feasibility` | 0.20 | Positive-proof: balance, gen bounds, base flows at normal ratings |\n| `reward_security` | 0.25 | Fraction of contingencies survived at emergency ratings (gated on base feasibility) |\n| `reward_optimality` | 0.45 | `exp(−5·|gap|)` vs the SCOPF optimum — **hard-gated on full N-1 survival**: a cheaper dispatch that fails even one outage scores 0 |\n\nAnti-reward-hacking, factory standard (6 regression-tested attack gates): the *insecure-cheap* attack (submitting the plain OPF optimum — cheaper and base-feasible — earns optimality 0.0), `NaN`/`Infinity` literals, >4300-digit integers and bracket bombs (rejected, never crash), and tolerance-rent (violations inside the ±0.5 MW grading tolerance settled at 2× the highest offer, below-optimum cost penalized symmetrically).\n\n## Example failure (claude-haiku-4-5, saved 50-instance eval run)\n\n> *\"After iterative feasibility checks on the most critical single-line outages (particularly Line 0, 4, 5, 6, 14 which form critical paths) ... Verification check on critical scenarios confirms this maintains: ... All single-line outages with emergency ratings: ✓ ... {\"dispatch_mw\": [180.0, 165.0, 84.3]}\"*\n\nThe base case is feasible and the model *claims* full N-1 verification — but it only spot-checked \"critical scenarios,\" and it even names line 0 among them before failing exactly that outage. Its cheap unit injects 180 MW at bus 1, which has only two outlets: when line 0 (bus 0–1) trips, the full 180 MW must leave over line 5 (bus 1–6) against a 150.5 MW emergency rating. Security **16/17**, optimality hard-gated to **0** — and at $25,107/h this \"conservative\" dispatch is dearer than the SCOPF optimum ($23,220/h): it paid for security it didn't get.\n\nFrom a saved `vf-eval n1-contingency-dispatch -p anthropic -m claude-haiku-4-5-20251001 -n 50 -r 1 --max-tokens 8000 --save-results` run. Rollouts are stochastic; the graded verdict is deterministic:\n\n```python\nimport n1_contingency_dispatch as env\ninst = env.generate_instance(33)   # the instance behind example 33, regenerated exactly\nenv.check_security(inst, [180.0, 165.0, 84.3])\n# -> (16, 17, ['outage of line 0: line 5 at 180.0 MW > emergency rating'])\nsum(p * g[\"cost\"] for p, g in zip([180.0, 165.0, 84.3], inst[\"generators\"]))  # -> 25107.24\nenv.solve_scopf(inst)[\"cost\"]                                                 # -> 23219.52\n```\n\n## Baseline\n\nHaiku 4.5, 50 examples, 1 rollout each (reproduce with the `vf-eval` line\nbelow):\n\n| Metric | Haiku 4.5 |\n|---|---|\n| Mean reward | **0.382** |\n| Format | 1.000 |\n| Optimality (hard-gated on full N-1 security) | 0.217 |\n| Errors / truncations | 0 / 0 |\n\nHonesty notes: two clean 50-rollout Haiku runs exist — 0.382 and 0.333 —\nsingle-rollout runs at differing token budgets carry meaningful variance, and\nthe ladder quotes the run matching the published 16k-token eval line. The\nfailure mode is the one in the example above: the model *claims* full N-1\nverification, spot-checks a few \"critical\" outages, and is caught by the\nexhaustive per-outage security gate. An Opus 4.8 baseline is **not published**:\nthe saved Opus runs are error-storm partials (33–38/50 API errors at high\nconcurrency — the run that taught this portfolio its concurrency-2-3 rule) and\npublishing numbers from error-riddled runs is not the house style; a clean\nretry is queued.\n\n## Usage\n\n```bash\npip install -e .\nN_INSTANCES=200 python tests/test_validation.py   # dual-formulation cross-check + attack gates\npython calibration/measure.py --n 300             # difficulty distribution sweep\n\n# give frontier models room to reason; -r 1 matches published baselines\nvf-eval n1-contingency-dispatch -p anthropic -m <model> -n 50 -r 1 --max-tokens 16000\n```\n\n```python\nimport verifiers as vf\nenv = vf.load_environment(\"n1-contingency-dispatch\", num_examples=300)\n# disjoint train/eval: load_environment(1000) + load_environment(200, seed_offset=1000)\n```\n\n## Instance generation\n\nMeshed random networks (spanning tree + loops, 4–8 buses, extra-edge probability 0.35 — N-1 only bites where parallel paths exist), tiered baseload/mid/peaker costs, ~9 non-islanding contingencies per instance. **Line ratings are anchored to duty**: normal ratings to each line's flow under a nominal proportional dispatch (tight draws at 1.05–1.35×, loose at 1.8–3×), emergency ratings to the line's *worst N-1 duty* (tight 1.02–1.20×) — so ratings correlate with usage the way real thermal ratings track expected duty, and the nominal dispatch is N-1 secure by construction (draw rejection 7.7%, no survivor bias; see [CALIBRATION.md](CALIBRATION.md) for the two rating constructions the metrics rejected). Non-islanding screening only, as in real N-1 practice for radial taps. Fully deterministic per seed.\n\n## The vertical\n\nmerit order → congestion (space) → ramps (time) → **N-1 security (uncertainty)** → [price formation (LMP)](https://github.com/JWilksBooth/nodal-pricing-lmp). Next: unit-commitment / non-convex pricing.\n\nEnergy siblings: [economic-dispatch](https://github.com/JWilksBooth/economic-dispatch), [dcopf-grid-verifiers](https://github.com/JWilksBooth/dcopf-grid-verifiers), [multiperiod-dispatch](https://github.com/JWilksBooth/multiperiod-dispatch), [nodal-pricing-lmp](https://github.com/JWilksBooth/nodal-pricing-lmp). Robotics vertical: [robot-cycle-time](https://github.com/JWilksBooth/robot-cycle-time), [bimanual-chore-scheduling](https://github.com/JWilksBooth/bimanual-chore-scheduling).\n","encoding":"utf-8","truncated":false,"total_bytes":8214},"status":null}