Repository navigation
Conversation
Documentation build overview
75 files changed ·
|
Merging this PR will degrade performance by 67.75%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
FBumann
pushed a commit
that referenced
this pull request
Oct 1, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CM4oeTkzkk5G5zE6zgikSE
…mes and dimensions Rebased onto the rebased #1793 as one commit: the branch's net diff over its old base, without the sinks import that only the retired check(sink=) used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017HhMcpuGcaXgttYMf9Jg2q
FBumann
force-pushed
the
feat/linopy-model
branch
from
October 2, 2026 09:31
1d8dfd9 to
84d4472
Compare
# Conflicts: # docs/howto/solvers.md
…opy is named among the sinks that take a model linopy's table sits in EXPORTS, so a quadratic constraint is refused as every sink's table refuses one, naming the sinks that take it. Its refusal of an objective constant and of a termless row no point meets moves into the engine as linopy_ingest, which imports no linopy, and to_linopy asks the check before it builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017HhMcpuGcaXgttYMf9Jg2q
uv.lock is regenerated with `uv lock` from the merged pyproject.toml. That also takes the ruff, pymdown-extensions and zensical pins that main's pyproject.toml already names and its uv.lock did not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011T4ckkidC1vKWRnqZKnfVn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011T4ckkidC1vKWRnqZKnfVn
This was referenced Oct 6, 2026
The [linopy] extra follows the oracle to linopy 0.10.0, so it no longer names a git URL and hatch no longer needs direct references. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DSYMFAGbSZpZ4ECVdXGMxc
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.
Scope added later: "Why not move them over? Or call them from check() ?"
Note
The following content was generated by AI.
Model.to_linopy()returns alinopy.Model. Each variable and each constraint keeps its declared name and dims, som.variables['p'].sel(generator='wind')works. Coordinates the build did not produce are masked out.Model.check('linopy')refuses what the export refuses, without importing linopy. It needs the new[linopy]extra, pinned to the oracle's linopy, 0.10.0.Stacked on #1793
The base is
feat/pyomo-model(#1793, which is itself on #1795). This PR reads the sameDeclaredfromsinks/handoff.py: which declaration owns each column, row and SOS set, and at which coordinate. Merge #1795, then #1793, then this one.What the model holds, and what it refuses
int,stranddatetimestay as they are._termand are built through linopy's publicLinearExpression(Dataset, model). Shorter rows are padded with linopy's absent variable,-1. A masked entry carries bounds 0 and 1 and a right-hand side of 0. linopy refuses aNaNconstant, and a binary bound other than 0 or 1, even where the mask hides it.add_sos_constraints(variable, sos_type, sos_dim), which matches mathspec'ssos:exactly (a variable and the dim it is ordered along).rename; this export needs norename..lp,gurobi,pyomo). The message no longer names the constraint and its coordinate, as no table refusal does;osemosys_utopiahas one. The oracle has the same gap, already an xfail citing eager lane: an objective constant refuses a model the relational lane solves #894;0 >= 10. Probed on this linopy: it drops a row without terms, even with a+0placeholder term, so an infeasible model solved as optimal. A termless row that every point satisfies is dropped without changing the answer.The check
EXPORTSgains'linopy': LINOPY_CAPABILITIES(every capability but a quadratic constraint). Another sink's refusal now lists linopy among the takers where it takes the model.specsolve/linopy.pytorelational/sinks/linopy_ingest.py. They read only the handoff andDeclared, with numpy and polars, so the engine may hold them:test_engine_is_isolatedforbids importing linopy or xarray, not knowing what linopy drops. The engine'scheck('linopy')calls them;Model.to_linopycalls that check, then builds. One path, and a test assertscheckandto_linopygive equal messages for each of the three refusals.linopy.py:LAZY_ORACLE_ALLOWEDis keyed on that file name, so a second one would be allow-listed by accident.check('linopy')needs no linopy installed;to_linopystill refuses without the extra.Policy and packaging decisions
specsolve/linopy.py, outsiderelational/, becausetest_engine_is_isolatedforbids the engine subpackage from importing linopy, even lazily.LAZY_ORACLE_ALLOWED, with its reason.docs/about/linopy.mdnow describes three relationships: not a dependency, an export, the oracle. The architecture page says why the module sits outside a fence.src/imports linopy are corrected.tests/linopy_lanedoes not read the export, so the differential comparison is still a check.[linopy]extra pinslinopy==0.10.0, the oracle's linopy, as asked. Since docs: the tests, the benchmarks and every reference model run on the linopy 0.10.0 release #1945 moved the oracle to that release, the extra names no git URL, hatch needs noallow-direct-references, and a release can be uploaded to PyPI.".[linopy]". Onmainit greps the oracle's pin out ofpyproject.toml. The extra writes the pin a second time, so that grep would return two lines, and uv would refuse them. The local command indifferential/pypsa/parity.pychanges with it.SetRun.sos_typeis nowprogram.SosType(Literal[1, 2]), mathspec's own type, instead ofint. linopy's signature takes the literal.Verification
2521241, aftermainwas merged in through the stack (feat(api): a written LP or MPS file can name each variable and constraint by its declaration and coordinate #1795 → feat(api): a built model can be handed to pyomo as a ConcreteModel indexed by its labels #1793 → this PR): withuv(pixi is not installed in the session):ruff check .,ruff format --check .,pyrefly checkonsrc/, and the full suite (5892 passed, 566 skipped, 4 xfailed). The merge changed one test here: activity is now read only when asked for (outputs={'activity'}), and a printed term coordinate names its dims (snapshot=1, generator=wind). The same two changes were made to the row tests of feat(api): a written LP or MPS file can name each variable and constraint by its declaration and coordinate #1795 and feat(api): a built model can be handed to pyomo as a ConcreteModel indexed by its labels #1793. Not run on this commit:docs-build,docs-test(the docstring-link test ran in the suite),test-floors, the PyPSA parity job, the mutation table.21ad24d:pixi run check(4833 passed, 522 skipped, 1 xfailed).pixi run docs-buildran on1d8dfd9, before the rebase ontomainand the check, and was not run again.b057163): the workflow's ownuv runline, with".[linopy]", run locally against a mathspecv0.2.0checkout. It resolved linopy master, and every rung matched PyPSA. Not run again since.pixi run test-floors(2843 passed; linopy is absent there, so the new tests skip) andpixi run docs-test, both clean.tests/test_linopy_model.py, solved through linopy with HiGHS, and with Gurobi for SOS:osemosys_utopiareaches its published objective to 1e-6.osemosys_utopiais refused for its objective constant.Model.rowreads at that coordinate. The masked count shows that the constraint holds nothing else.>=,<=and==.check('linopy')refuses each of the three in the export's words, and a model linopy takes checks clean.Mutation table (full suite each time; the tree came back clean after every row). The last two rows were taken on
21ad24d. The rest were taken before the refusals moved tolinopy_ingest.py; they moved unchanged, except the quadratic-row refusal, which the capability table replaced. None was taken again after the merge ofmain:tools.mutate, thenlinopy.py:83-87)tools.mutate, thenlinopy.py:88-93; now a table entry)tools.mutate, thenlinopy.py:100-107)tools.mutate,linopy.py:186-187)NaN(by hand)check(tools.mutate,engine.py:158-159)to_linopyasking the check first (tools.mutate,api.py:453)Not done
_from_csr), so the export stays on the public dense path.🤖 Generated with Claude Code
https://claude.ai/code/session_01CM4oeTkzkk5G5zE6zgikSE
https://claude.ai/code/session_017HhMcpuGcaXgttYMf9Jg2q
https://claude.ai/code/session_01DSYMFAGbSZpZ4ECVdXGMxc