coin-or / SHOT

A solver for mixed-integer nonlinear optimization problems
https://shotsolver.dev
Eclipse Public License 2.0
119 stars 25 forks source link

Cbc stability #2

Closed andreaslundell closed 4 years ago

andreaslundell commented 6 years ago

Cbc is still not as stable as CPLEX/Gurobi for solving MIP problems. It is recommended that either CPLEX or Gurobi is used if these are available.

Convex MINLP problems with issues:

andreaslundell commented 4 years ago

The reason why enpro48pb and procsyn are not working seems to be an issue with Cbc: when adding a cutting plane with a large RHS, it gets replaced by +infinity, i.e. the RHS is made larger, making the constraint and thus the problem unbounded.

The assert in https://github.com/coin-or/SHOT/blob/8dea3c01e3ca314180cd16a70ec29e9f11d51fe9/src/MIPSolver/MIPSolverCbc.cpp#L292-L293 fails with large values, e.g. -constant = 1.1e50, while otherwise, it works well. The limit when it fails seems to go somewhere around 1e26. Is this somehow strange, but "expected" behavior or is it a bug in Cbc/Clp/Osi @svigerske?

svigerske commented 4 years ago

Well, how would SHOT feel if you give it a MINLP with 1e26 in some constants? :)

Numerical solvers usually assume some decent numerical properties on the problem. Cplex or Gurobi may be more robust than Cbc and especially handle huge values in a constraint sides better, but it would be good if SHOT could check the numerics of a cut that it is adding to the MIP, and maybe improve numerics or omit the cut.

Given a cut sum_i a_i x_i <= b and assume all a_i being nonzero, check whether min_i |a_i| is not too tiny, max_i |a_i| and |b| are not too large, and the range max_i|a_i|/min_i|a_i| is not too large either.

What is small and large you can depend on the machine precision (1+1e-12=1 with double precision floating point) and feasibility tolerance, maybe. In SCIP the defaults are 1e-9 for tiny and 1e15 for huge, but keeping the max range under something like 10/feastol may make sense.

andreaslundell commented 4 years ago

Yes, I understand that it is not ideal (and I probably need to add some fix to get it more robust), but the main issue is that when a too large value is given to Cbc, it changes that bound from a large bound to something larger (infinity) :) Gurobi and Cplex replaces it with something smaller (i.e. their max bound)...

Do you know exactly at what limit it does this, or is it somehow dependent on the cut as a whole?

svigerske commented 4 years ago

I don't know. You can ask Cbc, or OsiClp, for the value for infinity (getInfinity()), but I think that defaults to COIN_DBL_MAX, which should be std::numeric_limits<double>::max(). But there are a number of constants scattered around in the Cbc code and one would have to debug through the code to see where and why this is happening.