Skip to main content

Multiple Objectives: MIPGap of each objective

Answered

Comments

9 comments

  • Michael Lindahl
    Gurobi-versary
    First Comment

    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. 

    0
  • Phillip Meng
    Gurobi-versary
    Conversationalist
    First Question

    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 :)

    1
  • Menkes van den Briel
    Gurobi-versary
    First Comment

    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?

    0
  • Avi Itzhakov
    First Comment

    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 objective
    model._mip_gap_abs = {
    0: 1e-3,
    ...
    }


    # use callback during optimize()
    model.optimize(grb_callback_mip_gap_abs_per_objective)

     

     

    1
  • Xavier Nodet
    Gurobi Staff 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.

    1
  • Avi Itzhakov
    First Comment

    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:

    0
  • Xavier Nodet
    Gurobi Staff 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?

     

    1
  • Eli Towle
    Gurobi Staff 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)
    1
  • Avi Itzhakov
    First Comment

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

    0

Please sign in to leave a comment.