feat(language): a model states its topology as relations, the way math-spec 0.0.0-alpha.89 does - #1646
Merged
Conversation
…h-spec 0.0.0-alpha.89 does The pin moves to v0.0.0-alpha.89, where `lookups:` became `relations:`: a table with one column per dimension it relates and a `key:` saying which columns identify a row, walked in whichever direction the call names. Both lanes read the new plan — `Walk` on every `by=` node, the relation predicate nodes, and `shift`/`sum_back`'s renamed `along=`/`window=` keywords — and the models, examples, ladder rungs and pages are written in it. Either lane builds the single-valued map the old lookup was: two columns, one of them the key. `lpspec.relations.refusal` turns away a wider table at `lowered`, so check, build and an archive refuse the same file, and the message names the rewrite its shape asks for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RuEnfVdQZKP2fxRWrgJRH1
Merging this PR will not alter performance
Comparing Footnotes
|
Documentation build overview
58 files changed ·
|
…ather than a field it lost `prepared` read `relation.over` and the projection read `lk['over']`/`lk['into']`, which a `RelationBlock` no longer carries: its columns are `columns:` and the side that is one is `key:`. The runner now cuts a relation's table by its key roles and keeps the dimensions its columns name, so every rung prepares again. The rung projections are regenerated, and the ladder pages that embed them with them. `references.json` and the written tables are byte-identical, so no objective, dual or structural comparison moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RuEnfVdQZKP2fxRWrgJRH1
fluxopt-release-bot Bot
added a commit
that referenced
this pull request
Sep 15, 2026
🤖 I have created a release *beep* *boop* --- ## [0.0.1-alpha.334](v0.0.1-alpha.333...v0.0.1-alpha.334) (2026-09-15) ### Features * **language:** a model states its topology as relations, the way math-spec 0.0.0-alpha.89 does ([#1646](#1646)) ([1fd8926](1fd8926)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: fluxopt-release-bot[bot] <307443024+fluxopt-release-bot[bot]@users.noreply.github.com>
This was referenced Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
The following content was generated by AI.
The pin moves to
v0.0.0-alpha.89, whose one feature (#437) replacedlookups:withrelations:and renamed two operator keywords. Both lanes read the new plan; every model, example, rung and page is written in it.Either lane still builds the single-valued map the old lookup was — two columns, one of them the key. A wider table is refused at
lowered, socheck,buildand an archive refuse the same file.What the language change is
A relation is a table with one column per dimension it relates, and
key:names the columns a row is identified by. The declaration fixes no direction: the operator says which column it consumes and which it produces.shift(over=, …)becameshift(along=, …), andsum_back(over=, within=)becamesum_back(along=, window=).lookups: {gen_bus: {over: generator, into: bus}}relations: {gen_bus: {columns: [generator, bus], key: generator}}shift(soc, over=snapshot, offset=1)shift(soc, along=snapshot, offset=1)sum_back(started, over=hour, within=min_up)sum_back(started, along=hour, window=min_up)What moved in the source
relations.pyis new: the one reading of a declared relation —refusal, and the accessors that are well-defined once a wider table has been turned away. Documented in ARCHITECTURE's module table.WalkonGroupSum,At,Translate.partition,Window.partitionandDimensionPositionNode.partition;RelationComparisonNode,RelationPairComparisonNodeandRelationDefinedNodeinwhere.sources.pyreads a relation's table under its declared roles and hands on the(key dim, relation)frame both lanes already read, so a self-map supplies cleanly and no reader downstream changed shape. The checks are the ones it ran before: keys are labels, values are labels, one row per key, no null.lpspec.relations: its subpackage may import onlylpspec.errorsandmath_spec.program(hard rule 2), andWalkalready carries everything it askedDimensionDeclaration.targetsfor._Walk.of,_named_amountand_grouped_intotake the walk instead of a partition name, which drops acompiler.programlookup from_grouped_into.key:where it readlookup.over, and the projection keeps the dimensions a relation'scolumns:name. Second commit; it is whydifferential/is a separatechore.What I deliberately did not do
The new reach is not implemented. A bare relation, a key of several columns, a walk with a column joined on, and
within=on a partition are all refused rather than built. Following a pin is not the PR that grows two lanes a new join shape, and the refusal names the rewrite its shape asks for:Worth its own issue, since the relational lane is close:
_remap_fragmentalready trades tuples of dims, and a joined column is that join on more keys.Coverage that moved
test_a_hand_built_node_whose_tuples_disagree_is_refusedasserted a guard the new IR makes unreachable —GroupSumderivescoordinate,overandintofromwalks, so the two tuples cannot disagree. Thezip(strict=True)it certified is still there and still reachable, by the route that now exists: a walk onto two columns at once. It istest_a_hand_built_walk_onto_two_columns_is_refusedin the same file, with the same purpose in its docstring.tests/test_sum_by_lookups.pyistests/test_sum_by_relations.py.tests/test_assertions.py's ratchet falls 208 → 207.The new guard, deleted and re-run
relations.refusal's loop deleted, whole suite re-run:relations.refusal's shape loopIts complement,
test_the_map_the_wider_shapes_are_rewritten_to_is_the_one_that_loads, keeps the pair from passing by refusing everything.PyPSA parity
Every rung matches, and
references.jsonand the written tables come back byte-identical — so no objective, dual or structural comparison moved. The rung projections changed in layout only, because the first commit hand-edited files the harness generates; they and the ladder pages that embed them are regenerated by the harness and bytools.ladder.Run a second time on the regenerated tree with no further change, which is what the job's
git diff --exit-code -- differential/pypsastep asks.What was verified, and what was not
Every gate the required check runs, plus the docs build, the bench harness and the parity runner, on
14de16e:Generated output was regenerated by its own generator and the diff read:
tools.gallery_math(47 pages),tools.ladder(the ladder page and 16 rungs), the parity runner (references.json,rungs/,tables/),uv lock. The YAML fences the gallery pages carry byte for byte, and the two PyPSA referencebuild()fences, were refreshed from their files.Not run, and why.
pixiis not installed in this environment, so the gates ran in auvvenv on the pinnedruff==0.16.1andpyrefly==1.2.0rather than throughpixi run check. On an unpinnedpyrefly 1.3.1six errors appear, all inapi.py,frames.pyandassembly.py, none of which this diff touches. No benchmark was taken: nothing here claims a number, and the machine was not idle — CodSpeed reports the PR does not alter performance.🤖 Generated with Claude Code
https://claude.ai/code/session_01RuEnfVdQZKP2fxRWrgJRH1