Skip to main content

Is ObjBoundC ensured to be a valid bound?

Answered

Comments

9 comments

  • Riley Clement
    • Gurobi Staff

    Hi Daisy,

    Is ObjBoundC ensured to be a valid bound (i.e., an upper bound in a maximization problem and a lower bound in a minimization problem) throughout the computation?

    In the absence of bugs, yes.

    My understanding is that, in a maximization problem, ObjBoundC provides a potentially “loose” upper bound at the beginning of the solve

    It is potentially loose, it is potentially tight - this depends on the model.  In most cases ObjBoundC is going to be the same as ObjBound.

    When I inserted the heuristic solution into Gurobi, it accepted the solution and updated the bound, suggesting that the previous bound was not a valid upper bound.

    This could be buggy, although perhaps there are small violations (constraint or bound or integer) within tolerances that allow the heuristic solution to be accepted.

    I would also appreciate a better explanation of what the "best bound" (i.e., ObjBoundC) actually represents during the MIP solve

    The best bound is coming from LP relaxations.  For a minimization problem it's going to be the minimum value of the LP relaxation at all unexplored nodes.  Typically though you would just use ObjBound, which uses integrality information - i.e. if you know the objective should be integer and the value of an LP relaxation is fractional, you can round it up (for a minimization).

    If you'd like me to take a look at the issue regarding the heuristic solution and lower bound contradicting then please share a model file (MPS) and solution file (SOL) using a service such as Google Drive, Dropbox, Github etc.

    - Riley

    0
  • Daisy Wang
    • First Comment
    • First Question

    Hi Riley,

    Thank you very much for your prompt and helpful response.

    I’ve isolated and cleaned up the code, and uploaded it to GitHub [https://github.com/Daisy0419/Orienteering-Problem-with-Gurobi-Solver.git]. It would be greatly appreciated if you could take a closer look.

    The problematic case is for data file GW191127_050227 with a time budget of 1400. I’ve also included the heuristic solution we generated (as init_solution) for this instance. If you run the code with and without the init solution, you’ll see the behavior I described:

    - Without the heuristic solution, Gurobi returns a best bound (ObjBoundC) of 0.765767
    - With the solution provided, Gurobi accepts it as a feasible solution and updates the bound to 0.766293

    This behavior seems inconsistent with the expectation that ObjBoundC should always remain a valid upper bound in a maximization problem.

    The original code is in cpp. I also translated the instance into AMPL format (located in the AMPL_formation directory) in case that’s more convenient for you to review.

    Additionally, we tested the same case using CPLEX under identical constraints. The results were:

    - GCP(our heuristic) solution: 0.766293
    - CPLEX upper bound (without plugging in GCP solution): 0.766367
    - CPLEX upper bound (after plugging in GCP solution): 0.766367
    which suggests that the bound of CPLEX is well above the solution from our heuristic, and remains unchanged after inserting the init_solution.

    This somehow contrasts with Gurobi's behaviour, where the bound improves after inserting the known feasible solution.

    We've identified a few other similar cases as well. I’d be happy to share them if it would help with debugging or further investigation.

    Thanks again, and I look forward to hearing your thoughts.

    Best regards,
    Daisy

    0
  • Riley Clement
    • Gurobi Staff

    Thanks Daisy, I'll take a look and see if I can replicate the issue.

    - Riley

    0
  • Riley Clement
    • Gurobi Staff

    Hi Daisy,

    The issue is coming from the very small objective coefficients:

    Coefficient statistics:
     Matrix range     [5e-01, 2e+03]
     Objective range  [2e-05, 1e-02]
     Bounds range     [1e+00, 9e+02]
     RHS range        [1e+00, 1e+03]

    Our machines use floating point arithmetic and the limitations of this must be navigated by using tolerances.  The tolerances are an absolute, not relative, value and the default value of OptimalityTol (1e-6) is not much smaller than these objective coefficients meaning it is relatively loose in comparison.

    There are a couple of things you can do to fix the issue:

    • Tighten OptimalityTol  - 1e-7 looks to be enough
    • Scale the objective function, either manually, or with ObjScale - I tried ObjScale=0.01 and it also seemed to resolve the issue.

    You can read more about tolerances and numerics in this section of our Guidelines for Numerical Issues.

    - Riley

     

    1
  • Daisy Wang
    • First Comment
    • First Question

    Hi Riley,

    Thank you again for your explanation and suggestions.

    I followed your recommendations and experimented with tightening OptimalityTol and adjusting ObjScale:

    model.set(GRB_DoubleParam_OptimalityTol, 1e-7);
    model.set(GRB_DoubleParam_ObjScale, 0.01);

    With OptimalityTol <= 1e-7 or ObjScale <= 0.01, the reported objBound becomes consistent (up to 7 digits) before and after I plug in the GCP heuristic solution. In these cases, the bound remains well above the GCP solution, so the earlier inconsistency is resolved.

    But I’m still unsure whether the reported bound in these cases should be considered a reliable UPPER bound, since the bound value shifts depending on the specific tolerance or scaling value:

    ObjScale vs. objBound:
    ObjScale = 0.01   → objBound = 0.7663953617142  
    ObjScale = 0.001  → objBound = 0.7664111072815  
    ObjScale = 0.0001 → objBound = 0.7664127461065  

    OptimalityTol vs. objBound:
    OptimalityTol = 1e-7 → objBound = 0.7663133514886  
    OptimalityTol = 1e-8 → objBound = 0.7663991915745  
    OptimalityTol = 1e-9 → objBound = 0.7664121034737  

    For comparison, I tried a similar setting in CPLEX:

    cplex.setParam(IloCplex::Param::MIP::Tolerances::AbsMIPGap, 1e-7);

    And changing this value (from the default 1e-6 to 1e-9) did not seem to change the reported bound, which remained fixed at:
    objBound = 0.766367

    I'm not sure whether this value is more reliable or if it’s simply because of different numerical handling in CPLEX.

    I understand this is fundamentally a numerical issue. Does this mean that relying on Gurobi's BestBound to estimate the performance of other algorithms may be unreliable when objective coefficients are very small?

    Thanks again for your help.

    Best regards,
    Daisy
     

     

     

    0
  • Daisy Wang
    • First Comment
    • First Question

    Actually, the differences in the reported bounds under different tolerance settings are small enough to be ignored in practice. Just to double confirm, would you say it's safer to set OptimalityTol to a smaller value (e.g., 1e-9) to ensure that the reported BestBound is a reliable upper bound on the true optimal value?

    0
  • Riley Clement
    • Gurobi Staff

    Hi Daisy,

    But I’m still unsure whether the reported bound in these cases should be considered a reliable UPPER bound, since the bound value shifts depending on the specific tolerance or scaling value

    This is not Gurobi specific, unfortunately we must take numerics into consideration when building a model and setting tolerances.  

    Ask your computer if the following is true 0.2 + 0.1 == 0.3 , e.g. in Python print(0.1 + 0.2 == 0.3).  The answer will be false, because the result of 0.2 + 0.1 is 0.30000000000000004, so this comparison needs to be done with a tolerance involved and the answer will be dependent on the tolerance.  Does this mean the result is unreliable?  If your answer is yes, then in general you can consider all computation on digital machines unreliable. 

    For comparison, I tried a similar setting in CPLEX:

    cplex.setParam(IloCplex::Param::MIP::Tolerances::AbsMIPGap, 1e-7);

    This is not a similar parameter and would not affect the bound in the same way.  (Our MIPGapAbs parameter is the equivalent).  The equivalent in CPLEX would be IloCplex::Param::Simplex::Tolerances::Optimality.

    Just to double confirm, would you say it's safer to set OptimalityTol to a smaller value (e.g., 1e-9) to ensure that the reported BestBound is a reliable upper bound on the true optimal value?

    If tolerances are loose the solver can accept solutions which are theoretically not feasible.  If they are too tight the solver can reject solutions which are theoretically feasible.  This sounds like a balancing game but for the vast majority of models there is no issue assuming it has been constructed in accordance with best practice.

    So yes, setting OptimalityTol=1e-9 will get you a more reliable upper bound, but it may make the “optimality” of the best solution unreliable.

    In your case I would solve the issue by manually scaling the objective up by multiplying it by 1000, but this is a personal preference.

    - Riley

     

    1
  • Daisy Wang
    • First Comment
    • First Question

    Hi Riley,

    I see. Thanks a million for your patience and clear explanation, it’s been very helpful. I really appreciate your time and support!

    Best regards, 
    Daisy

    0
  • Riley Clement
    • Gurobi Staff

    No problem at all Daisy, best of luck!

    0

Please sign in to leave a comment.