メインコンテンツへスキップ

How to Define a Constraint for Calculating the Maximum of Two Multi-Dimensional Variables in Gurobi

回答済み

コメント

4件のコメント

  • Maliheh Aramon
    • Gurobi Staff

    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
  • Amir Fayaz Heidari
    • Gurobi-versary
    • Conversationalist
    • First Question

    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 = 2

    P_tot = np.zeros((M,R))
    P_tot[0,0] = 5000
    P_tot[0,1] = 2000
    P_tot[1,0] = 3000
    P_tot[1,1] = 1000

    min_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 = 600

     

    x_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_SCG

    objective_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, h

    0
  • Maliheh Aramon
    • Gurobi Staff

    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,
    Maliheh

    0
  • Amir Fayaz Heidari
    • Gurobi-versary
    • Conversationalist
    • First Question

    Thanks Maliheh.

    0

サインインしてコメントを残してください。