Skip to content

feat(operators): a window may stop at each group's edge - #1260

Merged
FBumann merged 1 commit into
mainfrom
feat/window-partition
Aug 25, 2026
Merged

FBumann merged 1 commit into
mainfrom
feat/window-partition

Conversation

@FBumann

@FBumann FBumann commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Prompt: "Then we stack the feature PR ontop"

Follows #1258, which merged while this was being written — so it is against main rather than stacked.

Note

The following content was generated by AI.

sum_back(x, over=t, within=w, by=lookup) builds on both lanes, so the refusal
#1258 added comes straight back out. Positions are counted inside the group the
lookup makes: a window at the first hour of a representative day reaches back
over that day's own hours and stops there.

What it takes

the call what it builds
sum_back(started, over=t, within=3, by=day_of) the last three hours of that hour's own day
…, by=day_of, edge='wrap' the wrap closes on the group's size, not the axis's
within=up with up over day one window length per day, read through the lookup
an hour day_of places nowhere reaches nothing, itself included — the row is not built

That last row is the one behaviour a window did not have before: unpartitioned
it always contains the position it sits at, so every row is built.

How

Both lanes already walk a partitioned shift, and the window walks it the
same way — the relational lane ranks the dim table inside each group and joins
the landing position back on (group, position); the eager lane gathers each
lag through _gather_in_groups. What was inline in translate_fragment is now
_walked and _named_amount, read by both operators, so the rank, the span and
the per-group key rewrite have one home rather than two.

The one thing that is not shared: a per-group width has to go through
_per_group on the eager lane before the within > lag comparison, or it
broadcasts the constraint onto the group's dimension — measured, the eager
constraint came back as [t: 6, day: 2] against the relational lane's six rows.

Verified

  • suite 3106 passed, 249 skipped, 1 xfailed; sweep at depth 3 2782 passed.
    The 35 failures are xpress-parametrised and pre-existing on this machine
    (the Community licence), red on main too.

  • ruff check · ruff format --check . · pyrefly 0 errors.

  • test_both_lanes_read_every_keyword_the_language_declares is narrowed as
    build(deps): a rule the language now enforces has one home again #1258 said it would be: _call's interception is credited only to the
    operators it spells out by name, so an eager operator that ignores a keyword
    the lowering builds is red. That is what the guard was measured missing.

  • mutation table:

    mutation result
    the group-less coordinate keeps no row (reindex.py:133-137) caught
    a wrap closes on the group, not the axis (reindex.py:110-111) caught
    a per-group width is read through the lookup (operators.py:229) caught

Deliberately not done

  • No port uses it yet. The construct arrived from math-spec, not from a
    model in examples/; the representative-day case that wants it is
    pypsa_min_up_down under time-series clustering, which this repository does
    not carry.
  • shift's stray-dim case with a partition still has no test in math-spec
    (noted on build(deps): a rule the language now enforces has one home again #1258); this PR does not add one there.

`sum_back(x, over=t, within=w, by=lookup)` builds on both lanes. Positions are
counted inside the group the lookup makes, so a window at the first hour of a
representative day reaches back over that day's own hours and no further, and a
width declared over the group's dimension is read through the lookup — one
window length per day, per season, per scenario.

Both lanes walk a partition the same way they already walk a shift's: the
relational one ranks the dim table inside each group and joins the landing
position back on `(group, position)`; the eager one gathers each lag through
`_gather_in_groups`. `_walked` and `_named_amount` are what the two operators
now share, a translation having had both inline.

An hour the lookup places in no group reaches nothing at all, itself included,
which is the one way a window loses a row it would otherwise keep.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 lpspec | 🛠️ Build #34218808 | 📁 Comparing 94d6ad2 against latest (95b3896)

  🔍 Preview build  

1 file changed
± about/linopy/index.html

@codspeed

codspeed Bot commented Aug 25, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 16 untouched benchmarks
⏩ 42 skipped benchmarks1


Comparing feat/window-partition (94d6ad2) with main (64b994f)2

Open in CodSpeed

Footnotes

  1. 42 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

  2. No successful run was found on main (95b3896) during the generation of this report, so 64b994f was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@FBumann
FBumann enabled auto-merge (squash) August 25, 2026 06:42
@FBumann
FBumann merged commit 027345c into main Aug 25, 2026
7 checks passed
@FBumann
FBumann deleted the feat/window-partition branch August 25, 2026 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant