Skip to main content

Constraints doesn't work

Answered

Comments

9 comments

  • Official comment
    Simranjit Kaur
    • Gurobi Staff
    This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum. Or why not try our AI Gurobot?.
  • Eli Towle
    • Gurobi Staff

    Hi Xiangfeng,

    Do you have a few lines of code that show how the data ( \(\texttt{speed}\), \(\texttt{bw}\), etc.) is defined for a small instance of the problem?

    Thanks,

    Eli

    0
  • Xiangfeng Zhu
    • Gurobi-versary
    • First Question
    • Conversationalist

    Hi Eli,

     

    Thanks for your prompt reply! For example, if there are two classes of interest and there are 5 clients.

    num_of_class = 2
    num_of_clients = 5
    preference = [50, 50] # We want 50 samples of class 1 and 50 samples of class 2
    datas  = [[15, 5], [35, 20], [40, 20], [30, 15], [70, 19]] # client 1 holds 15 samples of class 1 and 5 samples of class 2 etc.
    speed = [0.13, 0.10, 0.15, 0.20] # client 1 needs .013 seconds to process a sample , client 2 needs .010 secs, etc.
    bw = [20, 10, 23, 5] # client 1 needs 20 secs to transmit the information ...

    Please let me know if you have any questions. Thansk so much!!!

     

     

     

    0
  • Xiangfeng Zhu
    • Gurobi-versary
    • First Question
    • Conversationalist

    Hi Eli,

    Sorry to bother you, but any ideas? 

    Thanks,

    Xiangfeng

    0
  • Eli Towle
    • Gurobi Staff

    Hi Xiangfeng,

    I added an element to your \( \texttt{speed} \) and \( \texttt{bw} \) lists. They each contain four elements, but \( \texttt{num_of_clients = 5} \).

    speed = [0.13, 0.10, 0.15, 0.20, 0.25]
    bw = [20, 10, 23, 5, 10]

    What exactly isn't correct with the solution? The model has the following constraints:

    slowest >= 20 + 0.00013 quantity[0,0] + 0.00013 quantity[0,1] 
    slowest >= 10 + 0.0001 quantity[1,0] + 0.0001 quantity[1,1]
    slowest >= 23 + 0.00015 quantity[2,0] + 0.00015 quantity[2,1] 
    slowest >= 5 + 0.0002 quantity[3,0] + 0.0002 quantity[3,1] 
    slowest >= 10 + 0.00025 quantity[4,0] + 0.00025 quantity[4,1]

    The values of \( \texttt{bw} \) dominate the right-hand sides of these inequalities, since the \( \texttt{quantity} \) variables have tiny coefficients and relatively small upper bounds:

    quantity[0,0] <= 15
    quantity[0,1] <= 5
    quantity[1,0] <= 35
    quantity[1,1] <= 20
    quantity[2,0] <= 40
    quantity[2,1] <= 20
    quantity[3,0] <= 30
    quantity[3,1] <= 15
    quantity[4,0] <= 70
    quantity[4,1] <= 19

    So, the optimal solution is to assign the samples such that the client with the highest transmission time doesn't run any samples. In this case, the optimal objective function value is 23 (the largest value in \( \texttt{bw} \)).

    Maybe a client's processing time \( \texttt{bw} \) should only be counted if the client is assigned at least one sample?

    If the model doesn't seem correct, you can use Model.write() to write an LP file to visually inspect the model. E.g.:

    m.write('model.lp')

    Thanks,

    Eli

    0
  • Xiangfeng Zhu
    • Gurobi-versary
    • First Question
    • Conversationalist

    >Maybe a client's processing time should only be counted if the client is assigned at least one sample?

    Yes! I think that might be the problem. I'll check this. Thanks so much!

    0
  • Xiangfeng Zhu
    • Gurobi-versary
    • First Question
    • Conversationalist

    Hi Eli,

    I really appreciate your help and I'm trying to fix the problem. However, it seems like it didn't work. (the slowest is smaller than the data transmission time)

    status = m.addVars([i for i in range(num_of_clients)], vtype = GRB.BINARY, name = 'status') # Binary var indicates the selection status
    for i in range(num_of_clients):
        m.addGenConstrIndicator(status[i], True, gp.quicksum([quantity[(i, j)] for j in range(num_of_class)]) >= 0.9)


    # Minimize the slowest(I removed bw[i] from the time_list)
    for idx, t in enumerate(time_list):
        m.addConstr(slowest >= t + status[idx] * bw[idx], name=f'slow_{idx}')

     

    I think the problem is this line:

    m.addGenConstrIndicator(status[i], True, gp.quicksum([quantity[(i, j)] for j in range(num_of_class)]) >= 0.9)

    What's the correct approach to set this indicator constraint? I think >= 0.9 doesn't work, but I don't know how to solve it

    Thanks so much! 

    0
  • Eli Towle
    • Gurobi Staff

    Hi Xiangfeng,

    Right now, that constraint is structured for the implication \( \texttt{status[i]} = 1 \implies f_i(x) \geq 0.9 \), where \( f_i(x) \) represents the quantity of samples assigned to client \( i \). With this approach, it can (and will) happen that \( f_i(x) \) is greater than \( 0.9 \), but \( \texttt{status[i]} \) is equal to \( 0 \). Thus, the \( \texttt{bw} \) terms on the RHS of the "slow" constraints won't ever matter.

    I think what you really want is the converse: \( f_i(x) \geq 1 \implies \texttt{status[i]} = 1 \). In other words, if any quantity of samples is assigned to client \( i \), we force \( \texttt{status[i]} \) to \( 1 \), which adds the corresponding \( \texttt{bw} \) value to that client's "slow" constraint. We can rewrite this implication in terms of the (logically equivalent) contrapositive: \( \texttt{status[i]} = 0 \implies f_i(x) \leq 0 \). Note that the right side of this implication should really be \( f(x) < 1 \), but since \( f_i(x) \) is integer-valued, this is equivalent to \( f_i(x) \leq 0 \).

    Then, following the documentation for Model.addGenConstrIndicator():

    status = m.addVars(num_of_clients, vtype=GRB.BINARY, name='status')
    for i in range(num_of_clients):
    m.addGenConstrIndicator(status[i], False, quantity.sum(i, '*') <= 0)

    Does this work for you?

    Eli

    0
  • Xiangfeng Zhu
    • Gurobi-versary
    • First Question
    • Conversationalist

    Hi Eli,

    I think you're right. I think didn't understand how Model.addGenConstrIndicator()  works before. Thanks so much for your help.

    Xiangfeng

    0

Post is closed for comments.