Some cases of invalid data produce error messages from the gurobipy layer, but we could possibly catch them earlier and provide a better error message by attempting a cast to numeric type. The difficulty is distinguishing from cases which are legitimate gurobipy objects (would be easier with extension types for gurobipy objects).
Example:
import pandas as pd
import gurobipy as gp
from gurobipy import GRB
import gurobipy_pandas as gppd
model = gp.Model()
i = pd.Index([1, 2, 3], name="i")
x = gppd.add_vars(model, i, name="x")
rhs = pd.Series(index=i, data=[1, 2, "a"])
gppd.add_constrs(model, x, GRB.EQUAL, rhs, name="c")
Output:
Traceback (most recent call last):
File "src/gurobipy/model.pxi", line 3256, in gurobipy.Model.addLConstr
ValueError: could not convert string to float: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "src/gurobipy/model.pxi", line 3259, in gurobipy.Model.addLConstr
gurobipy.GurobiError: Invalid argument to Model.addLConstr
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/bowly/workspaces/gurobipy-pandas/bug.py", line 10, in <module>
gppd.add_constrs(model, x, GRB.EQUAL, rhs, name="c")
File "/Users/bowly/workspaces/gurobipy-pandas/src/gurobipy_pandas/api.py", line 198, in add_constrs
return add_constrs_from_series(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/bowly/workspaces/gurobipy-pandas/src/gurobipy_pandas/constraints.py", line 89, in add_constrs_from_series
return add_constrs_from_dataframe(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/bowly/workspaces/gurobipy-pandas/src/gurobipy_pandas/constraints.py", line 57, in add_constrs_from_dataframe
return _add_constrs_from_dataframe_args(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/bowly/workspaces/gurobipy-pandas/src/gurobipy_pandas/constraints.py", line 193, in _add_constrs_from_dataframe_args
constrs = [
^
File "/Users/bowly/workspaces/gurobipy-pandas/src/gurobipy_pandas/constraints.py", line 194, in <listcomp>
_add_constr(
File "/Users/bowly/workspaces/gurobipy-pandas/src/gurobipy_pandas/constraints.py", line 144, in _add_constr
return model.addLConstr(lhs, sense, rhs, name=name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "src/gurobipy/model.pxi", line 3350, in gurobipy.Model.addLConstr
gurobipy.GurobiError: Invalid argument to Model.addLConstr
Calling pd.to_numeric(rhs) gives a potentially more informative error to the user:
Traceback (most recent call last):
File "pandas/_libs/lib.pyx", line 2369, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "a"
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/bowly/workspaces/gurobipy-pandas/bug.py", line 10, in <module>
pd.to_numeric(rhs)
File "/Users/bowly/.pyenv/versions/3.11.2/lib/python3.11/site-packages/pandas/core/tools/numeric.py", line 185, in to_numeric
values, _ = lib.maybe_convert_numeric(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "pandas/_libs/lib.pyx", line 2411, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "a" at position 2
Some cases of invalid data produce error messages from the gurobipy layer, but we could possibly catch them earlier and provide a better error message by attempting a cast to numeric type. The difficulty is distinguishing from cases which are legitimate gurobipy objects (would be easier with extension types for gurobipy objects).
Example:
Output:
Calling
pd.to_numeric(rhs)
gives a potentially more informative error to the user: