メインコンテンツへスキップ

Constraint has no bool value (are you trying "lb <= expr <= ub"?)

進行中

コメント

16件のコメント

  • Sagnik Basumallik
    Gurobi-versary
    Investigator
    Conversationalist

    I had to break the constraint into two parts and it worked

    m.addConstrs(0 <= f1[i,j,h] for i,j in arcs for h in area) #(4g)
    m.addConstrs(f1[i,j,h] <= 200*z[i,j] for i,j in arcs for h in area) #(4g)

     

    I am wondering why this change was made!

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Hi Sagnik,

    Adding two-sided constraints was never supported in Gurobi 8.1.1. This is noted in the Gurobi 8.1.1 documentation here:

    "Note that double inequality constraints, like 1 <= x + y <= 2 or 1 <= x[i] + y[i] <= 2 for i in range(3) are NOT supported in this API, and will result in one of the inequalities to be silently disregarded, which will result in unexpected behavior."

    For example, consider the following code:

    m = Model()
    x = m.addVar(name="x")
    m.addConstr(1 <= x <= 2, name="twosided")

    In Gurobi 8.1.1, this results in the following model (in LP format):

    Minimize

    Subject To
      twosided: x <= 2
    Bounds
    End

    Note the missing constraint. This change of behavior in Gurobi 9.0 simply disallows this syntax, preventing unexpected behavior like this.

    In your example, is f1 is a variable? If so, it is nonnegative by default (unless you explicitly set its lower bound), so you may not even need the nonnegativity constraint.

    I hope this helps. Thanks!

    Eli

     

    0
  • Sagnik Basumallik
    Gurobi-versary
    Investigator
    Conversationalist

    thank you so much! 

    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Hello, I am having a similar problem, I know that if we want to write a constraint like this \(LB \leq v \leq UB\) I have to do it separately so, I wrote them like this:

    rxn = ['a','b','c','d','e']

    LB = [-1000,0,-1000,0,-1000]

    UB = [1000,1000,1000,1000,1000]

    reactions = [i for i in range(len(rxn))]

    m = gp.Model()

    vo = m.addVars(range(len(rxn),name='v')

    m.addConstrs((LB[j] <= vo[j] for j in reactions), name='LB')

    m.addConstrs((vo[j] <= UB[j] for j in reactions), name='UB)

    And I get the same error:

    ---> 16 f.addConstrs((LB[j] <= v[j] for j in reactions), name='LB')
         17 
         18 f.addConstrs((v[j] <= UB[j] for j in reactions), name='UB')
    
    src\gurobipy\tempconstr.pxi in gurobipy.gurobipy.TempConstr.__bool__()
    
    GurobiError: Constraint has no bool value (are you trying "lb <= expr <= ub"?)

     

    Ultimately I want to have a set of constraints like this:

    \[LB*y_j \leq v_j \leq UB*y_j\] for j in a knockout set and:

    \[LB \leq v_j \leq UB\] if j not in the knockout set, the easiest way I could think of is:

    for j in reactions:
    if j in knockout:
    m.addConstr((LB[j] * yo[j] <= vo[j]), name='LBy')
    m.addConstr((vo[j] <= yo[j] * UB[j]), name='UBy')
    else:
    m.addConstr((LB[j] <= vo[j]), name='LB')
    m.addConstr((vo[j] <= UB[j]), name='UB')

    It is worth to mention that \(v_o\) is a continuous variable and \(y_o\) is binary, I would appreciate some help with this.

    Thanks in advance

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Which version of Gurobi are you using? The first code snippet is missing a parenthesis in the call to Model.addVars() and an apostrophe in the last line. Otherwise, the code should work as intended. I.e., the snippet

    import gurobipy as gp

    rxn = ['a', 'b', 'c', 'd', 'e']
    LB = [-1000, 0, -1000, 0, -1000]
    UB = [1000, 1000, 1000, 1000, 1000]
    reactions = [i for i in range(len(rxn))]

    m = gp.Model()
    vo = m.addVars(range(len(rxn)), name='v')
    m.addConstrs((LB[j] <= vo[j] for j in reactions), name='LB')
    m.addConstrs((vo[j] <= UB[j] for j in reactions), name='UB')

    adds the following constraints to the model:

    LB[0]: v[0] >= -1000
    LB[1]: v[1] >= 0
    LB[2]: v[2] >= -1000
    LB[3]: v[3] >= 0
    LB[4]: v[4] >= -1000
    UB[0]: v[0] <= 1000
    UB[1]: v[1] <= 1000
    UB[2]: v[2] <= 1000
    UB[3]: v[3] <= 1000
    UB[4]: v[4] <= 1000
    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Hello Eli,

    Thanks for your answer, 

    I am using 9.1.0 and python 3.7.6

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Can you please try running the code snippet I posted, and also post the output of \( \texttt{gp.gurobi.version()} \)? The error message you posted does not match the code you posted (the error message references a model named \( \texttt{f} \) instead of \( \texttt{m} \)).

    Note that since \( \texttt{LB} \) and \( \texttt{UB} \) are bounds on the \( \texttt{vo} \) variables, you could just assign these bounds in the call to Model.addVars():

    vo = m.addVars(range(len(rxn)), lb=LB, ub=UB, name='v')

    Of course, this approach won't work for constraints of the form \( \ell y_j \leq v_j \leq u y_j \), which you're working towards.

    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Hello Eli, 

    I ran the code snippet you posted and it gives me the same constraints as you wrote 

    These are the actual constraints I have written in my model:

    f = gp.Model()

    reactions = [i for i in range(len(rxn))]

    metabolites = [i for i in range(len(met))]


    v = f.addVars(range(len(rxn)),obj=c, name='v')

    f.modelSense = GRB.MAXIMIZE

    f.addConstrs((gp.quicksum(S[i,j] * v[j] for j in reactions) == b[i] for i in metabolites), name='FBA')

    f.addConstrs((LB[j] <= v[j] for j in reactions), name='LB')

    f.addConstrs((v[j] <= UB[j] for j in reactions), name='UB')

    f.optimize()

    Note that: reactions, c, LB and UB are arrays of the same length, and S has a length of (metabolitesXreactions) b and metabolites have the same length 

    Other than the name I see no difference, I will try to run again my code, I tried with the bounds being declared in m.AddVars but as you point out is not what I am working towards, if I relaxed the model that way it works without any problem

    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Hello, 

    I tried by allowing the lb and ub in f.addVars to be from - infinity to infinity and declaring them as continuos, but I still get the same error, I thought maybe it had to do with the values the variables were taking given the default values in the bounds 

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Can you please post a complete, self-contained code example that reproduces the issue? I don't see anything wrong with the snippet you posted, but it is missing some definitions. Based on the error message, I would guess that \( \texttt{LB} \) was at some point overwritten to include a TempConstr object.

    0
  • Jose Vindel
    Gurobi-versary
    Thought Leader
    Investigator

    Hello Eli, 

    This is just a brief example, but the error doesn't show, I will go carefully on my model to figure what's causing it

    met = ['A','B','C','D','E']

    metabolites = [ i for i in range(len(met))]

    reac = ['v1','v2','v3','v4','v5','v6','v7']

    reactions = [i for i in range(len(reac))]

    LB =[0,-10,0,0,-10,-10,-10]
    UB =[10,10,10,10,10,10,10]

    SM = {(0,0):-1,(0,1):0,(0,2):1,(0,3):0,(0,4):0,(0,5):0,(0,6):0,
    (1,0):1,(1,1):-1,(1,2):0,(1,3):-1,(1,4):0,(1,5):0,(1,6):0,
    (2,0):0,(2,1):1,(2,2):0,(2,3):0,(2,4):1,(2,5):0,(2,6):0,
    (3,0):-1,(3,1):0,(3,2):0,(3,3):0,(3,4):0,(3,5):1,(3,6):0,
    (4,0):1,(4,1):0,(4,2):0,(4,3):0,(4,4):0,(4,5):0,(4,6):1}

    ob = [0,0,0,1,0,0,0]

    m = gp.Model()

    v = m.AddVars(range(len(reac)), vtype=GRB.CONTINUOUS, obj=ob, name='v')

    m.addConstrs((gp.quicksum(SM[i,j]*v[j] for j in reactions) == 0 for ir in metabolites), name='FBA')

    m.addConstrs((LB[j] <= v[j] for j in reactions), name='LB')

    m.addConstrs((v[j] <= UB[j] for j in reactions), name='UB)

    m.optimize()

    if m.status == GRB.OPTIMAL:
    obj = m.getObjective()
    print('Max v4 Flux','->',obj.getValue())
    var = m.getAttr('X',m.getVars())
    print('------>')
    for i in range(len(reac)):
    print('flux:',reac[i],'->',var[i])


    which produces :

    Gurobi Optimizer version 9.1.0 build v9.1.0rc0 (win64)
    Thread count: 4 physical cores, 8 logical processors, using up to 8 threads
    Optimize a model with 19 rows, 7 columns and 25 nonzeros
    Model fingerprint: 0x4d86fd76

    Coefficient statistics:
    Matrix range [1e+00, 1e+00] Objective range [1e+00, 1e+00] Bounds range [0e+00, 0e+00] RHS range [1e+01, 1e+01]
    Presolve removed 19 rows and 7 columns
    Presolve time: 0.01s
    Presolve: All rows and columns removed
    Iteration Objective Primal Inf. Dual Inf. Time 0 -0.0000000e+00 0.000000e+00 0.000000e+00 0s Solved in 0 iterations and 0.01 seconds Optimal objective -0.000000000e+00
    Max v4 Flux -> 0.0 ------>
    flux: v1 -> 0.0
    flux: v2 -> 0.0
    flux: v3 -> 0.0
    flux: v4 -> 0.0
    flux: v5 -> 0.0
    flux: v6 -> 0.0
    flux: v7 -> 0.0

    However, when I declare the bounds and delete the corresponding constraints 

    m.AddVars(range(len(reac)),lb=UB,ub=UB, vtype=GRB.CONTINUOUS, obj=ob, name='v')

    The result is different (and the correct answer)

    Gurobi Optimizer version 9.1.0 build v9.1.0rc0 (win64)
    Thread count: 4 physical cores, 8 logical processors, using up to 8 threads
    Optimize a model with 19 rows, 7 columns and 25 nonzeros
    Model fingerprint: 0xbc50aaa9
    Coefficient statistics: Matrix range [1e+00, 1e+00] Objective range [1e+00, 1e+00] Bounds range [1e+01, 1e+01] RHS range [1e+01, 1e+01]
    Presolve removed 19 rows and 7 columns Presolve time: 0.02s Presolve: All rows and columns removed
    Iteration Objective Primal Inf. Dual Inf. Time 0 1.0000000e+01 0.000000e+00 0.000000e+00 0s Solved in 0 iterations and 0.02 seconds Optimal objective 1.000000000e+01
    Max v4 Flux -> 10.0 ------>
    flux: v1 -> 0.0
    flux: v2 -> -10.0
    flux: v3 -> 0.0
    flux: v4 -> 10.0
    flux: v5 -> 10.0
    flux: v6 -> 0.0
    flux: v7 -> 0.0

    Upon further analysis, I realized the difference is that if I declare lb=GRB.INFINITY, ub=GRB.INFINITY in the first model, the result is the same, so I am assuming it has to do with how 'open' the variable is. Still quite confused to be honest but, I appreciate the time you've taken to answer me back. 

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    By default, the lower bound on variables added with Model.addVar()/Model.addVars() is 0. Since your variables can be negative, you either need to pass \( \texttt{LB} \) as the \( \texttt{lb} \) keyword argument of Model.addVars(), or explicitly set a lower bound of \( \texttt{-GRB.CONTINUOUS} \) and add lower-bound constraints later.

    0
  • Denise Birabwa
    Gurobi-versary
    First Comment

    Hello Eli,

    Kindly let me know why the following code sets the indicator variable z to zero. 

    My work is such that if the variable resource_allocation_variables[j,p,r] is one, then the constraint cap_2[1] <= quicksum(DR_dicts_using_user_BS_BBU_pair_key[(j,p,r)]*resource_allocation_variables[j,p,r] for r in MBS_BBU_list) <= capacity_vector[1] should be satisfied, for a given user p attached to node j.

    So I created indicator variable z for this conditional statement. Now I am wondering why no user p is allocated any resource r on the node j, yet the resources are available.

    z = f.addVars(DR_dicts_using_user_BS_pair_key.keys(), vtype=GRB.BINARY, name="z")

    f.addConstrs(((z[j,p]==1)>>(cap_2[1] <= quicksum(DR_dicts_using_user_BS_BBU_pair_key[(j,p,r)]*resource_allocation_variables[j,p,r] for r in MBS_BBU_list)) for j in MBS_list for p in list_R_users), name='MBS_uRLLC_QoS_1')
    f.addConstrs(((z[j,p]==1)>>(quicksum(DR_dicts_using_user_BS_BBU_pair_key[(j,p,r)]*resource_allocation_variables[j,p,r] for r in MBS_BBU_list) <= capacity_vector[1]) for j in MBS_list for p in list_R_users), name='MBS_uRLLC_QoS_1')
    f.addConstrs(((z[j,p]==0) >> (quicksum(resource_allocation_variables[j,p,r] for r in MBS_BBU_list) <=0) for j in MBS_list for p in list_R_users), name='MBS_uRLLC_QoS_2')
    f.addConstrs(((z[j+Num_BS,p]==1)>>(cap_2[1] <= quicksum(DR_dicts_using_user_BS_BBU_pair_key[(j+Num_BS,p,r)]*resource_allocation_variables[j+Num_BS,p,r] for r in UAV_BBU_list)) for j in UAV_list for p in list_R_users), name='UAV_uRLLC_QoS_1')
    f.addConstrs(((z[j+Num_BS,p]==1)>>(quicksum(DR_dicts_using_user_BS_BBU_pair_key[(j+Num_BS,p,r)]*resource_allocation_variables[j+Num_BS,p,r] for r in UAV_BBU_list) <= capacity_vector[1]) for j in UAV_list for p in list_R_users), name='UAV_uRLLC_QoS_1')
    f.addConstrs(((z[j+Num_BS,p]==0) >> (quicksum(resource_allocation_variables[j+Num_BS,p,r] for r in UAV_BBU_list) <=0) for j in UAV_list for p in list_R_users), name='UAV_uRLLC_QoS_2')
    f.addConstrs(((z[j+Num_BS+Num_UAVS,p]==1)>>(cap_2[1] <= quicksum(DR_dicts_using_user_BS_BBU_pair_key[(j+Num_BS+Num_UAVS,p,r)]*resource_allocation_variables[j+Num_BS+Num_UAVS,p,r] for r in HAP_BBU_list)) for j in HAP_list for p in list_R_users), name='HAP_uRLLC_QoS_1')
    f.addConstrs(((z[j+Num_BS+Num_UAVS,p]==1)>>(quicksum(DR_dicts_using_user_BS_BBU_pair_key[(j+Num_BS+Num_UAVS,p,r)]*resource_allocation_variables[j+Num_BS+Num_UAVS,p,r] for r in HAP_BBU_list) <= capacity_vector[1]) for j in HAP_list for p in list_R_users), name='HAP_uRLLC_QoS_1')
    f.addConstrs(((z[j+Num_BS+Num_UAVS,p]==0) >> (quicksum(resource_allocation_variables[j+Num_BS+Num_UAVS,p,r] for r in HAP_BBU_list) <=0) for j in HAP_list for p in list_R_users), name='HAP_uRLLC_QoS_2')
    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    if the variable resource_allocation_variables[j,p,r] is one, then the constraint [...] should be satisfied, for a given user p attached to node j

    Do you mean the constraint should be satisfied if the variable \( \texttt{z[j, p]} \) equals \( 1 \)? This is what your code currently models.

    It's hard to say exactly what's wrong, because the code you provided does not run on its own. Due to your third constraint family, it is expected that if \( \texttt{z[j, p]} \) equals \( 0 \), then all of the corresponding resource allocation variables also equal \( 0 \).

    Below are a few ideas that may help:

    1. You can use Model.write() to write out an LP model file, then visually inspect the constraints for correctness. Before you do this, I recommend changing your constraint names to be unique. Your first two constraint families both use the name \( \texttt{MBS_uRLLC_QoS_1} \). This will result in (e.g.) two constraints named \( \texttt{MBS_uRLLC_QoS_1[0,0]} \), two constraints named \( \texttt{MBS_uRLLC_QoS_1[0,1]} \), etc.
    2. If there is a specific \( \texttt{z[j, p]} \) variable you think should equal \( 1 \) in the optimal solution, you could try fixing that variable to \( 1 \) and solving the model again. The resulting model should either (i) be infeasible, or (ii) admit an optimal objective value that is no less than (for a minimization problem) the optimal objective value obtained by leaving that \( \texttt{z[j, p]} \) variable unfixed.
    3. Semi-continuous variables are variables that must assume a value of \( 0 \), or a value between the specified lower and upper bounds. You could remove the binary indicator variables \( \texttt{z} \) and instead introduce semi-continuous variables equal to the weighted resource allocation for each user and node. The code to do so would look something like this:
    y = f.addVars(
    DR_dicts_using_user_BS_pair_key.keys(),
    lb=cap_2[1],
    ub=capacity_vector[1],
    vtype=GRB.SEMICONT,
    name="y"
    )

    m.addConstrs(
    (
    y[j, p]
    == quicksum(
    DR_dicts_using_user_BS_BBU_pair_key[(j, p, r)]
    * resource_allocation_variables[j, p, r]
    for r in MBS_BBU_list
    )
    for j in MBS_list
    for p in list_R_users
    ),
    name="MBS_uRLLC_QoS"
    )

    If these ideas do not help, please post a minimal, self-contained code example that reproduces the behavior you describe.

    0
  • Laela Widiyaningsih
    Gurobi-versary
    First Comment

    Hello Eli,

    I've same problem with error "Constraint has no bool value (are you trying "lb <= expr <= ub"?)". I worked in Gurobi 10.0.3 and python 3.11.4

    This is my main code:

    import pandas as pd
    import gurobipy as gp
    import timeit
    import numpy as np

    df = pd.read_excel('3D_data_IJRT.xlsx')

    J = [int(value) for value in df['J'].unique().tolist()]
    T = [int(value) for value in df['P'].unique().tolist()]
    max_T = max(T)
    I = [int(value) for value in df.columns[2:].tolist()]  # Assuming C0, C1, C3, C4 are the column headers

    R = []

    # Define the rank_value function
    def rank_value(value):
        if value <= 8:
            return 1
        elif value <= 15:
            return 2
        else:
            return 3

    for j in J:
        for t in T:
            filtered_data = df[(df['J'] == j) & (df['P'] == t)][I].values.flatten()  # Get values as a flattened NumPy array
            ranked_data = [rank_value(value) for value in filtered_data]  # Apply rank_value to each element
            R.extend(ranked_data) 
    D = {}
    for i in I:
        D[i] = {}
        for t in T:
            D[i][t] = df[df['P'] == t][i].count()
    alpha = {}
    for i in I:
        alpha[i] = {}
        for t in T:
            alpha[i][t] = D[i][t] * 1/3
            
    S = {}

    for i in I:
        S[i] = {}
        for j in J:
            S[i][j] = {}
            for t in T:
                S[i][j][t] = (df[(df['J'] == j) & (df['P'] == t)][i].values) + 2 + 10 + 5
    This is my Decision Variable code:
    def decisionVariables(M, gp, I, J, T, R, x, y, d, delta, theta, ar): 
        for j in J:
            for t in T:
                y[j, t] = M.addVar(vtype=gp.GRB.INTEGER, name=f"y_{j}_{t}")
        M.update()

        for i in I:
            for j in J:
                for r in R:
                    for t in T:
                       d[i, j, r, t] = M.addVar(vtype=gp.GRB.CONTINUOUS, name=f"d_{i}_{j}_{r}_{t}")


    And this is my constraint code:

     for j in  (J):
            for t in  (T):
             result = gp.quicksum(alpha[i][t] * S[i][j][t] * d[i, j, r, t] for i in (I) for r in (R))
             M.addConstr(result <= (150 * y[j, t]))

    The Error:
    constraints.constraints(M, gp, x, y, I, J, T, R, Zmax, Atotal, Amax, delta, d, theta, alpha, ar, max_T, S, L)

      File D:\Laela Widiyaningsih\py\constraints.py:67 in constraints
        M.addConstr(result <= (150 * y[j, t]))

      File src\gurobipy\tempconstr.pxi:57 in gurobipy.TempConstr.__bool__

    GurobiError: Constraint has no bool value (are you trying "lb <= expr <= ub"?)
    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Unfortunately, I can't say for certain what's causing the issue, because the code is not self-contained. Can you please (i) post a link to the \(\texttt{3D_data_IJRT.xlsx}\) workbook, and (ii) modify the code so it will run without any modifications?

    0

サインインしてコメントを残してください。