Upgrade linopy to >=0.9.0 - #275
Merged
Merged
Conversation
linopy 0.9 requires Python >= 3.11, so requires-python moves from >=3.10 to >=3.11 and the 3.10 classifier is dropped. CI already runs on 3.11. linopy 0.9 also refuses to solve a model whose objective is empty. A handful of tests built pure feasibility problems (models with no objective contribution); they now declare a null objective (0 * variable) so the solve goes through, with objective values unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NetqdfrCBHwavdcB2EQj4G
tbittar
approved these changes
Aug 19, 2026
| # linopy >= 0.9 refuses to solve a model with no objective: set a null one. | ||
| linopy_model = problem.linopy_model | ||
| first_var = linopy_model.variables[next(iter(linopy_model.variables))] | ||
| linopy_model.add_objective(0 * first_var) |
Collaborator
There was a problem hiding this comment.
We cannot set a constant 0 objective ?
Collaborator
Author
There was a problem hiding this comment.
Unfortunately not — linopy 0.9 gives no way to express a constant objective. Verified against linopy 0.9.0:
m.add_objective(0)raisesValueError: Invalid type of 'expr' (<class 'int'>). Must be a LinearExpression or QuadraticExpression.- A
LinearExpressionholding only a constant (no variable terms) isempty, andsolve()rejects an empty objective withValueError: No objective has been set on the model. linopy's own error message suggests exactly this workaround: "Usem.add_objective(...)first (e.g.m.add_objective(0 * x)for a pure feasibility problem)."
So 0 * <variable> is the minimal objective linopy accepts: one term with a zero coefficient. The solved objective value is still 0, so the assertion below is unaffected.
Generated by Claude Code
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.
Process ID
Process: N/A
Description
Upgrades the
linopydependency from>=0.6to>=0.9.0and re-locksuv.lock(linopy 0.6.6 → 0.9.0).Two consequences of the upgrade:
Python 3.10 support is dropped. linopy 0.9 requires Python >= 3.11, so
requires-pythonmoves to>=3.11and the 3.10 classifier is removed. CI and publishing already run on 3.11, so no workflow changes are needed.linopy 0.9 refuses to solve a model with no objective (
ValueError: No objective has been set on the model). Six tests built pure feasibility problems from models with no objective contribution and started failing. Rather than changing the solver pipeline (optimization.pyis deliberately untouched), those tests now declare a useless null objective:test_simulation_table_extra_outputs.pygainobjective_contributions={"null_objective": (literal(0) * var(...)).time_sum().expec()};test_short_term_storage_base_with_yamluses models from the sharedlib_unittest.ymlfixture (left untouched, since other tests assert exact objective values against it), so the test sets0 * <first variable>directly on the built linopy model before solving.Objective values are unchanged in all six tests. Note this means a user-authored library with no objective contribution at all now fails at solve time under linopy 0.9; the changelog entry documents the null-objective idiom.
Impact Analysis
pyproject.toml/uv.lock: linopy floor raised to 0.9.0, Python floor raised to 3.11 (the lock file shrinks ~800 lines because dropping 3.10 collapses the forked numpy/pandas/xarray/scipy resolutions).docs/CHANGELOG.md: entry added under[Unreleased].tests/: null objectives added to the six tests described above.expression/,simulation/,study/,optim_config/untouched).Checklist
pytest) — 587 passed, 6 skipped, 2 xfailedmypy)black,isort)pyproject.tomlversion bumped if applicable — left at 0.1.3; bump deferred to the maintainers since this changes the supported Python rangeAGENTS.mdreviewed for impact and updated if needed — no Python-version or linopy-version statements to update