Fix a bug in dual variables and reduced costs when we add implied bounds on free variables#1237
Fix a bug in dual variables and reduced costs when we add implied bounds on free variables#1237chris-maes wants to merge 3 commits into
Conversation
…nds on free variables When -inf <= x_j <= inf and we add implied bounds on x_j, we will compute a dual solution (u, w) that satisfies A^T u + w = c + Qx but w_j could be nonzero. When x_j is free, we need to enforce that the corresponding reduced cost is zero. We do this by transforming (u, w) into (y, z) such that A^T y + z = c + Qx with z_j = 0 for all j such that -inf < x_j < inf. We also add a unit test on a small QP to confirm the fix.
|
/ok to test 23789ff |
|
/ok to test 06eb7d2 |
📝 WalkthroughWalkthroughThis PR extends presolve to track which constraints imply finite bounds on formerly-free variables, then applies a post-solve dual correction during solution uncrushing. Presolve records constraint indices and coefficients for each bounded variable, and uncrush uses these to adjust dual variables and reduced costs via the original constraint matrix. ChangesBarrier dual correction for bounded free variables
🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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.
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/dual_simplex/presolve.cpp`:
- Around line 1758-1759: The dual correction unconditionally computes du = w_j /
bfv.coefficient which can produce Inf/NaN when bfv.coefficient is zero or
near-zero; in the block around du, guard the division by checking
fabs(bfv.coefficient) against a small epsilon (e.g. machine or
domain-appropriate epsilon) and only compute and apply input_y[bfv.constraint]
+= du when the coefficient is safe; if the coefficient is too small, skip the
update or handle it deterministically (clamp, set du = 0, or record/log the
event) to avoid division-by-zero and maintain numerical stability in the dual
correction path.
🪄 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: f10782e8-e45e-4214-85b0-0c7d011d8f83
📒 Files selected for processing (5)
cpp/src/dual_simplex/presolve.cppcpp/src/dual_simplex/presolve.hppcpp/src/dual_simplex/solve.cppcpp/tests/dual_simplex/unit_tests/solve.cppcpp/tests/dual_simplex/unit_tests/solve_barrier.cu
When -inf <= x_j <= inf and we add implied bounds on x_j, we will compute a dual solution (u, w) that satisfies
A^T u + w = c + Qx
but w_j could be nonzero. When x_j is free, we need to enforce that the corresponding reduced cost is zero. We do this by transforming (u, w) into (y, z) such that A^T y + z = c + Qx with z_j = 0 for all j such that -inf < x_j < inf.
We also add a unit test on a small QP to confirm the fix.
Fixes #1119