Issue Description
linopy's binary operators disagree on how to align coordinates when two operands share a same-size dimension:
| Operator |
Alignment |
* |
by label |
+, -, / |
by position — coordinate labels discarded (override join) |
<=, >=, == (constraint creation) |
by label |
Because some operators align by label and others by position, algebraically identical expressions produce different results.
Reproducible Example
import pandas as pd
import linopy
m = linopy.Model()
x = m.add_variables(coords=[["A1", "A5", "A11", "A100"]], name="x")
coef = pd.Series([100, 1, 5, 11], index=["A100", "A1", "A5", "A11"])
# coef["A1"] == 1 (coef's first entry is A100 == 100)
(x + coef).const.sel(dim_0="A1") # 100 positional — should be 1
(x - coef).const.sel(dim_0="A1") # -100 positional — should be -1
(x * coef).coeffs.sel(dim_0="A1") # 1 by label — correct
(x / coef).coeffs.sel(dim_0="A1") # 0.01 positional — should be 1
Broken equivalences
Mixing a positional operator with a by-label one makes identical forms disagree:
Expected Behavior
Every operator should align coordinates the same way — by label — and a label mismatch should raise rather than silently pair by position.
Context
Confirmed on linopy 0.7.0. Related: #586, #670, #707. The strict-alignment convention in #591 makes all operators align by label uniformly.
Issue Description
linopy's binary operators disagree on how to align coordinates when two operands share a same-size dimension:
*+,-,/<=,>=,==(constraint creation)Because some operators align by label and others by position, algebraically identical expressions produce different results.
Reproducible Example
Broken equivalences
Mixing a positional operator with a by-label one makes identical forms disagree:
x - a <= 0≠x <= a—-positional,<=by label (x - a <= 0andx <= abuild different constraints #707).x / a≠x * (1 / a)—/positional,*by label:x / coefpairsx[A1]with1/100;x * (1/coef)pairs it with1/1.Expected Behavior
Every operator should align coordinates the same way — by label — and a label mismatch should raise rather than silently pair by position.
Context
Confirmed on linopy 0.7.0. Related: #586, #670, #707. The strict-alignment convention in #591 makes all operators align by label uniformly.