Skip to content

Commit a92be43

Browse files
jkiviluoclaude
andcommitted
release: v4.0.0b19 — retiring-unit existing-map read + Benders cut-tolerance fix
Bundles two independent fixes landed on main since b18: - fix(unitsize): read retiring `existing` Map by per-period MAX, not last row - fix(benders): key cut self-check tolerance to row scale, not cancelled rhs No schema migration (stays v62); dependency floors unchanged (polar-high>=3.2.0). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f1ad731 commit a92be43

2 files changed

Lines changed: 49 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,51 @@
1+
## Release 4.0.0b19 (1.7.2026) — retiring-unit `existing` map read + Benders cut-tolerance fix
2+
3+
No database migration (schema stays **v62**) and dependency floors unchanged
4+
(`polar-high>=3.2.0`, `polars>=1.40`, `highspy<=1.14.0`). Two independent
5+
fixes: one corrects an output/dispatch parameter for retiring units; the other
6+
removes a spurious hard-failure in the spatial-Benders decomposition solver.
7+
8+
### Outputs / dispatch
9+
10+
- **Read a retiring unit's `existing` capacity by the per-period MAX, not the
11+
last row.** `_entity_unitsize_lf` gated the `existing`-map cascade input on
12+
`"period" in columns`, but Spine names a Map's index column with its
13+
silent-default `"x"`, so the gate never matched and every period row fell
14+
through to a `unique(keep="last")` that kept the *last* period's value. For a
15+
unit whose `existing` map decays to `0` at expiry, that collapsed the cascade
16+
input to `0`, defaulted `unitsize` to `1000`, and turned
17+
`existing_count = existing/unitsize` into a spurious fraction — capping
18+
continuous online at that fraction and making integer online impossible to
19+
commit. The reader now takes the per-entity MAX over whatever period rows
20+
exist, index-name-agnostically (CLAUDE.md Invariant #2). Byte-identical for
21+
scalar `existing` (a single-row group-by is a no-op) and for every existing
22+
test fixture; corrects the reported online/count for retiring-unit models.
23+
Adds regression tests in the silent-default-index coverage file and a dev-doc
24+
audit of the readers that live outside the `_param_shapes` resolver.
25+
26+
### Decomposition (Benders)
27+
28+
- **The spatial-Benders cut self-check no longer hard-fails on solver
29+
round-off.** After each master solve, `_check_cuts_satisfied` asserts every
30+
just-appended optimality cut is honoured at the new master point. That check
31+
re-derives a row already present in the master LP, so it can only differ from
32+
the solved value by the solver's feasibility tolerance — which HiGHS measures
33+
on its internally-scaled matrix, making the *unscaled* slack scale with the
34+
cut row's coefficient magnitude, not its right-hand side. On early iterations
35+
a node group whose recourse cost overshoots produces large reduced-cost
36+
slopes, so `cost_r` and `Σ slope·f̄` nearly cancel: the rhs collapses to `O(1)`
37+
while the coefficients stay at `O(1e6)`. The old tolerance keyed off the
38+
cancelled rhs and demanded a precision the ill-conditioned row cannot deliver,
39+
aborting an otherwise-converging solve (observed on a 7-node-group hydrogen-
40+
trade model: a `7e-4` slack on a `2.66e6`-scale row — `2.7e-10` relative). The
41+
tolerance is now keyed off the row magnitude, matching the fail-safe design of
42+
the sibling flow-clamp / lower-bound / sandwich guards: numerical noise is
43+
absorbed, a moderate gap is warned, and only a gross violation (a genuinely
44+
un-appended cut, whose recourse estimate sits near its large-negative floor)
45+
still hard-fails — now with the same three-section plain-English diagnostic as
46+
the other guards. The affected model converges to the monolith objective
47+
within tolerance.
48+
149
## Release 4.0.0b18 (30.6.2026) — fix zeroed existing capacity for scalar+Map entity classes
250

351
No database migration (schema stays **v62**) and dependency floors unchanged

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "flextool"
77
# restructure are in. 4.0.0 final follows after the remaining
88
# minor-functionality additions, cleanup and testing land. PEP 440
99
# pre-release suffix: 4.0.0a1, 4.0.0a2, ... 4.0.0b1, 4.0.0rc1, then 4.0.0.
10-
version = "4.0.0b18"
10+
version = "4.0.0b19"
1111
description = "IRENA FlexTool is an energy and power systems model for understanding the role of variable power generation in future energy systems."
1212
readme = "README.md"
1313
license = { file = "LICENSE.txt" }

0 commit comments

Comments
 (0)