Repository navigation
Conversation
…where:`, and outside them it is absent A parameter takes a `where:` mask in the condition grammar. Outside it the parameter is absent wherever it is read, a consumer drops the rows of its data there, and `missing:` applies only inside. A mask that reads a variable, its own parameter (directly or through other masks), or a dimension the parameter lacks is refused at load. The case check no longer assumes a masked parameter's fill outside its mask, and a bare int or str name of a masked parameter is a mask rather than a no-op. The typeset legend prints the mask beside the dimensions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113aUbLChfQVBrVR5FVQnJq
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113aUbLChfQVBrVR5FVQnJq
Documentation build overview
34 files changed ·
|
…hen applies to the coordinates it keeps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113aUbLChfQVBrVR5FVQnJq
…ds through a named condition is refused The golden model gains `link_eff`, masked by the bare relation `connection`, so each format's legend prints a mask and the LaTeX gate compiles it. The notation page is regenerated from it. Two refusal cases pin a mask that reaches a variable, or its own parameter, through a named condition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113aUbLChfQVBrVR5FVQnJq
This was referenced Oct 22, 2026
…masked parameters, so no two masks wait on each other A mask that reads a parameter with a mask of its own is refused, with the rewrite named. That replaces the search for a cycle of masks: with no masked parameter in any mask, no cycle can form. The reference page states the order: dimensions, then relations, then unmasked parameters, then masks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113aUbLChfQVBrVR5FVQnJq
…ensions, comes before every mask, and is checked by an assumption Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113aUbLChfQVBrVR5FVQnJq
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015MPR9MKVJ9XwN68qHLrX5g
FBumann
added this pull request to stack #952
October 23, 2026 12:14
This branch has not been deployed
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
A parameter takes a
where:mask. The mask comes first: outside it the parameter is absent, and its data rows there are dropped.missing:then applies to the coordinates the mask keeps. This gives #944's connection case with no multi-dimension. Stacked on #894.The connection case from #944, which loads on this branch:
where: connectionreads "a row exists".efficiencyhas coordinates only at the listed pairs,missing: 1fills only there, and a data row at any other pair is dropped.connection == 'output'reads the role column, for the role conditions in Datarecord alignment #944.Two connections of one entity to one bus (PyPSA/PyPSA#2015) do not fit a relation keyed by
(entity, bus), because a key has one row for each pair. Key the relation by port instead, with the bus as its value. The mask is still the relation's key, so the parameter is indexed by port:Two ports may name one bus. This also loads on this branch, and needs nothing beyond this PR.
The rule, the order of stages, the refusals, and the two load checks that changed
A parameter's coordinates are decided in two steps, in this order:
where:is a mask on thedims. It keeps the coordinates where its condition is true. At every other coordinate, the parameter is absent wherever it is read, and a row of the data there is dropped when the data is attached.missing:: it is refused, absent, or the valuemissing:names.missing:never reaches a coordinate that the mask leaves out. The reference page, the engine guide (reading.md), and the docs onParameterSpec.whereandParameter.whereall state this order.What a mask may read: the stages before it.
missing:is about the keywhere:A relation stays the authority on which combinations exist, and no parameter overrules it. A coverage rule on a relation is an assumption, a check rather than an authority. The parameters page states the order, and the relations page now states the other half: a relation reads only its dimensions, comes before every mask, and is checked by an assumption, such as
{holds: "line_to", where: "closed"}.Refused at load, each with its own test:
With no masked parameter in any mask, no two masks wait on each other, so no search for a cycle is needed. Every mask in #944 reads an unmasked flag, a named condition or a relation. A later PR can allow a mask to read a masked parameter, and no file that loads today would then be refused.
Two load checks assumed that a parameter has a row at every coordinate:
missing:names. Outside a mask, the parameter is absent and every comparison on it is false. So two cases that look disjoint under the fill value can both claim a coordinate there. For example, withmissing: 0, the casesNOT cost > -1andNOT cost < 1both hold wherecostis absent. A masked parameter now gives the check no fill value.intorstrname underrefusedwas refused as a no-op, because such a parameter "has a row at every coordinate". With a mask, the name is true only inside the mask, so it loads.The divisor check of #894 needs no change. Outside the mask, an absent divisor removes the row and is never
0. Inside the mask,missing: 0reads as it does today.Typesetting. The legend prints the mask beside the dimensions, in all three formats:$\mathcal{E} \times \mathcal{B} \times \mathcal{T}$ , only where $(e, b) \in \mathrm{connection}$ , $1$ where the data has no row. The golden spec gains
efficiencyoverlink_eff: { dims: [generator, bus], where: connection, missing: 1 }. Each golden output, and the notation page generated from that spec, gains exactly that one legend line. The golden spec is in thecompile-texcorpus, so CI compiles the LaTeX legend.Composition needs nothing new. A parameter is declared in one fragment only. A sibling reads it under
given:, which takes nowhere:and gives the case check no fill value.Mutation table
Each guard was deleted in turn, and the full suite was run. The file was restored with
git checkout --, and__pycache__was dropped before and after each run. The tree came back clean. Taken onb062e0f. The later commitff91d15changes the relations page only.test_a_parameter_mask_that_nothing_can_evaluate_is_refused[a-mask-that-reads-a-variable],[…-through-a-named-condition][a-mask-that-reads-its-own-parameter],[…-through-a-named-condition],[a-mask-that-reads-a-masked-parameter],[two-masks-that-read-each-other][a-mask-over-a-dimension-the-parameter-lacks]intorstrname is not a no-optest_a_bare_parameter_whose_answer_needs_the_data_loads[a-masked-int]test_a_masked_parameter_is_not_read_as_its_fill_outside_the_masktest_the_legend_says_where_a_parameter_has_coordinates[latex],[markdown],[typst], the golden outputs, and the notation pageGates
On the head,
aa9ca2c, which merges #894's branch aftermain(0.4.0, #931, #946, #947) went into it. The merge had no conflict. With pixi:pixi run lintpasses.pixi run testpasses: 3120 passed, 1 skipped.pixi run docs-buildpasses.compile-texfailed on every document because the container could not download the TeX bundle. CI runs it.With #949. A trial merge of #949 (the case-check fixes) into #948's head conflicts only in
CHANGELOG.md, andpytestgives 3143 passed, 1 skipped on the combined code.Earlier, on
ff91d15, in a uv venv on Python 3.13 with the pinnedruff==0.16.1,pyrefly==1.2.0andzensical==0.0.63:pytest3108 passed, 3 skipped. The schema (python -m tools.schema), the golden outputs (python -m tests.typesetting.golden) and the notation page (python -m tools.notation) were regenerated, not edited.python -m mathspec checkloads both YAML blocks above, the YAML on the reference page, and theline_toassumption on the relations page.Open questions, and what was not done
For review: filter or refuse. A data row outside the mask is dropped, not refused. This is what mask means in the glossary, and the targets in #944 need it:
p_nom_max: { where: "p_nom_extendable" }, with PyPSA data that givesp_nom_maxfor every generator. A file that wants such a row to be an error states it once as an assumption,{holds: "connection", where: "efficiency"}. The reference page says so.Not done:
missing:inside. That is a separate PR in fluxopt/specsolve. Until then, this spelling loads and typesets, but it does not solve.where:on a relation. A relation is the stage a mask reads, so it takes none.-1on a link's input bus.missing: 1gives every connection the same fill, so the-1comes from the data or from a two-case expression (Casedmissing#940).points:withmissing: refusedstill ignores a mask. That refusal stays on the safe side, and a file can declareabsent.mainand in this branch. fix(language): the case check reads a comparison on a relation as false where the relation has no row #949 makes the case check follow it.Departures from AGENTS.md:
missing: neutralis gone #894's branch, notorigin/main, so that the change stacks onmissing:as it now reads.feat/parameter-wherepushes to the session's branchclaude/gallant-franklin-6ndbd1.Why
#935 and #939 propose multi-dimensions and properties, so that a parameter over several dimensions holds only the valid combinations. A mask on a parameter says the same with constructs the language has: one relation lists the valid pairs and their role, and the members stay real dimensions.
🤖 Generated with Claude Code
https://claude.ai/code/session_0113aUbLChfQVBrVR5FVQnJq