KeyError 10 in Constraint line of Python code; MCLP Optimization model building
AnsweredI am trying to implement a constraint of the maximal coverage problem (Equation 16.2 from the image at the bottom of this post). A minimal Python code is below.
But the code is giving me error KeyError: 10 in Constraint1 (bold line in the code). Explanation of Keyerror seems like certain index values might not exist. I check my data, all index values iterating c,f are available in cartesian_prod.
model1 = gp.Model('facility_location')
select = model1.addVars(num_customers, vtype=GRB.BINARY, name='Select')
assign = model1.addVars(cartesian_prod, ub=1, vtype=GRB.CONTINUOUS, name='Assign')
constrain1 = model1.addConstrs((assign[c,f] >= select[f] for c,f in cartesian_prod), name='Constraint1')

-
Could you please add to your code, how you define \(\texttt{num_customers}\) and \(\texttt{cartesian_prod}\)?
1 -
num_facilities = len(facilities)
num_customers = len(customers)
cartesian_prod = list(product(range(num_customers), range(num_facilities)))0 -
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 -
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 -
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 -
Hello Jaromil,
I will keep your suggestions in mind.
I solved the conflict of C1 & C3 by changing comparison operator == into <= in C3model1.addConstrs((cover.sum(c,'*') <= 1 for c in range(num_customers)), name='c3')
0
Please sign in to leave a comment.
Comments
6 comments