How to Define a Constraint for Calculating the Maximum of Two Multi-Dimensional Variables in Gurobi
AnsweredHi team,
The max_ function for the 1-dimension variable works. However, I need to add the constraint below:
model.addConstrs(X_3[m,r] == max_( X_1[m,r] , X_2[m,r] ) for m in range(M) for r in range(R))
Where X_1, X_2, and X_3 are multi-dimensional variables. When I run my code, I get the error below:
GurobiError: Invalid data in vars array
How can I consider this type of constraint? I do not want to use binary variables to linearize this constraint. I do not want to replace it with the two constraints below because there are some other challenges regarding my objective function and other constraints.
model.addConstrs(X_3[m,r] >= X_1[m,r] for m in range(M) for r in range(R))
model.addConstrs(X_3[m,r] >= X_2[m,r] for m in range(M) for r in range(R))
Also, I cannot write the constraints for each m and r individually because the input parameters M and R are big.
What about the constraint below which the variables have different dimensions?
model.addConstrs(X_6[m,r,y,d,h] == min_( X_4[m,r,y,d,h] , X_5[m,r] ) for m in range(M) for r in range(R) for y in range(Y) for d in range(D) for h in range(H))
Thanks for your time in advance
-
Official comment
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. -
Hi Amir,
It is possible to use the max_() helper function regardless of the variables dimension and there is no need for the variables to have similar dimensions. See the code snippet below:
import gurobipy as gp
model = gp.Model()
M, R = 5, 4
x1 = model.addVars(M, R, name="x1")
x2 = model.addVars(M, R, name="x2")
x3 = model.addVars(M, R, name="x3")
model.addConstrs((x3[m,r] == gp.max_(x1[m,r], x2[m,r]) for m in range(M) for r in range(R)), name="c_max")Could you please post a small working example so that we can reproduce the error you see?
Best regards,
Maliheh
0 -
Thanks for your response.
Could you please check the code below? It works correctly without the constraint regarding the max function.
" model.addConstrs((con_SCG[m,r] == gp.max_(x_SCG[m,r], min_con_SCG[m,r]) for m in range(M) for r in range(R)), name="c_max") "
However, when I deactivate it (excluded from the optimization problem), I get the error "GurobiError: Invalid data in vars array"import gurobipy as gp
from gurobipy import *
import numpy as np# Create a new model
model = Model()M = 2
R = 2
N = 2P_tot = np.zeros((M,R))
P_tot[0,0] = 5000
P_tot[0,1] = 2000
P_tot[1,0] = 3000
P_tot[1,1] = 1000min_con_SCG = np.zeros((M,R))
min_con_SCG[0,0] = 200
min_con_SCG[0,1] = 200
min_con_SCG[1,0] = 300
min_con_SCG[1,1] = 300
# Define decision variables
x_SCG = model.addVars(M,R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="x_SCG")
x_ON_SCG = model.addVars(M,R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="x_ON_SCG")
x_act_SCG = model.addVars(M,R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="x_act_SCG")
con_SCG = model.addVars(M,R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="con_SCG")
Total_con_SCG = model.addVars(R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="con_RES")x_SCG[0,0].ub = 1000
x_SCG[1,0].ub = 800
x_SCG[0,1].ub = 500
x_SCG[1,1].ub = 600x_RES = model.addVars(N,R, lb=0.0, ub=400, vtype=GRB.CONTINUOUS, name="x_RES")
con_RES = model.addVars(N,R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="con_RES")
Total_con_RES = model.addVars(R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="con_RES")
z = model.addVar(lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="z")
delta_P = model.addVars(R, lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="delta_P")
SSS_1 = model.addVar(lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="SSS_1")
SSS_2 = model.addVar(lb=0.0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="SSS_2")
# objective_expr = 10 * x_SCG + 5 * x_act_SCG + 3 * x_RES + ( SSS_1 + SSS_2 )*1000 + con_SCGobjective_expr = gp.quicksum( gp.quicksum( 10 * x_SCG[m,r] for r in range(R) ) for m in range(M) ) + gp.quicksum( gp.quicksum( 5 * x_act_SCG[m,r] for r in range(R) ) for m in range(M) ) + gp.quicksum( gp.quicksum( 3 * x_RES[n,r] for r in range(R) ) for n in range(N) )
model.addConstr(gp.quicksum( x_SCG[m,0] for m in range(M) ) + gp.quicksum( x_RES[n,0] for n in range(N) ) == 2500 , name="Demand")
model.addConstr(gp.quicksum( x_SCG[m,1] for m in range(M) ) + gp.quicksum( x_RES[n,1] for n in range(N) ) == 500 , name="Demand")
model.addConstrs(x_SCG[m,r] <= x_ON_SCG[m,r] for m in range(M) for r in range(R))
model.addConstrs(x_ON_SCG[m,r] <= x_act_SCG[m,r] for m in range(M) for r in range(R))
model.addConstrs(x_act_SCG[m,r] <= P_tot[m,r] for m in range(M) for r in range(R))model.addConstrs((con_SCG[m,r] == gp.max_(x_SCG[m,r], min_con_SCG[m,r]) for m in range(M) for r in range(R)), name="c_max")
model.addConstrs(Total_con_SCG[r] == max_( con_SCG[0,r] , con_SCG[1,r]) for r in range(R))
# model.addConstr(con_SCG <= x_SCG , name="Constraint555")
# model.addConstr(con_SCG <= 200 , name="Constraint555")# model.addConstr(con_SCG >= x_SCG - SSS_1 - SSS_2 , name="Constraint3")
# model.addConstr(con_SCG >= 200 - SSS_1 - SSS_2 , name="Constraint4")
# model.addConstr(SSS_1 >= x_SCG - 200, name="Constraint5")
# model.addConstr(SSS_2 >= 200 - x_SCG , name="Constraint6")
model.addConstrs(con_RES[n,r] == 0.25 * x_RES[n,r] for n in range(N) for r in range(R))
model.addConstrs(Total_con_RES[r] == max_( con_RES[0,r] , con_RES[1,r]) for r in range(R))
model.addConstrs(delta_P[r] == max_( Total_con_SCG[r] , Total_con_RES[r]) for r in range(R))
# model.addConstr(delta_P >= con_SCG , name="Constraint555")
# model.addConstr(delta_P[r] >= con_RES[n,r] for n in range(N) for r in range(R) )
model.addConstrs(3 * gp.quicksum( x_act_SCG[m,r] for m in range(M) ) >= 50 * delta_P[r] for r in range(R))
model.setObjective(objective_expr, GRB.MINIMIZE)
model.optimize()# Access the values of decision variables
x_SCG_values = model.getAttr('X', x_SCG)
x_ON_SCG_values = model.getAttr('X', x_ON_SCG)
x_act_SCG_values = model.getAttr('X', x_act_SCG)
con_SCG_values = model.getAttr('X', con_SCG)
x_RES_values = model.getAttr('X', x_RES)
con_RES_values = model.getAttr('X', con_RES)
Total_con_RES_values = model.getAttr('X', Total_con_RES)
Total_con_SCG_values = model.getAttr('X', Total_con_SCG)
z_value = z.X
delta_P_values = model.getAttr('X', delta_P)
SSS_1_value = SSS_1.X
SSS_2_value = SSS_2.X# You can access the values of variables, one by one, like the examples above.
# For example, to print the values of x_SCG for all indices:
for m in range(M):
for r in range(R):
print(f'x_SCG[{m}, {r}] = {x_SCG_values[m, r]}')
print(f'x_ON_SCG[{m}, {r}] = {x_ON_SCG_values[m, r]}')
print(f'x_act_SCG[{m}, {r}] = {x_act_SCG_values[m, r]}')
print(f'con_SCG[{m}, {r}] = {con_SCG_values[m, r]}')
print()for n in range(N):
for r in range(R):
print(f'x_RES[{n}, {r}] = {x_RES_values[n, r]}')
print(f'con_RES[{n}, {r}] = {con_RES_values[n, r]}')
print()
for r in range(R):
print(f'Total_con_SCG[{r}] = {Total_con_SCG_values[r]}')
print(f'Total_con_RES[{r}] = {Total_con_RES_values[r]}')
print(f'delta_P[{r}] = {delta_P_values[r]}')
print()
# Close the model
model.close()
In my main code, I want to add these constraints:
SCG_type_con[m,r,y,d,h] == min ( SCG_dis[m,r,y,d,h] , x_1[m,r] ) ∀ m, r, y, d, h
SCG_con[r,y,d,h] == max ( SCG_type_con[m,r,y,d,h] ) over all m and ∀ r, y, d, h
## For example: SCG_con[r,y,d,h] == max ( SCG_type_con[0,r,y,d,h] , SCG_type_con[1,r,y,d,h] , SCG_type_con[2,r,y,d,h] )
## However, I want to define generally not manually like the above example
RES_con[r,y,d,h] == max ( RES_type_con[n,r,y,d,h] ) over all n and ∀ r, y, d, h
delta_P[r,y,d,h] == max ( SCG_con[r,y,d,h] , RES_con[r,y,d,h] ) ∀ r, y, d, h0 -
Hi,
In the constraint below:
model.addConstrs(
(
con_SCG[m,r] == gp.max_(x_SCG[m,r], min_con_SCG[m,r])
for m in range(M)
for r in range(R)
),
name="c_max",
)The \(\texttt{min_con_SCG[m,r]}\) is a constant and not a Gurobi variable. According to the Gurobi documentation, the signature of the max_() function is:
max_(*args, constant=None )Therefore, your constraint needs to change to:
model.addConstrs(
(
con_SCG[m, r] ==gp.max_(x_SCG[m, r], constant=min_con_SCG[m, r])
for m in range(M)
for r in range(R)
),
name="c_max",
)Best regards,
Maliheh0 -
Thanks Maliheh.
0
Post is closed for comments.
Comments
5 comments