From 00ae695f3257e567fa67b0df19ec90eadf3a8a54 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 22 Oct 2025 08:36:59 -0700 Subject: [PATCH 01/30] no recombiner --- cpp/src/mip/local_search/local_search.cu | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index bf96380cb..dc149193a 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -691,16 +691,16 @@ void local_search_t::reset_alpha_and_run_recombiners( population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (population_ptr->current_size() > 1 && i - last_improved_iteration > iterations_for_stagnation) { - fp.config.alpha = default_alpha; - population_ptr->diversity_step(max_iterations_without_improvement); - population_ptr->print(); - population_ptr->update_weights(); - save_solution_and_add_cutting_plane( - population_ptr->best_feasible(), best_solution, best_objective); - raft::copy(solution.assignment.data(), - best_solution.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); + // fp.config.alpha = default_alpha; + // population_ptr->diversity_step(max_iterations_without_improvement); + // population_ptr->print(); + // population_ptr->update_weights(); + // save_solution_and_add_cutting_plane( + // population_ptr->best_feasible(), best_solution, best_objective); + // raft::copy(solution.assignment.data(), + // best_solution.data(), + // solution.assignment.size(), + // solution.handle_ptr->get_stream()); } } From 049d07e5ae67f2498610857f8c9a5310f5cb134e Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Thu, 23 Oct 2025 09:15:03 -0700 Subject: [PATCH 02/30] temporary test on obj cut --- cpp/CMakeLists.txt | 2 +- cpp/src/mip/diversity/population.cu | 26 ++++++++++++----- cpp/src/mip/diversity/population.cuh | 2 ++ cpp/src/mip/local_search/local_search.cu | 36 +++++++++++++++--------- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index ab18b6fab..2f0591461 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -452,7 +452,7 @@ install(TARGETS cuopt_cli endif() -option(BUILD_MIP_BENCHMARKS "Build MIP benchmarks" OFF) +option(BUILD_MIP_BENCHMARKS "Build MIP benchmarks" ON) if(BUILD_MIP_BENCHMARKS AND NOT BUILD_LP_ONLY) add_executable(solve_MIP ../benchmarks/linear_programming/cuopt/run_mip.cpp) target_compile_options(solve_MIP diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index 03f658a0b..b9597c8b4 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -74,6 +74,19 @@ i_t get_max_var_threshold(i_t n_vars) return n_vars - 10; } +template +void population_t::apply_problem_ptr_to_all_solutions() +{ + for (size_t i = 1; i < indices.size(); i++) { + solutions[indices[i].first].second.problem_ptr = problem_ptr; + solutions[indices[i].first].second.resize_to_problem(); + solutions[indices[i].first].second.compute_feasibility(); + indices[i].second = solutions[indices[i].first].second.get_quality(weights); + } + update_qualities(); + weights.cstr_weights.resize(problem_ptr->n_constraints, problem_ptr->handle_ptr->get_stream()); +} + template void population_t::allocate_solutions() { @@ -119,12 +132,11 @@ std::pair, solution_t> population_t::ge auto second_solution = solutions[indices[j].first].second; // if best feasible and best are the same, take the second index instead of best if (i == 0 && j == 1) { - bool same = - check_integer_equal_on_indices(first_solution.problem_ptr->integer_indices, - first_solution.assignment, - second_solution.assignment, - first_solution.problem_ptr->tolerances.integrality_tolerance, - first_solution.handle_ptr); + bool same = check_integer_equal_on_indices(problem_ptr->integer_indices, + first_solution.assignment, + second_solution.assignment, + problem_ptr->tolerances.integrality_tolerance, + first_solution.handle_ptr); if (same) { auto new_sol = solutions[indices[2].first].second; second_solution = std::move(new_sol); @@ -285,7 +297,7 @@ void population_t::run_solution_callbacks(solution_t& sol) if (context.settings.mip_scaling) { context.scaling.unscale_solutions(temp_sol.assignment, dummy); // Need to get unscaled problem as well - problem_t n_problem(*sol.problem_ptr->original_problem_ptr); + problem_t n_problem(*problem_ptr->original_problem_ptr); temp_sol.problem_ptr = &n_problem; temp_sol.resize_to_original_problem(); temp_sol.compute_feasibility(); diff --git a/cpp/src/mip/diversity/population.cuh b/cpp/src/mip/diversity/population.cuh index deeca2f94..9e8dfae06 100644 --- a/cpp/src/mip/diversity/population.cuh +++ b/cpp/src/mip/diversity/population.cuh @@ -170,6 +170,8 @@ class population_t { void diversity_step(i_t max_iterations_without_improvement); + void apply_problem_ptr_to_all_solutions(); + // does some consistency tests bool test_invariant(); diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index dc149193a..b34cb45d8 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -649,16 +649,20 @@ void local_search_t::reset_alpha_and_save_solution( raft::common::nvtx::range fun_scope("reset_alpha_and_save_solution"); fp.config.alpha = default_alpha; solution_t solution_copy(solution); - solution_copy.problem_ptr = old_problem_ptr; - solution_copy.resize_to_problem(); + // solution_copy.problem_ptr = old_problem_ptr; + // solution_copy.resize_to_problem(); population_ptr->add_solution(std::move(solution_copy)); auto new_sol_vector = population_ptr->get_external_solutions(); population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (!cutting_plane_added_for_active_run) { - solution.problem_ptr = &problem_with_objective_cut; + CUOPT_LOG_DEBUG("Adding cutting plane to problem with objective cut"); + solution.problem_ptr = &problem_with_objective_cut; + population_ptr->problem_ptr = &problem_with_objective_cut; solution.resize_to_problem(); resize_to_new_problem(); cutting_plane_added_for_active_run = true; + population_ptr->weights.cstr_weights.resize(problem_with_objective_cut.n_constraints, + solution.handle_ptr->get_stream()); raft::copy(population_ptr->weights.cstr_weights.data(), fj.cstr_weights.data(), population_ptr->weights.cstr_weights.size(), @@ -667,6 +671,7 @@ void local_search_t::reset_alpha_and_save_solution( population_ptr->update_weights(); save_solution_and_add_cutting_plane( population_ptr->best_feasible(), best_solution, best_objective); + population_ptr->apply_problem_ptr_to_all_solutions(); raft::copy(solution.assignment.data(), best_solution.data(), solution.assignment.size(), @@ -691,16 +696,17 @@ void local_search_t::reset_alpha_and_run_recombiners( population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (population_ptr->current_size() > 1 && i - last_improved_iteration > iterations_for_stagnation) { - // fp.config.alpha = default_alpha; - // population_ptr->diversity_step(max_iterations_without_improvement); - // population_ptr->print(); - // population_ptr->update_weights(); - // save_solution_and_add_cutting_plane( - // population_ptr->best_feasible(), best_solution, best_objective); - // raft::copy(solution.assignment.data(), - // best_solution.data(), - // solution.assignment.size(), - // solution.handle_ptr->get_stream()); + fp.config.alpha = default_alpha; + population_ptr->apply_problem_ptr_to_all_solutions(); + population_ptr->diversity_step(max_iterations_without_improvement); + population_ptr->print(); + population_ptr->update_weights(); + save_solution_and_add_cutting_plane( + population_ptr->best_feasible(), best_solution, best_objective); + raft::copy(solution.assignment.data(), + best_solution.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); } } @@ -731,7 +737,9 @@ bool local_search_t::run_fp(solution_t& solution, // Do the copy here for proper handling of the added constraints weight fj.copy_weights( population_ptr->weights, solution.handle_ptr, problem_with_objective_cut.n_constraints); - solution.problem_ptr = &problem_with_objective_cut; + solution.problem_ptr = &problem_with_objective_cut; + population_ptr->problem_ptr = &problem_with_objective_cut; + population_ptr->apply_problem_ptr_to_all_solutions(); solution.resize_to_problem(); resize_to_new_problem(); } From b1e7e85de6db3ae24fa9f704839dc8be4c89d09b Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 24 Oct 2025 04:03:16 -0700 Subject: [PATCH 03/30] fix few issues --- cpp/src/mip/diversity/diversity_manager.cu | 3 ++- cpp/src/mip/diversity/population.cu | 2 +- cpp/src/mip/local_search/local_search.cu | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index d8e413a0d..2f93c9b57 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -437,7 +437,8 @@ void diversity_manager_t::diversity_step(i_t max_iterations_without_im while (k-- > 0) { if (check_b_b_preemption()) { return; } auto new_sol_vector = population.get_external_solutions(); - recombine_and_ls_with_all(new_sol_vector); + population.add_solutions_from_vec(std::move(new_sol_vector)); + population.apply_problem_ptr_to_all_solutions(); population.adjust_weights_according_to_best_feasible(); cuopt_assert(population.test_invariant(), ""); if (population.current_size() < 2) { diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index b9597c8b4..e8c9d4d47 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -77,7 +77,7 @@ i_t get_max_var_threshold(i_t n_vars) template void population_t::apply_problem_ptr_to_all_solutions() { - for (size_t i = 1; i < indices.size(); i++) { + for (size_t i = 0; i < indices.size(); i++) { solutions[indices[i].first].second.problem_ptr = problem_ptr; solutions[indices[i].first].second.resize_to_problem(); solutions[indices[i].first].second.compute_feasibility(); diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index b34cb45d8..0e9ada642 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -815,6 +815,8 @@ bool local_search_t::run_fp(solution_t& solution, solution.resize_to_problem(); resize_to_old_problem(old_problem_ptr); solution.handle_ptr->sync_stream(); + population_ptr->problem_ptr = old_problem_ptr; + population_ptr->apply_problem_ptr_to_all_solutions(); return is_feasible; } From 11d853e69d5a1941ad748bb5c8300d93acbfa399 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 24 Oct 2025 05:45:26 -0700 Subject: [PATCH 04/30] handle weight mismatch --- cpp/src/mip/local_search/local_search.cu | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 0e9ada642..85b5023e7 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -661,12 +661,15 @@ void local_search_t::reset_alpha_and_save_solution( solution.resize_to_problem(); resize_to_new_problem(); cutting_plane_added_for_active_run = true; - population_ptr->weights.cstr_weights.resize(problem_with_objective_cut.n_constraints, - solution.handle_ptr->get_stream()); raft::copy(population_ptr->weights.cstr_weights.data(), fj.cstr_weights.data(), population_ptr->weights.cstr_weights.size(), solution.handle_ptr->get_stream()); + population_ptr->weights.cstr_weights.resize(problem_with_objective_cut.n_constraints, + solution.handle_ptr->get_stream()); + const f_t one = 1.0; + population_ptr->weights.cstr_weights.set_element_async( + population_ptr->weights.cstr_weights.size() - 1, one, solution.handle_ptr->get_stream()); } population_ptr->update_weights(); save_solution_and_add_cutting_plane( From 55700160239d183c8f9b07a261965c5f07bd2c65 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 24 Oct 2025 05:46:48 -0700 Subject: [PATCH 05/30] ls time always 1 s --- cpp/src/mip/local_search/local_search.cu | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 85b5023e7..bc4446036 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -345,17 +345,18 @@ bool local_search_t::run_local_search(solution_t& solution, fj_settings_t fj_settings; if (timer.check_time_limit()) return false; // adjust these time limits - if (!solution.get_feasible()) { - if (ls_config.at_least_one_parent_feasible) { - fj_settings.time_limit = 0.5; - timer = timer_t(fj_settings.time_limit); - } else { - fj_settings.time_limit = 0.25; - timer = timer_t(fj_settings.time_limit); - } - } else { - fj_settings.time_limit = std::min(1., timer.remaining_time()); - } + // if (!solution.get_feasible()) { + // if (ls_config.at_least_one_parent_feasible) { + // fj_settings.time_limit = 0.5; + // timer = timer_t(fj_settings.time_limit); + // } else { + // fj_settings.time_limit = 0.25; + // timer = timer_t(fj_settings.time_limit); + // } + // } else { + // fj_settings.time_limit = std::min(1., timer.remaining_time()); + // } + fj_settings.time_limit = std::min(1., timer.remaining_time()); fj_settings.update_weights = false; fj_settings.feasibility_run = false; fj.set_fj_settings(fj_settings); From 300ad962a0eae969eec2f737e5186d4ef28b76a3 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 24 Oct 2025 05:56:52 -0700 Subject: [PATCH 06/30] fix timer --- cpp/src/mip/local_search/local_search.cu | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index bc4446036..a3b69fcfc 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -357,6 +357,7 @@ bool local_search_t::run_local_search(solution_t& solution, // fj_settings.time_limit = std::min(1., timer.remaining_time()); // } fj_settings.time_limit = std::min(1., timer.remaining_time()); + timer = timer_t(fj_settings.time_limit); fj_settings.update_weights = false; fj_settings.feasibility_run = false; fj.set_fj_settings(fj_settings); From 6f557c00c601e3ec5945419754383b7baad9ca9c Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 24 Oct 2025 07:13:01 -0700 Subject: [PATCH 07/30] shorter fj, longer lp --- cpp/src/mip/diversity/diversity_config.hpp | 2 +- cpp/src/mip/local_search/local_search.cu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_config.hpp b/cpp/src/mip/diversity/diversity_config.hpp index e78b2f29d..575afdc56 100644 --- a/cpp/src/mip/diversity/diversity_config.hpp +++ b/cpp/src/mip/diversity/diversity_config.hpp @@ -38,7 +38,7 @@ struct diversity_config_t { size_t n_sol_for_skip_init_gen = 3; double max_fast_sol_time = 10; double lp_run_time_if_feasible = 2.; - double lp_run_time_if_infeasible = 1.; + double lp_run_time_if_infeasible = 2.; bool halve_population = false; }; diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index a3b69fcfc..43969a607 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -356,7 +356,7 @@ bool local_search_t::run_local_search(solution_t& solution, // } else { // fj_settings.time_limit = std::min(1., timer.remaining_time()); // } - fj_settings.time_limit = std::min(1., timer.remaining_time()); + fj_settings.time_limit = std::min(0.5, timer.remaining_time()); timer = timer_t(fj_settings.time_limit); fj_settings.update_weights = false; fj_settings.feasibility_run = false; From b99ed04c4ea2ed6967112e525ed3d7e305541604 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 24 Oct 2025 09:17:39 -0700 Subject: [PATCH 08/30] best in population, restart fp, longer fj --- cpp/src/mip/diversity/diversity_manager.cu | 4 ++-- cpp/src/mip/local_search/local_search.cu | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 2f93c9b57..247d267d5 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -454,8 +454,8 @@ void diversity_manager_t::diversity_step(i_t max_iterations_without_im auto [inserted_pos_2, best_updated_2] = population.add_solution(std::move(offspring)); if (best_updated_1 || best_updated_2) { recombine_stats.add_best_updated(); } cuopt_assert(population.test_invariant(), ""); - if ((inserted_pos_1 != -1 && inserted_pos_1 <= 2) || - (inserted_pos_2 != -1 && inserted_pos_2 <= 2)) { + if ((inserted_pos_1 != -1 && inserted_pos_1 <= 1) || + (inserted_pos_2 != -1 && inserted_pos_2 <= 1)) { improved = true; recombine_stats.print(); break; diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 43969a607..4e4552be8 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -356,7 +356,7 @@ bool local_search_t::run_local_search(solution_t& solution, // } else { // fj_settings.time_limit = std::min(1., timer.remaining_time()); // } - fj_settings.time_limit = std::min(0.5, timer.remaining_time()); + fj_settings.time_limit = std::min(1., timer.remaining_time()); timer = timer_t(fj_settings.time_limit); fj_settings.update_weights = false; fj_settings.feasibility_run = false; @@ -649,7 +649,7 @@ void local_search_t::reset_alpha_and_save_solution( f_t& best_objective) { raft::common::nvtx::range fun_scope("reset_alpha_and_save_solution"); - fp.config.alpha = default_alpha; + fp.reset(); solution_t solution_copy(solution); // solution_copy.problem_ptr = old_problem_ptr; // solution_copy.resize_to_problem(); @@ -701,7 +701,7 @@ void local_search_t::reset_alpha_and_run_recombiners( population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (population_ptr->current_size() > 1 && i - last_improved_iteration > iterations_for_stagnation) { - fp.config.alpha = default_alpha; + // fp.config.alpha = default_alpha; population_ptr->apply_problem_ptr_to_all_solutions(); population_ptr->diversity_step(max_iterations_without_improvement); population_ptr->print(); From d1413c8ea0f8ce09bca8422adb6266abf252e652 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 24 Oct 2025 09:18:04 -0700 Subject: [PATCH 09/30] return first feas --- cpp/src/mip/diversity/diversity_manager.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 247d267d5..e281988e6 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -347,7 +347,7 @@ solution_t diversity_manager_t::run_solver() relaxed_lp_settings_t lp_settings; lp_settings.time_limit = lp_time_limit; lp_settings.tolerance = context.settings.tolerances.absolute_tolerance; - lp_settings.return_first_feasible = false; + lp_settings.return_first_feasible = true; lp_settings.save_state = true; lp_settings.concurrent_halt = &global_concurrent_halt; lp_settings.has_initial_primal = false; From 60c26202b5ee56b2bc471bc1175531779a7d1c4e Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 27 Oct 2025 04:27:22 -0700 Subject: [PATCH 10/30] Revert "return first feas" This reverts commit d1413c8ea0f8ce09bca8422adb6266abf252e652. --- cpp/src/mip/diversity/diversity_manager.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index e281988e6..247d267d5 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -347,7 +347,7 @@ solution_t diversity_manager_t::run_solver() relaxed_lp_settings_t lp_settings; lp_settings.time_limit = lp_time_limit; lp_settings.tolerance = context.settings.tolerances.absolute_tolerance; - lp_settings.return_first_feasible = true; + lp_settings.return_first_feasible = false; lp_settings.save_state = true; lp_settings.concurrent_halt = &global_concurrent_halt; lp_settings.has_initial_primal = false; From 30375e22b9af0904ed37657f3f5ac8ada17b7421 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 27 Oct 2025 13:36:47 -0700 Subject: [PATCH 11/30] only do weights on FJ --- cpp/CMakeLists.txt | 14 +++++---- cpp/src/mip/diversity/diversity_manager.cu | 8 +++++- cpp/src/mip/diversity/population.cu | 33 +++++++++++++++------- cpp/src/mip/diversity/population.cuh | 8 ++++-- cpp/src/mip/local_search/local_search.cu | 26 +++++++---------- cpp/src/mip/solution/solution.cu | 27 ++++++++++++++---- cpp/src/mip/solution/solution.cuh | 3 ++ 7 files changed, 78 insertions(+), 41 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 2f0591461..544d13f21 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -86,6 +86,13 @@ if(CMAKE_COMPILER_IS_GNUCXX) list(APPEND CUOPT_CXX_FLAGS -Werror -Wno-error=deprecated-declarations) endif(CMAKE_COMPILER_IS_GNUCXX) +# Undefine NDEBUG if assert mode is on +if(DEFINE_ASSERT) + message(STATUS "Undefining NDEBUG with assert mode enabled") + add_definitions(-UNDEBUG) + set(CMAKE_BUILD_TYPE RelWithDebInfo) +endif() + # To use sanitizer with cuda runtime, one must follow a few steps: # 1. Run the binary with env var set: LD_PRELOAD="$(gcc -print-file-name=libasan.so)" ASAN_OPTIONS='protect_shadow_gap=0:replace_intrin=0' # 2. (Optional) To run with a debugger (gdb or cuda-gdb) use the additional ASAN option alloc_dealloc_mismatch=0 @@ -153,15 +160,10 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) elseif(CMAKE_CUDA_LINEINFO) message(STATUS "Enabling line info") list(APPEND CUOPT_CUDA_FLAGS -lineinfo) + list(APPEND CUOPT_CXX_FLAGS -lineinfo) set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE} -lineinfo") endif(CMAKE_BUILD_TYPE MATCHES Debug) -# Undefine NDEBUG if assert mode is on -if(DEFINE_ASSERT) - message(STATUS "Undefining NDEBUG with assert mode enabled") - add_definitions(-UNDEBUG) -endif() - # ################################################################################################## # - find CPM based dependencies ------------------------------------------------------------------ diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 247d267d5..91b8c55d4 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -591,7 +591,13 @@ diversity_manager_t::recombine_and_local_search(solution_t& ls_config_t ls_config; ls_config.best_objective_of_parents = best_objective_of_parents; ls_config.at_least_one_parent_feasible = at_least_one_parent_feasible; - success = this->run_local_search(offspring, population.weights, timer, ls_config); + offspring.swap_problem_pointers(); + raft::copy(population.weights_with_cuts.cstr_weights.data(), + population.weights.cstr_weights.data(), + population.weights.cstr_weights.size(), + offspring.handle_ptr->get_stream()); + success = this->run_local_search(offspring, population.weights_with_cuts, timer, ls_config); + offspring.swap_problem_pointers(); if (!success) { // add the attempt mab_recombiner.add_mab_reward(mab_recombiner.last_chosen_option, diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index e8c9d4d47..439d8b0c8 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -51,8 +51,8 @@ population_t::population_t(std::string const& name_, max_solutions(max_solutions_), infeasibility_importance(infeasibility_weight_), weights(0, context.problem_ptr->handle_ptr), + weights_with_cuts(0, context.problem_ptr->handle_ptr), rng(cuopt::seed_generator::get_seed()), - early_exit_primal_generation(false), population_hash_map(*problem_ptr), timer(0) { @@ -78,13 +78,8 @@ template void population_t::apply_problem_ptr_to_all_solutions() { for (size_t i = 0; i < indices.size(); i++) { - solutions[indices[i].first].second.problem_ptr = problem_ptr; - solutions[indices[i].first].second.resize_to_problem(); - solutions[indices[i].first].second.compute_feasibility(); - indices[i].second = solutions[indices[i].first].second.get_quality(weights); + solutions[indices[i].first].second.problem_with_cuts_ptr = problem_ptr_with_cuts; } - update_qualities(); - weights.cstr_weights.resize(problem_ptr->n_constraints, problem_ptr->handle_ptr->get_stream()); } template @@ -96,6 +91,20 @@ void population_t::allocate_solutions() } } +template +void population_t::set_problem_ptr_with_cuts(problem_t* problem_ptr_with_cuts) +{ + constexpr f_t ten = 10.; + this->problem_ptr_with_cuts = problem_ptr_with_cuts; + weights_with_cuts.cstr_weights.resize(problem_ptr_with_cuts->n_constraints, + problem_ptr_with_cuts->handle_ptr->get_stream()); + // fill last element with default + thrust::uninitialized_fill(problem_ptr_with_cuts->handle_ptr->get_thrust_policy(), + weights_with_cuts.cstr_weights.begin() + problem_ptr->n_constraints, + weights_with_cuts.cstr_weights.end(), + ten); +} + template void population_t::initialize_population() { @@ -110,6 +119,12 @@ void population_t::initialize_population() weights.cstr_weights.begin(), weights.cstr_weights.end(), ten); + weights_with_cuts.cstr_weights.resize(problem_ptr->n_constraints, + problem_ptr->handle_ptr->get_stream()); + thrust::uninitialized_fill(problem_ptr->handle_ptr->get_thrust_policy(), + weights_with_cuts.cstr_weights.begin(), + weights_with_cuts.cstr_weights.end(), + ten); } template @@ -197,7 +212,6 @@ void population_t::add_external_solution(const std::vector& solut CUOPT_LOG_DEBUG("Found new best solution %g in external queue", problem_ptr->get_user_obj_from_solver_obj(objective)); } - if (external_solution_queue.size() >= 5) { early_exit_primal_generation = true; } } template @@ -212,8 +226,7 @@ void population_t::add_external_solutions_to_population() template void population_t::preempt_heuristic_solver() { - preempt_heuristic_solver_ = true; - early_exit_primal_generation = true; + preempt_heuristic_solver_ = true; } template diff --git a/cpp/src/mip/diversity/population.cuh b/cpp/src/mip/diversity/population.cuh index 9e8dfae06..713ca5409 100644 --- a/cpp/src/mip/diversity/population.cuh +++ b/cpp/src/mip/diversity/population.cuh @@ -170,6 +170,7 @@ class population_t { void diversity_step(i_t max_iterations_without_improvement); + void set_problem_ptr_with_cuts(problem_t* problem_ptr_with_cuts); void apply_problem_ptr_to_all_solutions(); // does some consistency tests @@ -180,6 +181,7 @@ class population_t { std::string name; mip_solver_context_t& context; problem_t* problem_ptr; + problem_t* problem_ptr_with_cuts; diversity_manager_t& dm; i_t var_threshold; i_t initial_threshold; @@ -189,6 +191,7 @@ class population_t { f_t infeasibility_importance = 100.; size_t max_solutions; weight_t weights; + weight_t weights_with_cuts; std::vector> indices; std::vector>> solutions; @@ -208,9 +211,8 @@ class population_t { std::mt19937 rng; i_t update_iter = 0; std::mutex solution_mutex; - std::atomic early_exit_primal_generation = false; - std::atomic preempt_heuristic_solver_ = false; - f_t best_feasible_objective = std::numeric_limits::max(); + std::atomic preempt_heuristic_solver_ = false; + f_t best_feasible_objective = std::numeric_limits::max(); assignment_hash_map_t population_hash_map; cuopt::timer_t timer; }; diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 4e4552be8..63b38e7f6 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -231,7 +231,6 @@ bool local_search_t::do_fj_solve(solution_t& solution, if (time_limit == 0.) return solution.get_feasible(); timer_t timer(time_limit); - auto h_weights = cuopt::host_copy(in_fj.cstr_weights, solution.handle_ptr->get_stream()); auto h_objective_weight = in_fj.objective_weight.value(solution.handle_ptr->get_stream()); for (auto& cpu_fj : ls_cpu_fj) { @@ -651,15 +650,14 @@ void local_search_t::reset_alpha_and_save_solution( raft::common::nvtx::range fun_scope("reset_alpha_and_save_solution"); fp.reset(); solution_t solution_copy(solution); - // solution_copy.problem_ptr = old_problem_ptr; - // solution_copy.resize_to_problem(); + solution_copy.problem_ptr = old_problem_ptr; + solution_copy.resize_to_problem(); population_ptr->add_solution(std::move(solution_copy)); auto new_sol_vector = population_ptr->get_external_solutions(); population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (!cutting_plane_added_for_active_run) { - CUOPT_LOG_DEBUG("Adding cutting plane to problem with objective cut"); - solution.problem_ptr = &problem_with_objective_cut; - population_ptr->problem_ptr = &problem_with_objective_cut; + solution.problem_ptr = &problem_with_objective_cut; + population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); solution.resize_to_problem(); resize_to_new_problem(); cutting_plane_added_for_active_run = true; @@ -667,11 +665,10 @@ void local_search_t::reset_alpha_and_save_solution( fj.cstr_weights.data(), population_ptr->weights.cstr_weights.size(), solution.handle_ptr->get_stream()); - population_ptr->weights.cstr_weights.resize(problem_with_objective_cut.n_constraints, - solution.handle_ptr->get_stream()); - const f_t one = 1.0; - population_ptr->weights.cstr_weights.set_element_async( - population_ptr->weights.cstr_weights.size() - 1, one, solution.handle_ptr->get_stream()); + raft::copy(population_ptr->weights_with_cuts.cstr_weights.data(), + fj.cstr_weights.data(), + fj.cstr_weights.size(), + solution.handle_ptr->get_stream()); } population_ptr->update_weights(); save_solution_and_add_cutting_plane( @@ -701,7 +698,6 @@ void local_search_t::reset_alpha_and_run_recombiners( population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (population_ptr->current_size() > 1 && i - last_improved_iteration > iterations_for_stagnation) { - // fp.config.alpha = default_alpha; population_ptr->apply_problem_ptr_to_all_solutions(); population_ptr->diversity_step(max_iterations_without_improvement); population_ptr->print(); @@ -742,8 +738,8 @@ bool local_search_t::run_fp(solution_t& solution, // Do the copy here for proper handling of the added constraints weight fj.copy_weights( population_ptr->weights, solution.handle_ptr, problem_with_objective_cut.n_constraints); - solution.problem_ptr = &problem_with_objective_cut; - population_ptr->problem_ptr = &problem_with_objective_cut; + solution.problem_ptr = &problem_with_objective_cut; + population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); population_ptr->apply_problem_ptr_to_all_solutions(); solution.resize_to_problem(); resize_to_new_problem(); @@ -820,8 +816,6 @@ bool local_search_t::run_fp(solution_t& solution, solution.resize_to_problem(); resize_to_old_problem(old_problem_ptr); solution.handle_ptr->sync_stream(); - population_ptr->problem_ptr = old_problem_ptr; - population_ptr->apply_problem_ptr_to_all_solutions(); return is_feasible; } diff --git a/cpp/src/mip/solution/solution.cu b/cpp/src/mip/solution/solution.cu index ec30fda86..1ed7ff05c 100644 --- a/cpp/src/mip/solution/solution.cu +++ b/cpp/src/mip/solution/solution.cu @@ -52,6 +52,8 @@ rmm::device_uvector get_lower_bounds( template solution_t::solution_t(problem_t& problem_) : problem_ptr(&problem_), + problem_with_cuts_ptr(&problem_), + current_problem_is_cut(false), handle_ptr(problem_.handle_ptr), assignment(std::move(get_lower_bounds(problem_.variable_bounds, handle_ptr))), lower_excess(problem_.n_constraints, handle_ptr->get_stream()), @@ -69,6 +71,8 @@ solution_t::solution_t(problem_t& problem_) template solution_t::solution_t(const solution_t& other) : problem_ptr(other.problem_ptr), + problem_with_cuts_ptr(other.problem_with_cuts_ptr), + current_problem_is_cut(other.current_problem_is_cut), handle_ptr(other.handle_ptr), assignment(other.assignment, handle_ptr->get_stream()), lower_excess(other.lower_excess, handle_ptr->get_stream()), @@ -95,11 +99,13 @@ template void solution_t::copy_from(const solution_t& other_sol) { // TODO handle resize - problem_ptr = other_sol.problem_ptr; - handle_ptr = other_sol.handle_ptr; - h_obj = other_sol.h_obj; - h_user_obj = other_sol.h_user_obj; - h_infeasibility_cost = other_sol.h_infeasibility_cost; + problem_ptr = other_sol.problem_ptr; + problem_with_cuts_ptr = other_sol.problem_with_cuts_ptr; + current_problem_is_cut = other_sol.current_problem_is_cut; + handle_ptr = other_sol.handle_ptr; + h_obj = other_sol.h_obj; + h_user_obj = other_sol.h_user_obj; + h_infeasibility_cost = other_sol.h_infeasibility_cost; expand_device_copy(assignment, other_sol.assignment, handle_ptr->get_stream()); expand_device_copy(lower_excess, other_sol.lower_excess, handle_ptr->get_stream()); expand_device_copy(upper_excess, other_sol.upper_excess, handle_ptr->get_stream()); @@ -133,6 +139,17 @@ void solution_t::resize_to_problem() lp_state.prev_dual.resize(problem_ptr->n_constraints, handle_ptr->get_stream()); } +template +void solution_t::swap_problem_pointers() +{ + current_problem_is_cut = !current_problem_is_cut; + cuopt_assert(problem_with_cuts_ptr != nullptr, "Problem with cuts pointer must be set"); + cuopt_assert(problem_with_cuts_ptr != problem_ptr, "Problem pointers must be different"); + std::swap(problem_ptr, problem_with_cuts_ptr); + resize_to_problem(); + compute_feasibility(); +} + template void solution_t::resize_to_original_problem() { diff --git a/cpp/src/mip/solution/solution.cuh b/cpp/src/mip/solution/solution.cuh index 74820be83..17caebbda 100644 --- a/cpp/src/mip/solution/solution.cuh +++ b/cpp/src/mip/solution/solution.cuh @@ -108,6 +108,7 @@ class solution_t { f_t compute_max_constraint_violation(); f_t compute_max_int_violation(); f_t compute_max_variable_violation(); + void swap_problem_pointers(); struct view_t { // let's not bloat the class for every simple getter and setters @@ -133,6 +134,8 @@ class solution_t { // we might need to change it later as we tighten the bounds // and run lp on fixed parts problem_t* problem_ptr; + problem_t* problem_with_cuts_ptr; + bool current_problem_is_cut = false; const raft::handle_t* handle_ptr; rmm::device_uvector assignment; rmm::device_uvector lower_excess; From 9dc0ace2e96dce9bbfffef87857c93aa5cded496 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 27 Oct 2025 13:37:31 -0700 Subject: [PATCH 12/30] sqrt diversiyt --- cpp/src/mip/diversity/population.cu | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index 439d8b0c8..8685b99ce 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -62,6 +62,7 @@ population_t::population_t(std::string const& name_, template i_t get_max_var_threshold(i_t n_vars) { + return n_vars - sqrt(n_vars); if (n_vars < 50) { return std::max(1, n_vars - 1); } else if (n_vars < 80) { From 58b7b2a8bfbaaeb2faf10ab48ca4174c68ca45d1 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 28 Oct 2025 04:12:38 -0700 Subject: [PATCH 13/30] fix external solutions adding --- cpp/src/mip/diversity/diversity_manager.cu | 2 ++ cpp/src/mip/local_search/local_search.cu | 39 ++++++++++++++-------- cpp/src/mip/local_search/local_search.cuh | 5 +++ 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 91b8c55d4..28cc6f8f3 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -592,6 +592,8 @@ diversity_manager_t::recombine_and_local_search(solution_t& ls_config.best_objective_of_parents = best_objective_of_parents; ls_config.at_least_one_parent_feasible = at_least_one_parent_feasible; offspring.swap_problem_pointers(); + population.weights_with_cuts.cstr_weights.resize(offspring.problem_ptr->n_constraints, + offspring.handle_ptr->get_stream()); raft::copy(population.weights_with_cuts.cstr_weights.data(), population.weights.cstr_weights.data(), population.weights.cstr_weights.size(), diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 63b38e7f6..77eca5361 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -638,23 +638,12 @@ void local_search_t::resize_to_old_problem(problem_t* old_pr } template -void local_search_t::reset_alpha_and_save_solution( +void local_search_t::handle_cutting_plane_and_weights( solution_t& solution, - problem_t* old_problem_ptr, population_t* population_ptr, - i_t i, - i_t last_improved_iteration, rmm::device_uvector& best_solution, f_t& best_objective) { - raft::common::nvtx::range fun_scope("reset_alpha_and_save_solution"); - fp.reset(); - solution_t solution_copy(solution); - solution_copy.problem_ptr = old_problem_ptr; - solution_copy.resize_to_problem(); - population_ptr->add_solution(std::move(solution_copy)); - auto new_sol_vector = population_ptr->get_external_solutions(); - population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (!cutting_plane_added_for_active_run) { solution.problem_ptr = &problem_with_objective_cut; population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); @@ -678,6 +667,27 @@ void local_search_t::reset_alpha_and_save_solution( best_solution.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); +} + +template +void local_search_t::reset_alpha_and_save_solution( + solution_t& solution, + problem_t* old_problem_ptr, + population_t* population_ptr, + i_t i, + i_t last_improved_iteration, + rmm::device_uvector& best_solution, + f_t& best_objective) +{ + raft::common::nvtx::range fun_scope("reset_alpha_and_save_solution"); + fp.reset(); + solution_t solution_copy(solution); + solution_copy.problem_ptr = old_problem_ptr; + solution_copy.resize_to_problem(); + population_ptr->add_solution(std::move(solution_copy)); + auto new_sol_vector = population_ptr->get_external_solutions(); + population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); + handle_cutting_plane_and_weights(solution, population_ptr, best_solution, best_objective); population_ptr->print(); } @@ -692,10 +702,13 @@ void local_search_t::reset_alpha_and_run_recombiners( f_t& best_objective) { raft::common::nvtx::range fun_scope("reset_alpha_and_run_recombiners"); - constexpr i_t iterations_for_stagnation = 3; + constexpr i_t iterations_for_stagnation = 1; constexpr i_t max_iterations_without_improvement = 8; auto new_sol_vector = population_ptr->get_external_solutions(); population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); + if (population_ptr->is_feasible()) { + handle_cutting_plane_and_weights(solution, population_ptr, best_solution, best_objective); + } if (population_ptr->current_size() > 1 && i - last_improved_iteration > iterations_for_stagnation) { population_ptr->apply_problem_ptr_to_all_solutions(); diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index a8fc6a77f..b60f524a2 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -139,6 +139,11 @@ class local_search_t { rmm::device_uvector& best_solution, f_t& best_objective); + void handle_cutting_plane_and_weights(solution_t& solution, + population_t* population_ptr, + rmm::device_uvector& best_solution, + f_t& best_objective); + mip_solver_context_t& context; rmm::device_uvector& lp_optimal_solution; bool lp_optimal_exists{false}; From 28ac0e85faa238a2697a64885932c3efa6b03a9d Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 28 Oct 2025 07:12:11 -0700 Subject: [PATCH 14/30] fix cut issues --- .../linear_programming/cuopt/run_mip.cpp | 4 +- cpp/src/mip/diversity/population.cu | 34 ------ cpp/src/mip/diversity/population.cuh | 1 - cpp/src/mip/local_search/local_search.cu | 109 +++++++----------- cpp/src/mip/local_search/local_search.cuh | 19 ++- 5 files changed, 54 insertions(+), 113 deletions(-) diff --git a/benchmarks/linear_programming/cuopt/run_mip.cpp b/benchmarks/linear_programming/cuopt/run_mip.cpp index 5c5781245..21198f158 100644 --- a/benchmarks/linear_programming/cuopt/run_mip.cpp +++ b/benchmarks/linear_programming/cuopt/run_mip.cpp @@ -387,8 +387,6 @@ int main(int argc, char* argv[]) double memory_limit = program.get("--memory-limit"); bool track_allocations = program.get("--track-allocations")[0] == 't'; - if (num_cpu_threads < 0) { num_cpu_threads = omp_get_max_threads() / n_gpus; } - if (program.is_used("--out-dir")) { out_dir = program.get("--out-dir"); result_file = out_dir + "/final_result.csv"; @@ -425,6 +423,7 @@ int main(int argc, char* argv[]) paths.push_back(entry.path()); } } + if (num_cpu_threads < 0) { num_cpu_threads = omp_get_max_threads() / n_gpus; } // if batch_num is given, trim the paths to only concerned batch if (batch_num != -1) { if (n_batches <= 0) { @@ -491,6 +490,7 @@ int main(int argc, char* argv[]) } merge_result_files(out_dir, result_file, n_gpus, batch_num); } else { + if (num_cpu_threads < 0) { num_cpu_threads = omp_get_max_threads(); } auto memory_resource = make_async(); if (memory_limit > 0) { auto limiting_adaptor = diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index 8685b99ce..24b963ab2 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -692,40 +692,6 @@ std::vector> population_t::population_to_vector() return sol_vec; } -template -void population_t::halve_the_population() -{ - raft::common::nvtx::range fun_scope("halve_the_population"); - // try 3/4 here - if (current_size() <= (max_solutions * halving_skip_ratio)) { return; } - CUOPT_LOG_DEBUG("Halving the population, current size: %lu", current_size()); - // put population into a vector - auto sol_vec = population_to_vector(); - i_t counter = 0; - constexpr i_t max_adjustments = 4; - size_t max_var_threshold = get_max_var_threshold(problem_ptr->n_integer_vars); - while (current_size() > max_solutions / 2) { - clear_except_best_feasible(); - var_threshold = std::max(var_threshold * 0.97, 0.5 * problem_ptr->n_integer_vars); - for (auto& sol : sol_vec) { - add_solution(solution_t(sol)); - } - if (counter++ > max_adjustments) break; - } - counter = 0; - // if we removed too many decrease the diversity a little - while (current_size() < max_solutions / 4) { - clear_except_best_feasible(); - var_threshold = std::min( - max_var_threshold, - std::min((size_t)(var_threshold * 1.02), (size_t)(0.995 * problem_ptr->n_integer_vars))); - for (auto& sol : sol_vec) { - add_solution(solution_t(sol)); - } - if (counter++ > max_adjustments) break; - } -} - template size_t population_t::find_free_solution_index() { diff --git a/cpp/src/mip/diversity/population.cuh b/cpp/src/mip/diversity/population.cuh index 713ca5409..f1bceb238 100644 --- a/cpp/src/mip/diversity/population.cuh +++ b/cpp/src/mip/diversity/population.cuh @@ -160,7 +160,6 @@ class population_t { void find_diversity(std::vector>& initial_sol_vector, bool avg); std::vector> population_to_vector(); - void halve_the_population(); void run_solution_callbacks(solution_t& sol); diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 77eca5361..2daefb618 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -602,15 +602,15 @@ void local_search_t::resize_vectors(problem_t& problem, template void local_search_t::save_solution_and_add_cutting_plane( - solution_t& solution, rmm::device_uvector& best_solution, f_t& best_objective) + solution_t& best_in_population, solution_t& solution, f_t& best_objective) { raft::common::nvtx::range fun_scope("save_solution_and_add_cutting_plane"); - if (solution.get_objective() < best_objective) { - raft::copy(best_solution.data(), - solution.assignment.data(), + if (best_in_population.get_objective() < best_objective) { + raft::copy(solution.assignment.data(), + best_in_population.assignment.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); - best_objective = solution.get_objective(); + best_objective = best_in_population.get_objective(); f_t objective_cut = best_objective - std::max(std::abs(0.001 * best_objective), OBJECTIVE_EPSILON); problem_with_objective_cut.add_cutting_plane_at_objective(objective_cut); @@ -639,10 +639,7 @@ void local_search_t::resize_to_old_problem(problem_t* old_pr template void local_search_t::handle_cutting_plane_and_weights( - solution_t& solution, - population_t* population_ptr, - rmm::device_uvector& best_solution, - f_t& best_objective) + solution_t& solution, population_t* population_ptr, f_t& best_objective) { if (!cutting_plane_added_for_active_run) { solution.problem_ptr = &problem_with_objective_cut; @@ -660,24 +657,17 @@ void local_search_t::handle_cutting_plane_and_weights( solution.handle_ptr->get_stream()); } population_ptr->update_weights(); - save_solution_and_add_cutting_plane( - population_ptr->best_feasible(), best_solution, best_objective); + save_solution_and_add_cutting_plane(population_ptr->best_feasible(), solution, best_objective); population_ptr->apply_problem_ptr_to_all_solutions(); - raft::copy(solution.assignment.data(), - best_solution.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); } template -void local_search_t::reset_alpha_and_save_solution( - solution_t& solution, - problem_t* old_problem_ptr, - population_t* population_ptr, - i_t i, - i_t last_improved_iteration, - rmm::device_uvector& best_solution, - f_t& best_objective) +void local_search_t::reset_alpha_and_save_solution(solution_t& solution, + problem_t* old_problem_ptr, + population_t* population_ptr, + i_t i, + i_t last_improved_iteration, + f_t& best_objective) { raft::common::nvtx::range fun_scope("reset_alpha_and_save_solution"); fp.reset(); @@ -687,19 +677,17 @@ void local_search_t::reset_alpha_and_save_solution( population_ptr->add_solution(std::move(solution_copy)); auto new_sol_vector = population_ptr->get_external_solutions(); population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); - handle_cutting_plane_and_weights(solution, population_ptr, best_solution, best_objective); + handle_cutting_plane_and_weights(solution, population_ptr, best_objective); population_ptr->print(); } template -void local_search_t::reset_alpha_and_run_recombiners( - solution_t& solution, - problem_t* old_problem_ptr, - population_t* population_ptr, - i_t i, - i_t last_improved_iteration, - rmm::device_uvector& best_solution, - f_t& best_objective) +void local_search_t::run_recombiners(solution_t& solution, + problem_t* old_problem_ptr, + population_t* population_ptr, + i_t i, + i_t last_improved_iteration, + f_t& best_objective) { raft::common::nvtx::range fun_scope("reset_alpha_and_run_recombiners"); constexpr i_t iterations_for_stagnation = 1; @@ -707,7 +695,23 @@ void local_search_t::reset_alpha_and_run_recombiners( auto new_sol_vector = population_ptr->get_external_solutions(); population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); if (population_ptr->is_feasible()) { - handle_cutting_plane_and_weights(solution, population_ptr, best_solution, best_objective); + if (!cutting_plane_added_for_active_run) { + solution.problem_ptr = &problem_with_objective_cut; + population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); + solution.resize_to_problem(); + resize_to_new_problem(); + cutting_plane_added_for_active_run = true; + raft::copy(population_ptr->weights.cstr_weights.data(), + fj.cstr_weights.data(), + population_ptr->weights.cstr_weights.size(), + solution.handle_ptr->get_stream()); + raft::copy(population_ptr->weights_with_cuts.cstr_weights.data(), + fj.cstr_weights.data(), + fj.cstr_weights.size(), + solution.handle_ptr->get_stream()); + } + population_ptr->update_weights(); + save_solution_and_add_cutting_plane(population_ptr->best_feasible(), solution, best_objective); } if (population_ptr->current_size() > 1 && i - last_improved_iteration > iterations_for_stagnation) { @@ -715,12 +719,7 @@ void local_search_t::reset_alpha_and_run_recombiners( population_ptr->diversity_step(max_iterations_without_improvement); population_ptr->print(); population_ptr->update_weights(); - save_solution_and_add_cutting_plane( - population_ptr->best_feasible(), best_solution, best_objective); - raft::copy(solution.assignment.data(), - best_solution.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); + save_solution_and_add_cutting_plane(population_ptr->best_feasible(), solution, best_objective); } } @@ -736,7 +735,6 @@ bool local_search_t::run_fp(solution_t& solution, cutting_plane_added_for_active_run = is_feasible; double best_objective = is_feasible ? solution.get_objective() : std::numeric_limits::max(); - rmm::device_uvector best_solution(solution.assignment, solution.handle_ptr->get_stream()); problem_t* old_problem_ptr = solution.problem_ptr; fp.timer = timer_t(timer.remaining_time()); // if it has not been initialized yet, create a new problem and move it to the cut problem @@ -779,13 +777,8 @@ bool local_search_t::run_fp(solution_t& solution, if (is_feasible) { CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); - reset_alpha_and_save_solution(solution, - old_problem_ptr, - population_ptr, - i, - last_improved_iteration, - best_solution, - best_objective); + reset_alpha_and_save_solution( + solution, old_problem_ptr, population_ptr, i, last_improved_iteration, best_objective); last_improved_iteration = i; } // if not feasible, it means it is a cycle @@ -802,29 +795,15 @@ bool local_search_t::run_fp(solution_t& solution, if (is_feasible) { CUOPT_LOG_DEBUG("Found feasible during restart with obj %f. Continue with FJ!", solution.get_objective()); - reset_alpha_and_save_solution(solution, - old_problem_ptr, - population_ptr, - i, - last_improved_iteration, - best_solution, - best_objective); + reset_alpha_and_save_solution( + solution, old_problem_ptr, population_ptr, i, last_improved_iteration, best_objective); last_improved_iteration = i; } else { - reset_alpha_and_run_recombiners(solution, - old_problem_ptr, - population_ptr, - i, - last_improved_iteration, - best_solution, - best_objective); + run_recombiners( + solution, old_problem_ptr, population_ptr, i, last_improved_iteration, best_objective); } } } - raft::copy(solution.assignment.data(), - best_solution.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); solution.problem_ptr = old_problem_ptr; solution.resize_to_problem(); resize_to_old_problem(old_problem_ptr); diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index b60f524a2..0c64db5d6 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -119,29 +119,26 @@ class local_search_t { const std::string& source); i_t ls_threads() const { return ls_cpu_fj.size() + scratch_cpu_fj.size(); } - void save_solution_and_add_cutting_plane(solution_t& solution, - rmm::device_uvector& best_solution, + void save_solution_and_add_cutting_plane(solution_t& best_in_population, + solution_t& solution, f_t& best_objective); void resize_to_new_problem(); void resize_to_old_problem(problem_t* old_problem_ptr); - void reset_alpha_and_run_recombiners(solution_t& solution, - problem_t* old_problem_ptr, - population_t* population_ptr, - i_t i, - i_t last_unimproved_iteration, - rmm::device_uvector& best_solution, - f_t& best_objective); + void run_recombiners(solution_t& solution, + problem_t* old_problem_ptr, + population_t* population_ptr, + i_t i, + i_t last_unimproved_iteration, + f_t& best_objective); void reset_alpha_and_save_solution(solution_t& solution, problem_t* old_problem_ptr, population_t* population_ptr, i_t i, i_t last_unimproved_iteration, - rmm::device_uvector& best_solution, f_t& best_objective); void handle_cutting_plane_and_weights(solution_t& solution, population_t* population_ptr, - rmm::device_uvector& best_solution, f_t& best_objective); mip_solver_context_t& context; From 50f3d8eaae8fa50dc18f50a299789194fe73ef99 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 28 Oct 2025 08:40:16 -0700 Subject: [PATCH 15/30] old diversity --- cpp/src/mip/diversity/population.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index 24b963ab2..c57115466 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -62,7 +62,7 @@ population_t::population_t(std::string const& name_, template i_t get_max_var_threshold(i_t n_vars) { - return n_vars - sqrt(n_vars); + // return n_vars - sqrt(n_vars); if (n_vars < 50) { return std::max(1, n_vars - 1); } else if (n_vars < 80) { From dca499e4bb33b20d5d13096d84d4e335a225775b Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 29 Oct 2025 03:05:09 -0700 Subject: [PATCH 16/30] run submip with cuts --- cpp/src/mip/diversity/population.cu | 3 +-- cpp/src/mip/diversity/recombiners/sub_mip.cuh | 9 +++++++-- cpp/src/mip/local_search/local_search.cu | 6 ++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index c57115466..e3a50309e 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -34,7 +34,6 @@ constexpr double weight_decrease_ratio = 0.9; constexpr double max_infeasibility_weight = 1e12; constexpr double min_infeasibility_weight = 1.; constexpr double infeasibility_balance_ratio = 1.1; -constexpr double halving_skip_ratio = 0.75; template population_t::population_t(std::string const& name_, @@ -62,7 +61,7 @@ population_t::population_t(std::string const& name_, template i_t get_max_var_threshold(i_t n_vars) { - // return n_vars - sqrt(n_vars); + return n_vars - sqrt(n_vars); if (n_vars < 50) { return std::max(1, n_vars - 1); } else if (n_vars < 80) { diff --git a/cpp/src/mip/diversity/recombiners/sub_mip.cuh b/cpp/src/mip/diversity/recombiners/sub_mip.cuh index 2f465b39d..c37e20232 100644 --- a/cpp/src/mip/diversity/recombiners/sub_mip.cuh +++ b/cpp/src/mip/diversity/recombiners/sub_mip.cuh @@ -56,6 +56,7 @@ class sub_mip_recombiner_t : public recombiner_t { auto& other_solution = a.get_feasible() ? b : a; // copy the solution from A solution_t offspring(guiding_solution); + offspring.swap_problem_pointers(); // find same values and populate it to offspring i_t n_different_vars = this->assign_same_integer_values(guiding_solution, other_solution, offspring); @@ -156,7 +157,6 @@ class sub_mip_recombiner_t : public recombiner_t { } cuopt_func_call(offspring.test_variable_bounds()); cuopt_assert(offspring.test_number_all_integer(), "All must be integers after offspring"); - offspring.compute_feasibility(); // bool same_as_parents = this->check_if_offspring_is_same_as_parents(offspring, a, b); // adjust the max_n_of_vars_from_other if (n_different_vars > (i_t)sub_mip_recombiner_config_t::max_n_of_vars_from_other) { @@ -181,10 +181,15 @@ class sub_mip_recombiner_t : public recombiner_t { rmm::device_uvector dummy(0, offspring.handle_ptr->get_stream()); scaling.unscale_solutions(fixed_assignment, dummy); sol.unfix_variables(fixed_assignment, variable_map); - sol.compute_feasibility(); + // the current problem is the proble with objective cut + // to add to the population, swap problem to original + cuopt_assert(sol.compute_feasibility(), "Solution must be feasible"); + sol.swap_problem_pointers(); + cuopt_assert(sol.get_feasible(), "Solution must be feasible"); cuopt_func_call(sol.test_variable_bounds()); population.add_solution(std::move(sol)); } + offspring.swap_problem_pointers(); bool better_cost_than_parents = offspring.get_quality(weights) < std::min(other_solution.get_quality(weights), guiding_solution.get_quality(weights)); diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 2daefb618..d2b3607eb 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -238,8 +238,6 @@ bool local_search_t::do_fj_solve(solution_t& solution, solution, h_weights, h_weights, h_objective_weight, fj_settings_t{}, true); } - auto solution_copy = solution; - // Start CPU solver in background thread for (auto& cpu_fj : ls_cpu_fj) { cpu_fj.start_cpu_solver(); @@ -258,7 +256,7 @@ bool local_search_t::do_fj_solve(solution_t& solution, auto gpu_fj_end = std::chrono::high_resolution_clock::now(); double gpu_fj_duration = std::chrono::duration(gpu_fj_end - gpu_fj_start).count(); - solution_t solution_cpu(*solution.problem_ptr); + solution_t solution_cpu(solution); f_t best_cpu_obj = std::numeric_limits::max(); // // Wait for CPU solver to finish @@ -690,7 +688,7 @@ void local_search_t::run_recombiners(solution_t& solution, f_t& best_objective) { raft::common::nvtx::range fun_scope("reset_alpha_and_run_recombiners"); - constexpr i_t iterations_for_stagnation = 1; + constexpr i_t iterations_for_stagnation = 3; constexpr i_t max_iterations_without_improvement = 8; auto new_sol_vector = population_ptr->get_external_solutions(); population_ptr->add_solutions_from_vec(std::move(new_sol_vector)); From aaa10971aff7cc449f2b0eb00278351069613a71 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 29 Oct 2025 03:38:58 -0700 Subject: [PATCH 17/30] add cutting plane to line segment --- cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh b/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh index f3a819909..73e7b1ce5 100644 --- a/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh +++ b/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh @@ -85,6 +85,7 @@ class line_segment_recombiner_t : public recombiner_t { auto& other_solution = a.get_feasible() ? b : a; // copy the solution from A solution_t offspring(guiding_solution); + offspring.swap_problem_pointers(); timer_t line_segment_timer{ls_recombiner_config_t::time_limit}; // TODO after we have the conic combination, detect the lambda change // (i.e. the integral variables flip on line segment) @@ -125,6 +126,7 @@ class line_segment_recombiner_t : public recombiner_t { ls_recombiner_config_t::decrease_max_n_of_vars_from_other(); } } + offspring.swap_problem_pointers(); if (better_cost_than_parents || better_feasibility_than_parents) { CUOPT_LOG_DEBUG("Offspring is feasible or better than both parents"); return std::make_pair(offspring, true); From a99d0f4ea486963ae23ae4df79b4ca230c980502 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 29 Oct 2025 05:12:10 -0700 Subject: [PATCH 18/30] added bounds prop --- .../mip/diversity/recombiners/bound_prop_recombiner.cuh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh b/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh index 6aca26fb6..0aa280752 100644 --- a/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh +++ b/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh @@ -149,6 +149,7 @@ class bound_prop_recombiner_t : public recombiner_t { auto& other_solution = a.get_feasible() ? b : a; // copy the solution from guiding solution_t offspring(guiding_solution); + offspring.swap_problem_pointers(); // find same values and populate it to offspring i_t n_different_vars = this->assign_same_integer_values(a, b, offspring); CUOPT_LOG_DEBUG("BP rec: Number of different variables %d MAX_VARS %d", @@ -190,8 +191,9 @@ class bound_prop_recombiner_t : public recombiner_t { rmm::device_uvector old_assignment(offspring.assignment, offspring.handle_ptr->get_stream()); offspring.handle_ptr->sync_stream(); - offspring.assignment = std::move(fixed_assignment); - offspring.problem_ptr = &fixed_problem; + offspring.assignment = std::move(fixed_assignment); + problem_t* orig_problem_ptr = offspring.problem_ptr; + offspring.problem_ptr = &fixed_problem; cuopt_func_call(offspring.test_variable_bounds(false)); get_probing_values_for_feasible(guiding_solution, other_solution, @@ -208,7 +210,7 @@ class bound_prop_recombiner_t : public recombiner_t { constraint_prop.single_rounding_only = false; cuopt_func_call(bool feasible_after_bounds_prop = offspring.get_feasible()); offspring.handle_ptr->sync_stream(); - offspring.problem_ptr = a.problem_ptr; + offspring.problem_ptr = orig_problem_ptr; fixed_assignment = std::move(offspring.assignment); offspring.assignment = std::move(old_assignment); offspring.handle_ptr->sync_stream(); @@ -243,6 +245,7 @@ class bound_prop_recombiner_t : public recombiner_t { bp_recombiner_config_t::decrease_max_n_of_vars_from_other(); } } + offspring.swap_problem_pointers(); if (better_cost_than_parents || better_feasibility_than_parents) { CUOPT_LOG_DEBUG("Offspring is feasible or better than both parents"); return std::make_pair(offspring, true); From 550635f5805d0bde60c191837d7372908878a14b Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 29 Oct 2025 05:21:59 -0700 Subject: [PATCH 19/30] add also FP --- cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh | 2 +- cpp/src/mip/diversity/recombiners/fp_recombiner.cuh | 2 ++ cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh b/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh index 0aa280752..33edf9b3f 100644 --- a/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh +++ b/cpp/src/mip/diversity/recombiners/bound_prop_recombiner.cuh @@ -228,6 +228,7 @@ class bound_prop_recombiner_t : public recombiner_t { } constraint_prop.max_n_failed_repair_iterations = 1; cuopt_func_call(offspring.test_number_all_integer()); + offspring.swap_problem_pointers(); bool better_cost_than_parents = offspring.get_quality(weights) < std::min(other_solution.get_quality(weights), guiding_solution.get_quality(weights)); @@ -245,7 +246,6 @@ class bound_prop_recombiner_t : public recombiner_t { bp_recombiner_config_t::decrease_max_n_of_vars_from_other(); } } - offspring.swap_problem_pointers(); if (better_cost_than_parents || better_feasibility_than_parents) { CUOPT_LOG_DEBUG("Offspring is feasible or better than both parents"); return std::make_pair(offspring, true); diff --git a/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh b/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh index f3d4d7355..ce9a15597 100644 --- a/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh +++ b/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh @@ -54,6 +54,7 @@ class fp_recombiner_t : public recombiner_t { auto& other_solution = a.get_feasible() ? b : a; // copy the solution from A solution_t offspring(guiding_solution); + offspring.swap_problem_pointers(); // find same values and populate it to offspring i_t n_different_vars = this->assign_same_integer_values(guiding_solution, other_solution, offspring); @@ -136,6 +137,7 @@ class fp_recombiner_t : public recombiner_t { fp_recombiner_config_t::decrease_max_n_of_vars_from_other(); } } + offspring.swap_problem_pointers(); bool better_cost_than_parents = offspring.get_quality(weights) < std::min(other_solution.get_quality(weights), guiding_solution.get_quality(weights)); diff --git a/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh b/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh index 73e7b1ce5..cf8dcdf75 100644 --- a/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh +++ b/cpp/src/mip/diversity/recombiners/line_segment_recombiner.cuh @@ -110,6 +110,7 @@ class line_segment_recombiner_t : public recombiner_t { is_feasibility_run, line_segment_timer); line_segment_search.settings = {}; + offspring.swap_problem_pointers(); bool better_cost_than_parents = offspring.get_quality(weights) < std::min(other_solution.get_quality(weights), guiding_solution.get_quality(weights)); @@ -126,7 +127,6 @@ class line_segment_recombiner_t : public recombiner_t { ls_recombiner_config_t::decrease_max_n_of_vars_from_other(); } } - offspring.swap_problem_pointers(); if (better_cost_than_parents || better_feasibility_than_parents) { CUOPT_LOG_DEBUG("Offspring is feasible or better than both parents"); return std::make_pair(offspring, true); From f1c977babe7cc554570245ab6360fa678feb4b39 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Thu, 30 Oct 2025 03:44:34 -0700 Subject: [PATCH 20/30] old diversity and no objective cut on population --- cpp/src/mip/diversity/population.cu | 1 - cpp/src/mip/local_search/local_search.cu | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index e3a50309e..a47e52233 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -61,7 +61,6 @@ population_t::population_t(std::string const& name_, template i_t get_max_var_threshold(i_t n_vars) { - return n_vars - sqrt(n_vars); if (n_vars < 50) { return std::max(1, n_vars - 1); } else if (n_vars < 80) { diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index d2b3607eb..398fe8721 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -641,7 +641,7 @@ void local_search_t::handle_cutting_plane_and_weights( { if (!cutting_plane_added_for_active_run) { solution.problem_ptr = &problem_with_objective_cut; - population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); + // population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); solution.resize_to_problem(); resize_to_new_problem(); cutting_plane_added_for_active_run = true; @@ -695,7 +695,7 @@ void local_search_t::run_recombiners(solution_t& solution, if (population_ptr->is_feasible()) { if (!cutting_plane_added_for_active_run) { solution.problem_ptr = &problem_with_objective_cut; - population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); + // population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); solution.resize_to_problem(); resize_to_new_problem(); cutting_plane_added_for_active_run = true; @@ -748,8 +748,8 @@ bool local_search_t::run_fp(solution_t& solution, fj.copy_weights( population_ptr->weights, solution.handle_ptr, problem_with_objective_cut.n_constraints); solution.problem_ptr = &problem_with_objective_cut; - population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); - population_ptr->apply_problem_ptr_to_all_solutions(); + // population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); + // population_ptr->apply_problem_ptr_to_all_solutions(); solution.resize_to_problem(); resize_to_new_problem(); } From 47c62fa6bccc5cf3ec2362d9f24d4831d0e2c06f Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Thu, 27 Nov 2025 08:49:30 -0800 Subject: [PATCH 21/30] fix few merge conflicts --- cpp/src/mip/diversity/diversity_manager.cu | 4 +--- cpp/src/mip/diversity/population.cu | 1 + cpp/src/mip/local_search/local_search.cu | 24 ++++++---------------- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 3a9e29030..b37c5be29 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -430,9 +430,7 @@ void diversity_manager_t::diversity_step(i_t max_iterations_without_im improved = false; while (k-- > 0) { if (check_b_b_preemption()) { return; } - auto new_sol_vector = population.get_external_solutions(); - population.add_solutions_from_vec(std::move(new_sol_vector)); - population.apply_problem_ptr_to_all_solutions(); + population.add_external_solutions_to_population(); population.adjust_weights_according_to_best_feasible(); cuopt_assert(population.test_invariant(), ""); if (population.current_size() < 2) { diff --git a/cpp/src/mip/diversity/population.cu b/cpp/src/mip/diversity/population.cu index c46db3c90..e18660114 100644 --- a/cpp/src/mip/diversity/population.cu +++ b/cpp/src/mip/diversity/population.cu @@ -209,6 +209,7 @@ void population_t::add_external_solutions_to_population() auto new_sol_vector = get_external_solutions(); add_solutions_from_vec(std::move(new_sol_vector)); + apply_problem_ptr_to_all_solutions(); } // normally we would need a lock here but these are boolean types and race conditions are not diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index c2d9e42f0..79b2faccb 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -32,15 +32,9 @@ local_search_t::local_search_t(mip_solver_context_t& context fj_sol_on_lp_opt(context.problem_ptr->n_variables, context.problem_ptr->handle_ptr->get_stream()), fj(context), - // fj_tree(fj), constraint_prop(context), line_segment_search(fj, constraint_prop), - fp(context, - fj, - // fj_tree, - constraint_prop, - line_segment_search, - lp_optimal_solution_), + fp(context, fj, constraint_prop, line_segment_search, lp_optimal_solution_), rng(cuopt::seed_generator::get_seed()), problem_with_objective_cut(*context.problem_ptr, context.problem_ptr->handle_ptr) { @@ -540,9 +534,6 @@ template void local_search_t::resize_to_new_problem() { resize_vectors(problem_with_objective_cut, problem_with_objective_cut.handle_ptr); - // hint for next PR in case load balanced is reintroduced - // lb_constraint_prop.temp_problem.setup(problem_with_objective_cut); - // lb_constraint_prop.bounds_update.setup(lb_constraint_prop.temp_problem); constraint_prop.bounds_update.resize(problem_with_objective_cut); } @@ -550,9 +541,6 @@ template void local_search_t::resize_to_old_problem(problem_t* old_problem_ptr) { resize_vectors(*old_problem_ptr, old_problem_ptr->handle_ptr); - // hint for next PR in case load balanced is reintroduced - // lb_constraint_prop.temp_problem.setup(*old_problem_ptr); - // lb_constraint_prop.bounds_update.setup(lb_constraint_prop.temp_problem); constraint_prop.bounds_update.resize(*old_problem_ptr); } @@ -594,7 +582,7 @@ void local_search_t::reset_alpha_and_save_solution(solution_tadd_solution(std::move(solution_copy)); - auto new_sol_vector = population_ptr->add_external_solutions_to_population(); + population_ptr->add_external_solutions_to_population(); handle_cutting_plane_and_weights(solution, population_ptr, best_objective); population_ptr->print(); } @@ -610,11 +598,11 @@ void local_search_t::run_recombiners(solution_t& solution, raft::common::nvtx::range fun_scope("reset_alpha_and_run_recombiners"); constexpr i_t iterations_for_stagnation = 3; constexpr i_t max_iterations_without_improvement = 8; - auto new_sol_vector = population_ptr->add_external_solutions_to_population(); + population_ptr->add_external_solutions_to_population(); if (population_ptr->is_feasible()) { if (!cutting_plane_added_for_active_run) { solution.problem_ptr = &problem_with_objective_cut; - // population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); + population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); solution.resize_to_problem(); resize_to_new_problem(); cutting_plane_added_for_active_run = true; @@ -667,8 +655,8 @@ bool local_search_t::run_fp(solution_t& solution, fj.copy_weights( population_ptr->weights, solution.handle_ptr, problem_with_objective_cut.n_constraints); solution.problem_ptr = &problem_with_objective_cut; - // population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); - // population_ptr->apply_problem_ptr_to_all_solutions(); + population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); + population_ptr->apply_problem_ptr_to_all_solutions(); solution.resize_to_problem(); resize_to_new_problem(); } From 67f50082f2edd13bdbaa0490dc7c312e72f978a1 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 28 Nov 2025 05:07:12 -0800 Subject: [PATCH 22/30] handle review comments --- cpp/src/mip/local_search/local_search.cu | 18 +++++++----------- cpp/src/mip/solution/solution.cu | 22 ++++++++++++++++++++++ cpp/src/mip/solution/solution.cuh | 1 + 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 79b2faccb..37bdcd16d 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -549,9 +549,9 @@ void local_search_t::handle_cutting_plane_and_weights( solution_t& solution, population_t* population_ptr, f_t& best_objective) { if (!cutting_plane_added_for_active_run) { - solution.problem_ptr = &problem_with_objective_cut; - // population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); - solution.resize_to_problem(); + population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); + constexpr bool is_cuts_problem = true; + solution.set_problem_ptr(&problem_with_objective_cut, is_cuts_problem); resize_to_new_problem(); cutting_plane_added_for_active_run = true; raft::copy(population_ptr->weights.cstr_weights.data(), @@ -579,8 +579,7 @@ void local_search_t::reset_alpha_and_save_solution(solution_t solution_copy(solution); - solution_copy.problem_ptr = old_problem_ptr; - solution_copy.resize_to_problem(); + solution_copy.set_problem_ptr(old_problem_ptr); population_ptr->add_solution(std::move(solution_copy)); population_ptr->add_external_solutions_to_population(); handle_cutting_plane_and_weights(solution, population_ptr, best_objective); @@ -601,9 +600,8 @@ void local_search_t::run_recombiners(solution_t& solution, population_ptr->add_external_solutions_to_population(); if (population_ptr->is_feasible()) { if (!cutting_plane_added_for_active_run) { - solution.problem_ptr = &problem_with_objective_cut; + solution.set_problem_ptr(&problem_with_objective_cut); population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); - solution.resize_to_problem(); resize_to_new_problem(); cutting_plane_added_for_active_run = true; raft::copy(population_ptr->weights.cstr_weights.data(), @@ -654,10 +652,9 @@ bool local_search_t::run_fp(solution_t& solution, // Do the copy here for proper handling of the added constraints weight fj.copy_weights( population_ptr->weights, solution.handle_ptr, problem_with_objective_cut.n_constraints); - solution.problem_ptr = &problem_with_objective_cut; + solution.set_problem_ptr(&problem_with_objective_cut); population_ptr->set_problem_ptr_with_cuts(&problem_with_objective_cut); population_ptr->apply_problem_ptr_to_all_solutions(); - solution.resize_to_problem(); resize_to_new_problem(); } i_t last_improved_iteration = 0; @@ -710,8 +707,7 @@ bool local_search_t::run_fp(solution_t& solution, } } } - solution.problem_ptr = old_problem_ptr; - solution.resize_to_problem(); + solution.set_problem_ptr(old_problem_ptr); resize_to_old_problem(old_problem_ptr); solution.handle_ptr->sync_stream(); return is_feasible; diff --git a/cpp/src/mip/solution/solution.cu b/cpp/src/mip/solution/solution.cu index 7ef8e6c20..bc9d5b145 100644 --- a/cpp/src/mip/solution/solution.cu +++ b/cpp/src/mip/solution/solution.cu @@ -140,6 +140,28 @@ void solution_t::swap_problem_pointers() compute_feasibility(); } +template +void solution_t::set_problem_ptr(problem_t* _problem_ptr, bool is_cuts_problem) +{ + cuopt_assert(_problem_ptr != nullptr, "Problem pointer must be set"); + // FIXME: when we create ping_pong problems with constant cuts, adjust this logic + if (is_cuts_problem) { + cuopt_assert(!current_problem_is_cut, "Current problem must not be with cuts"); + // set original problem to be swap pointer + problem_with_cuts_ptr = problem_ptr; + // set current problem to new cut problem + problem_ptr = _problem_ptr; + current_problem_is_cut = true; + } else { + problem_ptr = _problem_ptr; + // if we are setting non-cut problem, the cut version should be invalidated + problem_with_cuts_ptr = nullptr; + current_problem_is_cut = false; + } + resize_to_problem(); + compute_feasibility(); +} + template void solution_t::resize_to_original_problem() { diff --git a/cpp/src/mip/solution/solution.cuh b/cpp/src/mip/solution/solution.cuh index e5ae05dd2..4359c879c 100644 --- a/cpp/src/mip/solution/solution.cuh +++ b/cpp/src/mip/solution/solution.cuh @@ -99,6 +99,7 @@ class solution_t { f_t compute_max_int_violation(); f_t compute_max_variable_violation(); void swap_problem_pointers(); + void set_problem_ptr(problem_t* _problem_ptr, bool is_cuts_problem = false); struct view_t { // let's not bloat the class for every simple getter and setters From 1695286b88e3f86d862770ce2911129d821ffc4f Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 28 Nov 2025 06:44:45 -0800 Subject: [PATCH 23/30] build run_mip off --- cpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index f9e01218a..2e782f0ff 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -454,7 +454,7 @@ install(TARGETS cuopt_cli endif() -option(BUILD_MIP_BENCHMARKS "Build MIP benchmarks" ON) +option(BUILD_MIP_BENCHMARKS "Build MIP benchmarks" OFF) if(BUILD_MIP_BENCHMARKS AND NOT BUILD_LP_ONLY) add_executable(solve_MIP ../benchmarks/linear_programming/cuopt/run_mip.cpp) target_compile_options(solve_MIP From 0acb5be3a8c438eee30c89cf675a20f984d70489 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 1 Dec 2025 02:56:28 -0800 Subject: [PATCH 24/30] fix lp time and population insert --- cpp/src/mip/diversity/diversity_config.hpp | 2 +- cpp/src/mip/diversity/diversity_manager.cu | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_config.hpp b/cpp/src/mip/diversity/diversity_config.hpp index 60cd10525..5d95a51df 100644 --- a/cpp/src/mip/diversity/diversity_config.hpp +++ b/cpp/src/mip/diversity/diversity_config.hpp @@ -28,7 +28,7 @@ struct diversity_config_t { size_t n_sol_for_skip_init_gen = 3; double max_fast_sol_time = 10; double lp_run_time_if_feasible = 2.; - double lp_run_time_if_infeasible = 2.; + double lp_run_time_if_infeasible = 1.; bool halve_population = false; }; diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index b37c5be29..4372819d1 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -446,8 +446,8 @@ void diversity_manager_t::diversity_step(i_t max_iterations_without_im auto [inserted_pos_2, best_updated_2] = population.add_solution(std::move(offspring)); if (best_updated_1 || best_updated_2) { recombine_stats.add_best_updated(); } cuopt_assert(population.test_invariant(), ""); - if ((inserted_pos_1 != -1 && inserted_pos_1 <= 1) || - (inserted_pos_2 != -1 && inserted_pos_2 <= 1)) { + if ((inserted_pos_1 != -1 && inserted_pos_1 <= 2) || + (inserted_pos_2 != -1 && inserted_pos_2 <= 2)) { improved = true; recombine_stats.print(); break; From aa78fa6328b76ac92544320790b136c8b248948f Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 1 Dec 2025 02:57:19 -0800 Subject: [PATCH 25/30] revert timer changes --- cpp/src/mip/local_search/local_search.cu | 27 ++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 37bdcd16d..2c47fda87 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -255,19 +255,20 @@ bool local_search_t::run_local_search(solution_t& solution, fj_settings_t fj_settings; if (timer.check_time_limit()) return false; // adjust these time limits - // if (!solution.get_feasible()) { - // if (ls_config.at_least_one_parent_feasible) { - // fj_settings.time_limit = 0.5; - // timer = timer_t(fj_settings.time_limit); - // } else { - // fj_settings.time_limit = 0.25; - // timer = timer_t(fj_settings.time_limit); - // } - // } else { - // fj_settings.time_limit = std::min(1., timer.remaining_time()); - // } - fj_settings.time_limit = std::min(1., timer.remaining_time()); - timer = timer_t(fj_settings.time_limit); + if (!solution.get_feasible()) { + if (ls_config.at_least_one_parent_feasible) { + fj_settings.time_limit = 0.5; + timer = timer_t(fj_settings.time_limit); + } else { + fj_settings.time_limit = 0.25; + timer = timer_t(fj_settings.time_limit); + } + } else { + fj_settings.time_limit = std::min(1., timer.remaining_time()); + timer = timer_t(fj_settings.time_limit); + } + // fj_settings.time_limit = std::min(1., timer.remaining_time()); + // timer = timer_t(fj_settings.time_limit); fj_settings.update_weights = false; fj_settings.feasibility_run = false; fj.set_fj_settings(fj_settings); From 7fb2ed53f1dfd8134b7ac057fadc6c8dbe3f5ffc Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 1 Dec 2025 12:56:56 -0800 Subject: [PATCH 26/30] fix timer --- cpp/src/mip/local_search/local_search.cu | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 2c47fda87..dd2637a4a 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -254,21 +254,8 @@ bool local_search_t::run_local_search(solution_t& solution, raft::common::nvtx::range fun_scope("local search"); fj_settings_t fj_settings; if (timer.check_time_limit()) return false; - // adjust these time limits - if (!solution.get_feasible()) { - if (ls_config.at_least_one_parent_feasible) { - fj_settings.time_limit = 0.5; - timer = timer_t(fj_settings.time_limit); - } else { - fj_settings.time_limit = 0.25; - timer = timer_t(fj_settings.time_limit); - } - } else { - fj_settings.time_limit = std::min(1., timer.remaining_time()); - timer = timer_t(fj_settings.time_limit); - } - // fj_settings.time_limit = std::min(1., timer.remaining_time()); - // timer = timer_t(fj_settings.time_limit); + fj_settings.time_limit = std::min(1., timer.remaining_time()); + timer = timer_t(fj_settings.time_limit); fj_settings.update_weights = false; fj_settings.feasibility_run = false; fj.set_fj_settings(fj_settings); From fd701f6119f5aa9b61e744cdb36df40e499c155b Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 13 Jan 2026 03:12:41 -0800 Subject: [PATCH 27/30] license precommit runs --- benchmarks/linear_programming/cuopt/run_mip.cpp | 2 +- cpp/src/mip/diversity/recombiners/fp_recombiner.cuh | 2 +- cpp/src/mip/local_search/local_search.cuh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmarks/linear_programming/cuopt/run_mip.cpp b/benchmarks/linear_programming/cuopt/run_mip.cpp index 60326f562..2da2a3d04 100644 --- a/benchmarks/linear_programming/cuopt/run_mip.cpp +++ b/benchmarks/linear_programming/cuopt/run_mip.cpp @@ -1,6 +1,6 @@ /* clang-format off */ /* - * SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ /* clang-format on */ diff --git a/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh b/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh index d64a53145..07e00499b 100644 --- a/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh +++ b/cpp/src/mip/diversity/recombiners/fp_recombiner.cuh @@ -1,6 +1,6 @@ /* clang-format off */ /* - * SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ /* clang-format on */ diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index 656076534..0224fa0b1 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -1,6 +1,6 @@ /* clang-format off */ /* - * SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ /* clang-format on */ From b22e3a493fb7b300f7f3edfc4695a52b7c6f038e Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 13 Jan 2026 04:10:14 -0800 Subject: [PATCH 28/30] fix merge conflicts --- cpp/src/mip/diversity/population.cuh | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/src/mip/diversity/population.cuh b/cpp/src/mip/diversity/population.cuh index b29b1a43d..4a51d82a5 100644 --- a/cpp/src/mip/diversity/population.cuh +++ b/cpp/src/mip/diversity/population.cuh @@ -209,7 +209,6 @@ class population_t { std::atomic preempt_heuristic_solver_ = false; std::atomic solutions_in_external_queue_ = false; f_t best_feasible_objective = std::numeric_limits::max(); - std::atomic solutions_in_external_queue_ = false; assignment_hash_map_t population_hash_map; cuopt::timer_t timer; }; From 6b26c1b44ec9b00e24e3507397e8f08dbccc677e Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 14 Jan 2026 07:32:19 -0800 Subject: [PATCH 29/30] revert lineinfo --- cpp/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 20daad750..5b1ce76ce 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -79,7 +79,6 @@ endif(CMAKE_COMPILER_IS_GNUCXX) if(DEFINE_ASSERT) message(STATUS "Undefining NDEBUG with assert mode enabled") add_definitions(-UNDEBUG) - set(CMAKE_BUILD_TYPE RelWithDebInfo) endif() # To use sanitizer with cuda runtime, one must follow a few steps: @@ -176,7 +175,6 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) elseif(CMAKE_CUDA_LINEINFO) message(STATUS "Enabling line info") list(APPEND CUOPT_CUDA_FLAGS -lineinfo) - list(APPEND CUOPT_CXX_FLAGS -lineinfo) set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE} -lineinfo") endif(CMAKE_BUILD_TYPE MATCHES Debug) From 79e71a1782eeae74ba1f9444c8f4854c58f6b2f3 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 16 Jan 2026 02:03:08 -0800 Subject: [PATCH 30/30] revert cmake pos change --- cpp/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 5b1ce76ce..b1f9d6940 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -75,11 +75,6 @@ if(CMAKE_COMPILER_IS_GNUCXX) list(APPEND CUOPT_CXX_FLAGS -Werror -Wno-error=deprecated-declarations) endif(CMAKE_COMPILER_IS_GNUCXX) -# Undefine NDEBUG if assert mode is on -if(DEFINE_ASSERT) - message(STATUS "Undefining NDEBUG with assert mode enabled") - add_definitions(-UNDEBUG) -endif() # To use sanitizer with cuda runtime, one must follow a few steps: # 1. Run the binary with env var set: LD_PRELOAD="$(gcc -print-file-name=libasan.so)" ASAN_OPTIONS='protect_shadow_gap=0:replace_intrin=0' @@ -178,6 +173,11 @@ elseif(CMAKE_CUDA_LINEINFO) set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE} -lineinfo") endif(CMAKE_BUILD_TYPE MATCHES Debug) +# Undefine NDEBUG if assert mode is on +if(DEFINE_ASSERT) + message(STATUS "Undefining NDEBUG with assert mode enabled") + add_definitions(-UNDEBUG) +endif() # ################################################################################################## # - find CPM based dependencies ------------------------------------------------------------------