• 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ł

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)
• 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ł

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

• Gurobi Staff

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

Hi.

I now face this error.

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

• 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, maximumminimum = 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 == ...)

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?
• 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)

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)
• 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).

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

• 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 gpm = 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 constraintlinexprc1 = m.getRow(c1)linexprc2 = m.getRow(c2)# construct a new constraint by adding the lhs and rhsm.addConstr( linexprc1 + linexprc2 <= c1.rhs + c2.rhs)# write LP file to check the resultm.write("myLP.lp")

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

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

• 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?

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

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.

• 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.

How would such constraints be instantiated?

• Gurobi Staff

You just add it as a regular constraint. For example

import gurobipy as gpm = 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.