Skip to main content

Inventory balance constraints in gurobipy-pandas framewoek




  • Riley Clement
    Gurobi Staff Gurobi Staff

    Hi Madhushini,

    We might need to see what your dataframes look like in order for someone to provide an appropriate answer.

    - Riley

  • Madhushini Narayana Prasad
    First Question

    Here is the snippet:

    I = ['a', 'b', 'c'] #List of facilities

    W = [1,2,3,4,5] #List of weeks

    P_initialWt = {'a': 0.1, 'b': 0.3, 'c': 0.2}

    data = pandas.DataFrame(list(product(I, W)), columns=['Facility', 'Week']).set_index(["Facility","Week"])

    m = gp.Model("Model1")

    CV_EndInv = gppd.add_vars(m, data, name="end_inv", lb=0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS)

    CV_StartInv = gppd.add_vars(m, data, name="start_inv", lb=0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS)


    #Constraint I am trying to model in pandas vectorized form is CV_StartInv[i,w] = CV_EndInv[i,w-1] if w > 1 else P_InitialWt[i], for all i in I and w in W.




  • Simon Bowly
    Gurobi Staff Gurobi Staff

    Hi Madhushini,

    In your initial data setup, you should first create P_initialWt as a pandas series over the same Facility index as your other data:

    P_initialWt = pd.Series({'a': 0.1, 'b': 0.3, 'c': 0.2}) = 'Facility'

    Your initial inventory constraints can then be created by aligning this data with your w=1 variables:

    initial = gppd.add_constrs(
        CV_StartInv.loc[:, 1],  # All facilities, time step 1

    For the balance constraints, you will need to shift the position of the CV_EndInv variables relative to the Week index, before aligning with the start variables. One way to do this is as follows:

    # Shift the end variables so that 'w' in the index aligns with
    # the 'w-1' variable
    lhs = CV_EndInv.groupby("Facility").transform(lambda s: s.shift(1)).dropna()
    # Extract only the 'w > 1' part of the start variables
    rhs = CV_StartInv.loc[:, 2:]
    # Both series are now on the index w = 2..5, so can be aligned
    balance = gppd.add_constrs(m, lhs, GRB.EQUAL, rhs, name="Balance")

    A quick sense-check of the result is helpful to make sure all the index alignment was done correctly. Here we get the linear terms for all constraints (internally, the constraint is stored as "end[w-1] - start[w] == 0"):

    m.update()  # Update the model so constraints can be read back
    Facility  Week
    a 2 end_inv[a,1] + -1.0 start_inv[a,2]
    3 end_inv[a,2] + -1.0 start_inv[a,3]
    4 end_inv[a,3] + -1.0 start_inv[a,4]
    5 end_inv[a,4] + -1.0 start_inv[a,5]
    b 2 end_inv[b,1] + -1.0 start_inv[b,2]
    3 end_inv[b,2] + -1.0 start_inv[b,3]
    4 end_inv[b,3] + -1.0 start_inv[b,4]
    5 end_inv[b,4] + -1.0 start_inv[b,5]
    c 2 end_inv[c,1] + -1.0 start_inv[c,2]
    3 end_inv[c,2] + -1.0 start_inv[c,3]
    4 end_inv[c,3] + -1.0 start_inv[c,4]
    5 end_inv[c,4] + -1.0 start_inv[c,5]
    Name: Balance, dtype: object

Please sign in to leave a comment.