How to add conditions in objective functions?
回答済みHi Gurobi team,
I want to implement some conditions in my objective function. I know adding conditions to constraints is possible through addGenConstrIndicator() but I don't know how I can add conditions in the objective function. Here is a minimal example snippet for my problem. I have variable v with size = 3, prev_values are the previous values for this variable (consider a temporal scenario with the next variable values is dependent on the previous variable values). Now, I want to check if the current value is either equal to 0 or equal to its previous values, and use it in my objective function. How can I implement this in Gurobi (below is a sketch of what I intend to implement)?
model = gp.Model()
E = [2, 4, 7]
prev_values = [4, 5, 1]
v = model.addVar(3, lb=0, vtype=gp.GRB.INTEGER, )
def check(vn, vp):
if vn == 0 or vn == vp:
return 0
return 1
model.setObjective(max([check(v[i], prev_values[i]) * E[i] for i in range(3)]) , gp.GRB.MINIMIZE)
Thank you!
-
正式なコメント
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. -
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 -
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 -
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 codev = 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
投稿コメントは受け付けていません。
コメント
4件のコメント