I recently started optimization with Gurobi-Python and I'm having some trouble here. I hope that someone can help me. I am describing a simple part of the problem that I am struggling with. I want to make an entity that is composed of 3 items which should be selected from 3 groups (only one item could be selected from each group). A pair of items has a strength index, so the pairs with the highest indices are desirable. In this case, only 2 pairs are required to make the entity (and all itemms are included). I am having problem with the formulation of the constraints. If I run the model without the 4th constraint. The solution includes all 12 pairs instead of 3pairs. If I include the 4th constraint in order to select the desirable 2 pairs, the model does not run. Please help in formulating these constraints correctly. See the model:
from gurobipy import *
GroupA = ['ItemA1', 'ItemA2']
GroupB = ['ItemB1', 'ItemB2']
GroupC = ['ItemC1', 'ItemC2']
Grppair, Index = multidict({
('ItemA1', 'ItemB1'): 0.8, ('ItemA1', 'ItemB2'): 0.75,
('ItemA2', 'ItemB1'): 0.45, ('ItemA2', 'ItemB2'): 0.35,
('ItemB1', 'ItemC1'): 0.45, ('ItemB1', 'ItemC2'): 0.55,
('ItemB2', 'ItemC1'): 0.5, ('ItemB2', 'ItemC2'): 0.65,
('ItemA1', 'ItemC1'): 0.55, ('ItemA1', 'ItemC2'): 0.75,
('ItemA2', 'ItemC1'): 0.55, ('ItemA2', 'ItemC2'): 0.55 })
Grppair = tuplelist(Grppair)
m = Model('NPD')
# Create variables for GrpAB
GrpAB = {}
for i in GroupA:
for j in GroupB:
GrpAB[i,j] = m.addVar(vtype=GRB.BINARY, obj=Index[i,j])
# Create variables for GrpBC
GrpBC = {}
for j in GroupB:
for k in GroupC:
GrpBC[j,k] = m.addVar(vtype=GRB.BINARY, obj=Index[j,k])
# Create variables for GrpAC
GrpAC = {}
for i in GroupA:
for k in GroupC:
GrpAC[i,k] = m.addVar(vtype=GRB.BINARY, obj=Index[i,k])
m.modelSense = GRB.MAXIMIZE
m.update()
# constraint1: select a AB pair
for i in GroupA:
for j in GroupB:
m.addConstr(quicksum(GrpAB[i,j] for i, j in Grppair.select(i,j)) <=1)
# constraint2: Select BC pair
for j in GroupB:
for k in GroupC:
m.addConstr(quicksum(GrpBC[j,k] for j, k in Grppair.select(j,k)) <=1)
# constraint3: Select AC pair
for i in GroupA:
for k in GroupC:
m.addConstr(quicksum(GrpAC[i,k] for i, k in Grppair.select(i,k)) <=1)
# Constraint4: Select 2 pairs from above (and all three items are included)
### m.addConstr((quicksum(GrpAB[i,j] for i, j in Grppair.select(i,j))
## + quicksum(GrpBC[j,k]) for j, k in Grppair.select(j,k)
## + quicksum(GrpAC[i,k] for i, k in Grppair.select(i,k))) == 2)
m.optimize()
if m.status == GRB.OPTIMAL:
solution = m.getAttr('X')
print('\nINDEX: %g' % m.objVal)
for i,j in GrpAB:
if GrpAB[i,j].x == 1.0:
print('%s_%s pair is included in the product' % (i,j))
else:
print('%s_%s pair is not in the product' % (i,j))
for j,k in GrpBC:
if GrpBC[j,k].x == 1:
print('%s_%s pair is included in the product' % (j,k))
else:
print('%s_%s pair is not in the product' % (j,k))
for i,k in GrpAC:
if GrpAC[i,k].x == 1:
print('%s_%s pair is included in the product' % (i,k))
else:
print('%s_%s pair is not in the product' % (i,k))