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
Not yet sure if this is a bug or just an api decision.
Note
This bug report was generated by AI (Claude), and the reproduction was verified by running it against current master (0.8.0.post1.dev141+g0402431f6).
Model.add_sos_constraints takes no weights= parameter and uses the coordinate labels of sos_dim as the SOS weights. That has two consequences:
A string-labeled dimension cannot carry an SOS constraint at all — add_sos_constraints raises ValueError: SOS constraint requires numeric coordinates.
Numeric labels that are not in sorted order silently redefine SOS2 adjacency. Solvers order SOS members by weight, so "consecutive" means consecutive by label value, not by array position. Two models that are element-for-element identical (same declaration order, same bounds, same objective coefficients) reach different optima depending only on what the coordinates are named — both reported as optimal.
case 1: SOS constraint requires numeric coordinates for dimension 'size', but got object
case 2: identical model, members declared in the same order
labels [0, 1, 2] -> objective 2.0 nonzero: [0, 1]
labels [30, 10, 20] -> objective 1.1 nonzero: [10, 20]
In case 2 the objective coefficients are (1.0, 1.0, 0.1) by position in both runs. With labels [30, 10, 20] the weight order is 10 < 20 < 30, so the consecutive pairs are {10, 20} and {20, 30} — the first-two-declared pair {30, 10} is no longer expressible, and the optimum drops from 2.0 to 1.1 with no error or warning.
This is not an artifact of the big-M reformulation — all three emission paths agree on value order:
sos_reformulation.py:285-288 argsorts members by coordinate value before building adjacency,
solvers.py:138 passes labels.coords[sos_dim].values as weights to the native addSOS APIs (Gurobi, Xpress),
io.py:456 writes the coordinate values as weights into the LP file's sos section.
Suggested fix
An optional weights= parameter on add_sos_constraints (an array along sos_dim, defaulting to the current behavior) would resolve both: string-labeled dims get positional or user-supplied weights, and callers who mean array-order adjacency can say so. At minimum the docstring — currently just "The dimension values are used as SOS" (model.py:928) — should state that SOS2 adjacency follows sorted coordinate values, not array order.
Not yet sure if this is a bug or just an api decision.
Note
This bug report was generated by AI (Claude), and the reproduction was verified by running it against current
master(0.8.0.post1.dev141+g0402431f6).Model.add_sos_constraintstakes noweights=parameter and uses the coordinate labels ofsos_dimas the SOS weights. That has two consequences:add_sos_constraintsraisesValueError: SOS constraint requires numeric coordinates.Reproduction
Output:
In case 2 the objective coefficients are (1.0, 1.0, 0.1) by position in both runs. With labels
[30, 10, 20]the weight order is 10 < 20 < 30, so the consecutive pairs are {10, 20} and {20, 30} — the first-two-declared pair {30, 10} is no longer expressible, and the optimum drops from 2.0 to 1.1 with no error or warning.This is not an artifact of the big-M reformulation — all three emission paths agree on value order:
sos_reformulation.py:285-288argsorts members by coordinate value before building adjacency,solvers.py:138passeslabels.coords[sos_dim].valuesas weights to the nativeaddSOSAPIs (Gurobi, Xpress),io.py:456writes the coordinate values as weights into the LP file'ssossection.Suggested fix
An optional
weights=parameter onadd_sos_constraints(an array alongsos_dim, defaulting to the current behavior) would resolve both: string-labeled dims get positional or user-supplied weights, and callers who mean array-order adjacency can say so. At minimum the docstring — currently just "The dimension values are used as SOS" (model.py:928) — should state that SOS2 adjacency follows sorted coordinate values, not array order.