• Gurobi Staff

Hi Abdul,

Your code is currently adding a constraint for every $$i = 1, ..., N-1$$. In particular, the code corresponds to the following $$N - 1$$ constraints:

$$\sum_{j = 2}^N t_{ij} x_{ij} \leq T_{\text{max}} \quad i = 1, ..., N-1$$

Instead, you should incorporate the for loop into the summation:

opt_model.addConstr((grb.quicksum(x_vars[i,j]*distance(points, i, j) for j in range(1,n) for i in range(n-1))) <= Distance)

I hope this helps!

Eli

Dear Eli,

Yes it solved the problem!. Also kudos for illustrating what the existing code was doing. So the code was merely adding a constraint on i, i.e. what values it can take, but was not permutating the values of i with j and summing that up. Right?

Best,

Abdul

• Gurobi Staff

Hi Abdul,

The code was adding a constraint for every $$i$$ rather than a single constraint that sums over every value of $$i$$. You can tell this immediately by looking at the structure of the code:

for i in range(n-1):  opt_model.addConstr(...)

Here, we are looping over the addConstr() method N-1 times. This means N-1 constraints are added to the model, which doesn't match what we want to do. If we want to add a single constraint, we should only call the addConstr() method once.

Thanks!

Eli

Dear Eli,

Quite nicely explained!

Thanks a lot!
Abdul

Dear Eli,

I have one last question pertaining to the constraints. Can we add multiple constraints in a single expression or it has to be separated. Consider the following equation:

Can this be written down as:

for k in range(1, n-1):  opt_model.addConstr(grb.quicksum(x_vars[i,k] for i in range(n-1))                      == grb.quicksum(x_vars[k,j] for j in range(1, n)))for k in range(1, n-1):  opt_model.addConstr(grb.quicksum(x_vars[i,k] for i in range(n-1))                       <=1)  for k in range(1, n-1):      opt_model.addConstr(grb.quicksum(x_vars[k, j] for j in range(1, n))                          <= 1)

Instead of a single equation as :

for k in range(1, n-1):  opt_model.addConstr(grb.quicksum(x_vars[i,k] for i in range(n-1))                      == grb.quicksum(x_vars[k,j] for j in range(1, n)) <= 1)

Because the results differ in each case.

• Gurobi Staff

Hi Abdul,

In the Gurobi 8.1 documentation for Model.addConstr(), there is a warning that adding multiple constraints via the addConstr() method is not supported. In Gurobi 9.0 (scheduled for release in a few weeks), your second code snippet will result in an error.

Hence, you should use the first approach to add these two sets of constraints. I have two brief comments:

1. The third set of constraints isn't necessary, because this constraint family is implied by the first two. For example, if you add constraints that $$x = y$$ and $$x \leq 1$$, then the constraint $$y \leq 1$$ will automatically be satisfied.
2. The Model.addConstrs() method is perfectly suited for situations where you are adding constraints in a for loop. With this method, you can enforce these constraints in two lines:
opt_model.addConstrs((grb.quicksum(x_vars[i,k] for i in range(n-1)) == grb.quicksum(x_vars[k,j] for j in range(1, n))) for k in range(1, n-1))opt_model.addConstrs((grb.quicksum(x_vars[i,k] for i in range(n-1)) <= 1) for k in range(1, n-1))

I hope this helps. Thanks!

Eli

Dear Eli,

Wow Awsome! Great explanation with good insights!

I shall remove the redundancy and make my code compact.

Cheers,

Abdul