Skip to main content

How to add conditions in objective functions?

Answered

Comments

3 comments

  • Marika Karbstein
    • Gurobi Staff

    To work with general expressions, you may need to add intermediate decision variables, see How do I model logical and general expressions? This is not only the case for constraints but also for conditions on objective variables.

    A possible solution for your case could be

    import gurobipy as gp

    model = gp.Model()
    # get current integer feasibility tolerance value
    IntFeasTol = model.getParamInfo('IntFeasTol')[2]
    E = [2, 4, 7]
    prev_values = [4, 5, 1]
    v = model.addVars(3, lb=0, vtype=gp.GRB.INTEGER)
    # several helper variables are needed
    diff_v_prev = model.addVars(3, lb=-gp.GRB.INFINITY, vtype=gp.GRB.INTEGER)
    absVar =model.addVars(3, vtype=gp.GRB.INTEGER)
    check_v = model.addVars(3, vtype=gp.GRB.BINARY)
    forObj = model.addVars(3, vtype = gp.GRB.INTEGER)
    objVar = model.addVar(name='obj')

    model.addConstrs(diff_v_prev[i] == prev_values[i] - v[i] for i in range(3))
    model.addConstrs(absVar[i] == gp.abs_(diff_v_prev[i]) for i in range(3))
    # check_v is only allowed to be 0 if 0 < v and |v - prev_values| > 0 (use IntFeasTol)
    model.addConstrs((check_v[i]==0) >> (v[i] >= IntFeasTol) for i in range(3))
    model.addConstrs((check_v[i]==0) >> (absVar[i] >= IntFeasTol) for i in range(3))
    model.addConstrs(forObj[i] == check_v[i] * E[i] for i in range(3))
    model.addConstr(objVar == gp.max_([forObj[i] for i in range(3)]))
    model.setObjective(objVar , gp.GRB.MINIMIZE)

    model.optimize()
    There might be a simpler solution that I am currently not aware of.
    0
  • Saeid Ghafouri
    • Gurobi-versary
    • Curious
    • Conversationalist

    Hi,

    Thank you for your response, It was very helpful. I faced another problem implementing that.

    Actually, instead of 0 we want check_v to be 1 if both the conditions (v > 0 and |v-p| > 0) are true.

    But when I do:

    (check_v[i]==1) >> ...

    I see no effect and check_v values are all zero, while v[i] and absVar[i] values are all positive integers.

    0
  • Marika Karbstein
    • Gurobi Staff

    The two indicator constraints

    model.addConstrs((check_v[i]==0) >> (v[i] >= IntFeasTol) for i in range(3))
    model.addConstrs((check_v[i]==0) >> (absVar[i] >= IntFeasTol) for i in range(3))

    make sure that if check_v == 0 then also v > 0 and |v-p| > 0. It also implies if v==0 or v-p==0 then check_v=1. But it does not forbid to set check_v to 1 if  v > 0 and |v-p| > 0.

    I probably misinterpreted your check-function. Here is another try.

    So we want to have the following condition:
    If v != 0 and v != p then check_v=1
    This is equivalent to
    If check_v = 0 then v=0 or v=p
    which, I think, can be achieved with the following code

    v = model.addVars(3, lb=1, ub=2, vtype=gp.GRB.INTEGER, name='v')
    check_v = model.addVars(3, vtype=gp.GRB.BINARY, name='check_v')
    vIs0 = model.addVars(3, vtype=gp.GRB.BINARY, name='vIs0')
    vIsP = model.addVars(3, vtype=gp.GRB.BINARY, name='vIsP')
    # if check_v is 0 then v=0 or v=p (this implies if v!=0 and v!=p then check_v=1)
    model.addConstrs((vIs0[i]==1) >> (v[i] == 0) for i in range(3))
    model.addConstrs((vIsP[i]==1) >> (v[i] == prev_values[i]) for i in range(3))
    model.addConstrs((check_v[i]==0) >> (vIs0[i] + vIsP[i] >= 1) for i in range(3))

     

    0

Please sign in to leave a comment.