Skip to content

Conversation

@nguidotti
Copy link
Contributor

@nguidotti nguidotti commented Jan 20, 2026

  • Fixed early termination in CMS750_4 due to an incorrect root objective from the PDLP. It provides an objective in user space and B&B expects the objective in the solver space.
  • Fixed setting the number of threads to a fixed value when running cuopt_cli. Now the number of threads in the probing cache can be controlled by the bounds_update::settings_t.
  • Inverted loop order in probing cache to avoid creating and deleting the OpenMP thread pool each iteration.
  • Silence the logs from the concurrent mode when running inside MIP.

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

Summary by CodeRabbit

  • New Features
    • Added configurable per-run threading and a bidirectional solver↔user objective conversion.
  • Optimizations
    • More consistent, configurable threading for preprocessing to improve performance stability.
  • Bug Fixes
    • Safer handling to avoid unwanted state updates during active solves.
  • Behavior Changes
    • Objective-value handling adjusted for more accurate solver/user consistency.
  • Quality of Life
    • Reduced verbose logging during mixed-mode solves for clearer output.

✏️ Tip: You can customize this high-level summary in your review settings.

@nguidotti nguidotti added this to the 26.02 milestone Jan 20, 2026
@nguidotti nguidotti self-assigned this Jan 20, 2026
@nguidotti nguidotti requested a review from a team as a code owner January 20, 2026 14:33
@nguidotti nguidotti added bug Something isn't working non-breaking Introduces a non-breaking change labels Jan 20, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 20, 2026

📝 Walkthrough

Walkthrough

Reads PDLP objective as solver-space and derives user-space for callbacks; adds user→solver objective conversion API; makes presolve thread count configurable with OpenMP and binds per-thread pools to that count; guards B&B root assignment during runs; conditionally suppresses LP solver logs during MIP solves.

Changes

Cohort / File(s) Summary
Objective conversion API
cpp/src/mip/problem/problem.cuh, cpp/src/mip/problem/problem.cu
Adds get_solver_obj_from_user_obj(f_t user_obj) const to problem_t to convert user-space objective → solver-space.
Diversity manager objective handling
cpp/src/mip/diversity/diversity_manager.cu
Reads PDLP objective as solver-space (lp_result.get_objective_value()), computes user-space objective, and updates root-relaxation callback call to (solver_obj, user_obj, reduction_costs, iters); adds clarifying comments about solver/user semantics.
Presolve threading / probing cache
cpp/src/mip/presolve/probing_cache.cu, cpp/src/mip/presolve/bounds_presolve.cuh
Introduces configurable num_threads from bound_presolve_t::settings_t (adds i_t num_threads = -1), includes <omp.h>, sizes per-thread pools by num_threads, and uses #pragma omp parallel num_threads(num_threads) with a subsequent #pragma omp for.
Dual simplex / B&B guard
cpp/src/dual_simplex/branch_and_bound.hpp
Adds guard in set_root_relaxation_solution to only assign root crossover and related fields when is_running is false.
LP solver logging
cpp/src/linear_programming/solve.cu
Adds CUOPT_LP_SOLVER_LOG_INFO macro to suppress verbose logs when settings.inside_mip is true; replaces multiple CUOPT_LOG_INFO calls with the macro; updates copyright year.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references two specific bug fixes (early termination in CMS750_4 and hard-coded thread count), both of which are substantive changes present in the changeset addressing objective mapping and thread configuration issues.

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

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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


auto user_obj = problem_ptr->get_user_obj_from_solver_obj(lp_result.get_objective_value());
// PDLP returns user-space objective (it applies objective_scaling_factor internally)
auto user_obj = lp_result.get_objective_value();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this uniform across the solvers? Or just PDLP behaves differently than others? We need to standardize this.

…ed concurrent solution when the B&B is already running. moved number of threads in the probing cache to the setting struct.
Copy link

@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: 0

Caution

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

⚠️ Outside diff range comments (1)
cpp/src/mip/presolve/probing_cache.cu (1)

859-910: Add defensive validation for num_threads before pool sizing and parallel launch

The code assumes settings.num_threads is always positive, but since settings_t is a public struct, external code can set num_threads to 0 (or modify it between initialization and use). If 0 is assigned:

  • modification_vector_pool and substitution_vector_pool would have size 0
  • #pragma omp parallel num_threads(0) produces undefined behavior (OpenMP spec)
  • If threads spawn despite 0, thread_idx from omp_get_thread_num() will exceed pool bounds, causing out-of-bounds access

Add a defensive clamp before sizing the pools:

Proposed fix
-  const size_t num_threads = bound_presolve.settings.num_threads;
+  const i_t requested_threads = bound_presolve.settings.num_threads;
+  size_t num_threads =
+    requested_threads > 0 ? static_cast<size_t>(requested_threads)
+                          : static_cast<size_t>(omp_get_max_threads());
+  if (num_threads == 0) { num_threads = 1; }

Aligns with multithreading safety guidelines to prevent resource exhaustion and thread safety violations.

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.

4 participants