gurobipy.GurobiError: Range constraint requires a list [lb,ub]
AnsweredHi Everyone,
I'm trying to play around with the gurobi environment and remodelled multiple times the optimization problem such that it becomes more simple and the task for gurobi easier as well.
In my Environment, I aim to optimize the following optimization problem:
model.setObjective(alpha * time_reloc[value2] + beta * node_dist_to_reloc[value2] + gamma * routeCoefficient_reloc[value2], gb.GRB.MINIMIZE)
Where alpha, beta and gamma are just weights to increase or decrease the importance of one parameter in the equation or decrease it, so alpha + beta + gamma = 1 and here alpha = beta = 0.25, gamma = 0.5
time_reloc, node_dist_to_reloc and route_coefficient_reloc are all lists of parameters already calculated in the following form:
time_reloc[(5, 2)] = 12.5
In essence, the list is of the following type: (x,y): time
Takes as list input the coordinates of a point (x,y) and gives to that specific position the time for relocation in this case.
The lists node_dist_to_reloc and route_coefficient_reloc have the same structure, however, at each coordinate (x,y) give another value corresponding to the routing coefficient (route_coefficient_reloc) and distance (node_dist_to_reloc).
All lists share the same points, so they share the same index (positions).
I defined in my model the following three variables:
value0 = model.addVar(lb=-30, ub=30, vtype=gb.GRB.INTEGER, name="x coordinate")
value1 = model.addVar(lb=-30, ub=30, vtype=gb.GRB.INTEGER, name="y coordinate")
value2 = model.addVar(name="value2")
The idea is simple: what I want to do, is to use gurobi variables value0 and value1 to explore the different combinations of x and y as positions and find the best (x,y), where the objective function is minimum.
All together would be the following:
value0 = model.addVar(lb=-30, ub=30, vtype=gb.GRB.INTEGER, name="value0")
value1 = model.addVar(lb=-30, ub=30, vtype=gb.GRB.INTEGER, name="value1")
value2 = model.addVar(name="value2")
model.update()
model.addConstr(value0 <= 30)
model.addConstr(value1 <= 30)
model.addConstr(value0 >= -30)
model.addConstr(value1 >= -30)
model.addConstr(value2 == (value0, value1))
model.setObjective(alpha * time_reloc[value2] + beta * node_dist_to_reloc[value2] + gamma * routeCoefficient_reloc[value2], gb.GRB.MINIMIZE)
model.optimize()
I tried here to add an additional gurobi variable value2 which is just the combination of value0 and value1 to get the coordinates required for the three lists of data.
However, I get the following error message:
line 588, in relocation: model.addConstr(value2 == (value0, value1))
gurobipy.GurobiError: Range constraint requires a list [lb,ub]
It's quite annoying because there is no reference on what kind of problem is it nor someone tried to ask this kind of issue before, so I don't really know how to solve it. This is probably already a bad way to solve the problem because I tried different approaches to solve this problem and I always got a different error, e.g.:
model.setObjective(alpha * time_reloc[(value0, value1)] + beta * node_dist_to_reloc[(value0, value1)] + gamma * routeCoefficient_reloc[(value0, value1)], gb.GRB.MINIMIZE)
This gives the following error:
line 590, in relocation: model.setObjective(alpha * time_reloc[(value0, value1)] + beta *node_dist_to_reloc[(value0, value1)] + gamma * routeCoefficient_reloc[(value0, value1)], gb.GRB.MINIMIZE)
KeyError: (<gurobi.Var value0>, <gurobi.Var value1>)
Which does not mean much to me.
Thanks in andvance for helping.
Best regards,
Marco
-
Hi Marco,
The issue lies within the constraint
model.addConstr(value2 == (value0, value1))
What you are trying to formulate is \(v_2 = (v_0,v_1)\). While this might be correct from a theoretical formulation point of view, it is not how you would formulate such an equality constraint.
In practice, you have to define a 2-dimensional optimization variable
value2 = model.addVar(2, lb=-30, ub=30,vtype=gb.GRB.INTEGER name="value2")
You can then define the equality constraints
model.addConstr(value2[0] == value0)
model.addConstr(value2[1] == value1)But here comes another issue. You would like to use \(v_0,v_1\) as indices for other list objects. This is not possible without a correct formulation because \(v_0,v_1\) are optimization variables and don't have any value during model construction. However, the compiler (or interpreter) requires a value to access the index of the respective list object.
It is possible to formulate variables as indices as described in the post use a decision variable as an index. However, this formulation is quite complex and I would not recommend it if there is a way to avoid it.
In your case you maybe could avoid having to formulate variables as indices. To achieve this, you can define a binary \(v\) variable for every \(v_0,v_1\) combination. In your case, this would be 3600 additional variables. You could then drop the \(v_0,v_1\) variables.
value = {}
for i in range(-30,31):
for j in range(-30,31):
value[i,j] = model.addVar(vtype=gb.GRB.BINARY, name="value[%d,%d]"%(i,j))Exactly one of these new variable has to be \(1\) at any time.
model.addConstr(gb.quicksum(value[i,j] for i in range(-30,31) for j in range(-30,31)) == 1)
You can now formulate your objective by summing over all list values and multiplying each of them with the binary value variable
model.setObjective(gb.quicksum( alpha * time_reloc[i,j] * value[i,j]
+ beta * node_dist_to_reloc[i,j] * value[i,j]
+ gamma * routeCoefficient_reloc[i,j] * value[i,j]
for i in range(-30,31)
for j in range(-30,31)), gb.GRB.MINIMIZE)Depending on your level of gurobipy knowledge, it might make sense to have a look at our Python introduction series and maybe our MIP introduction series.
Best regards,
Jaromił1
Please sign in to leave a comment.
Comments
1 comment