You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The following content was generated by AI (Claude Code), reviewed by @FabianHofmann.
Bug: frozen constraints break after any later variable change
CSRConstraint stores dense variable positions as column indices and a fixed column count (n_active_vars at freeze time). Any add_variables or remove_variables after freezing changes both, so model.matrices fails when stacking the blocks:
ValueError: inconsistent shapes (3, 6) and (1, 8)
This is independent of #870; it reproduces on master with a plain dense freeze=True constraint.
Reproduction
importlinopy, pandasaspdm=linopy.Model()
i=pd.RangeIndex(3, name="i")
a=m.add_variables(coords=[i], name="a")
b=m.add_variables(coords=[i], name="b")
m.add_constraints(2*b>=1, name="c1", freeze=True)
d=m.add_variables(coords=[pd.RangeIndex(2, name="i")], name="d")
m.add_constraints(d<=5, name="c2", freeze=True)
m.matrices.A# ValueError: inconsistent shapes (3, 6) and (1, 8)# same after m.remove_variables("a") instead of adding: (3, 6) vs (1, 5)
Proposal: label columns for CSRConstraint
Store raw variable labels as column indices (width model._xCounter), and map labels to dense positions once at matrix assembly via VariableLabelIndex.label_to_pos. This is the convention CSRPayload (#870) already uses for expressions, so the two CSR representations would agree.
Consequences:
to_matrix / to_matrix_with_rhs gather positions through label_to_pos and return n_active_vars-wide blocks; the bug above disappears by construction. has_labels, to_polars and the dataset reconstruction no longer need vlabels lookups.
from_payload drops its label-to-position mapping and no longer needs the label index at construction time.
The netcdf _linopy_format: csr writer stores labels; the reader gets a compatibility path for files written with positions (they carry vlabels in the same file).
Note
The following content was generated by AI (Claude Code), reviewed by @FabianHofmann.
Bug: frozen constraints break after any later variable change
CSRConstraintstores dense variable positions as column indices and a fixed column count (n_active_varsat freeze time). Anyadd_variablesorremove_variablesafter freezing changes both, somodel.matricesfails when stacking the blocks:This is independent of #870; it reproduces on
masterwith a plain densefreeze=Trueconstraint.Reproduction
Proposal: label columns for
CSRConstraintStore raw variable labels as column indices (width
model._xCounter), and map labels to dense positions once at matrix assembly viaVariableLabelIndex.label_to_pos. This is the conventionCSRPayload(#870) already uses for expressions, so the two CSR representations would agree.Consequences:
to_matrix/to_matrix_with_rhsgather positions throughlabel_to_posand returnn_active_vars-wide blocks; the bug above disappears by construction.has_labels,to_polarsand the dataset reconstruction no longer needvlabelslookups.from_payloaddrops its label-to-position mapping and no longer needs the label index at construction time._linopy_format: csrwriter stores labels; the reader gets a compatibility path for files written with positions (they carryvlabelsin the same file).LinearExpression.to_constrainton a payload-backed expression can return an unassignedCSRConstraint(cindex=None) directly.Constraint._from_pending, the lazyConstraint.databranch andextract_pendingintroduced in feat(v1): CSR-backed sparse groupby-sum - skew-independent build memory (6-9x on the #745 hub case) #870 as a stopgap can then be deleted;add_constraintsonly assigns labels.linopy/persistent/snapshot.pyreadsto_matrix_with_rhsoutput and needs a check that buffer ownership assumptions still hold.This is also the prerequisite for making the CSR-backed constraint the default without a dense-to-sparse conversion step.
Refs: #870