@@ -214,4 +214,70 @@ inline T fractionality(T input, T* intval = nullptr) {
214214 if (intval != nullptr ) *intval = val;
215215 return abs (input - val);
216216}
217+
218+ inline std::pair<double , double > infeasiblity (const double * lower,
219+ const double * value,
220+ const double * upper,
221+ const double * tolerance) {
222+ using std::fabs;
223+ using std::min;
224+ double residual = 0 ;
225+ double infeasiblity = 0 ;
226+ std::string bound_type = " " ;
227+ double bound_value = 0 ;
228+ // Determine the infeasiblity exceeding the tolerance used in
229+ // computing the number of infeasibilities - which defines
230+ // feasibility of a solution
231+ if (*value < *lower - *tolerance) {
232+ infeasiblity = *lower - *value;
233+ }
234+ if (*value > *upper + *tolerance) {
235+ infeasiblity = *value - *upper;
236+ }
237+ // Determine the residual used in computing the sum of
238+ // infeasibilities and max infeasibility - which are just for
239+ // reporting
240+ if (*tolerance > 0 ) {
241+ if (*value < *lower) {
242+ bound_type = " LB" ;
243+ bound_value = *lower;
244+ residual = *lower - *value;
245+ }
246+ if (*value > *upper) {
247+ bound_type = " UB" ;
248+ bound_value = *upper;
249+ residual = *value - *upper;
250+ }
251+ } else {
252+ residual = infeasiblity;
253+ }
254+ // Now, if the bound defining the residual is large, it's possible
255+ // for the infeasiblity to be zero, but the residual to exceed the
256+ // tolerance due to numerical rounding
257+ //
258+ // Case in point is #2653 where row 1 has l = 157345 and the
259+ // activity gives zero infeasiblity, but a residual of
260+ // 1.00000761449e-06, exceeding the tolerance of 1e-6 by delta =
261+ // 7.61449e-12.
262+ //
263+ // Now delta / l = 4.83937e-17, which is less than machine precision
264+ // (2.22045e-16), so the reliable residual value should ignore this
265+ // delta.
266+ //
267+ // In general, it might be possible to subtract delta from the
268+ // residual conditional on (something like)
269+ //
270+ // delta < 1e1 * max(1.0, fabs(bound_value)) * kHighsMacheps
271+ //
272+ // to give a reasonable value but, in practice, when infeasiblity is
273+ // 0, it would seem fine to set
274+ //
275+ // residual = min(residual, tolerance)
276+ //
277+ // so that values of maximum infeasibility defined by residual
278+ // doesn't exceed the tolerance
279+ //
280+ // if (infeasiblity == 0) residual = min(residual, *tolerance);
281+ return std::make_pair (infeasiblity, residual);
282+ }
217283#endif // UTIL_HIGHSUTILS_H_
0 commit comments