feat(language): a divisor or a power over parameters may add, so a discount factor is written where it is used - #757
Merged
Merged
Conversation
…scount factor is written where it is used `x / (a + b)` and `(1 + rate) ** years` load. The degree check refused a sum anywhere under a divisor, a base or an exponent. The program already carries the tree, and the typesetter prints it in all three formats. The PyPSA stochastic example reads `alpha` and divides by `1 - alpha` in CVaR-def, instead of binding the inverted tail as data. expressions.md: n 92, avg 15.4, median 14, over25 11 (was n 91, same). Closes #277 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7TEPiMeF7aowcvTX6CRRh
The typesetting test's helper is called varied on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7TEPiMeF7aowcvTX6CRRh
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7TEPiMeF7aowcvTX6CRRh
Documentation build overview
45 files changed ·
|
FBumann
enabled auto-merge (squash)
September 29, 2026 05:34
FBumann
disabled auto-merge
September 29, 2026 05:34
…s0zjwf main split pypsa_stochastic into the pypsa spec and its topic files (#736, #620). The CVaR divisor change moves to examples/pypsa.yaml and its symbols; the topic files and gallery pages are regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C9UKzzVdzrcoK3sPrnean
FBumann
pushed a commit
that referenced
this pull request
Sep 29, 2026
Brings in #757, #765, #778 and #779, which the next commits use to drop two of the port's workarounds. CHANGELOG.md keeps both sides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N66KMDkSv1rZbhr8jqqJzJ
FBumann
pushed a commit
that referenced
this pull request
Sep 29, 2026
…multi-dimension sums as Calliope does #757 admits a sum of parameters under ** and as a divisor, so storage_retention and cost_annuity_factor are gone: the storage files read (1 - storage_loss) ** …, and the depreciation rate states Calliope's annuity factor. #778 and #779 admit sum(over=[a, b]), so the 21 nested sums are one call each. port.md marks gaps 1 and 8 closed and keeps the numbering. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N66KMDkSv1rZbhr8jqqJzJ
FBumann
added a commit
to fluxopt/specsolve
that referenced
this pull request
Oct 2, 2026
…ver parameters may add and a spec may be composed from several files (#1800) > **Prompt:** update specsolve to the latest mathspec release > [!NOTE] > The following content was generated by AI. specsolve now requires mathspec 0.2.1. A divisor, base or exponent that adds over parameters now builds. A spec fragment is refused by name instead of raising `KeyError`. The PyPSA parity corpus stays pinned at v0.2.0. <details><summary>What changed, and why</summary> **Main is red against 0.2.1 today.** The suite job solves its environment fresh, so it already resolves mathspec 0.2.1. 0.2.1 admits `x / (1 - cost)` and `(1 + rate) ** years` (energy-models/mathspec#757). The compiler then stopped at `AssertionError: a divisor that adds is refused at load`. `test_degree_parity[a-divisor-that-adds]` failed for the same reason. - **Compiler.** `_added_up` now adds a variable-free operand up to one value per coordinate at a build too. A read already did this. How a missing parameter row reads at a build: - **Divisor:** `spreads`. The divisor is null where any parameter under it has no row, so the existing check refuses it and names the parameter. This matches the linopy lane and mathspec's rule that a divisor has no fill value. - **Power base or exponent:** `zero`. This is how a missing row reads everywhere outside a divisor. The linopy lane agrees. - **Reads:** unchanged. - **Fragments.** `lowered` refuses a program whose `given:` is not empty. It names what the program reads and points to `mathspec.merge`. Before, `check` only warned, and a build raised `KeyError`. - **Pins.** The `[project.dependencies]` floor, the floors environment and `uv.lock` move to 0.2.1. The lock diff touches mathspec only. - **Parity corpus.** `pypsa-parity.yml` took its corpus tag from the floor. The 0.2.1 corpus has 58 rungs instead of 16. Its `pypsa.yaml` declares relations that `prep.py` does not supply (`snapshot_period`, `Link_carrier`, `Generator_maintenance_cover`), so every rung came back UNATTACHED. The job now checks out the corpus at `v0.2.0` and still installs mathspec at the floor. With mathspec 0.2.1 installed, all 16 rungs MATCH and `differential/pypsa` regenerates byte for byte. Moving the corpus is a separate `chore` PR, with the rungs it adds. **Coverage moved.** `test_degree_parity[a-divisor-that-adds]` and `test_power[an-operand-that-adds]` asserted the old refusal, so I removed them. The compound operands are now covered in two places: - `test_power`: three both-lane cases, the hand-computed discount factor written as `(1 + rate) ** period`, and a missing row under a power. - `test_arithmetic_laws`: a compound divisor on both lanes, and a sparse compound divisor refused with the same sentence on both lanes. `tests/test_composition.py` is new. A spec merged from the three files of mathspec's composition how-to solves to the hand-computed 40. Three fragments are each refused by name. </details> <details><summary>Verification</summary> - I wrote the six compound-operand tests first and watched them fail on the old tree, at the compiler's assertion. - `pixi run check`: lint, format, pyrefly, suite (4541 passed, 522 skipped, 1 xfailed). - `pixi run -e floors test-floors` on mathspec 0.2.1: 2838 passed. - `pixi run docs-test`: 70 passed. - `python -m tools.changelog check` and the `entry` check against this title both pass. - `parity.py` with the workflow's own command, against the v0.2.0 corpus with mathspec 0.2.1: every rung MATCH, no diff under `differential/`. - **Not run:** `pixi run test-bench` refused because the machine was loaded. The diff does not touch `bench/`. `docs-build` was not run. Mutation table, full suite each time. The first row comes from `tools/mutate.py`. The other three were taken by hand: clean tree, restore with `git checkout --`, `__pycache__` dropped on both sides. | mutation | result | |---|---| | the fragment guard (`lanes.py:120-127`) deleted | **caught** | | divisor `spreads` → `zero` | **caught** — `test_a_sparse_divisor_that_adds_is_named_and_refused_on_both_lanes` | | power `zero` → `spreads` | **caught** — `test_a_missing_row_under_a_power_that_adds_reads_as_zero_on_both_lanes` | | the old "a build skips adding up" early return restored | **caught** — 7 tests | </details> <details><summary>Not done, and departures</summary> - **Declared frame (energy-models/mathspec#741):** a named expression may now declare a frame wider than its body. `Result.evaluate('cap')` returns values over the body's dimensions, not the declared frame. A build that reads it is correct. I left this unchanged. - **Ladder catch-up:** moving the parity corpus to v0.2.1, with prep for the new relations and the 42 new rungs, is not in this PR. - **Worktree:** I worked on the session's assigned branch, not in a fresh `../wt/<topic>` worktree. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01XSFapw8E3nibM7VFUCScU3 --- _Generated by [Claude Code](https://claude.ai/code/session_01XSFapw8E3nibM7VFUCScU3)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
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.
#648 on current
main. It replaces #648, whose branch could only be rebased with a force-push.x / (a + b)and(1 + rate) ** yearsload, and a variable there is still refused. Closes #277.What moved in the rebase, gates, what was not done
The change is #648's, unchanged in substance. The method, typeset output and "deliberately not done" list in #648's body still hold.
What the rebase had to change.
src/math_spec/degree.pyis nowsrc/mathspec/degree.py(refactor: the package installs, imports and runs as mathspec, rather than math-spec and math_spec #702).tests/typesetting/test_walk.py: the new test callsvaried(...), the namemainnow gives the helper that feat(language): a divisor or a power over parameters may add, so a discount factor is written where it is used #648 calledoverride(...).CHANGELOG.mdgets its line under## Upcoming version.mainremovedexamples/pypsa_stochastic.yaml(docs(pypsa): a single spec covers every pypsa model class and component #620, docs(pypsa): the pypsa spec is also 24 topic files that merge back to it, each component adding its share of a sum by name #736). Its CVaR constraint is now inexamples/pypsa.yaml. The example change moved there:CVaR_alphareplacesCVaR_inv_tail, andCVaR_defdivides by1 - CVaR_alpha. The symbol is\alpha.examples/pypsa/cost.yamlwas regenerated withpython -m tools.pypsa_split split examples/pypsa, and the pages withpython -m tools.gallery.History. One commit replays #648's net diff onto
0efbf59. Two merge commits bring in whatmaingained after that. There is no force-push.Gates. pixi is not available in this container. The tools ran from a uv venv at the versions
pixi.tomlpins, on the last merge commit.ruff check,ruff format --check: pass.pyrefly check: 0 errors.pytest -n auto: 2518 passed, 52 skipped.prettier --checkonCHANGELOG.md,docs/andexamples/: clean.main'sdegree.pyrestored: 16 failed, 4 errors.lefthook(typos, reuse, taplo, zizmor),docs-buildandcompile-tex. CI runs them.Not done. #648 stays open. Close it when this one replaces it.
🤖 Generated with Claude Code
https://claude.ai/code/session_01C7TEPiMeF7aowcvTX6CRRh
https://claude.ai/code/session_019C9UKzzVdzrcoK3sPrnean