Skip to content

Bug fix of dual init point computation in barrier#1577

Open
yuwenchen95 wants to merge 4 commits into
NVIDIA:mainfrom
yuwenchen95:qcqp-init-point
Open

Bug fix of dual init point computation in barrier#1577
yuwenchen95 wants to merge 4 commits into
NVIDIA:mainfrom
yuwenchen95:qcqp-init-point

Conversation

@yuwenchen95

Copy link
Copy Markdown
Contributor

Description

Extend barrier initial-point handling for SOCP and fix augmented-path KKT assembly at initialization.

  • Add ensure_initial_point_interior to push linear variables into the nonnegative orthant and SOC blocks into strict Lorentz cone interior; apply to x and z at the end of initial_point.
  • Fix augmented init sign: remove erroneous diag.multiply_scalar(-1.0) so the first-call augmented build produces -(Q+D) on the primal block, matching augmented_multiply and the refactor path.
  • Size augmented primal/dual RHS and solution vectors to max(n+m, device_augmented.n) for sparse SOC expansion, zero-padding extra entries.
  • Enable initial-point iterative refinement for LP/QP augmented solves by seeding d_diag_ from host diag; skip IR for cone problems and direct-free linear variables where operator/factorization would disagree.
  • Move primal, bound, and dual residual checks to after interior enforcement so diagnostics reflect the final starting point.
  • Remove unused inv_sqrt_diag member and initialization.

Issue

Checklist

  • I am familiar with the Contributing Guidelines.
  • Testing
    • New or existing tests cover these changes
    • Added tests
    • Created an issue to follow-up
    • NA
  • Documentation
    • The documentation is up to date with these changes
    • Added new documentation
    • NA

Signed-off-by: yuwenchen95 <yuwchen@nvidia.com>
@yuwenchen95 yuwenchen95 added this to the 26.08 milestone Jul 15, 2026
@yuwenchen95
yuwenchen95 requested a review from rg20 July 15, 2026 17:18
@yuwenchen95 yuwenchen95 self-assigned this Jul 15, 2026
@yuwenchen95 yuwenchen95 added the improvement Improves an existing functionality label Jul 15, 2026
@yuwenchen95
yuwenchen95 requested a review from a team as a code owner July 15, 2026 17:18
@yuwenchen95
yuwenchen95 requested a review from a team as a code owner July 15, 2026 17:18
@yuwenchen95
yuwenchen95 requested review from aliceb-nv, chris-maes and ramakrishnap-nv and removed request for aliceb-nv July 15, 2026 17:18
@yuwenchen95 yuwenchen95 added non-breaking Introduces a non-breaking change bug Something isn't working and removed improvement Improves an existing functionality labels Jul 15, 2026
@yuwenchen95 yuwenchen95 changed the title Extend dual init point computation for QCQP Bug fix of dual init point computation Jul 15, 2026
@yuwenchen95 yuwenchen95 changed the title Bug fix of dual init point computation Bug fix of dual init point computation in barrier Jul 15, 2026
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9abce5b1-3916-43da-a106-50834f3dc0ed

📥 Commits

Reviewing files that changed from the base of the PR and between 1fd6a32 and 8489cd4.

📒 Files selected for processing (7)
  • cpp/include/cuopt/mathematical_optimization/constants.h
  • cpp/include/cuopt/mathematical_optimization/utilities/internals.hpp
  • cpp/src/barrier/barrier.cu
  • cpp/src/dual_simplex/simplex_solver_settings.hpp
  • cpp/src/math_optimization/solver_settings.cu
  • python/cuopt_server/cuopt_server/tests/test_lp.py
  • python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py
🚧 Files skipped from review as they are similar to previous changes (7)
  • cpp/src/dual_simplex/simplex_solver_settings.hpp
  • python/cuopt_server/cuopt_server/tests/test_lp.py
  • cpp/src/math_optimization/solver_settings.cu
  • cpp/include/cuopt/mathematical_optimization/constants.h
  • cpp/include/cuopt/mathematical_optimization/utilities/internals.hpp
  • python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py
  • cpp/src/barrier/barrier.cu

📝 Walkthrough

Walkthrough

Changes

The barrier solver adds SOC-aware interior initialization and a Sturm/SeDuMi mu-based strategy. Diagonal preprocessing stores inv_diag directly, augmented vectors use computed dimensions, iterative refinement is restricted, and option 2 is documented across interfaces.

Barrier initialization

Layer / File(s) Summary
Mu-based initial-point option
cpp/include/cuopt/mathematical_optimization/constants.h, cpp/include/cuopt/mathematical_optimization/utilities/internals.hpp, cpp/src/math_optimization/solver_settings.cu, cpp/src/dual_simplex/simplex_solver_settings.hpp, python/cuopt_server/...
Defines the initial-point strategy constants and enum, accepts barrier_dual_initial_point=2, and documents the Sturm/SeDuMi mu-based primal-plus-dual initialization.
Inverse diagonal preprocessing
cpp/src/barrier/barrier.cu
Replaces inverse-square-root diagonal state and calculations with direct inverse-diagonal storage.
SOC-aware initial-point construction
cpp/src/barrier/barrier.cu
Builds mu-based SOC initial points, sizes augmented vectors from the augmented system, restricts iterative refinement, enforces interiors, and recomputes residuals after shifts.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: improvement

Suggested reviewers: ramakrishnap-nv, chris-maes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and directly describes the main barrier dual initial-point fix.
Description check ✅ Passed The description accurately summarizes the barrier initial-point, SOC, and augmented KKT changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
cpp/src/barrier/barrier.cu (1)

2187-2236: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

SOC initial-point branches are unreachable for cone problems

data.has_cones() forces init_strategy to 2, and that branch returns immediately, so the later has_cones()/has_soc path in initial_point() never runs for SOCPs. That makes the new SOC interior-enforcement helper and the sparse-SOC aug_size path dead code here, and it also silently ignores any explicit barrier_dual_initial_point = 0/1 setting on cone problems.

🤖 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/barrier/barrier.cu` around lines 2187 - 2236, Update initial_point’s
init_strategy selection and early-return flow so cone problems do not
unconditionally force strategy 2. Preserve explicit barrier_dual_initial_point
values 0/1 for cone problems, and route those cases through the existing SOC
initialization/interior-enforcement and sparse-SOC aug_size logic; retain the
mu-based strategy 2 behavior when selected.

Source: Path instructions

python/cuopt_server/cuopt_server/tests/test_lp.py (1)

163-172: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add dual_initial_point=2 to the test matrix. The current @pytest.mark.parametrize list covers -1, 0, and 1, but not the new 2 value, so the mu-based path still isn’t exercised.

🤖 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 `@python/cuopt_server/cuopt_server/tests/test_lp.py` around lines 163 - 172,
Update the pytest parameterization for test_barrier_solver_options to include
dual_initial_point=2 alongside the existing -1, 0, and 1 values, ensuring the
mu-based path is exercised.
🤖 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.

Outside diff comments:
In `@cpp/src/barrier/barrier.cu`:
- Around line 2187-2236: Update initial_point’s init_strategy selection and
early-return flow so cone problems do not unconditionally force strategy 2.
Preserve explicit barrier_dual_initial_point values 0/1 for cone problems, and
route those cases through the existing SOC initialization/interior-enforcement
and sparse-SOC aug_size logic; retain the mu-based strategy 2 behavior when
selected.

In `@python/cuopt_server/cuopt_server/tests/test_lp.py`:
- Around line 163-172: Update the pytest parameterization for
test_barrier_solver_options to include dual_initial_point=2 alongside the
existing -1, 0, and 1 values, ensuring the mu-based path is exercised.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7b1686c5-e726-4b2a-8619-e97d44323b58

📥 Commits

Reviewing files that changed from the base of the PR and between 5658d72 and 130b9a4.

📒 Files selected for processing (5)
  • cpp/src/barrier/barrier.cu
  • cpp/src/dual_simplex/simplex_solver_settings.hpp
  • cpp/src/math_optimization/solver_settings.cu
  • python/cuopt_server/cuopt_server/tests/test_lp.py
  • python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py

Signed-off-by: yuwenchen95 <yuwchen@nvidia.com>
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

CI Test Summary

8 failed · 23 passed · 0 skipped

conda-cpp-tests / 12.2.2, 3.11, amd64, rockylinux8, v100, earliest-driver, oldest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise
conda-cpp-tests / 12.2.2, 3.11, arm64, ubuntu22.04, a100, latest-driver, latest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise
conda-cpp-tests / 13.3.0, 3.14, amd64, ubuntu26.04, h100, latest-driver, latest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise
conda-cpp-tests / 13.0.3, 3.12, amd64, ubuntu24.04, l4, latest-driver, latest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise
conda-cpp-tests / 13.0.3, 3.14, arm64, rockylinux8, l4, latest-driver, latest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise
conda-cpp-tests / 12.9.2, 3.14, amd64, ubuntu22.04, h100, latest-driver, latest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise
conda-cpp-tests / 13.3.0, 3.13, arm64, ubuntu26.04, l4, latest-driver, latest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise
conda-cpp-tests / 13.3.0, 3.13, amd64, ubuntu26.04, rtxpro6000, latest-driver, latest-deps — 1 failed test
  • FastMpsParserEdgeTest.QcMatrixRowsMatchReferenceBitwise

Comment thread cpp/src/barrier/barrier.cu Outdated
// Linear orthant
for (i_t j = 0; j < cs; ++j) {
// Full primal+dual point; no factorization/solve (main loop factorizes later).
if (init_strategy == 2) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use enums instead of constants for initial point strategy type.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you think we'd better rename barrier_dual_initial_point to barrier_initial_point now?

@rg20

rg20 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@yuwenchen95 did you run QCQP benchmark? are there any regressions?

@yuwenchen95

Copy link
Copy Markdown
Contributor Author

@yuwenchen95 did you run QCQP benchmark? are there any regressions?

Current change won't have any impact on the performance of QCQP since I only add the options but force the initialization of QCQP as before.

Signed-off-by: yuwenchen95 <yuwchen@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cpp/src/barrier/barrier.cu (1)

2478-2479: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Exclude direct-free variables from the z interior shift.

nonnegative_z is all ones, so a direct-free z[j] == 0 participates in the SOC helper’s minimum calculation and can shift every other linear reduced cost by epsilon_adjust. Resetting only the free entries afterward does not undo that shift.

Proposed fix
-  ensure_interior(data.z, nonnegative_z);
+  ensure_interior(data.z, nonnegative_variables);
🤖 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/barrier/barrier.cu` around lines 2478 - 2479, Update the z
interior-shift preparation around ensure_interior so direct-free z entries are
excluded from the SOC helper’s minimum calculation before shifting. Use the
existing direct-free indicator to mask or otherwise remove those entries from
nonnegative_z, while preserving the current handling of nonnegative_variables
and ensuring free z values remain unchanged without influencing other reduced
costs.
🧹 Nitpick comments (2)
cpp/include/cuopt/mathematical_optimization/constants.h (1)

186-189: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Expose the new strategy values in public documentation and bindings.

These public constants add an externally configurable strategy contract. Please verify that the barrier parameter documentation and supported bindings expose -1, 0, 1, and 2, including the new SeDuMi-Mu option.

As per path instructions, public C++ API changes should be checked for corresponding docs/updates.

🤖 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/include/cuopt/mathematical_optimization/constants.h` around lines 186 -
189, Update the public barrier parameter documentation and all supported
language bindings to expose the constants from the barrier dual initial-point
strategy contract: automatic (-1), Lustig-Marsten-Shanno (0), dual least squares
(1), and SeDuMi-Mu (2). Use the existing public symbols and binding-generation
patterns, ensuring the new SeDuMi-Mu option is included consistently.

Source: Path instructions

cpp/src/barrier/barrier.cu (1)

2195-2241: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add regression coverage for the new initial-point branches.

Please cover automatic SOCP selection, explicit SedumiMu, SOC identity points, augmented padding, and direct-free linear variables.

🤖 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/barrier/barrier.cu` around lines 2195 - 2241, Add regression tests
covering automatic SOCP initial-point selection and explicit SedumiMu
initialization. Verify SOC entries use the identity point (mu*sqrt(2) in the
first coordinate and zero elsewhere), augmented padding is initialized
correctly, and direct-free linear variables receive the expected z value while
other linear variables remain unchanged.
🤖 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.

Outside diff comments:
In `@cpp/src/barrier/barrier.cu`:
- Around line 2478-2479: Update the z interior-shift preparation around
ensure_interior so direct-free z entries are excluded from the SOC helper’s
minimum calculation before shifting. Use the existing direct-free indicator to
mask or otherwise remove those entries from nonnegative_z, while preserving the
current handling of nonnegative_variables and ensuring free z values remain
unchanged without influencing other reduced costs.

---

Nitpick comments:
In `@cpp/include/cuopt/mathematical_optimization/constants.h`:
- Around line 186-189: Update the public barrier parameter documentation and all
supported language bindings to expose the constants from the barrier dual
initial-point strategy contract: automatic (-1), Lustig-Marsten-Shanno (0), dual
least squares (1), and SeDuMi-Mu (2). Use the existing public symbols and
binding-generation patterns, ensuring the new SeDuMi-Mu option is included
consistently.

In `@cpp/src/barrier/barrier.cu`:
- Around line 2195-2241: Add regression tests covering automatic SOCP
initial-point selection and explicit SedumiMu initialization. Verify SOC entries
use the identity point (mu*sqrt(2) in the first coordinate and zero elsewhere),
augmented padding is initialized correctly, and direct-free linear variables
receive the expected z value while other linear variables remain unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a43dc334-21f6-41fe-95a5-6904a172062f

📥 Commits

Reviewing files that changed from the base of the PR and between 8e29f92 and d39ddef.

📒 Files selected for processing (4)
  • cpp/include/cuopt/mathematical_optimization/constants.h
  • cpp/include/cuopt/mathematical_optimization/utilities/internals.hpp
  • cpp/src/barrier/barrier.cu
  • cpp/src/dual_simplex/simplex_solver_settings.hpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • cpp/src/dual_simplex/simplex_solver_settings.hpp

const std::vector<i_t>& cone_dims)
{
f_t min_linear = inf;
for (i_t j = 0; j < linear_end; ++j) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we call values.ensure_positive(epsilon_adjust, linear_mask); instead of this loop?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point. Now we push the entry when min_linear <= epsilon_adjust compared to min_x <= 0.0 in the existing ensure_positive. We should redo the LP/QP test to see if we can use a consistent ensure_positive @rg20.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I agree it would be better to move this code into ensure_positive. But we should test if this code actually yields an improvement.

@copy-pr-bot

copy-pr-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

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 coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
cpp/include/cuopt/mathematical_optimization/constants.h (1)

197-200: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the public barrier initial-point strategies.

These new public constants encode externally visible values (-1 automatic, 0–2 explicit strategies). Add or update user-facing API documentation describing their behavior, including automatic selection for cone problems, and keep it aligned with the solver setting contract.

As per path instructions, public-header API changes should have corresponding documentation updates.

🤖 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/include/cuopt/mathematical_optimization/constants.h` around lines 197 -
200, Document the public constants CUOPT_BARRIER_DUAL_INITIAL_POINT_AUTOMATIC,
CUOPT_BARRIER_DUAL_INITIAL_POINT_LUSTIG_MARSTEN_SHANNO,
CUOPT_BARRIER_DUAL_INITIAL_POINT_DUAL_LEAST_SQUARES, and
CUOPT_BARRIER_DUAL_INITIAL_POINT_SEDUMI_MU in the user-facing API documentation.
Describe their externally visible values and strategies, including automatic
selection for cone problems, and ensure the documentation matches the solver
setting contract.

Source: Path instructions

🤖 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.

Nitpick comments:
In `@cpp/include/cuopt/mathematical_optimization/constants.h`:
- Around line 197-200: Document the public constants
CUOPT_BARRIER_DUAL_INITIAL_POINT_AUTOMATIC,
CUOPT_BARRIER_DUAL_INITIAL_POINT_LUSTIG_MARSTEN_SHANNO,
CUOPT_BARRIER_DUAL_INITIAL_POINT_DUAL_LEAST_SQUARES, and
CUOPT_BARRIER_DUAL_INITIAL_POINT_SEDUMI_MU in the user-facing API documentation.
Describe their externally visible values and strategies, including automatic
selection for cone problems, and ensure the documentation matches the solver
setting contract.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4a030491-2341-476d-bc3f-c9728b76eec0

📥 Commits

Reviewing files that changed from the base of the PR and between d39ddef and 1fd6a32.

📒 Files selected for processing (3)
  • cpp/include/cuopt/mathematical_optimization/constants.h
  • cpp/src/dual_simplex/simplex_solver_settings.hpp
  • cpp/src/math_optimization/solver_settings.cu
🚧 Files skipped from review as they are similar to previous changes (2)
  • cpp/src/math_optimization/solver_settings.cu
  • cpp/src/dual_simplex/simplex_solver_settings.hpp

Signed-off-by: yuwenchen95 <yuwchen@nvidia.com>
PSLP = CUOPT_PRESOLVE_PSLP
};

/**

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would be better if you put this in barrier.hpp.

settings.log.printf("min v %e min z %e\n", data.v.minimum(), data.z.minimum());
#endif

// Residual checks below reflect the final initial point, after positivity shifts.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We did the residual checks before the positivity shift to see how well we are solving the least squares problem. We already print out the residuals in the log after the positivity shift. So I think these are not necessary. I would restore the previous code.

@ramakrishnap-nv ramakrishnap-nv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Lets add any documentation if we are missing

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

Labels

barrier 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.

5 participants