Gurobi / gurobipy-pandas

Convenience wrapper for building optimization models from pandas data
https://gurobipy-pandas.readthedocs.io/en/stable/
Apache License 2.0
83 stars 15 forks source link

Could the sense be a series rather than a scalar string when adding constraints? #58

Closed jacksimpsoncartesian closed 8 months ago

jacksimpsoncartesian commented 9 months ago

Was there any chance it might be possible for the sense parameter in the add_constrs method have the option of being a series/column instead of a single string?

In energy market modelling we often have 'generic constraint' sets governing power station behaviour where there can be a mix of sense values used. It would be really helpful to be able to just have the add_constrs method pick up the sense directly from a dataframe column.

By the way, really loving using gurobipy-pandas at the moment!

simonbowly commented 9 months ago

@jacksimpsoncartesian thanks for raising this, glad to hear you're finding the library useful :-)

Sure, this seems like a reasonable addition. We initially didn't set up vectorization for categorical arguments (i.e. sense & vtype) since it seemed like these should not vary in most user-code for a set of constraints of the same type. For example, in a set of capacity constraints the sense is always <= and only the numerical data in the constraint varies for each capacitated item.

Could you expand a bit on the use case here or give a brief example? One thing I am wondering is whether a mix of constraint senses really belong in the same API call, or whether the data should somehow be grouped differently to avoid doing this.

simonbowly commented 9 months ago

Minor side note: for the DataFrame.gppd.add_constrs accessor, one concern is that it is hard to unambiguously interpret an argument which can either take a string value or a column name. e.g. for vtype the following would be a potential gotcha for users if we allowed both cases:

df.gppd.add_vars(model, ..., vtype="C")  # Does the user mean that a column named
                                         # 'C' should define the variable types, or that
                                         # all these variables should be continuous?

As a result currently vtype is not allowed to be a column name, we always interpret it as a constant (and I would be very hesitant to change that). However, for sense such a clash seems unlikely (though not impossible) since a user would have to create a column named <, >, or =.

jacksimpsoncartesian commented 9 months ago

Thanks so much Simon! So for large energy market models we often maintain big input files with sets of generic constraints forcing sets of power stations to generate above or below certain levels. Often modelling teams are maintaining these files rather than the developer themselves.

image

Most of the time these are <= constraints, however we will often run into situations where we want certain categories of generator to maintain a minimum output for system security and so there may be a mix of >= constraints in there as well.

It's mainly the sense that is valuable to have input as a series and be changing in the same constraint set - I can't think of a scenario where we'd need to have the vtype be an input as well.

It's not the end of the world if this is a pain on your end - I mainly just have to split up these kinds of input dataframes into multiple dataframes based on the sense and then apply the constraint to them. That said, if it was possible for the sense to be an optional series that would make things a bit easier and cleaner :)

simonbowly commented 9 months ago

Makes sense! :-P

I agree, it's nice to have a way to specify range constraints which don't always have both bounds. I've implemented this on my fork; there is a bit more to do to handle invalid inputs and to document this option. I'll work on that soon. If you have a chance to test this you can install the development branch using:

pip install --force-reinstall git+https://github.com/simonbowly/gurobipy-pandas@series-of-senses
jacksimpsoncartesian commented 9 months ago

Thanks so much! Just installed the fork and will test it out tomorrow - I've been doing a bunch of updates to my code handling this category of generic constraint inputs so will be keen to see how this plays with the changes :)

simonbowly commented 8 months ago

Implemented in #59