How to select a pair or some pairs from multiple pairs in Gurobi Python interface

187 views
Skip to first unread message

Johnson

unread,
Aug 13, 2016, 12:39:09 PM8/13/16
to Gurobi Optimization
Hello guys,

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))



Thanks,
Johnson

Sonja Mars

unread,
Aug 15, 2016, 6:08:28 AM8/15/16
to gur...@googlegroups.com
Hi,

When looking at your code I see three issues:

First one:
> # 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)
There is a ")" at the wrong place in the second quicksum. It should look like this:
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)

Second one:
> solution = m.getAttr('X')
X is not a model attribute, it belongs to a variable. Please see here for more details on attributes:http://www.gurobi.com/documentation/6.5/refman/attributes.html

and here for an example on how to query X:
http://www.gurobi.com/documentation/6.5/examples/diet_py.html

Third one:
> if GrpAB[i,j].x == 1.0:

Gurobi works with tolerances, so this comparison can cause some trouble as the variable value might not be exactly 1.0, but 0.9999999999. Please also see FAQ #26: "Why does Gurobi sometimes return values for integer variables that are not integers? " on this page: http://www.gurobi.com/support/faqs

If the model still gives not the desired result after fixing the above issues, you might want to write your model as an LP-file (https://www.gurobi.com/documentation/6.5/refman/py_model_write.html) and look at this file. So you can see if all the constraints look the way you think should do.

Best regards,
Sonja

-----------------------------------------------------------------
Dr. Sonja Mars
Gurobi Optimization

Johnson

unread,
Aug 16, 2016, 4:22:00 PM8/16/16
to Gurobi Optimization
Thanks Dr. Mars. I am working on it.

Regards,
Johnson
Reply all
Reply to author
Forward
0 new messages