-
Notifications
You must be signed in to change notification settings - Fork 219
Fix adj_list check bug and improve clique cuts #1386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d65be83
eb5d586
056552f
e7bf32c
5335b65
0b04683
bc5006f
af65630
3f0ace1
7995451
97e439b
8ad61dd
0a5149b
06352db
36e74d2
4d2fb18
dba39c8
0a4571f
56b6e84
b83836b
ce6d499
4de79a0
a17ffa3
e5bc991
b5bd4b2
947fc63
c35573a
85a4024
92d9996
14b0ab8
ee7f2b5
98b1ee2
59a05ac
6a75d1e
b3e0eef
bd4228d
dd69485
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,8 @@ | |
| #include <branch_and_bound/pseudo_costs.hpp> | ||
| #include <branch_and_bound/symmetry.hpp> | ||
|
|
||
| #include <cuopt/linear_programming/mip/solver_settings.hpp> // benchmark_info_t | ||
|
|
||
| #include <cuts/cuts.hpp> | ||
| #include <mip_heuristics/feasibility_jump/cpu_fj_thread.cuh> | ||
| #include <mip_heuristics/mip_constants.hpp> | ||
|
|
@@ -2361,6 +2363,11 @@ auto branch_and_bound_t<i_t, f_t>::do_cut_pass( | |
| } | ||
| root_objective_ = compute_objective(original_lp_, root_relax_soln_.x); | ||
|
|
||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| settings_.benchmark_info_ptr->root_lp_with_cuts = | ||
| compute_user_objective(original_lp_, root_objective_); | ||
| } | ||
|
|
||
| f_t remove_cuts_start_time = tic(); | ||
| mutex_original_lp_.lock(); | ||
| remove_cuts(original_lp_, | ||
|
|
@@ -2479,7 +2486,7 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut | |
| user_problem_t<i_t, f_t> problem_copy = original_problem_; | ||
| timer_t timer(std::numeric_limits<double>::infinity()); | ||
| detail::find_initial_cliques( | ||
| problem_copy, tolerances_for_clique, &clique_table_, timer, false, clique_signal); | ||
| problem_copy, tolerances_for_clique, &clique_table_, timer, clique_signal); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -2588,6 +2595,11 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut | |
| cut_info_t<i_t, f_t> cut_info; | ||
|
|
||
| if (num_fractional == 0) { | ||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| const double v = static_cast<double>(compute_user_objective(original_lp_, root_objective_)); | ||
| settings_.benchmark_info_ptr->root_lp_no_cuts = v; | ||
| settings_.benchmark_info_ptr->root_lp_with_cuts = v; | ||
| } | ||
| set_solution_at_root(solution, cut_info); | ||
| signal_extend_cliques_.store(true, std::memory_order_release); | ||
| #pragma omp taskwait depend(in : *clique_signal) | ||
|
|
@@ -2624,6 +2636,15 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut | |
| f_t last_objective = root_objective_; | ||
| f_t root_relax_objective = root_objective_; | ||
|
|
||
| // Publish the no-cuts root LP value once. The with-cuts companion is | ||
| // published below after the cut loop terminates. Both go to the | ||
| // benchmark_info_t so callers (run_mip.cpp) can compute | ||
| // gap-closed-by-cuts without instrumenting the cut loop directly. | ||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| settings_.benchmark_info_ptr->root_lp_no_cuts = | ||
| compute_user_objective(original_lp_, root_relax_objective); | ||
| } | ||
|
|
||
| constexpr bool enable_root_cut_cpufj = true; | ||
| std::unique_ptr<detail::fj_cpu_task_t<i_t, f_t>> root_cut_cpufj_task; | ||
| auto root_cut_cpufj_improvement_callback = | ||
|
|
@@ -2652,7 +2673,17 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut | |
| i_t cut_pool_size = 0; | ||
| for (i_t cut_pass = 0; cut_pass < settings_.max_cut_passes; cut_pass++) { | ||
| if (num_fractional == 0) { | ||
| // LP relaxation is already integer-feasible — solved at the root | ||
| // by the cuts added so far (possibly zero). Publish the with-cuts | ||
| // value so the gap-closed line still has a non-NaN dual bound. | ||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| settings_.benchmark_info_ptr->root_lp_with_cuts = | ||
| compute_user_objective(original_lp_, root_objective_); | ||
| } | ||
|
Comment on lines
+2679
to
+2682
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any scenario where benchmark_info_ptr != nullptr? We're just computing simple scalars, I think it'd make the code easier to read if it was just a regular reference / non-null ptr
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also nit but I tend to prefer implicit casts / C-style casts for non-critical things :) static_cast(...) is kinda harder to read
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The lambda encapsulates the logic of cut time and writing to benchmark info together. But okay let me remove the lambda and handle it on return blocks.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In production code, it For the cast, AI did the cast, I also prefer C style casts for simple static casts. Will corrrect it. |
||
| set_solution_at_root(solution, cut_info); | ||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| settings_.benchmark_info_ptr->cut_generation_time_sec = toc(cut_generation_start_time); | ||
| } | ||
| signal_extend_cliques_.store(true, std::memory_order_release); | ||
| #pragma omp taskwait depend(in : *clique_signal) | ||
| return mip_status_t::OPTIMAL; | ||
|
|
@@ -2692,6 +2723,9 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut | |
| } | ||
|
|
||
| if (cut_pass_result.action == cut_pass_action_t::RETURN) { | ||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| settings_.benchmark_info_ptr->cut_generation_time_sec = toc(cut_generation_start_time); | ||
| } | ||
| signal_extend_cliques_.store(true, std::memory_order_release); | ||
| #pragma omp taskwait depend(in : *clique_signal) | ||
| return cut_pass_result.status; | ||
|
|
@@ -2714,8 +2748,18 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut | |
| } | ||
| } | ||
|
|
||
| // Publish the post-cuts root LP value. | ||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| settings_.benchmark_info_ptr->root_lp_with_cuts = | ||
| compute_user_objective(original_lp_, root_objective_); | ||
| } | ||
|
|
||
| print_cut_info(settings_, cut_info); | ||
| f_t cut_generation_time = toc(cut_generation_start_time); | ||
| // Publish cut-generation time for reporting. | ||
| if (settings_.benchmark_info_ptr != nullptr) { | ||
| settings_.benchmark_info_ptr->cut_generation_time_sec = cut_generation_time; | ||
| } | ||
| if (cut_info.has_cuts()) { | ||
| settings_.log.printf("Cut generation time: %.2f seconds\n", cut_generation_time); | ||
| settings_.log.printf("Cut pool size : %d\n", cut_pool_size); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.