• Gurobi Staff

Hi Roee,

I don't know if this is the best approach, but here's an idea. First, estimate the upper limit for the variable. The program you have written does not have upper bounds on variables, but in general, specifying upper bounds has a positive effect on solving performance.

Then define a new binary variable z. When this variable is 1, the corresponding y value is suppressed to 0. This can be achieved by using the following constraint:
\begin{align*} y_{i} \leq M(1-z_{i}) \quad \forall i \end{align*}
where M is a sufficiently large constant, for example, the upper bound on y estimated earlier can be used.

The constraint that at least one of the subsets of y must be zero is satisfied by:
\begin{align*} \sum_{i \in I} z_{i} = 1 \quad \forall I \in \text{index_sets} \end{align*}
Here index_sets comes from your program, so the set $$I$$ will loop {0, 1, 2}, {3, 4}, {2, 6, 7}.

Regards,
Ryuta

Hi Ryuta,

Thank you very much  for the reply,

Do you mean something like this:

epsilon = 1e-6
for i in range(len(numpy_h)):
m.addGenConstrIndicator(b[i], True, y[i] == 0, name=f"indicator_y_zero_b_one_{i}")
m.addGenConstrIndicator(b[i], False, y[i] >= epsilon, name=f"indicator_y_nonzero_b_zero_{i}")

for idx, index_list in enumerate(paths_edges_indexs):
m.addConstr(gp.quicksum(b[i] for i in index_list ) >= 1, f"at_least_one_zero_{idx}")

From what I understood I should try to avoid indexing individual elements of the MVar, is there a more efficient way to do it?

Best Regards
Roee
• Gurobi Staff

Hi Roee,

As described in this post, addGenConstrIndicator() should support MVar. Therefore, you can write like this:

m.addGenConstrIndicator(b, True, y == 0, name=f"indicator_y_zero_b_one")
m.addGenConstrIndicator(b, False, y >= epsilon, name=f"indicator_y_nonzero_b_zero")

For the second constraint, it may be sufficient to create the corresponding matrix.

import scipy.sparse as spindex_sets = [{0, 1, 2}, {3, 4}, {2, 6, 7}]row = [0, 0, 0, 1, 1, 2, 2, 2]col = [0, 1, 2, 3, 4, 2, 6, 7]A = sp.csr_matrix(([1 for i in range(len(row))], (row, col)), shape=(len(index_sets), len(numpy_h)))m.addConstr(A @ b >= 1)

Here, A is a scipy.sparse matrix whose corresponding part of the index_sets has the value 1.

Regards,
Ryuta