Two tests were spinning up real CBC solves over 96-half-hour windows
with long runs of exactly-repeated prices (e.g. [0.0] * 40). That gives
the LP relaxation a huge set of economically indistinguishable ways to
spread a trade, which the MILP fallback's branch-and-bound then wastes
enormous effort disambiguating (47k+ nodes without closing the gap,
confirmed by running CBC verbosely). Real Attachment 2 data has no such
flat runs and solves in ~0.1s/window; a synthetic sine wiggle wasn't
enough either, since neighbouring half-hours stayed too similar.
Fixes, matched to what each test actually needs:
- The 9 validator tests only need *some* structurally valid schedule to
mutate; they were deriving it by running the real optimiser once per
test. Replaced with make_valid_schedule(), built directly from the
model's own energy-balance formulas -- no solver involved, and it's
now a true unit test of validate_schedule() in isolation.
- The rolling-horizon carry-forward test was exercising the mechanism
at full production scale (48h window / 24h commit) when a 2h/1h
window proves the same boundary-carrying behaviour with a trivial
MILP, regardless of price structure.
- Fixed a genuine tie in test_optimum_uses_whichever_market_pays_more:
two equal-price hours with just enough stored energy for one meant
either market was a valid optimum. Sized the charge phase so delivery
must split across both hours, pinning a unique answer.
Full suite: 38 passed in ~1.3s (previously hung indefinitely on CI and
locally within seconds of the same wall-clock variance CBC shows on
degenerate MIPs).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implements the package from PLAN.md: config/data loading, the LP-first
MILP-fallback rolling-horizon optimiser, battery degradation tracking,
independent schedule validation, metrics, plots and the CLI, plus the
matching test suite. Adds a Gitea Actions workflow (lint + tests) that
posts a pass/fail notification to ntfy on every run, and a .gitignore
for build/cache artefacts that had been tracked by mistake.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Commits the three source documents for the battery trading exercise
(task brief, battery specification, and three years of half-hourly
Market 1 and hourly Market 2 prices) together with PLAN.md, the
implementation plan for the dispatch model.
The plan covers a rolling-horizon MILP on the half-hourly grid with a
48-hour lookahead and 24-hour commitment, solved with PuLP/CBC, plus
degradation and cycle-life reporting, an independent schedule
validator, charts and tests.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>