Skip to main content

Constraining on parts of vector

Answered

Comments

3 comments

  • Ryuta Tamura
    Gurobi Staff 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}.

    Is this helpful?

    Regards,
    Ryuta

     

    0
  • Roee Idan
    First Comment
    First Question

    Hi Ryuta,

    Thank you very much  for the reply,

    Do you mean something like this:

    b = m.addMVar(shape=len(numpy_h), vtype=gp.GRB.BINARY, name="b")
    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
    0
  • Ryuta Tamura
    Gurobi Staff 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 sp

    index_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

    0

Please sign in to leave a comment.