Skip to main content

How to add conditions in objective functions?

Answered

Comments

4 comments

  • Official comment
    Simranjit Kaur
    • Gurobi Staff
    This post is more than two 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 try Gurobot, our chatbot interface offering instant, expert-level support.
  • 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

Post is closed for comments.