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
Widen the conditions under which Model.add_constraints keeps a CSRConstraint. Child of #756.
The sparse constraint path is narrow. add_constraints keeps the sparse object only when isinstance(con, CSRConstraint) and freeze and mask is None (linopy/model.py:1333). Any mask=, any penalty=, freeze=False (the default), or a set self.chunk reconstructs the full dense rectangle at model.py:1345.
Upstream of that, csr_rhs (linopy/constraints.py:1427-1441) returns None for a non-constant right-hand side, or one carrying helper dims or dims outside the grid, so to_constraint falls back to dense. An rhs that is itself an expression is a common case and always densifies.
The result is that a build which stayed sparse through every expression operation can still densify at the last step, silently.
Implementation ideas
mask=: a mask is a row selection on the CSR store, the same primitive the sparse where needs. These two should probably be implemented together.
Expression rhs: move the rhs to the left-hand side before building the constraint, which is what the dense path effectively does, then the existing constant-rhs path applies.
penalty/soft constraints are deliberately incompatible with freezing today (model.py:1313); worth confirming that is a permanent rule rather than a gap.
Separately, note that the sparse route currently needs three independent opt-ins to work end to end: semantics="v1", then sparse_groupby=True or a per-call sparse=True, then freeze_constraints=True. Reducing that to one decision would be worth discussing under #756.
Note
The following content was generated by AI.
Describe the feature you'd like to see
Widen the conditions under which
Model.add_constraintskeeps aCSRConstraint. Child of #756.The sparse constraint path is narrow.
add_constraintskeeps the sparse object only whenisinstance(con, CSRConstraint) and freeze and mask is None(linopy/model.py:1333). Anymask=, anypenalty=,freeze=False(the default), or a setself.chunkreconstructs the full dense rectangle atmodel.py:1345.Upstream of that,
csr_rhs(linopy/constraints.py:1427-1441) returnsNonefor a non-constant right-hand side, or one carrying helper dims or dims outside the grid, soto_constraintfalls back to dense. An rhs that is itself an expression is a common case and always densifies.The result is that a build which stayed sparse through every expression operation can still densify at the last step, silently.
Implementation ideas
mask=: a mask is a row selection on the CSR store, the same primitive the sparsewhereneeds. These two should probably be implemented together.penalty/soft constraints are deliberately incompatible with freezing today (model.py:1313); worth confirming that is a permanent rule rather than a gap.Separately, note that the sparse route currently needs three independent opt-ins to work end to end:
semantics="v1", thensparse_groupby=Trueor a per-callsparse=True, thenfreeze_constraints=True. Reducing that to one decision would be worth discussing under #756.