@@ -214,4 +214,58 @@ 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 > infeasibility (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 infeasibility = 0 ;
226+ // Determine the infeasibility exceeding the tolerance used in
227+ // computing the number of infeasibilities in a basic solution -
228+ // which defines its feasibility
229+ //
230+ // @primal_infeasibility calculation
231+ if (value < lower - tolerance) infeasibility = lower - value;
232+ if (value > upper + tolerance) infeasibility = value - upper;
233+ // Determine the residual used in computing the sum of
234+ // infeasibilities and max infeasibility - which are just for
235+ // reporting
236+ if (tolerance > 0 ) {
237+ if (value < lower) residual = lower - value;
238+ if (value > upper) residual = value - upper;
239+ } else {
240+ residual = infeasibility;
241+ }
242+ // Now, if the bound defining the residual is large, it's possible
243+ // for the infeasibility to be zero, but the residual to exceed the
244+ // tolerance due to numerical rounding
245+ //
246+ // Case in point is #2653 where row 1 has l = 157345 and the
247+ // activity gives zero infeasibility, but a residual of
248+ // 1.00000761449e-06, exceeding the tolerance of 1e-6 by delta =
249+ // 7.61449e-12.
250+ //
251+ // Now delta / l = 4.83937e-17, which is less than machine precision
252+ // (2.22045e-16), so the reliable residual value should ignore this
253+ // delta.
254+ //
255+ // In general, it might be possible to subtract delta from the
256+ // residual conditional on (something like)
257+ //
258+ // delta < 1e1 * max(1.0, fabs(bound_value)) * kHighsMacheps
259+ //
260+ // to give a reasonable value but, in practice, when infeasibility is
261+ // 0, it would seem fine to set
262+ //
263+ // residual = min(residual, tolerance)
264+ //
265+ // so that values of maximum infeasibility defined by residual
266+ // doesn't exceed the tolerance
267+ //
268+ if (infeasibility == 0 ) residual = min (residual, tolerance);
269+ return std::make_pair (infeasibility, residual);
270+ }
217271#endif // UTIL_HIGHSUTILS_H_
0 commit comments