feat(language): a piecewise where reaches a link that walks a relation, so only some converters need a curve - #635
Merged
FBumann merged 5 commits intoSep 23, 2026
Conversation
…sion, and composition is a limit on the file (#624)
Co-authored-by: energy-models-release-please[bot] <319464627+energy-models-release-please[bot]@users.noreply.github.com>
…at() `at(<predicate>, by=<relation>, over=<a>, into=<b>)` reads a mask over coarse coordinates at fine ones, as `at` reads an array: true where the relation has a row and the predicate holds at the coordinate it maps to, false where the relation has no row. It is the third operator that reads a predicate, beside `shift` and `count`, and is held to the rules of the expression `at`, so a bad read is refused in the same words in both. The program carries it as `PulledBackPredicate`: the operand mask, the `Direction`, and the dims after the read. `names_read` includes the relation. Exclusivity refuses it in a case `when:` as undecidable, as it refuses `shift` and `count`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxoXSQCyrcDs6vuRk3x6tz
…n, so only some converters need a curve A walked link's row is over the dims the walk produces, and the block's `where:` is over `dims:`. The row now reads the mask through the link's relation, `at(<where>, by=…, over=…, into=…)`, where the mask carries every dim the walk consumes or joins on, and as written where it carries none of them. A mask carrying some and not the rest is refused, naming the missing dims. The refusal of a block `where:` beside a walk is gone. A walked link's values are asked for at the rows it reads the curve at, under `<block>_<link>_complete`, so a flow of a converter with no curve needs no breakpoint row. `<block>_complete` keeps the links on `dims:`. `examples/piecewise_coupling.yaml` is now fluxopt's system: a CHP on a curve beside a fixed-ratio boiler, one `has_curve` read both ways. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxoXSQCyrcDs6vuRk3x6tz
Documentation build overview
23 files changed ·
|
Contributor
Author
Note The following content was generated by AI. Closed in favour of #630, which now carries this PR's commit. #630's branch was fast-forwarded to this branch's head Generated by Claude Code Generated by Claude Code |
26 of 37 tasks
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.
What this changes
Stacked on #630, with #634 merged in. A block
where:now reaches a walked link. The row reads the mask through the link's relation, so a converter with no curve gets no weights, no binaries and no rows, and its flows need no breakpoints.The expansion writes this row:
The rules
at(<where>, by, over, into). A ragged mask goes through asat(count(<where>, over=bp) > 0, …), as the rows overdims:alone take itsnapshotonly)where 'curved' carries ['generator'] and not ['snapshot'], and the link reads the curve through 'generator_of' at all of […]The completeness check splits.
<block>_completecovers the links ondims:. Each walked link states<block>_<link>_complete, which asks for its values only at the rows it reads the curve at: under the mask read through the relation, or where the relation has a row when there is no mask. Asked with the other links,bp_ratewas demanded at every flow, including flows of converters with no curve. The per-link name is reserved like the other derived names.examples/piecewise_coupling.yamlis fluxopt's mix. A CHP on a curve sits beside a fixed-ratio boiler, and onehas_curveis read both ways: the curve reads it, andfixed_ratioreadsNOT at(has_curve, …).Guard table: each guard deleted in turn, whole suite run, tree restored
wherethrough its relationtest_a_block_mask_reaches_a_walked_link_through_its_relationtest_a_mask_over_dims_the_walk_keeps_reaches_the_walked_row_as_writtentest_a_mask_carrying_part_of_what_a_walk_reads_through_is_refused…asked_only_at_the_rows_it_reads_the_curve_at[a-mask-read-through]…[no-mask-asks-only-where-the-relation-reaches]test_a_walked_links_own_condition_is_a_name_the_block_reservesCoverage moved:
test_a_block_mask_that_cannot_reach_a_walked_link_is_refusedasserted the refusal this PR removes. Its case is nowtest_a_block_mask_reaches_a_walked_link_through_its_relation.Gates, and what was not run
pytest -q -n autoruff,prettier,typos,reuse lintpyrefly checkmkdocs builddocs.python.orginventory fetch fails (proxy 403)compile-tex,pixi run ciDeliberately not done
where:per link. With the block mask reaching walked rows, and one relation per role for a subset of flows, no model asks for one yet.at()in awhere:. The diff against feat(language): a piecewise block states its dims and names its links, and its where reaches links that walk a relation #630 shows feat(language): a where may read a predicate through a relation with at() #634's commit until feat(language): a where may read a predicate through a relation with at() #634 reaches feat(language): a piecewise block states its dims and names its links, and its where reaches links that walk a relation #630's base.Why
fluxopt mixes converters on a curve with converters at a fixed ratio. Before this, a walked block built a curve and its binaries for every converter in
dims:, and demanded breakpoint rows for every flow.🤖 Generated with Claude Code
https://claude.ai/code/session_01HxoXSQCyrcDs6vuRk3x6tz
Generated by Claude Code