Skip to content

[test robustness] Cyclic-cluster storage tests assert a non-unique (degenerate) SOC level #733

Description

@FBumann

Category: test brittleness / solution degeneracy — NOT a semantics issue (reproduces identically under legacy AND v1)

Symptom

On linopy 0.8, these fail with a numeric AssertionError on charge_state values (objective and all flow rates are correct):

  • tests/test_math/test_clustering.py::TestClusteringExact::test_storage_cyclic_charge_discharge_pattern
  • tests/test_clustering/test_expansion_regression.py::...::test_expanded_storage

Example: cs_c0 expected [50,50,0,50,0], got [100,100,50,100,50] — a uniform +50 offset / the two clusters' levels swapped.

Root cause

In cluster_mode='cyclic', StorageModel._add_initial_final_constraints intentionally skips the initial/final constraints, so the absolute SOC level of each representative cluster is unpinned — only the per-cluster delta is fixed (by the cyclic start==end constraint and the [0, capacity] bounds). The LP is therefore degenerate in the SOC level: multiple equally-optimal vertices exist. A different linopy build orders the model differently, so HiGHS returns a different (equally valid) vertex. Verified: objective == 100.0 and grid/charge/discharge flow rates match exactly; only the non-unique SOC level differs.

Why this is filed here

It was surfaced by the linopy 0.8 bump during the v1-compat work, but it is not a v1-semantics fault and not a linopy correctness bug — it reproduces identically under "legacy" and "v1". Nothing to file upstream.

Proposed fix (test-side)

Assert the objective and flow rates (which are unique), and/or assert the SOC delta rather than the absolute level; or pin the level in the fixture (e.g. an anchor constraint) if a unique trajectory is intended.

Severity

Numerically-different result vs. the hard-coded expectation, but semantics-independent and physically equivalent (same cost & dispatch).

Context: #729.

Metadata

Metadata

Assignees

No one assigned

    Labels

    linopy-v1Compatibility with linopy v1 semantics (PR #717)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions