Fix loose tolerances in the objective function integrality detection - #1148
Conversation
📝 WalkthroughWalkthroughModified objective integrality recomputation in the problem solver to use a dedicated Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cpp/src/mip_heuristics/problem/problem.cu (1)
1359-1359: Use epsilon-based zero checks instead of exact== 0for objective coefficients.Line 1359 and Line 1372 use exact floating-point equality. Near-zero coefficients after transforms can be misclassified by exact zero checks.
As per coding guidelines, "Check numerical stability: prevent overflow/underflow, precision loss, division by zero/near-zero, and use epsilon comparisons for floating-point equality checks".Patch sketch
void problem_t<i_t, f_t>::recompute_objective_integrality() { using cuopt::linear_programming::detail::is_integer; + constexpr f_t objective_zero_tol = 1e-12; objective_is_integral = thrust::all_of(handle_ptr->get_thrust_policy(), thrust::make_counting_iterator(0), thrust::make_counting_iterator(n_variables), [v = view()] __device__(i_t var_idx) -> bool { - if (v.objective_coefficients[var_idx] == 0) return true; + auto c = v.objective_coefficients[var_idx]; + if (raft::abs(c) <= objective_zero_tol) return true; // Need a tight tolerance for integrality to weed out instances like // neos-827175 with very small objective coefficients - return is_integer<f_t>(v.objective_coefficients[var_idx], 1e-9) && + return is_integer<f_t>(c, 1e-9) && ((v.variable_types[var_idx] == var_t::INTEGER) || (v.var_flags[var_idx] & (i_t)VAR_IMPLIED_INTEGER)); }); bool objvars_all_integral = thrust::all_of(handle_ptr->get_thrust_policy(), thrust::make_counting_iterator(0), thrust::make_counting_iterator(n_variables), [v = view()] __device__(i_t var_idx) -> bool { - if (v.objective_coefficients[var_idx] == 0) return true; + if (raft::abs(v.objective_coefficients[var_idx]) <= objective_zero_tol) return true; return (v.variable_types[var_idx] == var_t::INTEGER) || (v.var_flags[var_idx] & (i_t)VAR_IMPLIED_INTEGER); });Also applies to: 1372-1372
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cpp/src/mip_heuristics/problem/problem.cu` at line 1359, The code uses exact equality checks against zero for objective coefficients (v.objective_coefficients[var_idx] == 0) at the two locations noted; replace these with an epsilon-based comparison (e.g., fabs(v.objective_coefficients[var_idx]) <= EPS) and define a sensible EPS constant (or compute one from std::numeric_limits<double>::epsilon() scaled appropriately) so near-zero coefficients are treated as zero; update both occurrences (the checks around var_idx and the second instance) and include <cmath> or use std::abs as needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@cpp/src/mip_heuristics/problem/problem.cu`:
- Line 1359: The code uses exact equality checks against zero for objective
coefficients (v.objective_coefficients[var_idx] == 0) at the two locations
noted; replace these with an epsilon-based comparison (e.g.,
fabs(v.objective_coefficients[var_idx]) <= EPS) and define a sensible EPS
constant (or compute one from std::numeric_limits<double>::epsilon() scaled
appropriately) so near-zero coefficients are treated as zero; update both
occurrences (the checks around var_idx and the second instance) and include
<cmath> or use std::abs as needed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: b45088a8-b6c5-4a85-ab8f-5e0ddfba9153
📒 Files selected for processing (1)
cpp/src/mip_heuristics/problem/problem.cu
|
/ok to test facf383 |
nguidotti
left a comment
There was a problem hiding this comment.
Approved! Thanks for the fix, Alice!
|
/merge |
The objective function integrality detection was relying on weak tolerances, which caused neos-827175 to be incorrectly accounted as integral and causing an incorrect solution bound to be reported. (objective coefficients were as low as 1e-5)
This PR uses a tighter 1e-9 tolerance for integrality detection in the objective function to avoid such issues.
Description
Issue
Checklist