Skip to main content

Obtaining Integer Values from Quicksum

Answered

Comments

20 comments

  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Could you please share a minimal reproducible example where you use Gurobi's build-in max function? I don't see a particular reason why using it would not work.

    Best regards, 
    Jaromił

    1
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    My code is as follows:

    And this is the error that is being displayed. Should maximum and minimum be set to some sort of Gurobi variable?

    Code in a code block:

    for ca1sh in CA1SH:

        minimum = ((ca1sh.min - quicksum(quicksum(x_ijs[i,j,s] for s in ca1sh.slots) for j in team_ids if i != j) for i in ca1sh.teams))

        maximum = ((quicksum(quicksum(x_ijs[i,j,s] - ca1sh.max for s in ca1sh.slots) for j in team_ids if i != j) for i in ca1sh.teams))

        max_val = grb_model.addGenConstrMax(minimum, maximum, 0)

       

        print(max_val)
    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    You have to follow the definition of the addGenConstrMax method. The arguments you provide are incorrect and you should try

    grb_model.addGenConstrMax(max_val, [minimum,maximum], constant=0, name="maxconstr")

    The above generates the constraint

    \[\text{max_val} = \max(\text{minimum}, \text{maximum}, 0) \]

    Best regards, 
    Jaromił

    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    Hi.

    Thanks for the quick reply. How should I instantiate the max_val variable? What type of Gurobi variable should it be set to?

    Regards

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    As described in the documentation of the addGenConstrMax method, \(\texttt{max_val}\) has to be a Var object.

    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    Hi.

    I now face this error.

    It is worth mentioning that x_ijs is a GRB.BINARY variable type.

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Please have a closer look at the documentation of the addGenConstrMax method.

    The objects \(\texttt{maximum,minimum}\) both have to be Var objects as well. Thus, you have to introduce equality constraints stating

    # define optimization variables minimum, maximum
    minimum = grb_model.addVar(lb=-GRB.INFINITY)
    maximum = grb_model.addVar(lb=-GRB.INFINITY)
    # add constraints minimum = ... and maximum = ...
    grb_model.addConstr(minimum == ((ca1sh.min - quicksum(...)))
    grb_model.addConstr(maximum == ...)
    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    Hi.

    Thanks again. When calculating the following: 

    quicksum(quicksum(x_ijs[i,j,s] for s in ca1sh.slots) for j in team_ids if i != j) for ca1sh in CA1SH for i in ca1sh.teams
     
    the result is being generated as a generator object.
     
    Any ideas?
    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    The quicksum function returns an expression object and not a list. Thus, you cannot use a quicksum result as input argument for the quicksum function. This is not a problem, because you can use multiple \(\texttt{for}\)-loops in one quicksum:

    quicksum(x_ijs[i,j,s] for s in ca1sh.slots for j in team_ids if i != j for ca1sh in CA1SH for i in ca1sh.teams)
    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    Hi. Regarding this issue, when I am trying to retrieve the value by updating the model (i.e. max_val.Obj), the value is always 0. Below is a code sample.

    I am using 2 models in one program because if I use the same model (grb_model), I would not be able to retrieve certain values and the model is not optimised. Also, is there a way in which I can merge the two constraints in the original post into one?

    Thanks Oleg

    for i in team_ids:
    for ca1sh in CA1SH:
    dev_model.addConstr(minimum == (ca1sh.min - quicksum(x_ijs[i,j,s] forsinca1sh.slots forjinca1sh.teams ifi != j)))

    dev_model.addConstr(maximum == (quicksum(x_ijs[i,j,s] forsinca1sh.slots forjinca1sh.teams ifi != j) - ca1sh.max))

    calc_max = dev_model.addGenConstrMax(max_val, [minimum, maximum], constant = 0)

    dev_model.update()

    maxi_val = max_val.Obj

    print(maxi_val)
    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    To access the objective value, you have to access the ObjVal attribute of the model object, i.e.,

    maxi_val = dev_model.ObjVal

    Note that the update method does not change any solution values. It propagates all model changes but it does not resolve the model. To get a new objective value after changing the objective function, you have to call the optimize method before accessing the ObjVal attribute.

    dev_model.addConstr(minimum == (ca1sh.min - quicksum(x_ijs[i,j,s] forsinca1sh.slots forjinca1sh.teams ifi != j)))
    dev_model.addConstr(maximum == (quicksum(x_ijs[i,j,s] forsinca1sh.slots forjinca1sh.teams ifi != j) - ca1sh.max))
    calc_max = dev_model.addGenConstrMax(max_val, [minimum, maximum], constant = 0)
    dev_model.update()
    dev_model.optimize()
    maxi_val = dev_model.ObjVal

    Please also note that you should check the Status attribute before accessing any solution information, cf. mip2.py example (unless you are 100% sure that the model is always feasible).

    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    I am still not sure about this. Is there a way to combine both constraints into one?

     

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Not directly. However, you can access the LinExpr objects describing the lhs of the constraints and add them together. You also have to to this for the RHS of each constraint.

    import gurobipy as gp

    m = gp.Model("test")
    x = m.addVar()
    y = m.addVar()
    c1 = m.addConstr(x + y <= 3)
    c2 = m.addConstr(2*x - 0.5*y <= 0.1)
    m.update()

    # get lhs of each constraint
    linexprc1 = m.getRow(c1)
    linexprc2 = m.getRow(c2)
    # construct a new constraint by adding the lhs and rhs
    m.addConstr( linexprc1 + linexprc2 <= c1.rhs + c2.rhs)
    # write LP file to check the result
    m.write("myLP.lp")

    Note that most often, combining constraints only makes sense if they have the same sense (\(\leq, \geq, =\).

    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    Thanks for your quick response. I wanted to ask, is it possible to use a max_ function in a constraint and store it? (See below)

    grb_model.addConstrs((quicksum(x[i,j,k] - ca1sh.max for j in ca1sh.teams for k in ca1sh.slots if i != j) <= max_(..., constant = 0) for i in team_ids for ca1sh in CA1SH), "Constraint 4.13")

    Thanks, Oleg

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    It is not possible to use the \(\texttt{max_}\) function directly in a constraint, cf. documentation of the max function. You have to define an auxiliary variable and equality constraint to model

    m.addConstr(aux == max_(...,constant))
    # use aux as max_(...,constant)

    Could you explain what exactly you mean by store?

    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    Storing it in a variable as you mentioned. Thanks for now.

    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    I have a question. Can you have constraints in a model which they should not be considered when optimising the model but need such constraints to obtain certain values? For example, getting the maximum value.

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    Can you have constraints in a model which they should not be considered when optimising the model but need such constraints to obtain certain values?

    Yes, redundant constraints are fine and will most likely be removed during presolve. You can still access the value of all variables/constraints after a successful optimization run even if the constraints/variables are redundant.

    0
  • Oleg Grech
    Gurobi-versary
    Collaborator
    First Question

    How would such constraints be instantiated?

    0
  • Jaromił Najman
    Gurobi Staff Gurobi Staff

    You just add it as a regular constraint. For example

    import gurobipy as gp

    m = gp.Model("test")
    x = m.addVar()
    y = m.addVar()
    c1 = m.addConstr(x >= 3)
    c2 = m.addConstr(y == 4*x)
    m.setObjective(x)
    m.optimize()

    print(y.X)

    Constraint \(\texttt{c2}\) and variable \(y\) do not affect the model at all, but through the solution value of \(y\) and constraint \(\texttt{c2}\), I am able to easily access the value of \(4\cdot x\). Note that while it may be convenient, adding an excessive amount of redundant constraint may slow down the optimization process significantly. Thus, it is best to compute specific values of interest manually using optimal solution point values, after the optimization process has been performed.

    0

Please sign in to leave a comment.