diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 88180844..81141551 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -4,31 +4,51 @@ Release Notes Upcoming Version ---------------- -* Add ``Model.copy()`` (default deep copy) with ``deep`` and ``include_solution`` options; support Python ``copy.copy`` and ``copy.deepcopy`` protocols via ``__copy__`` and ``__deepcopy__``. -* Harmonize coordinate alignment for operations with subset/superset objects: - - Multiplication and division fill missing coords with 0 (variable doesn't participate) - - Addition and subtraction of constants fill missing coords with 0 (identity element) and pin result to LHS coords - - Comparison operators (``==``, ``<=``, ``>=``) fill missing RHS coords with NaN (no constraint created) - - Fixes crash on ``subset + var`` / ``subset + expr`` reverse addition - - Fixes superset DataArrays expanding result coords beyond the variable's coordinate space -* Add ``add_piecewise_formulation()`` for piecewise linear constraints with SOS2, incremental, and disjunctive formulations: ``m.add_piecewise_formulation((power, x_pts), (fuel, y_pts))``. Supports N-variable linking (e.g. CHP with fuel/power/heat) and per-entity breakpoints. ``method="auto"`` picks the cheapest correct formulation automatically. The API is newly added and emits an :class:`linopy.EvolvingAPIWarning` to signal that details may be refined in minor releases — the current restrictions on per-tuple sign (at most one bounded tuple, N≥3 must be all equality) are the most likely candidates to relax as use cases come in. Feedback and use cases at https://github.com/PyPSA/linopy/issues shape what stabilises. Silence with ``warnings.filterwarnings("ignore", category=linopy.EvolvingAPIWarning)``. -* Add one-sided piecewise bounds via a per-tuple sign on ``add_piecewise_formulation``: append ``"<="`` or ``">="`` as a third tuple element — e.g. ``(fuel, y_pts, "<=")`` — to mark that expression as bounded by the curve while the others remain pinned. At most one tuple may carry a non-equality sign; with 3 or more tuples all signs must be ``"=="``. On convex/concave curves with a matching sign, ``method="auto"`` dispatches to a pure-LP chord formulation (``method="lp"``) with no auxiliary variables and automatic domain bounds on the input. Mismatched curvature+sign is detected and falls back to SOS2/incremental with an explanatory info log. -* Add unit-commitment gating via the ``active`` parameter on ``add_piecewise_formulation``: a binary variable that, when zero, forces all auxiliary variables (and thus the linked expressions) to zero. Works with the SOS2, incremental, and disjunctive methods. -* Surface formulation metadata on the returned ``PiecewiseFormulation``: ``.method`` (resolved method name) and ``.convexity`` (``"convex"`` / ``"concave"`` / ``"linear"`` / ``"mixed"`` when well-defined). Both persist across netCDF round-trip. -* Add ``tangent_lines()`` as a low-level helper that returns per-piece chord expressions as a ``LinearExpression`` — no variables created. Most users should prefer ``add_piecewise_formulation`` with a bounded tuple ``(y, y_pts, "<=")``, which builds on this helper and adds domain bounds and curvature validation. -* Add ``linopy.breakpoints()`` (lists/Series/DataFrame/DataArray/dict) and ``linopy.segments()`` (disjunctive operating regions) as breakpoint-construction helpers. -* Add ``linopy.Slopes`` for specifying a piecewise curve by marginal costs / per-piece slopes instead of absolute y-values — ``(fuel, Slopes([1.2, 1.4, 1.7], y0=0))`` borrows the x grid from a sibling tuple in ``add_piecewise_formulation``. -* Add the `sphinx-copybutton` to the documentation -* Add SOS1 and SOS2 reformulations for solvers not supporting them. -* Add semi-continous variables for solvers that support them -* Add ``OetcSettings.from_env()`` classmethod to create OETC settings from environment variables (``OETC_EMAIL``, ``OETC_PASSWORD``, ``OETC_NAME``, ``OETC_AUTH_URL``, ``OETC_ORCHESTRATOR_URL``, ``OETC_CPU_CORES``, ``OETC_DISK_SPACE_GB``, ``OETC_DELETE_WORKER_ON_ERROR``). -* Forward ``solver_name`` and ``**solver_options`` from ``Model.solve()`` to OETC handler. Call-level options override settings-level defaults. -* Improve handling of CPLEX solver quality attributes to ensure metrics such are extracted correctly when available. -* Enable quadratic problems with SCIP on windows. -* Add ``format_labels()`` on ``Constraints``/``Variables`` and ``format_infeasibilities()`` on ``Model`` that return strings instead of printing to stdout, allowing usage with logging, storage, or custom output handling. Deprecate ``print_labels()`` and ``print_infeasibilities()``. -* Add ``fix()``, ``unfix()``, and ``fixed`` to ``Variable`` and ``Variables`` for fixing variables to values via equality constraints. Supports automatic rounding for integer/binary variables. -* Add ``relax()``, ``unrelax()``, and ``relaxed`` to ``Variable`` and ``Variables`` for LP relaxation of integer/binary variables. Supports partial relaxation via filtered views (e.g. ``m.variables.integers.relax()``). Semi-continuous variables raise ``NotImplementedError``. -* Fix ``as_dataarray`` treating multi-index level names as extra dimensions when broadcasting a scalar against ``xarray.Coordinates``. +**Features** + +*Piecewise linear constraints (new)* + +* ``Model.add_piecewise_formulation((power, x_pts), (fuel, y_pts))`` adds piecewise constraints with SOS2, incremental, disjunctive, or pure-LP formulations and automatic method dispatch. Supports N-variable linking (e.g. CHP) and per-entity breakpoints; emits :class:`linopy.EvolvingAPIWarning` while the API stabilises. +* One-sided bounds: append ``"<="`` / ``">="`` to a tuple, e.g. ``(fuel, y_pts, "<=")``. On matching convex/concave curves this dispatches to a pure-LP chord formulation. +* Unit-commitment gating via ``active``: when zero, deactivates the piecewise relation. +* ``PiecewiseFormulation`` exposes ``.method`` / ``.convexity`` (persisted across netCDF round-trip). +* Construction helpers: ``linopy.breakpoints()``, ``linopy.segments()``, ``linopy.Slopes`` for per-piece slopes, and ``tangent_lines()``. + +*Variables* + +* ``fix()`` / ``unfix()`` / ``fixed`` for fixing variables to values via equality constraints (rounds integers/binaries). +* ``relax()`` / ``unrelax()`` / ``relaxed`` for LP relaxation; supports partial relaxation (e.g. ``m.variables.integers.relax()``). +* Semi-continuous variables on solvers that support them. + +*Model* + +* ``Model.copy()`` for a deep copy of a model, optionally including the solution; supports the ``copy`` protocol. +* SOS1 / SOS2 reformulations for solvers without native SOS, applied automatically by ``Model.solve()`` when needed. +* ``format_labels()`` / ``format_infeasibilities()`` return strings instead of printing; deprecates the ``print_*`` siblings. + +*Expressions* + +* Coordinate alignment between subset/superset operands: missing coords fill with 0 in arithmetic and NaN in comparisons. Fixes ``subset + var`` reverse-addition and result coords expanding past the variable's space. + +*Solvers* + +* OETC: ``Model.solve()`` forwards solver options to the handler; ``OetcSettings.from_env()`` reads ``OETC_*``. +* SCIP supports quadratic problems on Windows. + +**Performance** + +* Faster solution unpacking in ``Model.solve()``. + +**Bug Fixes** + +* ``Model.solve()`` raises a clear ``ValueError`` when no objective is set. +* ``add_variables`` no longer ignores ``coords`` when ``lower`` / ``upper`` are DataArrays, and handles MultiIndex coords correctly with scalar bounds. +* ``Model.to_netcdf`` works on the scipy netCDF backend (old files remain readable). +* CPLEX no longer errors on quality attributes that aren't always available. + +**Breaking Changes** + +* ``google-cloud-storage`` and ``requests`` are now optional. Install ``linopy[oetc]`` to keep the previous behaviour. Version 0.6.7