emallson / rplex

Rust bindings for CPLEX
BSD 3-Clause "New" or "Revised" License
5 stars 3 forks source link

Fix float comparison #6

Closed ki-la closed 2 years ago

ki-la commented 2 years ago

For binary variables CPLEX might return values that are not exactly 1.0 or 0.0 (due to machine precision). Thus, setting a binary variable to "x == 1.0" in function "solve_as" can return incorrect results. This was (hopefully - at least in my tests) fixed by checking if x is equal to 1.0 +/- f32::EPSILON (f64::EPSILON was still too precise in the tests).

emallson commented 2 years ago

Do you have an example test program where this occurs? CPLEX should be returning a literal 1.0 which has exact floating point representation in the case of a binary variable

emallson commented 2 years ago

hmm, looks like there is an edge case where it can return non-integral values for binary variables: https://www.ibm.com/support/pages/why-does-binary-or-integer-variable-take-noninteger-value-solution. The correct way to set the bound here is to:

  1. Add CPXgetdblparam to the external C functions.
  2. Use that method to retrieve the EpInt parameter https://www.ibm.com/docs/en/icos/12.8.0.0?topic=parameters-integrality-tolerance
  3. modify your patch to use this tolerance for rounding
ki-la commented 2 years ago

Thanks for the advice and useful links! The bound is now set using the CPLEX parameter for integrality tolerance.

emallson commented 2 years ago

Thanks!