Agree that this would be very helpful.

It is though possible to calculate them yourself by getting the incumbent and bound in a MIP or MIPSOL callback, and then keep track of which objective you are currently solving.

We've also hit this wall and kind of worked out from a mix of the lack of documentation and the back section of the online manual that it is currently not possible. May be better to say the solution mipgap can't be retrieved for multi objective models, or even better add the functionality :)

Same here, particularly if you have a hierarchical objective with certain allowed degradation, it would be nice to at least be able to recover the mipgap of the first objective before starting the optimisation on the second one. Is there any way to access this?

Although this is a four-year-old question, I didn't find a direct way to specify MIP gap tolerances for each objective in the latest Gurobi release.
I implemented it (for absolute gap) as follows based on @Michael Lindahl's suggestion.

def grb_callback_mip_gap_abs_per_objective(model, where):    if where == GRB.Callback.MIP:        objbst = model.cbGet(GRB.Callback.MIP_OBJBST)        objbnd = model.cbGet(GRB.Callback.MIP_OBJBND)        gap_abs = abs(objbst - objbnd)        if gap_abs < model._mip_gap_abs[model._obj_idx]:            model.cbStopOneMultiObj(model._obj_idx)    elif where == GRB.Callback.MULTIOBJ:        model._obj_idx = model.cbGet(GRB.Callback.MULTIOBJ_OBJCNT)
model._obj_idx = 0# specify absolute gaps per objectivemodel._mip_gap_abs = {    0: 1e-3,    ...}# use callback during optimize()model.optimize(grb_callback_mip_gap_abs_per_objective)

• Gurobi Staff

With Multi-Objective Environments, you can specify parameters for each optimisation pass in a multi-objective model.  This is described at https://www.gurobi.com/documentation/11.0/refman/additional_details.html.

According to the documentation for multi-objective environments, MIPGap tolerance is unsupported as it "does not make sense" (I think the intention is that MIPGap, as defined in Gurobi, is something related to the total objective and is thus something that cannot be used in a hierarchical objective model). Yet, we encountered a case where we would like to set a tolerance for a specific objective in the multi-objective model, and it seems that there is no way to do that with the existing params.

From the documentation:

• Gurobi Staff

This section of the documentation refers to attributes, not parameters.  Attributes are used "for querying and modifying properties of a Gurobi model", while "parameters control the operation of the Gurobi solvers".

The MIPGap _attribute_ doesn't exist because it is not possible to define a (global) MIPGap for a multi-objective model.  But I expect that you can set the MIPGap _parameter_ in a multi-objective environment to limit the time spent optimizing a given objective.  Are you facing an issue trying that?

• Gurobi Staff

Like Xavier mentioned, the MIPGap parameter is what you are trying to set. It is a termination criterion - Gurobi will stop solving a model (or multi-objective step) after reaching the specified relative optimality gap. You can set the MIPGap parameter for individual multi-objective environments with Model.getMultiObjEnv() and Env.setParam():

env0 = model.getMultiobjEnv(0)env1 = model.getMultiobjEnv(1)env0.setParam("MIPGap", 0.001)env1.setParam("MIPGap", 0.01)

The Multi-objective environments section of the documentation contains more details and an example.

The MIPGap attribute stores the value of the optimality gap after solving. Each multi-objective step has its own objective function, lower bound, and upper bound. Thus, the MIPGap attribute does not make sense as a queryable parameter for multi-objective problems.

The original question requests a way to query the optimality gaps for each individual multi-objective step (i.e., an indexed MIPGap attribute). As of Gurobi 11, there is no direct way to query the values of these individual gaps. However, you could parse the gaps from the log output using a MESSAGE callback. For example, in Python:

def callback(model, where):    if where == GRB.Callback.MESSAGE:        msg = model.cbGet(GRB.Callback.MSG_STRING)        m = re.search("Best objective ([^,]+), best bound ([^,]+), gap (.*)%\$", msg)        if m:            obj_best, obj_bound, gap = m.group(1, 2, 3)            obj_best = float(obj_best)            obj_bound = float(obj_bound)            gap = float(gap) / 100            print(f"obj_best={obj_best}, obj_bound={obj_bound}, gap={gap}")model.optimize(callback)

Thank you both for the clarification. Setting MIPGap parameter for each objective (as demonstrated by Eli Towle) is indeed what I want.