Open Amoozegar opened 11 months ago
Hi @Amoozegar, for a continuous index you can use pandas' shift method to align the left and right hand sides of your constraint on the same index:
import pandas as pd
import gurobipy as gp
from gurobipy import GRB
import gurobipy_pandas as gppd
J = 5
model = gp.Model()
F = gppd.add_vars(model, pd.RangeIndex(1, J+1), name="F")
index = pd.RangeIndex(1, J) # 1 .. J-1 index for constraints
constraints = gppd.add_constrs(
model,
F.shift(-1).loc[index], # Shift F[j+1] term onto index j
GRB.LESS_EQUAL,
F.loc[index]
)
After updating the model you can check the result as follows:
>>> model.update()
>>> constraints.apply(model.getRow)
1 -1.0 F[1] + F[2]
2 -1.0 F[2] + F[3]
3 -1.0 F[3] + F[4]
4 -1.0 F[4] + F[5]
dtype: object
>>> constraints.gppd.Sense
1 <
2 <
3 <
4 <
dtype: object
>>> constraints.gppd.RHS
1 0.0
2 0.0
3 0.0
4 0.0
dtype: float64
@Amoozegar I would do it a bit differently than @simonbowly
If I started with the following df/series of variables:
I would do it with the following pandas .assign
and .shift
to do it all in one command, with the built in gurobipy-pandas accessor to add the constraint:
(
df.assign(f_j_plus_1=lambda df: df["f_j"].shift(-1))
.dropna()
.gppd.add_constrs(
model, "f_j_plus_1", grb.GRB.LESS_EQUAL, "f_j", name="constr_name"
)
)
Which yields the following constraints:
Subject To
constr_name[0]: - f[0] + f[1] <= 0
constr_name[1]: - f[1] + f[2] <= 0
constr_name[2]: - f[2] + f[3] <= 0
constr_name[3]: - f[3] + f[4] <= 0
constr_name[4]: - f[4] + f[5] <= 0
constr_name[5]: - f[5] + f[6] <= 0
constr_name[6]: - f[6] + f[7] <= 0
constr_name[7]: - f[7] + f[8] <= 0
constr_name[8]: - f[8] + f[9] <= 0
Thanks for the response. How about formulating "Fi,j+1,z <= Fi,j,z" ?
Sure. You have to use a groupby
then a shift
to do that. Let's say we start with the following variables over i, j, and z
I can create a new column that contains the shifted variables using the following code:
df.assign(f_ij_plus_1z=lambda df: df["f_ijz"].groupby(['i', 'z']).shift(-1)).dropna()
which would yield the following DataFrame.
Then finally I can take that same code and using the gurobipy-pandas accessor can create the constraints:
(
df.assign(f_ij_plus_1z=lambda df: df["f_ijz"].groupby(['i', 'z']).shift(-1))
.dropna()
.gppd.add_constrs(
model, "f_ij_plus_1z", grb.GRB.LESS_EQUAL, "f_ijz", name="constr_name"
)
)
And you can see it in the LP file written out:
Subject To
constr_name[0,0,0]: - f[0,0,0] + f[0,1,0] <= 0
constr_name[0,0,1]: - f[0,0,1] + f[0,1,1] <= 0
constr_name[0,0,2]: - f[0,0,2] + f[0,1,2] <= 0
constr_name[0,1,0]: - f[0,1,0] + f[0,2,0] <= 0
constr_name[0,1,1]: - f[0,1,1] + f[0,2,1] <= 0
constr_name[0,1,2]: - f[0,1,2] + f[0,2,2] <= 0
constr_name[0,2,0]: - f[0,2,0] + f[0,3,0] <= 0
constr_name[0,2,1]: - f[0,2,1] + f[0,3,1] <= 0
constr_name[0,2,2]: - f[0,2,2] + f[0,3,2] <= 0
constr_name[1,0,0]: - f[1,0,0] + f[1,1,0] <= 0
constr_name[1,0,1]: - f[1,0,1] + f[1,1,1] <= 0
constr_name[1,0,2]: - f[1,0,2] + f[1,1,2] <= 0
constr_name[1,1,0]: - f[1,1,0] + f[1,2,0] <= 0
constr_name[1,1,1]: - f[1,1,1] + f[1,2,1] <= 0
constr_name[1,1,2]: - f[1,1,2] + f[1,2,2] <= 0
constr_name[1,2,0]: - f[1,2,0] + f[1,3,0] <= 0
constr_name[1,2,1]: - f[1,2,1] + f[1,3,1] <= 0
constr_name[1,2,2]: - f[1,2,2] + f[1,3,2] <= 0
constr_name[2,0,0]: - f[2,0,0] + f[2,1,0] <= 0
constr_name[2,0,1]: - f[2,0,1] + f[2,1,1] <= 0
constr_name[2,0,2]: - f[2,0,2] + f[2,1,2] <= 0
constr_name[2,1,0]: - f[2,1,0] + f[2,2,0] <= 0
constr_name[2,1,1]: - f[2,1,1] + f[2,2,1] <= 0
constr_name[2,1,2]: - f[2,1,2] + f[2,2,2] <= 0
constr_name[2,2,0]: - f[2,2,0] + f[2,3,0] <= 0
constr_name[2,2,1]: - f[2,2,1] + f[2,3,1] <= 0
constr_name[2,2,2]: - f[2,2,2] + f[2,3,2] <= 0
I think it's worth adding these to the documentation as examples. Probably a time-indexed formulation of some kind is the logical place to showcase it.
I think it's worth adding these to the documentation as examples. Probably a time-indexed formulation of some kind is the logical place to showcase it.
That makes sense.
I need to add constraints that include two indices on a same variable. Here is an example: