Fix adj_list check bug and improve clique cuts#1386
Conversation
Brings in upstream's unified OpenMP threading model (PR NVIDIA#1099) and other fixes (NVIDIA#1206 concurrent LP exception cleanup, NVIDIA#1214/NVIDIA#1216 destruction/ capture fixes) while preserving local work on the cut and clique stack. Conflict resolution highlights: - Drop std::future/std::async clique flow; adopt upstream's omp task + omp_atomic_t<bool> signal_extend pattern. - Drop modify_problem parameter from find_initial_cliques (we already removed the code that consumed it); adapt the omp-task call site in branch_and_bound::solve accordingly. - Take upstream's [this, &population] capture for the root-LP CPUFJ improvement callback; the new omp taskwait-before-destruction guarantee makes the prior context-lifetime fix unnecessary. - Take upstream's do_cut_pass refactor of the per-pass LP resolve loop; move our per-pass root_lp_with_cuts publish into do_cut_pass so the benchmark metric is still updated on early exits. - Keep our out-of-line omp_mutex_t definitions in omp_helpers.cpp; the enhanced omp_atomic_t with std::memory_order is taken from upstream.
generate_clique_cuts() used a hand-rolled emptiness test on only first + addtl_cliques, so it early-exited and skipped separation when only small_clique_adj (the small/adjacency-list cliques) was populated. Use the canonical clique_table_t::empty(), which also accounts for small_clique_adj, so those smaller clique cuts are generated. Signed-off-by: akif <akifcorduk@gmail.com>
|
/ok to test 98b1ee2 |
| f_t cut_generation_start_time = tic(); | ||
| i_t cut_pool_size = 0; | ||
| f_t cut_generation_start_time = tic(); | ||
| auto publish_cut_generation_time = [&](bool force_time_limit_value = false) { |
There was a problem hiding this comment.
I think it is useful to be able to track cut generation time, but i am commenting on this to discuss.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (2)
💤 Files with no reviewable changes (2)
📝 WalkthroughWalkthroughAdds per-instance MIPLIB gap-stat reporting and root-LP/cut timing telemetry, forwards benchmark pointers through solver components, and refactors clique-table storage/extension to CSR-backed maps with accompanying cut-generation and test updates. ChangesBenchmark gap reporting
Clique table storage and cut-generation refactor
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
🚥 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 |
|
@coderabbitai help |
ChatThere are 3 ways to chat with CodeRabbit:
CodeRabbit commands
Other keywords and placeholders
Status, support, documentation and community
|
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@benchmarks/linear_programming/cuopt/miplib2017_optima.hpp`:
- Line 25: Replace the lone "`#pragma` once" in the header with a traditional
include guard: remove "`#pragma` once", add an `#ifndef` / `#define` pair using a
unique uppercase macro (e.g.
BENCHMARKS_LINEAR_PROGRAMMING_CUOPT_MIPLIB2017_OPTIMA_HPP) at the top of the
file and close with a matching `#endif` with a trailing comment at the end of the
file; ensure the macro name matches the header (miplib2017_optima.hpp) and is
unique across the repo.
In `@cpp/include/cuopt/linear_programming/mip/solver_settings.hpp`:
- Around line 33-40: The comment incorrectly says the stored LP values are in
the "solver objective sense" which encourages mixing objective spaces; update
the text to state that root_lp_no_cuts and root_lp_with_cuts are published via
compute_user_objective(...) (see branch_and_bound.cpp) and therefore represent
user-space/objective values compatible with MIPLIB comparisons; replace the
phrase "in B&B's solver objective sense" with wording that they are user-space
objectives (or already converted by compute_user_objective) and clarify
quiet_NaN() meaning remains the same.
In `@cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cuh`:
- Around line 83-95: csr_var_map_t's slice helpers can compute pointers into an
empty indices vector causing UB; change slice_begin(i_t v) and slice_end(i_t v)
to first check if indices.empty() and return nullptr when empty, and update
slice_contains(i_t v, i_t value) to treat a nullptr range as empty (return
false) before calling std::binary_search; keep avg_slice_size() as-is. Also
ensure callers like fill_var_clique_maps / finalize_from_unsorted_pairs /
get_adj_set_of_var / check_adjacency rely on slice_contains or handle a nullptr
range as an empty slice.
🪄 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: 9be46e1d-b244-43be-ae7b-4ad7221fb149
📒 Files selected for processing (12)
benchmarks/linear_programming/cuopt/miplib2017_optima.hppbenchmarks/linear_programming/cuopt/run_mip.cppcpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/branch_and_bound/branch_and_bound.cppcpp/src/cuts/cuts.cppcpp/src/cuts/cuts.hppcpp/src/dual_simplex/simplex_solver_settings.hppcpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cucpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cuhcpp/src/mip_heuristics/solver.cucpp/src/utilities/omp_helpers.hppcpp/tests/mip/cuts_test.cu
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
cpp/src/utilities/omp_helpers.hpp (1)
31-31: ⚡ Quick winRemove redundant include.
<utility>is already included unconditionally at line 11, so the guarded include here is redundant.♻️ Proposed fix
`#include` <omp.h> `#include` <memory> -#include <utility> namespace cuopt {🤖 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/utilities/omp_helpers.hpp` at line 31, Remove the redundant guarded include of <utility> in omp_helpers.hpp — the header is already included unconditionally earlier (the "`#include` <utility>" at the top), so delete the second "`#include` <utility>" occurrence to avoid duplication and keep includes clean.
🤖 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/branch_and_bound/branch_and_bound.cpp`:
- Around line 2680-2692: The current lambda publish_cut_generation_time
overwrites the measured cut_generation_time with settings_.time_limit whenever
the measured time exceeds the global solver time limit, which overreports
because cut_generation_start_time is taken after earlier solver work; change the
logic so you only force-set cut_generation_time to settings_.time_limit when
force_time_limit_value is true (remove or tighten the condition "||
cut_generation_time > settings_.time_limit"), leaving the actual measured
cut_generation_time otherwise; apply the same change to the analogous code at
the other location (the block around the lines referenced 2743-2745) and keep
references to publish_cut_generation_time, cut_generation_start_time,
force_time_limit_value, and settings_.time_limit.
---
Nitpick comments:
In `@cpp/src/utilities/omp_helpers.hpp`:
- Line 31: Remove the redundant guarded include of <utility> in omp_helpers.hpp
— the header is already included unconditionally earlier (the "`#include`
<utility>" at the top), so delete the second "`#include` <utility>" occurrence to
avoid duplication and keep includes clean.
🪄 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: 7f53375c-0094-41f7-8499-7263553edbda
📒 Files selected for processing (12)
benchmarks/linear_programming/cuopt/miplib2017_optima.hppbenchmarks/linear_programming/cuopt/run_mip.cppcpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/branch_and_bound/branch_and_bound.cppcpp/src/cuts/cuts.cppcpp/src/cuts/cuts.hppcpp/src/dual_simplex/simplex_solver_settings.hppcpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cucpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cuhcpp/src/mip_heuristics/solver.cucpp/src/utilities/omp_helpers.hppcpp/tests/mip/cuts_test.cu
|
/ok to test |
@akifcorduk, there was an error processing your request: See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/1/ |
|
/ok to test b3e0eef |
|
/ok to test bd4228d |
Improve clique cut generation by simplifing the conflict-graph clique table and fix complement-pair handling in clique cut construction drop the paired variable to form a valid fixing cut; detect contradictory variable/complement cliques as infeasible.
Fixes a bug of skipping the small adjacency-list cliques, now we use clique_table_t::empty() function to check all clique data structures.
The mip gap or gap glosed doesn't change significantly but we add on average 1.5 optimal solutions. Tested on 2 batches for main and this PR.