lanl-ansi / Juniper.jl

A JuMP-based Nonlinear Integer Program Solver
https://lanl-ansi.github.io/Juniper.jl/stable/
MIT License
179 stars 22 forks source link

add slow progress due to numerical instability #248

Open GabrielPonte opened 2 years ago

GabrielPonte commented 2 years ago

When dealing with numerical problems, Mosek can return SLOW_PROGRESS in the termination status. Sometimes, in my experiments, the optimal solution wasn't reached because of this, maybe Juniper treats it as Infeasible, but not necessarily is an infeasible solution, most of the times is almost feasible solution or almost optimal solution. Links: https://docs.mosek.com/latest/capi/response-codes.html

MSK_RES_TRM_STALL (10006) The optimizer is terminated due to slow progress. Stalling means that numerical problems prevent the optimizer from making reasonable progress and that it makes no sense to continue. In many cases this happens if the problem is badly scaled or otherwise ill-conditioned. There is no guarantee that the solution will be feasible or optimal. However, often stalling happens near the optimum, and the returned solution may be of good quality. Therefore, it is recommended to check the status of the solution. If the solution status is optimal the solution is most likely good enough for most practical purposes. Please note that if a linear optimization problem is solved using the interior-point optimizer with basis identification turned on, the returned basic solution likely to have high accuracy, even though the optimizer stalled. Some common causes of stalling are a) badly scaled models, b) near feasible or near infeasible problems.

https://groups.google.com/g/mosek/c/v7lbk__Gr4s

My best guess is Mosek computes a fairly accurate solution. And most likely it is good enough for all practical purposes. You are aware you always get an approximate solution so even if Mosek had not said slow progress you would have to evaluate whether the solution is accurate enough. Btw you can see Mosek warns about a large number in the objective. That is because such things makes your problem harder numerically.

https://gitter.im/JuliaOpt/SumOfSquares.jl?at=5d02c3f12d3f89045fb6b444

With SLOW_PROGRESS you could also check primal_status to check if you have a feasible solution even if it's not optimal

ccoffrin commented 2 years ago

@Wikunia @odow this looks like a reasonable extension to me. What do you think?

ccoffrin commented 2 years ago

Possibly the MOI documentation makes SLOW_PROGRESS sound more problematic that it really is?

codecov[bot] commented 2 years ago

Codecov Report

Merging #248 (92340ac) into master (053661e) will decrease coverage by 0.04%. The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master     #248      +/-   ##
==========================================
- Coverage   91.81%   91.76%   -0.05%     
==========================================
  Files          20       20              
  Lines        2015     2015              
==========================================
- Hits         1850     1849       -1     
- Misses        165      166       +1     
Impacted Files Coverage Δ
src/util.jl 71.17% <100.00%> (ø)
src/BnBTree.jl 94.34% <0.00%> (-0.30%) :arrow_down:

:mega: Codecov can now indicate which changes are the most critical in Pull Requests. Learn more

odow commented 2 years ago

Yeah I don't know if you want Juniper to act as if SLOW_PROGRESS is the same as optimal. It's really telling you that there is a problem with the model formulation, and so it should be fixed on the modeling side.

See this recent discourse post: https://discourse.julialang.org/t/adding-objective-to-jump-model-changes-feasibility/83200

odow commented 2 years ago

This had the same underlying issue as https://github.com/lanl-ansi/Juniper.jl/pull/250. Now it should be fine because Juniper can return SLOW_PROGRESS as the termination status, and RESULT_STATUS_UNKNOWN for the primal status.

Claiming that SLOW_PROGRESS is the same as optimal is the wrong thing to do.