Skip to main content

KeyError 10 in Constraint line of Python code; MCLP Optimization model building

Answered

Comments

7 comments

  • Official comment
    Simranjit Kaur
    • Gurobi Staff
    This post is more than two years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum, or try Gurobot, our chatbot interface offering instant, expert-level support.
  • Jaromił Najman
    • Gurobi Staff

    Could you please add to your code, how you define \(\texttt{num_customers}\) and \(\texttt{cartesian_prod}\)?

    1
  • Tanmoy Das
    • Gurobi-versary
    • Investigator
    • Collaborator

    num_facilities = len(facilities)
    num_customers = len(customers)
    cartesian_prod = list(product(range(num_customers), range(num_facilities)))

    0
  • Jaromił Najman
    • Gurobi Staff

    You are constructing your cartesian product over num_customers x num_facilities. In your constraint you access it via c,f in cartesian_prod, i.e., f is from num_facilities. But you constructed select over num_customers, thus you get a key error. You could try either adjusting your cartesian_prod list or how you construct the constraint.

    cartesian_prod = list(itertools.product(range(num_facilities),range(num_customers)))

    or

    constrain1 = model1.addConstrs((assign[f,c] >= select[f] for f,c in cartesian_prod), name='Constraint1')

    Best regards, 
    Jaromił

    0
  • Tanmoy Das
    • Gurobi-versary
    • Investigator
    • Collaborator

    Revised formulation below:

    # MIP model formulation
    model1 = gp.Model('MCLP v1')
    # Decision variables
    cover = model1.addVars(pairings, vtype=GRB.BINARY, name='Cover')
    select = model1.addVars(num_facilities, vtype=GRB.BINARY, name='Select')
    # Objective function
    objective1 = gp.quicksum(cover[c, f]*demand[c] for c,f in pairings)
    model1.setObjective(objective1, GRB.MAXIMIZE)
    # Constraints
    c1 = model1.addConstrs((cover[c,f] <= select[f] for c,f in pairings), name='c1')
    c2 = model1.addConstr((gp.quicksum(select[f] for f in range(num_facilities)) == T_maxStations), name='c2')
    #c3 = model1.addConstrs((cover.sum(c,'*') == 1 for c in range(num_customers)), name='c3')
    model1.write('Outputs/model1.lp')
    model1.optimize()

    I got the following output where each c is covered twice. I need c to be covered only once. Constraint c3 (commented in current code) would to the job, but, c3 makes model1 infeasible. 

    ['cover',
     MultiIndex([(0, 14),
                 (0, 15),
                 (2, 14),
                 (2, 15),
                 (3, 14),
                 (3, 15),
                 (4, 14),
                 (4, 15),
                 (5, 14),
                 (5, 15),
                 (6, 14),
                 (6, 15),
                 (9, 14),
                 (9, 15)],
                ),
     'select',
     Int64Index([14, 15], dtype='int64')]

     

    Expected output is something like below:

    ['cover',
     MultiIndex([(0, 14),
                 (2, 14),
                 (3, 15),
                 (4, 14),
                 (5, 15),
                 (6, 15),
                 (9, 14),,
                ),
     'select',
     Int64Index([14, 15], dtype='int64')]

    I think index in Constraint1 in this Python implementation is NOT accurately reflecting the math model.

    0
  • Jaromił Najman
    • Gurobi Staff

    The example you provided is not a minimal reproducible example. There are definitions missing, e.g., pairings, num_facilities, demand.

    Did you analyze the LP file you write to \(\texttt{Output/model1.lp}\)? Maybe you can spot some mistake in there. It might be useful to reduce the size of your model when analyzing the LP file.

    0
  • Tanmoy Das
    • Gurobi-versary
    • Investigator
    • Collaborator

    Hello Jaromil,

    I will keep your suggestions in mind. 
    I solved the conflict of C1 & C3 by changing comparison operator == into <= in C3 

    model1.addConstrs((cover.sum(c,'*') <= 1 for c in range(num_customers)), name='c3')

    0

Post is closed for comments.