How to implement this constraint using addConstrs in Python?

2,262 views
Skip to first unread message

luukve

unread,
Feb 7, 2017, 12:32:12 PM2/7/17
to Gurobi Optimization
Hi, I am creating a timetabling program using ILP. In the timetable I am supposed to create, sometimes an order is defined in which some events need to take place.

I have binary variables x_{i,j,k} which indicate whether or not event 'i' is scheduled in timeslot 'j' in room 'k'. 

Suppose event 'a' needs to happen some time before event 'b'. I have tried adding constraints like this:

m.addConstrs(   (x.sum(a,j,'*') - (x.sum(b,j2,'*')) == 0 for j in range(timeslots) if (j2 > j)), "Order")

In other words, I am trying to create a constraint for each timeslot j which I associate with event 'a'. I sum over all the possible rooms event 'a' can be scheduled in in timeslot 'j', and then I make sure that event 'b' is scheduled sometime after that (j2 > j) by summing over all the variables associated to event 'b' and timeslot 'j2', and make the difference between these sums zero. 

I know for a fact the model is correct: I have used the same constraint by writing it in .lp file format. The problem is the error message that global name "j2" is not defined. 
This is confusing to me, because I have another constraint:

m.addConstrs((   x.sum(i,j,'*') <= 1 for j in range(timeslots) if i in set ), "Overlap"  )

where it does not complain about i not being defined. When I change the i's in this constraint into another letter it does give me the same error however.

Might be relevant to know I created and added variables like this:

v = [(i,j,k) for i in eventnames for j in range(timeslots) for k in roomnames]
x
= m.addVars(v, name="x", vtype=GRB.BINARY)

So this leads to the questions:
1. Why is it so sensitive to which letter I am using when I am just using it as index?
2. How do I resolve the problem of using another letter in my constraint than the ones I used to create the variables with?

des...@gurobi.com

unread,
Feb 7, 2017, 1:15:28 PM2/7/17
to Gurobi Optimization

Can you try this:

m.addConstrs(   (x.sum(a,j,'*') - (x.sum(b,j2,'*')) == 0 for j in range(timeslots) for j2 in range(timeslots) if (j2 > j)), "Order")


Amal de Silva
Gurobi Optimization

luukve

unread,
Feb 8, 2017, 3:06:42 AM2/8/17
to Gurobi Optimization
Hi Amal,

The problem is that it will then create a constraint for every possible pair of j and j2, right?
But that's not what I want. I want to create a constraint for every j and in each constraint sum over all j2 > j. 

Like I did with this constraint:

m.addConstrs((   x.sum(i,j,'*') <= 1 for j in range(timeslots) if i in set ), "Overlap"  )

I create a constraint for each j and in each constraint I sum over all i with a certain property (namely that it is in a certain set). I want to do a similar thing, but it does not recognize j2 but it does recognise i in this constraint.


Op dinsdag 7 februari 2017 19:15:28 UTC+1 schreef des...@gurobi.com:

des...@gurobi.com

unread,
Feb 8, 2017, 5:34:38 PM2/8/17
to Gurobi Optimization

Sorry, I misunderstood your question. You can use quicksum for this.
https://www.gurobi.com/documentation/7.0/refman/py_quicksum.html

You can include the if condition inside the quick sum such as  given below:

m.addConstrs(   (x.sum(a,j,'*') - quicksum(x[b,j2,k] for j2 in range(timeslots) for k in roomnames if j2 > j) ) == 0 for j in range(timeslots), "Order")



On Tuesday, February 7, 2017 at 9:32:12 AM UTC-8, luukve wrote:

luukve

unread,
Feb 9, 2017, 3:25:27 AM2/9/17
to Gurobi Optimization
That does the job, thanks a lot!

Op woensdag 8 februari 2017 23:34:38 UTC+1 schreef des...@gurobi.com:
Reply all
Reply to author
Forward
0 new messages