Skip to content

Add a guard for huge bounds in bounds propagation#1390

Open
hlinsen wants to merge 2 commits into
NVIDIA:mainfrom
hlinsen:add-bound-prop-check
Open

Add a guard for huge bounds in bounds propagation#1390
hlinsen wants to merge 2 commits into
NVIDIA:mainfrom
hlinsen:add-bound-prop-check

Conversation

@hlinsen
Copy link
Copy Markdown
Contributor

@hlinsen hlinsen commented Jun 4, 2026

Semi-continuous var with big-M reformulations can create large row activities where the true residual is
smaller than double precision at that scale.

    row activity      = -2.476e26
    var contribution  = -2.476e26
    true residual     = -2.0e10
    double ULP there  =  3.44e10

  After cancellation:
    computed residual = -3.44e10
    coeff             = -1.23
    candidate bound   =  2.8e10

In that case, floating point cancellation can produce an unsafe candidate bound and later false infeasibility.

We add an usual guard on huge bounds derived. Note that it does not protect against the float cancellation error.

A full cancellation-aware guard would require tracking row activity scale or using compensated activity arithmetic, which would add extra reductions/storage or broader propagation changes.

@hlinsen hlinsen requested a review from a team as a code owner June 4, 2026 03:18
@hlinsen hlinsen added the bug Something isn't working label Jun 4, 2026
@hlinsen hlinsen requested a review from akifcorduk June 4, 2026 03:18
@hlinsen hlinsen added the non-breaking Introduces a non-breaking change label Jun 4, 2026
@hlinsen hlinsen requested a review from nguidotti June 4, 2026 03:18
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented Jun 4, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds tolerance-aware validation to bound updates in the mixed-integer programming presolve routine. A new predicate function gates candidate lower and upper bound assignments, ensuring updates exceed a scaled absolute tolerance threshold relative to the bound's magnitude before being written back to the working interval.

Changes

Bound Update Validation

Layer / File(s) Summary
Tolerance check predicate
cpp/src/mip_heuristics/presolve/bounds_update_helpers.cuh
New device function accept_candidate_bound_update validates whether a candidate bound change is significant enough relative to its magnitude and the provided absolute tolerance.
Conditional bound updates in presolve
cpp/src/mip_heuristics/presolve/bounds_update_helpers.cuh
update_bounds_per_cnst now conditionally applies new_lb and new_ub only after passing the acceptance check using the problem's absolute tolerance, preventing spurious bound tightening.

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add a guard for huge bounds in bounds propagation' directly aligns with the main change: adding the accept_candidate_bound_update helper to guard against huge bounds in bounds propagation.
Description check ✅ Passed The description explains the problem (floating-point cancellation in semi-continuous variables with big-M reformulations), provides a concrete example, and describes the solution (adding a guard on huge bounds), all of which relate to the actual code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/src/mip_heuristics/presolve/bounds_update_helpers.cuh`:
- Around line 46-47: The hardcoded acceptance scale (candidate_bound_scale =
f_t{1e-14}) in bounds_update_helpers.cuh makes bound gating inflexible; change
the code to derive this scale from the solver's configured tolerances (or accept
a passed-in relative tolerance) instead of the magic constant: replace the
literal with a parameter or a value read from the solver settings (e.g.,
solver_tolerances.relative_bound_tol or an added function parameter rel_tol) and
use that derived value in the existing comparison that uses
candidate_bound_scale, while keeping the existing variables bound and abs_tol
intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f63805a4-c0d7-438e-9fec-93725704b9f2

📥 Commits

Reviewing files that changed from the base of the PR and between d6d6f9e and b148a3b.

📒 Files selected for processing (1)
  • cpp/src/mip_heuristics/presolve/bounds_update_helpers.cuh

Comment on lines +46 to +47
constexpr f_t candidate_bound_scale = f_t{1e-14};
return abs(bound) * candidate_bound_scale <= abs_tol;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid a hardcoded acceptance scale in bound gating.

Line 46 hardcodes 1e-14, which makes the guard policy fixed across models and can reject legitimate large-scale bound tightenings. Please derive this scale from configured solver tolerances (or pass a configurable relative tolerance) instead of embedding a magic constant.

As per coding guidelines, "Avoid hardcoded tolerances that fail on degenerate problems; ensure tolerance consistency with solver settings."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/mip_heuristics/presolve/bounds_update_helpers.cuh` around lines 46 -
47, The hardcoded acceptance scale (candidate_bound_scale = f_t{1e-14}) in
bounds_update_helpers.cuh makes bound gating inflexible; change the code to
derive this scale from the solver's configured tolerances (or accept a passed-in
relative tolerance) instead of the magic constant: replace the literal with a
parameter or a value read from the solver settings (e.g.,
solver_tolerances.relative_bound_tol or an added function parameter rel_tol) and
use that derived value in the existing comparison that uses
candidate_bound_scale, while keeping the existing variables bound and abs_tol
intact.

@hlinsen
Copy link
Copy Markdown
Contributor Author

hlinsen commented Jun 4, 2026

/ok to test b4ba3b1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant