Skip to content

docs(language): the relations page states what decides a sum from a read - #597

Merged
FBumann merged 6 commits into
mainfrom
claude/gifted-curie-8tk4mq
Sep 21, 2026
Merged

FBumann merged 6 commits into
mainfrom
claude/gifted-curie-8tk4mq

Conversation

@FBumann

@FBumann FBumann commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Prompt: "Anything wrong or misdefined about relations?", then, on the four findings that came back: "Lets fix all of this with a PR — 1. Fix that 2. Ok 3. ok 4. Yes. Make that clear". Then: "Lets work on #597. The rules need to be in the docs: reference/language/relations. I like the table! And is it correct that sum only consumes key columns?", "Doesnt at always land on the full key?", "I think the rule is: at lands on the full key (+ extra dims of the operand?)", and "I want to keep the docs about relations smaller and simpler to read."

Note

The following content was generated by AI.

The page constrained each call's ends by kind of column, which is not what the loader checks, and said nothing about what a read gives back. Both rules are now bullets under the one table, +10 lines on the page.

What this changes

docs/reference/language/relations.md, in Aggregates and reads:

  • The bare connection: { key: [generator, bus] } joins zone_of in the preamble, and the call table gains the row sum(p, by=connection, over=generator, into=bus) — consumes generator, joins on nothing, produces bus, result [bus, period].
  • The rule that constrained the ends becomes three. A read finds one row per coordinate and a sum finds many, because a read's landing and join hold the whole key. A sum consumes at least one key column and lands on any column it does not consume, key or value. A read consumes value columns and lands on the key, and its result carries every key column plus whatever else the operand carries that the read does not consume.
  • The refusal that teaches the split is quoted whole.
  • The paragraph above the table loses the half the result rule already states.

tests/test_dimensions.py gains four: a bare relation summed each way, a sum consuming a key column and a value column together, and a read whose result is the key plus the operand's spare dimension.

Why

The page constrained only the left end — "sum consumes at least one key column, and at consumes value columns only" — and every row of the table landed a sum on a value column. Two wrong readings follow. The first is that the split is keys on the left and values on the right, which is inverted for at. The second is that a sum's landing column must be a value column, which makes the bare many-to-many relation unwritable: connection has no value column, so a sum through it lands on a key column or cannot be written at all. That case is in tests/typesetting/golden/model.yaml already, and prints as $\sum_{g \in \mathcal{G} ,:, (g, b) \in \mathrm{connection}} p_{t,g} \le \mathrm{load}_{t,b}$.

Stating the ends by kind of column cannot be made right, because the loader does not work that way. It computes one fact — whether the key lies inside what the call lands on and joins on — and refuses a read when it does not hold and a sum when it does. The page states that, and lets the rest be what each call may write.

Method, gate output, what was not run

The claims, checked against the loader rather than read off the page. pixi does not install in this session (the installer is blocked by the proxy with a 403), so the gates ran from a uv venv on Python 3.13 with ruff==0.16.1.

call relation result
sum(f, by=gen_bt, over=[generator, bus], into=technology) {key: generator, values: [bus, technology]} loads — a sum consumes a key column and a value column together
sum(p, by=connection, over=generator, into=bus) {key: [generator, bus]} loads — a sum lands on a key column
sum(price, by=zone_of, over=zone, into=generator) {key: [generator, period], values: zone} refused — the message quoted on the page

The quoted refusal is this loader's output, not a paraphrase, from the model in the last row under a constraint named cap.

The sentence about a read's result was checked on four shapes, varying what the operand carries: [bus] reads to [generator], [bus, technology] to [generator, technology], [zone, snapshot] to [generator, snapshot] with snapshot arriving by the join, and [zone] with both key columns in into= to [generator, snapshot]. The key is there in every one.

Size. The section is five bullets under one table. The page is 140 lines and 1173 words, against 130 and 1038 on main, so the rules and the refusal cost ten lines. The sentence measure, with the script in the docs-writing skill, is n 37 avg 15.6 median 15 over25 4, against n 41 avg 15.2 median 15 over25 4 on main; each of the four long sentences is a bold lead-in the script joins to the sentence after it.

A hole this turned up, fixed in #598. at(x, by=gen_bt, over=bus, into=technology) loaded, and printed $w_{g,t} \le \mathrm{x}_{\mathrm{gen_bt.bus}(g),g} ;; \forall, g \in \mathcal{G},\ t \in \mathcal{T}$ — the read produced technology and nothing tied $t$ to $\mathrm{gen_bt.technology}(g)$. #598 refuses it. This page states the rule the language means either way, so the two agree; the one bullet #598 adds to this section is superseded here.

Gates.

  • pytest -q -n 4: 1355 passed, 6 skipped, the whole suite. The new rows are -k a-sum-through-a-bare-relation-lands-on-a-key-column, -k and-the-same-table-summed-the-other-way, -k test_a_sum_consumes_a_key_column_and_a_value_column_together and -k test_a_read_carries_the_whole_key_and_what_the_operand_brings_beside_it.
  • ruff check, ruff format --check: clean. prettier --check on the changed page: clean. typos on both changed files: clean.
  • mkdocs build: no link or anchor warning, and #aggregates-and-reads is untouched, which expressions.md and operators.md link to. --strict aborts here on fetching docs.python.org/objects.inv through the proxy, which is this environment and not the page.

Not run: pixi run ci as one command, pyrefly, reuse, zizmor, taplo, compile-tex. No generated file is touched, so no generator was re-run.

Deliberately not done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Fqgv4wZBmwHp4xgokj2xQb

The page constrained only the column a call consumes: a key column for `sum`,
value columns for `at`. Nothing said what either lands on, and every row of the
table landed a sum on a value column. The page now states both ends, and a
bare relation is one of the rows.

Sentence measure on relations.md: n 41, avg 15.2, median 15, over25 4. Three of
the four are the two sentences already on the page and a bold lead-in the
script joins to the sentence after it; the fourth is the quoted refusal, which
the script reads as prose because its fence is a `text` fence it does not skip.

tests/test_dimensions.py gains the two rows the new table row claims: a sum
through a bare relation, read each way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011cd94pb8EUBg1D31B79khs
@read-the-docs-community

read-the-docs-community Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Documentation build overview

📚 math-spec | 🛠️ Build #34674315 | 📁 Comparing 947903f against latest (11a8a2e)

  🔍 Preview build  

2 files changed
± CHANGELOG/index.html
± reference/language/relations/index.html

The page constrained the ends by kind of column, and neither end is fixed
to one kind: a sum may consume a value column beside its key column, and a
read may land on a value column and join on the key. What separates the
two calls is whether the columns a call lands on and joins on hold the
whole key.

The section now states that question, gives the two ends per call as a
table, and quotes both refusals — the sum that consumes no key column, and
the read that consumes one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fqgv4wZBmwHp4xgokj2xQb
@FBumann FBumann changed the title docs(language): the relations page states both ends of a sum and a read docs(language): the relations page states what decides a sum from a read Sep 21, 2026
…is the choice

A read covers the key by landing on it, so its ends are not a choice
between kinds of column the way a sum's are. The table says so, and the
claim that a read may land on a value column is gone with the test that
pinned it: that call renders a produced dimension nothing ties down, which
is a hole in the loader rather than a rule to document.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fqgv4wZBmwHp4xgokj2xQb
A read lands on the key however the call splits it between into= and the
join, and a dim the operand carries and the read does not consume rides
along. The section says both, and a dim-inference row holds the claim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fqgv4wZBmwHp4xgokj2xQb
The section had grown a second heading, a second table and two quoted
refusals for one idea. The rules are bullets under the call table again,
each a claim a reader can act on, with the one refusal that teaches the
split between a sum and a read.

The page is 140 lines and 1173 words, from 161 and 1367; the sentence
measure is `n 37 avg 15.6 median 15 over25 4`, from `n 43 avg 15.4
median 15 over25 7`, and each of the four long ones is a bold lead-in the
script joins to the sentence after it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fqgv4wZBmwHp4xgokj2xQb
#598 added a bullet to this section saying a read lands on the key and
nothing else. The bullets here say that and what a read's result carries,
so the section keeps this branch's wording and #598's rule stands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fqgv4wZBmwHp4xgokj2xQb
@FBumann
FBumann merged commit 3f6b632 into main Sep 21, 2026
5 checks passed
@FBumann FBumann added the docs Documentation pages, guides, reference and README label Sep 24, 2026 — with Claude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation pages, guides, reference and README

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants