From d1ab4ebcdb05a05bb0ad48d49cfef69eb0dcaa82 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Thu, 31 Jul 2025 07:09:40 -0700 Subject: [PATCH 01/29] test fp only --- cpp/src/CMakeLists.txt | 2 +- cpp/src/mip/diversity/diversity_manager.cu | 28 ++++-- cpp/src/mip/diversity/diversity_manager.cuh | 1 + .../feasibility_pump/feasibility_pump.cu | 1 - .../feasibility_pump/feasibility_pump.cuh | 3 +- cpp/src/mip/local_search/local_search.cu | 86 +++++++++++++++++-- cpp/src/mip/local_search/local_search.cuh | 2 +- cpp/tests/CMakeLists.txt | 6 +- 8 files changed, 109 insertions(+), 20 deletions(-) diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 18d83f393b..ad68305ee8 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -19,7 +19,7 @@ set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu add_subdirectory(linear_programming) add_subdirectory(math_optimization) add_subdirectory(mip) -add_subdirectory(routing) +# add_subdirectory(routing) add_subdirectory(dual_simplex) set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${UTIL_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index f7476a5eda..9bd67fcdbf 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -28,6 +28,7 @@ constexpr bool from_dir = false; constexpr bool fj_only_run = false; +constexpr bool fp_only_run = true; namespace cuopt::linear_programming::detail { @@ -293,7 +294,7 @@ void diversity_manager_t::generate_initial_solutions() population.var_threshold); population.print(); auto new_sol_vector = population.get_external_solutions(); - if (!fj_only_run) { recombine_and_ls_with_all(new_sol_vector); } + if (!fj_only_run && !fp_only_run) { recombine_and_ls_with_all(new_sol_vector); } } template @@ -382,6 +383,16 @@ void diversity_manager_t::run_fj_alone(solution_t& solution) CUOPT_LOG_INFO("FJ alone finished!"); } +// returns the best feasible solution +template +void diversity_manager_t::run_fp_alone(solution_t& solution) +{ + CUOPT_LOG_INFO("Running FP alone!"); + solution.round_nearest(); + ls.run_fp(solution, timer, false); + CUOPT_LOG_INFO("FP alone finished!"); +} + // returns the best feasible solution template solution_t diversity_manager_t::run_solver() @@ -418,7 +429,7 @@ solution_t diversity_manager_t::run_solver() std::min(max_time_on_probing, time_limit * time_ratio_of_probing_cache); timer_t probing_timer{time_for_probing_cache}; if (check_b_b_preemption()) { return population.best_feasible(); } - if (!fj_only_run) { + if (!fj_only_run && !fp_only_run) { compute_probing_cache(ls.constraint_prop.bounds_update, *problem_ptr, probing_timer); } // careful, assign the correct probing cache @@ -436,7 +447,7 @@ solution_t diversity_manager_t::run_solver() } // Mutex is unlocked here if (bb_thread_solution_exists) { ls.lp_optimal_exists = true; - } else if (!fj_only_run) { + } else if (!fj_only_run && !fp_only_run) { relaxed_lp_settings_t lp_settings; lp_settings.time_limit = lp_time_limit; lp_settings.tolerance = context.settings.tolerances.absolute_tolerance; @@ -477,8 +488,10 @@ solution_t diversity_manager_t::run_solver() } population.allocate_solutions(); if (check_b_b_preemption()) { return population.best_feasible(); } - // generate a population with 5 solutions(FP+FJ) - generate_initial_solutions(); + if (!fp_only_run) { + // generate a population with 5 solutions(FP+FJ) + generate_initial_solutions(); + } if (context.settings.benchmark_info_ptr != nullptr) { context.settings.benchmark_info_ptr->objective_of_initial_population = population.best_feasible().get_user_objective(); @@ -489,6 +502,11 @@ solution_t diversity_manager_t::run_solver() return population.best_feasible(); } + if (fp_only_run) { + run_fp_alone(population.best_feasible()); + return population.best_feasible(); + } + if (timer.check_time_limit()) { return population.best_feasible(); } main_loop(); return population.best_feasible(); diff --git a/cpp/src/mip/diversity/diversity_manager.cuh b/cpp/src/mip/diversity/diversity_manager.cuh index 712ad3f4a2..caf4d68036 100644 --- a/cpp/src/mip/diversity/diversity_manager.cuh +++ b/cpp/src/mip/diversity/diversity_manager.cuh @@ -46,6 +46,7 @@ class diversity_manager_t { // generates initial solutions void generate_initial_solutions(); void run_fj_alone(solution_t& solution); + void run_fp_alone(solution_t& solution); // main loop of diversity improvements void main_loop(); // randomly chooses a recombiner and returns the offspring diff --git a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu index ee04155d6c..5f421f1052 100644 --- a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu +++ b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu @@ -381,7 +381,6 @@ void feasibility_pump_t::reset() total_fp_time_until_cycle = 0; fp_fj_cycle_time_begin = timer.remaining_time(); max_n_of_integers = 0; - run_intensive_restart = false; config.alpha = default_alpha; last_distances.resize(0); } diff --git a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cuh b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cuh index 8b7891b04b..60a249f893 100644 --- a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cuh +++ b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cuh @@ -169,8 +169,7 @@ class feasibility_pump_t { f_t proj_and_round_time; f_t proj_begin; i_t n_fj_single_descents; - i_t max_n_of_integers = 0; - bool run_intensive_restart = false; + i_t max_n_of_integers = 0; 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 711612550b..fc266f8e86 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -140,7 +140,6 @@ bool local_search_t::run_fj_until_timer(solution_t& solution return is_feasible; } -// SIMULATED ANNEALING not fully implemented yet, placeholder template bool local_search_t::run_fj_annealing(solution_t& solution, timer_t timer, @@ -325,26 +324,99 @@ void local_search_t::resize_vectors(problem_t& problem, } template -bool local_search_t::run_fp(solution_t& solution, timer_t timer) +bool local_search_t::run_fp(solution_t& solution, + timer_t timer, + bool feasibility_run) { const i_t n_fp_iterations = 1000000; bool is_feasible = false; + double best_objective = std::numeric_limits::max(); + rmm::device_uvector best_solution(solution.assignment, solution.handle_ptr->get_stream()); for (i_t i = 0; i < n_fp_iterations && !timer.check_time_limit(); ++i) { - if (timer.check_time_limit()) { return false; } + if (timer.check_time_limit()) { + is_feasible = false; + break; + } CUOPT_LOG_DEBUG("fp_loop it %d", i); is_feasible = fp.run_single_fp_descent(solution); // if feasible return true if (is_feasible) { - return true; + if (feasibility_run) { + is_feasible = true; + break; + } else { + CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", + solution.get_objective()); + if (solution.get_objective() < best_objective) { + CUOPT_LOG_DEBUG("Found better feasible in FP with obj %f. Continue with FJ!", + solution.get_objective()); + best_objective = solution.get_objective(); + raft::copy(best_solution.data(), + solution.assignment.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + } + fp.config.alpha = default_alpha; + ls_config_t ls_config; + // assign current objective + ls_config.best_objective_of_parents = solution.get_objective(); + ls_config.n_local_mins = 500; + is_feasible = run_fj_annealing(solution, timer, ls_config); + if (is_feasible && solution.get_objective() < best_objective) { + raft::copy(solution.assignment.data(), + best_solution.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + best_objective = solution.get_objective(); + } + } } // if not feasible, it means it is a cycle else { - if (timer.check_time_limit()) { return false; } + if (timer.check_time_limit()) { + is_feasible = false; + break; + } is_feasible = fp.restart_fp(solution); - if (is_feasible) { return true; } + if (is_feasible) { + if (feasibility_run) { + is_feasible = true; + break; + } else { + CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", + solution.get_objective()); + if (solution.get_objective() < best_objective) { + CUOPT_LOG_DEBUG("Found better feasible in FP with obj %f. Continue with FJ!", + solution.get_objective()); + best_objective = solution.get_objective(); + raft::copy(best_solution.data(), + solution.assignment.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + } + fp.config.alpha = default_alpha; + ls_config_t ls_config; + // assign current objective + ls_config.best_objective_of_parents = solution.get_objective(); + ls_config.n_local_mins = 500; + is_feasible = run_fj_annealing(solution, timer, ls_config); + if (is_feasible && solution.get_objective() < best_objective) { + raft::copy(solution.assignment.data(), + best_solution.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + best_objective = solution.get_objective(); + } + } + } } } - return false; + raft::copy(solution.assignment.data(), + best_solution.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + solution.handle_ptr->sync_stream(); + return is_feasible; } template diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index fdb3ff5803..fedf68336f 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -66,7 +66,7 @@ class local_search_t { bool run_fj_on_zero(solution_t& solution, timer_t timer); bool check_fj_on_lp_optimal(solution_t& solution, bool perturb, timer_t timer); bool run_staged_fp(solution_t& solution, timer_t timer, bool& early_exit); - bool run_fp(solution_t& solution, timer_t timer); + bool run_fp(solution_t& solution, timer_t timer, bool feasibility_run = true); void resize_vectors(problem_t& problem, const raft::handle_t* handle_ptr); mip_solver_context_t& context; diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 50323dc7e8..7b4d610b04 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -81,12 +81,12 @@ if(RAPIDS_DATASET_ROOT_DIR) endif(RAPIDS_DATASET_ROOT_DIR) # ## test sources -add_subdirectory(routing) +# add_subdirectory(routing) add_subdirectory(linear_programming) -add_subdirectory(distance_engine) +# add_subdirectory(distance_engine) add_subdirectory(mip) add_subdirectory(dual_simplex) -add_subdirectory(examples) +# add_subdirectory(examples) add_subdirectory(utilities) enable_testing() From 47708f4a02d9e7e2ec4181c451f3938f8ba2b393 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 1 Aug 2025 01:38:57 -0700 Subject: [PATCH 02/29] generate and then run FP --- cpp/src/mip/diversity/diversity_manager.cu | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 9bd67fcdbf..b440e4b68c 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -388,7 +388,6 @@ template void diversity_manager_t::run_fp_alone(solution_t& solution) { CUOPT_LOG_INFO("Running FP alone!"); - solution.round_nearest(); ls.run_fp(solution, timer, false); CUOPT_LOG_INFO("FP alone finished!"); } @@ -422,7 +421,7 @@ solution_t diversity_manager_t::run_solver() population.initialize_population(); if (check_b_b_preemption()) { return population.best_feasible(); } // before probing cache or LP, run FJ to generate initial primal feasible solution - if (!from_dir) { generate_quick_feasible_solution(); } + if (!from_dir && !fp_only_run && !fj_only_run) { generate_quick_feasible_solution(); } constexpr f_t time_ratio_of_probing_cache = diversity_config_t::time_ratio_of_probing_cache; constexpr f_t max_time_on_probing = diversity_config_t::max_time_on_probing; f_t time_for_probing_cache = @@ -503,8 +502,9 @@ solution_t diversity_manager_t::run_solver() } if (fp_only_run) { - run_fp_alone(population.best_feasible()); - return population.best_feasible(); + auto sol = generate_solution(timer.remaining_time(), false); + run_fp_alone(sol); + return sol; } if (timer.check_time_limit()) { return population.best_feasible(); } From 17561a28832848bdecd55ea57e0be6fea3812d19 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 1 Aug 2025 01:59:10 -0700 Subject: [PATCH 03/29] with fj --- cpp/src/mip/diversity/diversity_manager.cu | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index b440e4b68c..642dcbdb37 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -503,7 +503,8 @@ solution_t diversity_manager_t::run_solver() if (fp_only_run) { auto sol = generate_solution(timer.remaining_time(), false); - run_fp_alone(sol); + ls.run_fj_until_timer(sol, population.weights, timer); + // run_fp_alone(sol); return sol; } From 6276efaa2cebb2b99d128a97dea749307a36140d Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 1 Aug 2025 07:18:29 -0700 Subject: [PATCH 04/29] with obj cut --- cpp/src/mip/diversity/diversity_manager.cu | 3 +- cpp/src/mip/local_search/local_search.cu | 40 +++++++++++++++------- cpp/src/mip/problem/problem.cu | 28 +++++++++++++++ cpp/src/mip/problem/problem.cuh | 2 ++ 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 642dcbdb37..b440e4b68c 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -503,8 +503,7 @@ solution_t diversity_manager_t::run_solver() if (fp_only_run) { auto sol = generate_solution(timer.remaining_time(), false); - ls.run_fj_until_timer(sol, population.weights, timer); - // run_fp_alone(sol); + run_fp_alone(sol); return sol; } diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index fc266f8e86..f1580ae6c4 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -189,10 +189,12 @@ bool local_search_t::check_fj_on_lp_optimal(solution_t& solu bool perturb, timer_t timer) { - raft::copy(solution.assignment.data(), - lp_optimal_solution.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); + if (lp_optimal_exists) { + raft::copy(solution.assignment.data(), + lp_optimal_solution.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + } if (perturb) { CUOPT_LOG_DEBUG("Perturbating solution on initial fj on optimal run!"); f_t perturbation_ratio = 0.2; @@ -318,8 +320,6 @@ void local_search_t::resize_vectors(problem_t& problem, const raft::handle_t* handle_ptr) { fj_sol_on_lp_opt.resize(problem.n_variables, handle_ptr->get_stream()); - fj.resize_vectors(handle_ptr); - // TODO resize LNS when it is used fp.resize_vectors(problem, handle_ptr); } @@ -332,6 +332,14 @@ bool local_search_t::run_fp(solution_t& solution, bool is_feasible = false; double best_objective = std::numeric_limits::max(); rmm::device_uvector best_solution(solution.assignment, solution.handle_ptr->get_stream()); + if (!feasibility_run) { + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective()); + solution.resize_to_problem(); + resize_vectors(*solution.problem_ptr, solution.handle_ptr); + lb_constraint_prop.temp_problem.setup(*solution.problem_ptr); + lb_constraint_prop.bounds_update.setup(lb_constraint_prop.temp_problem); + constraint_prop.bounds_update.resize(*solution.problem_ptr); + } for (i_t i = 0; i < n_fp_iterations && !timer.check_time_limit(); ++i) { if (timer.check_time_limit()) { is_feasible = false; @@ -355,19 +363,23 @@ bool local_search_t::run_fp(solution_t& solution, solution.assignment.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + OBJECTIVE_EPSILON); } fp.config.alpha = default_alpha; ls_config_t ls_config; // assign current objective ls_config.best_objective_of_parents = solution.get_objective(); - ls_config.n_local_mins = 500; + ls_config.n_local_mins = 5000; is_feasible = run_fj_annealing(solution, timer, ls_config); if (is_feasible && solution.get_objective() < best_objective) { - raft::copy(solution.assignment.data(), - best_solution.data(), + raft::copy(best_solution.data(), + solution.assignment.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); best_objective = solution.get_objective(); + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + OBJECTIVE_EPSILON); } } } @@ -393,19 +405,23 @@ bool local_search_t::run_fp(solution_t& solution, solution.assignment.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + OBJECTIVE_EPSILON); } fp.config.alpha = default_alpha; ls_config_t ls_config; // assign current objective ls_config.best_objective_of_parents = solution.get_objective(); - ls_config.n_local_mins = 500; + ls_config.n_local_mins = 5000; is_feasible = run_fj_annealing(solution, timer, ls_config); if (is_feasible && solution.get_objective() < best_objective) { - raft::copy(solution.assignment.data(), - best_solution.data(), + raft::copy(best_solution.data(), + solution.assignment.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); best_objective = solution.get_objective(); + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + OBJECTIVE_EPSILON); } } } diff --git a/cpp/src/mip/problem/problem.cu b/cpp/src/mip/problem/problem.cu index 888388ef18..ec9f45b232 100644 --- a/cpp/src/mip/problem/problem.cu +++ b/cpp/src/mip/problem/problem.cu @@ -1590,6 +1590,34 @@ f_t problem_t::get_user_obj_from_solver_obj(f_t solver_obj) return presolve_data.objective_scaling_factor * (solver_obj + presolve_data.objective_offset); } +template +void problem_t::add_cutting_plane_at_objective(f_t objective) +{ + CUOPT_LOG_INFO("Adding cutting plane at objective %f", objective); + if (cutting_plane_added) { + // modify the RHS + i_t last_constraint = n_constraints - 1; + constraint_upper_bounds.set_element_async(last_constraint, objective, handle_ptr->get_stream()); + return; + } + cutting_plane_added = true; + constraints_delta_t h_constraints; + auto h_objective_coefficients = cuopt::host_copy(objective_coefficients); + handle_ptr->sync_stream(); + std::vector var_indices; + std::vector constr_coeffs; + for (i_t i = 0; i < n_variables; ++i) { + if (h_objective_coefficients[i] != 0) { + var_indices.push_back(i); + constr_coeffs.push_back(h_objective_coefficients[i]); + } + } + h_constraints.add_constraint( + var_indices, constr_coeffs, -std::numeric_limits::infinity(), objective); + insert_constraints(h_constraints); + compute_transpose_of_problem(); +} + #if MIP_INSTANTIATE_FLOAT template class problem_t; #endif diff --git a/cpp/src/mip/problem/problem.cuh b/cpp/src/mip/problem/problem.cuh index cc29ce0e65..3fcb6b1e24 100644 --- a/cpp/src/mip/problem/problem.cuh +++ b/cpp/src/mip/problem/problem.cuh @@ -112,6 +112,7 @@ class problem_t { cuopt::linear_programming::dual_simplex::user_problem_t& user_problem) const; void write_as_mps(const std::string& path); + void add_cutting_plane_at_objective(f_t objective); struct view_t { DI std::pair reverse_range_for_var(i_t v) const @@ -272,6 +273,7 @@ class problem_t { // is always the same and only the RHS changes. Using this helps in warm start. lp_state_t lp_state; problem_fixing_helpers_t fixing_helpers; + bool cutting_plane_added{false}; }; } // namespace linear_programming::detail From b2ed360d60d82cbbfed5da52f8c540c34366c375 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 4 Aug 2025 05:06:28 -0700 Subject: [PATCH 05/29] test FP ls --- cpp/src/mip/diversity/diversity_manager.cu | 2 +- .../mip/feasibility_jump/feasibility_jump.cu | 2 +- cpp/src/mip/local_search/local_search.cu | 35 ++++++++++++++----- cpp/src/mip/local_search/local_search.cuh | 1 + 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index b440e4b68c..2091c7304b 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -28,7 +28,7 @@ constexpr bool from_dir = false; constexpr bool fj_only_run = false; -constexpr bool fp_only_run = true; +constexpr bool fp_only_run = false; namespace cuopt::linear_programming::detail { diff --git a/cpp/src/mip/feasibility_jump/feasibility_jump.cu b/cpp/src/mip/feasibility_jump/feasibility_jump.cu index fa88bddd19..a0e3990100 100644 --- a/cpp/src/mip/feasibility_jump/feasibility_jump.cu +++ b/cpp/src/mip/feasibility_jump/feasibility_jump.cu @@ -241,7 +241,7 @@ template void fj_t::copy_weights(const weight_t& weights, const raft::handle_t* handle_ptr) { - cuopt_assert(cstr_weights.size() == weights.cstr_weights.size(), "Size mismatch"); + cstr_weights.resize(weights.cstr_weights.size(), handle_ptr->get_stream()); raft::copy(cstr_weights.data(), weights.cstr_weights.data(), 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 f1580ae6c4..3894cf5a91 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -49,7 +49,8 @@ local_search_t::local_search_t(mip_solver_context_t& context lb_constraint_prop, line_segment_search, lp_optimal_solution_), - rng(cuopt::seed_generator::get_seed()) + rng(cuopt::seed_generator::get_seed()), + problem_with_objective_cut(*context.problem_ptr, context.problem_ptr->handle_ptr) { } @@ -118,6 +119,8 @@ bool local_search_t::run_local_search(solution_t& solution, } else { is_feas = run_fj_annealing(solution, timer, ls_config); } + timer = timer_t(std::min(5., timer.remaining_time())); + run_fp(solution, timer, false); return is_feas; } @@ -332,13 +335,19 @@ bool local_search_t::run_fp(solution_t& solution, bool is_feasible = false; double best_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; if (!feasibility_run) { - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective()); + if (!problem_with_objective_cut.cutting_plane_added) { + problem_with_objective_cut = std::move(problem_t(*old_problem_ptr)); + } + problem_with_objective_cut.add_cutting_plane_at_objective(solution.get_objective() - + OBJECTIVE_EPSILON); + solution.problem_ptr = &problem_with_objective_cut; solution.resize_to_problem(); - resize_vectors(*solution.problem_ptr, solution.handle_ptr); - lb_constraint_prop.temp_problem.setup(*solution.problem_ptr); + resize_vectors(problem_with_objective_cut, solution.handle_ptr); + 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(*solution.problem_ptr); + constraint_prop.bounds_update.resize(problem_with_objective_cut); } for (i_t i = 0; i < n_fp_iterations && !timer.check_time_limit(); ++i) { if (timer.check_time_limit()) { @@ -363,7 +372,7 @@ bool local_search_t::run_fp(solution_t& solution, solution.assignment.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - OBJECTIVE_EPSILON); } fp.config.alpha = default_alpha; @@ -378,7 +387,7 @@ bool local_search_t::run_fp(solution_t& solution, solution.assignment.size(), solution.handle_ptr->get_stream()); best_objective = solution.get_objective(); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - OBJECTIVE_EPSILON); } } @@ -405,7 +414,7 @@ bool local_search_t::run_fp(solution_t& solution, solution.assignment.data(), solution.assignment.size(), solution.handle_ptr->get_stream()); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - OBJECTIVE_EPSILON); } fp.config.alpha = default_alpha; @@ -420,7 +429,7 @@ bool local_search_t::run_fp(solution_t& solution, solution.assignment.size(), solution.handle_ptr->get_stream()); best_objective = solution.get_objective(); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() + + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - OBJECTIVE_EPSILON); } } @@ -432,6 +441,14 @@ bool local_search_t::run_fp(solution_t& solution, solution.assignment.size(), solution.handle_ptr->get_stream()); solution.handle_ptr->sync_stream(); + if (!feasibility_run) { + solution.problem_ptr = old_problem_ptr; + solution.resize_to_problem(); + resize_vectors(*old_problem_ptr, solution.handle_ptr); + 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); + } return is_feasible; } diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index fedf68336f..6d7b62a161 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -80,6 +80,7 @@ class local_search_t { line_segment_search_t line_segment_search; feasibility_pump_t fp; std::mt19937 rng; + problem_t problem_with_objective_cut; }; } // namespace cuopt::linear_programming::detail From ebbb5e44bad2622b14111d33dda2303152c8dbfd Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 4 Aug 2025 05:11:21 -0700 Subject: [PATCH 06/29] 20s fp run --- cpp/src/mip/local_search/local_search.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 3894cf5a91..4c4a52da07 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -119,7 +119,7 @@ bool local_search_t::run_local_search(solution_t& solution, } else { is_feas = run_fj_annealing(solution, timer, ls_config); } - timer = timer_t(std::min(5., timer.remaining_time())); + timer = timer_t(std::min(20., timer.remaining_time())); run_fp(solution, timer, false); return is_feas; } From 90c1696838050bd9aac0a23a1955cd3bc4bc4610 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 4 Aug 2025 08:50:58 -0700 Subject: [PATCH 07/29] fix feasibility run. 20s LS --- cpp/src/mip/local_search/local_search.cu | 40 ++++++++++++++---------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 4c4a52da07..73aa44972b 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -326,6 +326,25 @@ void local_search_t::resize_vectors(problem_t& problem, fp.resize_vectors(problem, handle_ptr); } +template +void save_best_fp_solution(solution_t& solution, + rmm::device_uvector& best_solution, + f_t& best_objective, + bool feasibility_run) +{ + if (feasibility_run || solution.get_objective() < best_objective) { + CUOPT_LOG_DEBUG("Found better feasible in FP with obj %f. Continue with FJ!", + solution.get_objective()); + best_objective = solution.get_objective(); + raft::copy(best_solution.data(), + solution.assignment.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - + OBJECTIVE_EPSILON); + } +} + template bool local_search_t::run_fp(solution_t& solution, timer_t timer, @@ -364,17 +383,6 @@ bool local_search_t::run_fp(solution_t& solution, } else { CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); - if (solution.get_objective() < best_objective) { - CUOPT_LOG_DEBUG("Found better feasible in FP with obj %f. Continue with FJ!", - solution.get_objective()); - best_objective = solution.get_objective(); - raft::copy(best_solution.data(), - solution.assignment.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - - OBJECTIVE_EPSILON); - } fp.config.alpha = default_alpha; ls_config_t ls_config; // assign current objective @@ -436,18 +444,18 @@ bool local_search_t::run_fp(solution_t& solution, } } } - raft::copy(solution.assignment.data(), - best_solution.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); - solution.handle_ptr->sync_stream(); if (!feasibility_run) { + 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_vectors(*old_problem_ptr, solution.handle_ptr); 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); + solution.handle_ptr->sync_stream(); } return is_feasible; } From 7e859fb498d42bfe46c86c680a3765e375e1d3c3 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 4 Aug 2025 08:51:06 -0700 Subject: [PATCH 08/29] fix feasibility run. 20s LS --- cpp/src/mip/local_search/local_search.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 73aa44972b..750584cd3c 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -119,7 +119,7 @@ bool local_search_t::run_local_search(solution_t& solution, } else { is_feas = run_fj_annealing(solution, timer, ls_config); } - timer = timer_t(std::min(20., timer.remaining_time())); + timer = timer_t(std::min(5., timer.remaining_time())); run_fp(solution, timer, false); return is_feas; } From 5363e79415824add0829b5808feca94ecc98e8c5 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 5 Aug 2025 04:30:35 -0700 Subject: [PATCH 09/29] add as part of the local search --- cpp/src/mip/local_search/local_search.cu | 9 ++++++--- cpp/src/mip/local_search/local_search.cuh | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 750584cd3c..ca954645e9 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -102,25 +102,28 @@ bool local_search_t::run_local_search(solution_t& solution, } } else { fj_settings.time_limit = std::min(10., timer.remaining_time()); + timer = timer_t(std::min(10., timer.remaining_time())); } fj_settings.update_weights = false; fj_settings.feasibility_run = false; fj.set_fj_settings(fj_settings); fj.copy_weights(weights, solution.handle_ptr); bool is_feas; - i_t rd = std::uniform_int_distribution(0, 1)(rng); + i_t rd = std::uniform_int_distribution(0, 2)(rng); if (ls_config.ls_method == ls_method_t::FJ_LINE_SEGMENT) { rd = ls_method_t::FJ_LINE_SEGMENT; } else if (ls_config.ls_method == ls_method_t::FJ_ANNEALING) { rd = ls_method_t::FJ_ANNEALING; + } else if (ls_config.ls_method == ls_method_t::FP_SEARCH) { + rd = ls_method_t::FP_SEARCH; } if (rd == ls_method_t::FJ_LINE_SEGMENT && lp_optimal_exists) { is_feas = run_fj_line_segment(solution, timer, ls_config); + } else if (rd == ls_method_t::FP_SEARCH) { + is_feas = run_fp(solution, timer, false); } else { is_feas = run_fj_annealing(solution, timer, ls_config); } - timer = timer_t(std::min(5., timer.remaining_time())); - run_fp(solution, timer, false); return is_feas; } diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index 6d7b62a161..b8d3e346f2 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -25,7 +25,7 @@ namespace cuopt::linear_programming::detail { -enum ls_method_t { FJ_ANNEALING = 0, FJ_LINE_SEGMENT, RANDOM }; +enum ls_method_t { FJ_ANNEALING = 0, FJ_LINE_SEGMENT, FP_SEARCH, RANDOM }; template struct ls_config_t { From 474d1704e9d205c9c3e2ea31a42c4d3704de7197 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 5 Aug 2025 04:44:43 -0700 Subject: [PATCH 10/29] fp ls with mab --- cpp/src/mip/diversity/diversity_manager.cu | 4 ++-- cpp/src/mip/diversity/multi_armed_bandit.cuh | 23 +++++--------------- cpp/src/mip/local_search/local_search.cuh | 1 + 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 2091c7304b..f4304c95fb 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -113,8 +113,8 @@ bool diversity_manager_t::run_local_search(solution_t& solut timer_t& timer, ls_config_t& ls_config) { - // i_t ls_mab_option = mab_ls.select_mab_option(); - // mab_ls_config_t::get_local_search_and_lm_from_config(ls_mab_option, ls_config); + i_t ls_mab_option = mab_ls.select_mab_option(); + mab_ls_config_t::get_local_search_and_lm_from_config(ls_mab_option, ls_config); assignment_hash_map.insert(solution); constexpr i_t skip_solutions_threshold = 3; if (assignment_hash_map.check_skip_solution(solution, skip_solutions_threshold)) { return false; } diff --git a/cpp/src/mip/diversity/multi_armed_bandit.cuh b/cpp/src/mip/diversity/multi_armed_bandit.cuh index f48601c65d..36f3f7ad8a 100644 --- a/cpp/src/mip/diversity/multi_armed_bandit.cuh +++ b/cpp/src/mip/diversity/multi_armed_bandit.cuh @@ -30,24 +30,13 @@ constexpr double ls_alpha = 0.03; template struct mab_ls_config_t { - static constexpr i_t n_of_ls = 2; - static constexpr i_t n_of_configs = 4; - static constexpr i_t n_of_arms = n_of_ls * n_of_configs; - static constexpr i_t ls_local_mins[n_of_configs] = {50, 100, 200, 500}; - static constexpr i_t ls_line_segment_local_mins[n_of_configs] = {10, 20, 40, 100}; + // RANDOM is the last ls method + static constexpr i_t n_of_arms = ls_method_t::RANDOM; static void get_local_search_and_lm_from_config(i_t config_id, ls_config_t& ls_config) { - ls_method_t local_search = ls_method_t(config_id % n_of_ls); - i_t lm_id = config_id / n_of_ls; - if (local_search == ls_method_t::FJ_LINE_SEGMENT) { - ls_config.ls_method = ls_method_t::FJ_LINE_SEGMENT; - ls_config.n_local_mins_for_line_segment = ls_line_segment_local_mins[lm_id]; - } else { - ls_config.ls_method = ls_method_t::FJ_ANNEALING; - ls_config.n_local_mins = ls_local_mins[lm_id]; - } - mab_ls_config_t::last_lm_config = lm_id; + ls_method_t local_search = ls_method_t(config_id % n_of_arms); + ls_config.ls_method = local_search; mab_ls_config_t::last_ls_mab_option = config_id; } static i_t last_lm_config; @@ -61,11 +50,9 @@ i_t mab_ls_config_t::last_ls_mab_option = 0; struct ls_work_normalized_reward_t { int option_id; - static constexpr double reward_per_option[mab_ls_config_t::n_of_configs] = { - 2, 1, 0.5, 0.25}; ls_work_normalized_reward_t(int option_id) : option_id(option_id) {} - double operator()(double factor) const { return factor * reward_per_option[option_id]; } + double operator()(double factor) const { return factor; } }; struct recombiner_work_normalized_reward_t { diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index b8d3e346f2..527f5d7cd6 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -25,6 +25,7 @@ namespace cuopt::linear_programming::detail { +// make sure RANDOM is always the last enum ls_method_t { FJ_ANNEALING = 0, FJ_LINE_SEGMENT, FP_SEARCH, RANDOM }; template From 06900837a1e3d5dd9a4e4555db8c365137ee97d6 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 5 Aug 2025 06:19:30 -0700 Subject: [PATCH 11/29] try with shorter run time --- cpp/src/mip/local_search/local_search.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index ca954645e9..3ae540f2c2 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -102,7 +102,6 @@ bool local_search_t::run_local_search(solution_t& solution, } } else { fj_settings.time_limit = std::min(10., timer.remaining_time()); - timer = timer_t(std::min(10., timer.remaining_time())); } fj_settings.update_weights = false; fj_settings.feasibility_run = false; @@ -120,6 +119,7 @@ bool local_search_t::run_local_search(solution_t& solution, if (rd == ls_method_t::FJ_LINE_SEGMENT && lp_optimal_exists) { is_feas = run_fj_line_segment(solution, timer, ls_config); } else if (rd == ls_method_t::FP_SEARCH) { + timer = timer_t(std::min(3., timer.remaining_time())); is_feas = run_fp(solution, timer, false); } else { is_feas = run_fj_annealing(solution, timer, ls_config); From 6c02547a2d1b573afb530e9adc4b6eef0fa1ee79 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 6 Aug 2025 02:39:30 -0700 Subject: [PATCH 12/29] tidy up functions and reduce local min to 500 --- cpp/src/mip/local_search/local_search.cu | 75 ++++++++++------------- cpp/src/mip/local_search/local_search.cuh | 7 +++ 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 3ae540f2c2..31ae9b91d2 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -348,6 +348,36 @@ void save_best_fp_solution(solution_t& solution, } } +template +void local_search_t::save_solution_and_add_cutting_plane( + solution_t& solution, rmm::device_uvector& best_solution, f_t& best_objective) +{ + if (solution.get_objective() < best_objective) { + raft::copy(best_solution.data(), + solution.assignment.data(), + solution.assignment.size(), + solution.handle_ptr->get_stream()); + best_objective = solution.get_objective(); + solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - + OBJECTIVE_EPSILON); + } +} + +template +void local_search_t::run_rp_restart(solution_t& solution, + rmm::device_uvector& best_solution, + f_t& best_objective, + timer_t timer) +{ + fp.config.alpha = default_alpha; + ls_config_t ls_config; + // assign current objective + ls_config.best_objective_of_parents = solution.get_objective(); + ls_config.n_local_mins = 500; + bool is_feasible = run_fj_annealing(solution, timer, ls_config); + if (is_feasible) { save_solution_and_add_cutting_plane(solution, best_solution, best_objective); } +} + template bool local_search_t::run_fp(solution_t& solution, timer_t timer, @@ -386,21 +416,8 @@ bool local_search_t::run_fp(solution_t& solution, } else { CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); - fp.config.alpha = default_alpha; - ls_config_t ls_config; - // assign current objective - ls_config.best_objective_of_parents = solution.get_objective(); - ls_config.n_local_mins = 5000; - is_feasible = run_fj_annealing(solution, timer, ls_config); - if (is_feasible && solution.get_objective() < best_objective) { - raft::copy(best_solution.data(), - solution.assignment.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); - best_objective = solution.get_objective(); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - - OBJECTIVE_EPSILON); - } + save_solution_and_add_cutting_plane(solution, best_solution, best_objective); + run_rp_restart(solution, best_solution, best_objective, timer); } } // if not feasible, it means it is a cycle @@ -417,32 +434,8 @@ bool local_search_t::run_fp(solution_t& solution, } else { CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); - if (solution.get_objective() < best_objective) { - CUOPT_LOG_DEBUG("Found better feasible in FP with obj %f. Continue with FJ!", - solution.get_objective()); - best_objective = solution.get_objective(); - raft::copy(best_solution.data(), - solution.assignment.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - - OBJECTIVE_EPSILON); - } - fp.config.alpha = default_alpha; - ls_config_t ls_config; - // assign current objective - ls_config.best_objective_of_parents = solution.get_objective(); - ls_config.n_local_mins = 5000; - is_feasible = run_fj_annealing(solution, timer, ls_config); - if (is_feasible && solution.get_objective() < best_objective) { - raft::copy(best_solution.data(), - solution.assignment.data(), - solution.assignment.size(), - solution.handle_ptr->get_stream()); - best_objective = solution.get_objective(); - solution.problem_ptr->add_cutting_plane_at_objective(solution.get_objective() - - OBJECTIVE_EPSILON); - } + save_solution_and_add_cutting_plane(solution, best_solution, best_objective); + run_rp_restart(solution, best_solution, best_objective, timer); } } } diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index 527f5d7cd6..668c40631a 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -69,6 +69,13 @@ class local_search_t { bool run_staged_fp(solution_t& solution, timer_t timer, bool& early_exit); bool run_fp(solution_t& solution, timer_t timer, bool feasibility_run = true); void resize_vectors(problem_t& problem, const raft::handle_t* handle_ptr); + void save_solution_and_add_cutting_plane(solution_t& solution, + rmm::device_uvector& best_solution, + f_t& best_objective); + void run_rp_restart(solution_t& solution, + rmm::device_uvector& best_solution, + f_t& best_objective, + timer_t timer); mip_solver_context_t& context; rmm::device_uvector& lp_optimal_solution; From 0a176f1b75bd071bbf4a64b49ba36d1dec6b2b06 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 6 Aug 2025 02:49:58 -0700 Subject: [PATCH 13/29] revert cmake comments --- cpp/src/CMakeLists.txt | 2 +- cpp/src/mip/local_search/local_search.cuh | 2 +- cpp/tests/CMakeLists.txt | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index ad68305ee8..18d83f393b 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -19,7 +19,7 @@ set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu add_subdirectory(linear_programming) add_subdirectory(math_optimization) add_subdirectory(mip) -# add_subdirectory(routing) +add_subdirectory(routing) add_subdirectory(dual_simplex) set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${UTIL_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index 668c40631a..fac6c22bb3 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -72,7 +72,7 @@ class local_search_t { void save_solution_and_add_cutting_plane(solution_t& solution, rmm::device_uvector& best_solution, f_t& best_objective); - void run_rp_restart(solution_t& solution, + void run_fp_restart(solution_t& solution, rmm::device_uvector& best_solution, f_t& best_objective, timer_t timer); diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 7b4d610b04..50323dc7e8 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -81,12 +81,12 @@ if(RAPIDS_DATASET_ROOT_DIR) endif(RAPIDS_DATASET_ROOT_DIR) # ## test sources -# add_subdirectory(routing) +add_subdirectory(routing) add_subdirectory(linear_programming) -# add_subdirectory(distance_engine) +add_subdirectory(distance_engine) add_subdirectory(mip) add_subdirectory(dual_simplex) -# add_subdirectory(examples) +add_subdirectory(examples) add_subdirectory(utilities) enable_testing() From e2d0d8b5157f82f3c2e26c525bc5b1bf81e12e9a Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 6 Aug 2025 04:22:21 -0700 Subject: [PATCH 14/29] fix typo --- cpp/src/mip/local_search/local_search.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 31ae9b91d2..2b321f89f0 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -364,7 +364,7 @@ void local_search_t::save_solution_and_add_cutting_plane( } template -void local_search_t::run_rp_restart(solution_t& solution, +void local_search_t::run_fp_restart(solution_t& solution, rmm::device_uvector& best_solution, f_t& best_objective, timer_t timer) From a4c37d68d72b88c611c7148a06c19b92b42a9284 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 6 Aug 2025 05:03:54 -0700 Subject: [PATCH 15/29] fix typo --- cpp/src/mip/local_search/local_search.cu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 2b321f89f0..d3827e601e 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -417,7 +417,7 @@ bool local_search_t::run_fp(solution_t& solution, CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); save_solution_and_add_cutting_plane(solution, best_solution, best_objective); - run_rp_restart(solution, best_solution, best_objective, timer); + run_fp_restart(solution, best_solution, best_objective, timer); } } // if not feasible, it means it is a cycle @@ -435,7 +435,7 @@ bool local_search_t::run_fp(solution_t& solution, CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); save_solution_and_add_cutting_plane(solution, best_solution, best_objective); - run_rp_restart(solution, best_solution, best_objective, timer); + run_fp_restart(solution, best_solution, best_objective, timer); } } } From 49584ed36cb057bb501b74e7efdeff243811e0a8 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 6 Aug 2025 05:14:26 -0700 Subject: [PATCH 16/29] remove the warning in pdlp solve --- cpp/src/linear_programming/solve.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/linear_programming/solve.cu b/cpp/src/linear_programming/solve.cu index c069859978..d0e625b7c9 100644 --- a/cpp/src/linear_programming/solve.cu +++ b/cpp/src/linear_programming/solve.cu @@ -718,7 +718,7 @@ optimization_problem_solution_t solve_lp( const optimization_problem_t& op_problem, \ detail::problem_t& problem, \ pdlp_solver_settings_t const& settings, \ - bool is_batch_mode = false); \ + bool is_batch_mode); \ \ template optimization_problem_t mps_data_model_to_optimization_problem( \ raft::handle_t const* handle_ptr, \ From 5ea08e8b1d556bb46e705d701d8a74e981b8a6c3 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Thu, 7 Aug 2025 05:30:18 -0700 Subject: [PATCH 17/29] handle review comments --- cpp/src/CMakeLists.txt | 2 +- cpp/src/mip/diversity/multi_armed_bandit.cuh | 2 +- .../mip/feasibility_jump/feasibility_jump.cu | 13 +++++-- cpp/src/mip/local_search/local_search.cu | 3 +- cpp/src/mip/local_search/local_search.cuh | 8 +++- cpp/src/mip/problem/problem.cu | 37 ++++++++++++------- cpp/src/mip/problem/problem.cuh | 1 + cpp/tests/CMakeLists.txt | 6 +-- 8 files changed, 47 insertions(+), 25 deletions(-) diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 18d83f393b..ad68305ee8 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -19,7 +19,7 @@ set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu add_subdirectory(linear_programming) add_subdirectory(math_optimization) add_subdirectory(mip) -add_subdirectory(routing) +# add_subdirectory(routing) add_subdirectory(dual_simplex) set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${UTIL_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/mip/diversity/multi_armed_bandit.cuh b/cpp/src/mip/diversity/multi_armed_bandit.cuh index 36f3f7ad8a..7b1cac6978 100644 --- a/cpp/src/mip/diversity/multi_armed_bandit.cuh +++ b/cpp/src/mip/diversity/multi_armed_bandit.cuh @@ -31,7 +31,7 @@ constexpr double ls_alpha = 0.03; template struct mab_ls_config_t { // RANDOM is the last ls method - static constexpr i_t n_of_arms = ls_method_t::RANDOM; + static constexpr i_t n_of_arms = static_cast(ls_method_t::LS_METHODS_SIZE); static void get_local_search_and_lm_from_config(i_t config_id, ls_config_t& ls_config) { diff --git a/cpp/src/mip/feasibility_jump/feasibility_jump.cu b/cpp/src/mip/feasibility_jump/feasibility_jump.cu index a0e3990100..022c469c6a 100644 --- a/cpp/src/mip/feasibility_jump/feasibility_jump.cu +++ b/cpp/src/mip/feasibility_jump/feasibility_jump.cu @@ -241,11 +241,16 @@ template void fj_t::copy_weights(const weight_t& weights, const raft::handle_t* handle_ptr) { + i_t old_size = cstr_weights.size(); cstr_weights.resize(weights.cstr_weights.size(), handle_ptr->get_stream()); - raft::copy(cstr_weights.data(), - weights.cstr_weights.data(), - weights.cstr_weights.size(), - handle_ptr->get_stream()); + thrust::for_each(handle_ptr->get_thrust_policy(), + thrust::counting_iterator(0), + thrust::counting_iterator(weights.cstr_weights.size()), + [old_size, + fj_weights = make_span(cstr_weights), + new_weights = make_span(weights.cstr_weights)] __device__(i_t idx) { + fj_weights[idx] = idx >= old_size ? 1. : new_weights[idx]; + }); thrust::transform(handle_ptr->get_thrust_policy(), weights.objective_weight.data(), weights.objective_weight.data() + 1, diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index d3827e601e..ffd70a812c 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -108,7 +108,8 @@ bool local_search_t::run_local_search(solution_t& solution, fj.set_fj_settings(fj_settings); fj.copy_weights(weights, solution.handle_ptr); bool is_feas; - i_t rd = std::uniform_int_distribution(0, 2)(rng); + ls_method_t rd = static_cast(std::uniform_int_distribution( + static_cast(ls_method_t::FJ_LINE_SEGMENT), static_cast(ls_method_t::FP_SEARCH))(rng)); if (ls_config.ls_method == ls_method_t::FJ_LINE_SEGMENT) { rd = ls_method_t::FJ_LINE_SEGMENT; } else if (ls_config.ls_method == ls_method_t::FJ_ANNEALING) { diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index fac6c22bb3..b6712e61ed 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -26,7 +26,13 @@ namespace cuopt::linear_programming::detail { // make sure RANDOM is always the last -enum ls_method_t { FJ_ANNEALING = 0, FJ_LINE_SEGMENT, FP_SEARCH, RANDOM }; +enum class ls_method_t : int { + FJ_ANNEALING = 0, + FJ_LINE_SEGMENT, + FP_SEARCH, + RANDOM, + LS_METHODS_SIZE = RANDOM +}; template struct ls_config_t { diff --git a/cpp/src/mip/problem/problem.cu b/cpp/src/mip/problem/problem.cu index ec9f45b232..3ffc90833a 100644 --- a/cpp/src/mip/problem/problem.cu +++ b/cpp/src/mip/problem/problem.cu @@ -92,8 +92,8 @@ void problem_t::op_problem_cstr_body(const optimization_problem_tget_stream()); compute_n_integer_vars(); compute_binary_var_table(); + compute_vars_with_objective_coeffs(); } - compute_transpose_of_problem(); // Check after modifications check_problem_representation(true, is_mip); @@ -716,7 +716,7 @@ void problem_t::recompute_auxilliary_data(bool check_representation) { compute_n_integer_vars(); compute_binary_var_table(); - + compute_vars_with_objective_coeffs(); // TODO: speedup compute related variables const double time_limit = 30.; compute_related_variables(time_limit); @@ -999,6 +999,7 @@ void problem_t::insert_variables(variables_delta_t& h_vars) compute_n_integer_vars(); compute_binary_var_table(); + compute_vars_with_objective_coeffs(); } // note that these don't change the reverse structure @@ -1590,6 +1591,21 @@ f_t problem_t::get_user_obj_from_solver_obj(f_t solver_obj) return presolve_data.objective_scaling_factor * (solver_obj + presolve_data.objective_offset); } +template +void problem_t::compute_vars_with_objective_coeffs() +{ + auto h_objective_coefficients = cuopt::host_copy(objective_coefficients); + std::vector vars_with_objective_coeffs_; + std::vector objective_coeffs_; + for (i_t i = 0; i < pb.n_variables; ++i) { + if (h_objective_coefficients[i] != 0) { + vars_with_objective_coeffs_.push_back(i); + objective_coeffs_.push_back(h_objective_coefficients[i]); + } + } + vars_with_objective_coeffs = std::make_pair(vars_with_objective_coeffs_, objective_coeffs_); +} + template void problem_t::add_cutting_plane_at_objective(f_t objective) { @@ -1602,20 +1618,13 @@ void problem_t::add_cutting_plane_at_objective(f_t objective) } cutting_plane_added = true; constraints_delta_t h_constraints; - auto h_objective_coefficients = cuopt::host_copy(objective_coefficients); - handle_ptr->sync_stream(); - std::vector var_indices; - std::vector constr_coeffs; - for (i_t i = 0; i < n_variables; ++i) { - if (h_objective_coefficients[i] != 0) { - var_indices.push_back(i); - constr_coeffs.push_back(h_objective_coefficients[i]); - } - } - h_constraints.add_constraint( - var_indices, constr_coeffs, -std::numeric_limits::infinity(), objective); + h_constraints.add_constraint(vars_with_objective_coeffs.first, + vars_with_objective_coeffs.second, + -std::numeric_limits::infinity(), + objective); insert_constraints(h_constraints); compute_transpose_of_problem(); + cuopt_func_call(check_problem_representation(true)); } #if MIP_INSTANTIATE_FLOAT diff --git a/cpp/src/mip/problem/problem.cuh b/cpp/src/mip/problem/problem.cuh index 3fcb6b1e24..37e94066c1 100644 --- a/cpp/src/mip/problem/problem.cuh +++ b/cpp/src/mip/problem/problem.cuh @@ -274,6 +274,7 @@ class problem_t { lp_state_t lp_state; problem_fixing_helpers_t fixing_helpers; bool cutting_plane_added{false}; + std::pair, std::vector> vars_with_objective_coeffs; }; } // namespace linear_programming::detail diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 50323dc7e8..7b4d610b04 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -81,12 +81,12 @@ if(RAPIDS_DATASET_ROOT_DIR) endif(RAPIDS_DATASET_ROOT_DIR) # ## test sources -add_subdirectory(routing) +# add_subdirectory(routing) add_subdirectory(linear_programming) -add_subdirectory(distance_engine) +# add_subdirectory(distance_engine) add_subdirectory(mip) add_subdirectory(dual_simplex) -add_subdirectory(examples) +# add_subdirectory(examples) add_subdirectory(utilities) enable_testing() From 85820e0b21fb3fbcc78df82b5b5cb79a1e1b7c54 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Thu, 7 Aug 2025 06:47:03 -0700 Subject: [PATCH 18/29] handle review comments --- cpp/src/CMakeLists.txt | 2 +- cpp/src/mip/local_search/local_search.cu | 1 + cpp/src/mip/problem/problem.cu | 2 +- cpp/src/mip/problem/problem.cuh | 1 + cpp/tests/CMakeLists.txt | 6 +++--- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index ad68305ee8..18d83f393b 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -19,7 +19,7 @@ set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu add_subdirectory(linear_programming) add_subdirectory(math_optimization) add_subdirectory(mip) -# add_subdirectory(routing) +add_subdirectory(routing) add_subdirectory(dual_simplex) set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${UTIL_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index ffd70a812c..939b2a120d 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -390,6 +390,7 @@ bool local_search_t::run_fp(solution_t& solution, rmm::device_uvector best_solution(solution.assignment, solution.handle_ptr->get_stream()); problem_t* old_problem_ptr = solution.problem_ptr; if (!feasibility_run) { + // if it has not been initialized yet, create a new problem and move it to the cut problem if (!problem_with_objective_cut.cutting_plane_added) { problem_with_objective_cut = std::move(problem_t(*old_problem_ptr)); } diff --git a/cpp/src/mip/problem/problem.cu b/cpp/src/mip/problem/problem.cu index 3ffc90833a..bc9c0392c6 100644 --- a/cpp/src/mip/problem/problem.cu +++ b/cpp/src/mip/problem/problem.cu @@ -1597,7 +1597,7 @@ void problem_t::compute_vars_with_objective_coeffs() auto h_objective_coefficients = cuopt::host_copy(objective_coefficients); std::vector vars_with_objective_coeffs_; std::vector objective_coeffs_; - for (i_t i = 0; i < pb.n_variables; ++i) { + for (i_t i = 0; i < n_variables; ++i) { if (h_objective_coefficients[i] != 0) { vars_with_objective_coeffs_.push_back(i); objective_coeffs_.push_back(h_objective_coefficients[i]); diff --git a/cpp/src/mip/problem/problem.cuh b/cpp/src/mip/problem/problem.cuh index 37e94066c1..d8b57ac6f3 100644 --- a/cpp/src/mip/problem/problem.cuh +++ b/cpp/src/mip/problem/problem.cuh @@ -113,6 +113,7 @@ class problem_t { void write_as_mps(const std::string& path); void add_cutting_plane_at_objective(f_t objective); + void compute_vars_with_objective_coeffs(); struct view_t { DI std::pair reverse_range_for_var(i_t v) const diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 7b4d610b04..50323dc7e8 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -81,12 +81,12 @@ if(RAPIDS_DATASET_ROOT_DIR) endif(RAPIDS_DATASET_ROOT_DIR) # ## test sources -# add_subdirectory(routing) +add_subdirectory(routing) add_subdirectory(linear_programming) -# add_subdirectory(distance_engine) +add_subdirectory(distance_engine) add_subdirectory(mip) add_subdirectory(dual_simplex) -# add_subdirectory(examples) +add_subdirectory(examples) add_subdirectory(utilities) enable_testing() From 4437481bd6f93a93b5df2fdadb40f9cad91e116b Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 8 Aug 2025 03:42:15 -0700 Subject: [PATCH 19/29] try without fp --- cpp/src/mip/local_search/local_search.cu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 939b2a120d..30e7689a76 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -120,8 +120,8 @@ bool local_search_t::run_local_search(solution_t& solution, if (rd == ls_method_t::FJ_LINE_SEGMENT && lp_optimal_exists) { is_feas = run_fj_line_segment(solution, timer, ls_config); } else if (rd == ls_method_t::FP_SEARCH) { - timer = timer_t(std::min(3., timer.remaining_time())); - is_feas = run_fp(solution, timer, false); + timer = timer_t(std::min(3., timer.remaining_time())); + // is_feas = run_fp(solution, timer, false); } else { is_feas = run_fj_annealing(solution, timer, ls_config); } From c0b0a216273f4b7c4f7c2f0ebff58f929be163e8 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 8 Aug 2025 06:45:43 -0700 Subject: [PATCH 20/29] fix warning --- cpp/src/mip/local_search/local_search.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 30e7689a76..269e077b98 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -107,7 +107,7 @@ bool local_search_t::run_local_search(solution_t& solution, fj_settings.feasibility_run = false; fj.set_fj_settings(fj_settings); fj.copy_weights(weights, solution.handle_ptr); - bool is_feas; + bool is_feas = false; ls_method_t rd = static_cast(std::uniform_int_distribution( static_cast(ls_method_t::FJ_LINE_SEGMENT), static_cast(ls_method_t::FP_SEARCH))(rng)); if (ls_config.ls_method == ls_method_t::FJ_LINE_SEGMENT) { From ebb4958b4f24b62457b91b51e8e93452473edfa4 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 11 Aug 2025 06:44:26 -0700 Subject: [PATCH 21/29] enable lp and probing cache --- cpp/src/mip/diversity/diversity_manager.cu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index f4304c95fb..5c1f3c8371 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -428,7 +428,7 @@ solution_t diversity_manager_t::run_solver() std::min(max_time_on_probing, time_limit * time_ratio_of_probing_cache); timer_t probing_timer{time_for_probing_cache}; if (check_b_b_preemption()) { return population.best_feasible(); } - if (!fj_only_run && !fp_only_run) { + if (!fj_only_run) { compute_probing_cache(ls.constraint_prop.bounds_update, *problem_ptr, probing_timer); } // careful, assign the correct probing cache @@ -446,7 +446,7 @@ solution_t diversity_manager_t::run_solver() } // Mutex is unlocked here if (bb_thread_solution_exists) { ls.lp_optimal_exists = true; - } else if (!fj_only_run && !fp_only_run) { + } else if (!fj_only_run) { relaxed_lp_settings_t lp_settings; lp_settings.time_limit = lp_time_limit; lp_settings.tolerance = context.settings.tolerances.absolute_tolerance; From 54afd53c645851789fbf734e9f2c9f590bfa32b2 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Thu, 14 Aug 2025 05:53:39 -0700 Subject: [PATCH 22/29] fix issues including the objective cut not being on copy constructor --- .../linear_programming/cuopt/run_mip.cpp | 12 +++---- cpp/src/mip/diversity/diversity_manager.cu | 2 +- .../feasibility_pump/feasibility_pump.cu | 5 +-- cpp/src/mip/local_search/local_search.cu | 34 ++++++++++--------- cpp/src/mip/local_search/local_search.cuh | 8 ++--- cpp/src/mip/problem/problem.cu | 6 ++-- cpp/src/mip/solve.cu | 4 +-- 7 files changed, 38 insertions(+), 33 deletions(-) diff --git a/benchmarks/linear_programming/cuopt/run_mip.cpp b/benchmarks/linear_programming/cuopt/run_mip.cpp index b20ae26ea6..a45104bed3 100644 --- a/benchmarks/linear_programming/cuopt/run_mip.cpp +++ b/benchmarks/linear_programming/cuopt/run_mip.cpp @@ -201,12 +201,12 @@ int run_single_file(std::string file_path, } } - settings.time_limit = time_limit; - settings.heuristics_only = heuristics_only; - settings.num_cpu_threads = num_cpu_threads; - settings.log_to_console = log_to_console; - // settings.tolerances.relative_tolerance = 1e-10; - // settings.tolerances.absolute_tolerance = 1e-6; + settings.time_limit = time_limit; + settings.heuristics_only = heuristics_only; + settings.num_cpu_threads = num_cpu_threads; + settings.log_to_console = log_to_console; + settings.tolerances.relative_tolerance = 1e-12; + settings.tolerances.absolute_tolerance = 1e-6; cuopt::linear_programming::benchmark_info_t benchmark_info; settings.benchmark_info_ptr = &benchmark_info; auto start_run_solver = std::chrono::high_resolution_clock::now(); diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 5c1f3c8371..7f63e75fe0 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -28,7 +28,7 @@ constexpr bool from_dir = false; constexpr bool fj_only_run = false; -constexpr bool fp_only_run = false; +constexpr bool fp_only_run = true; namespace cuopt::linear_programming::detail { diff --git a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu index 5f421f1052..8286d8148e 100644 --- a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu +++ b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu @@ -288,7 +288,7 @@ bool feasibility_pump_t::run_fj_cycle_escape(solution_t& sol bool is_feasible; fj.settings.mode = fj_mode_t::EXIT_NON_IMPROVING; fj.settings.update_weights = true; - fj.settings.feasibility_run = true; + fj.settings.feasibility_run = false; fj.settings.n_of_minimums_for_exit = 5000; fj.settings.time_limit = std::min(3., timer.remaining_time()); is_feasible = fj.solve(solution); @@ -344,9 +344,10 @@ bool feasibility_pump_t::handle_cycle(solution_t& solution) cuopt_assert(solution.test_number_all_integer(), "All must be integers before fj"); is_feasible = run_fj_cycle_escape(solution); cuopt_assert(solution.test_number_all_integer(), "All must be integers after fj"); - if (!is_feasible && cycle_queue.check_cycle(solution)) { + if (cycle_queue.check_cycle(solution)) { CUOPT_LOG_DEBUG("Cycle couldn't be broken. Perturbating FP"); perturbate(solution); + is_feasible = solution.get_feasible(); } cycle_queue.n_iterations_without_cycle = 0; cycle_queue.update_recent_solutions(solution); diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 269e077b98..c82ff6076f 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -226,7 +226,7 @@ bool local_search_t::check_fj_on_lp_optimal(solution_t& solu fj.settings.mode = fj_mode_t::EXIT_NON_IMPROVING; fj.settings.n_of_minimums_for_exit = 20000; fj.settings.update_weights = true; - fj.settings.feasibility_run = true; + fj.settings.feasibility_run = false; fj.settings.time_limit = std::min(30., timer.remaining_time()); fj.solve(solution); return solution.get_feasible(); @@ -243,7 +243,7 @@ bool local_search_t::run_fj_on_zero(solution_t& solution, ti fj.settings.mode = fj_mode_t::EXIT_NON_IMPROVING; fj.settings.n_of_minimums_for_exit = 20000; fj.settings.update_weights = true; - fj.settings.feasibility_run = true; + fj.settings.feasibility_run = false; fj.settings.time_limit = std::min(30., timer.remaining_time()); bool is_feasible = fj.solve(solution); return is_feasible; @@ -365,18 +365,19 @@ void local_search_t::save_solution_and_add_cutting_plane( } template -void local_search_t::run_fp_restart(solution_t& solution, - rmm::device_uvector& best_solution, - f_t& best_objective, - timer_t timer) +void local_search_t::run_fj_and_add_cutting_plane(solution_t& solution, + rmm::device_uvector& best_solution, + f_t& best_objective, + timer_t timer) { fp.config.alpha = default_alpha; - ls_config_t ls_config; - // assign current objective - ls_config.best_objective_of_parents = solution.get_objective(); - ls_config.n_local_mins = 500; - bool is_feasible = run_fj_annealing(solution, timer, ls_config); - if (is_feasible) { save_solution_and_add_cutting_plane(solution, best_solution, best_objective); } + // ls_config_t ls_config; + // // assign current objective + // ls_config.best_objective_of_parents = solution.get_objective(); + // ls_config.n_local_mins = 500; + // bool is_feasible = run_fj_annealing(solution, timer, ls_config); + // if (is_feasible) { save_solution_and_add_cutting_plane(solution, best_solution, + // best_objective); } } template @@ -385,10 +386,11 @@ bool local_search_t::run_fp(solution_t& solution, bool feasibility_run) { const i_t n_fp_iterations = 1000000; - bool is_feasible = false; - double best_objective = std::numeric_limits::max(); + bool is_feasible = solution.compute_feasibility(); + double best_objective = solution.get_objective(); 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 (!feasibility_run) { // if it has not been initialized yet, create a new problem and move it to the cut problem if (!problem_with_objective_cut.cutting_plane_added) { @@ -419,7 +421,7 @@ bool local_search_t::run_fp(solution_t& solution, CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); save_solution_and_add_cutting_plane(solution, best_solution, best_objective); - run_fp_restart(solution, best_solution, best_objective, timer); + run_fj_and_add_cutting_plane(solution, best_solution, best_objective, timer); } } // if not feasible, it means it is a cycle @@ -437,7 +439,7 @@ bool local_search_t::run_fp(solution_t& solution, CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); save_solution_and_add_cutting_plane(solution, best_solution, best_objective); - run_fp_restart(solution, best_solution, best_objective, timer); + run_fj_and_add_cutting_plane(solution, best_solution, best_objective, timer); } } } diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index b6712e61ed..1b904807aa 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -78,10 +78,10 @@ class local_search_t { void save_solution_and_add_cutting_plane(solution_t& solution, rmm::device_uvector& best_solution, f_t& best_objective); - void run_fp_restart(solution_t& solution, - rmm::device_uvector& best_solution, - f_t& best_objective, - timer_t timer); + void run_fj_and_add_cutting_plane(solution_t& solution, + rmm::device_uvector& best_solution, + f_t& best_objective, + timer_t timer); mip_solver_context_t& context; rmm::device_uvector& lp_optimal_solution; diff --git a/cpp/src/mip/problem/problem.cu b/cpp/src/mip/problem/problem.cu index bc9c0392c6..b3ca958d2d 100644 --- a/cpp/src/mip/problem/problem.cu +++ b/cpp/src/mip/problem/problem.cu @@ -193,7 +193,8 @@ problem_t::problem_t(const problem_t& problem_) is_scaled_(problem_.is_scaled_), preprocess_called(problem_.preprocess_called), lp_state(problem_.lp_state), - fixing_helpers(problem_.fixing_helpers, handle_ptr) + fixing_helpers(problem_.fixing_helpers, handle_ptr), + vars_with_objective_coeffs(problem_.vars_with_objective_coeffs) { } @@ -291,7 +292,8 @@ problem_t::problem_t(const problem_t& problem_, bool no_deep is_scaled_(problem_.is_scaled_), preprocess_called(problem_.preprocess_called), lp_state(problem_.lp_state), - fixing_helpers(problem_.fixing_helpers, handle_ptr) + fixing_helpers(problem_.fixing_helpers, handle_ptr), + vars_with_objective_coeffs(problem_.vars_with_objective_coeffs) { } diff --git a/cpp/src/mip/solve.cu b/cpp/src/mip/solve.cu index 841770c4db..fc153bfc7d 100644 --- a/cpp/src/mip/solve.cu +++ b/cpp/src/mip/solve.cu @@ -67,8 +67,8 @@ template mip_solution_t run_mip(detail::problem_t& problem, mip_solver_settings_t const& settings) { - const f_t time_limit = - settings.time_limit == 0 ? std::numeric_limits::max() : settings.time_limit; + constexpr f_t max_time_limit = 1000000000; + const f_t time_limit = settings.time_limit == 0 ? max_time_limit : settings.time_limit; if (settings.heuristics_only && time_limit == std::numeric_limits::max()) { CUOPT_LOG_ERROR("Time limit cannot be infinity when heuristics only is set"); cuopt_expects(false, From df34a0119d8c2a998446c8eeec2368c9e06e9e38 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 15 Aug 2025 08:44:53 -0700 Subject: [PATCH 23/29] without probing cache --- 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 7f63e75fe0..e4ec47c64a 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -429,7 +429,7 @@ solution_t diversity_manager_t::run_solver() timer_t probing_timer{time_for_probing_cache}; if (check_b_b_preemption()) { return population.best_feasible(); } if (!fj_only_run) { - compute_probing_cache(ls.constraint_prop.bounds_update, *problem_ptr, probing_timer); + // compute_probing_cache(ls.constraint_prop.bounds_update, *problem_ptr, probing_timer); } // careful, assign the correct probing cache ls.lb_constraint_prop.bounds_update.probing_cache.probing_cache = From 5ebb86c4b2d395b7a0da9409b2a30bb0bf7ccca5 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 15 Aug 2025 08:51:17 -0700 Subject: [PATCH 24/29] nearest rounding --- cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu index 8286d8148e..0c9731bbb8 100644 --- a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu +++ b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu @@ -262,7 +262,8 @@ bool feasibility_pump_t::round(solution_t& solution) CUOPT_LOG_DEBUG("Rounding the point"); timer_t bounds_prop_timer(std::min(2., timer.remaining_time())); const f_t lp_run_time_after_feasible = std::min(3., timer.remaining_time() / 20.); - result = constraint_prop.apply_round(solution, lp_run_time_after_feasible, bounds_prop_timer); + // result = constraint_prop.apply_round(solution, lp_run_time_after_feasible, bounds_prop_timer); + result = solution.round_nearest(); cuopt_func_call(solution.test_variable_bounds(true)); // copy the last rounding raft::copy(last_rounding.data(), From 57b1b9dfbefb4ab64426cf95511bdd3829d0d2d8 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Fri, 15 Aug 2025 08:53:07 -0700 Subject: [PATCH 25/29] FJ alone run --- cpp/src/mip/diversity/diversity_manager.cu | 6 +++--- .../mip/local_search/feasibility_pump/feasibility_pump.cu | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index e4ec47c64a..52d06f6d06 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -27,8 +27,8 @@ #include "cuda_profiler_api.h" constexpr bool from_dir = false; -constexpr bool fj_only_run = false; -constexpr bool fp_only_run = true; +constexpr bool fj_only_run = true; +constexpr bool fp_only_run = false; namespace cuopt::linear_programming::detail { @@ -429,7 +429,7 @@ solution_t diversity_manager_t::run_solver() timer_t probing_timer{time_for_probing_cache}; if (check_b_b_preemption()) { return population.best_feasible(); } if (!fj_only_run) { - // compute_probing_cache(ls.constraint_prop.bounds_update, *problem_ptr, probing_timer); + compute_probing_cache(ls.constraint_prop.bounds_update, *problem_ptr, probing_timer); } // careful, assign the correct probing cache ls.lb_constraint_prop.bounds_update.probing_cache.probing_cache = diff --git a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu index 0c9731bbb8..8286d8148e 100644 --- a/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu +++ b/cpp/src/mip/local_search/feasibility_pump/feasibility_pump.cu @@ -262,8 +262,7 @@ bool feasibility_pump_t::round(solution_t& solution) CUOPT_LOG_DEBUG("Rounding the point"); timer_t bounds_prop_timer(std::min(2., timer.remaining_time())); const f_t lp_run_time_after_feasible = std::min(3., timer.remaining_time() / 20.); - // result = constraint_prop.apply_round(solution, lp_run_time_after_feasible, bounds_prop_timer); - result = solution.round_nearest(); + result = constraint_prop.apply_round(solution, lp_run_time_after_feasible, bounds_prop_timer); cuopt_func_call(solution.test_variable_bounds(true)); // copy the last rounding raft::copy(last_rounding.data(), From ee861a22656ad40f702696c3418a9decc038670f Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Mon, 18 Aug 2025 04:47:11 -0700 Subject: [PATCH 26/29] remove unnecessary function --- cpp/src/mip/diversity/diversity_manager.cu | 3 +-- cpp/src/mip/local_search/local_search.cu | 24 ++++------------------ cpp/src/mip/local_search/local_search.cuh | 4 ---- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index 52d06f6d06..526561c30a 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -27,7 +27,7 @@ #include "cuda_profiler_api.h" constexpr bool from_dir = false; -constexpr bool fj_only_run = true; +constexpr bool fj_only_run = false; constexpr bool fp_only_run = false; namespace cuopt::linear_programming::detail { @@ -323,7 +323,6 @@ bool diversity_manager_t::run_presolve(f_t time_limit) stats.presolve_time = presolve_timer.elapsed_time(); lp_optimal_solution.resize(problem_ptr->n_variables, problem_ptr->handle_ptr->get_stream()); problem_ptr->handle_ptr->sync_stream(); - cudaDeviceSynchronize(); return true; } diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index c82ff6076f..5bc153cd47 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -120,8 +120,8 @@ bool local_search_t::run_local_search(solution_t& solution, if (rd == ls_method_t::FJ_LINE_SEGMENT && lp_optimal_exists) { is_feas = run_fj_line_segment(solution, timer, ls_config); } else if (rd == ls_method_t::FP_SEARCH) { - timer = timer_t(std::min(3., timer.remaining_time())); - // is_feas = run_fp(solution, timer, false); + timer = timer_t(std::min(3., timer.remaining_time())); + is_feas = run_fp(solution, timer, false); } else { is_feas = run_fj_annealing(solution, timer, ls_config); } @@ -364,22 +364,6 @@ void local_search_t::save_solution_and_add_cutting_plane( } } -template -void local_search_t::run_fj_and_add_cutting_plane(solution_t& solution, - rmm::device_uvector& best_solution, - f_t& best_objective, - timer_t timer) -{ - fp.config.alpha = default_alpha; - // ls_config_t ls_config; - // // assign current objective - // ls_config.best_objective_of_parents = solution.get_objective(); - // ls_config.n_local_mins = 500; - // bool is_feasible = run_fj_annealing(solution, timer, ls_config); - // if (is_feasible) { save_solution_and_add_cutting_plane(solution, best_solution, - // best_objective); } -} - template bool local_search_t::run_fp(solution_t& solution, timer_t timer, @@ -421,7 +405,7 @@ bool local_search_t::run_fp(solution_t& solution, CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); save_solution_and_add_cutting_plane(solution, best_solution, best_objective); - run_fj_and_add_cutting_plane(solution, best_solution, best_objective, timer); + fp.config.alpha = default_alpha; } } // if not feasible, it means it is a cycle @@ -439,7 +423,7 @@ bool local_search_t::run_fp(solution_t& solution, CUOPT_LOG_DEBUG("Found feasible in FP with obj %f. Continue with FJ!", solution.get_objective()); save_solution_and_add_cutting_plane(solution, best_solution, best_objective); - run_fj_and_add_cutting_plane(solution, best_solution, best_objective, timer); + fp.config.alpha = default_alpha; } } } diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index 1b904807aa..fc0a398148 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -78,10 +78,6 @@ class local_search_t { void save_solution_and_add_cutting_plane(solution_t& solution, rmm::device_uvector& best_solution, f_t& best_objective); - void run_fj_and_add_cutting_plane(solution_t& solution, - rmm::device_uvector& best_solution, - f_t& best_objective, - timer_t timer); mip_solver_context_t& context; rmm::device_uvector& lp_optimal_solution; From cc21c3d9bd3dd946f49d4d6a3a2f6cd842d27368 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 19 Aug 2025 03:15:24 -0700 Subject: [PATCH 27/29] add assert --- cpp/src/mip/feasibility_jump/feasibility_jump.cu | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/src/mip/feasibility_jump/feasibility_jump.cu b/cpp/src/mip/feasibility_jump/feasibility_jump.cu index 022c469c6a..e70dcb090e 100644 --- a/cpp/src/mip/feasibility_jump/feasibility_jump.cu +++ b/cpp/src/mip/feasibility_jump/feasibility_jump.cu @@ -250,6 +250,7 @@ void fj_t::copy_weights(const weight_t& weights, fj_weights = make_span(cstr_weights), new_weights = make_span(weights.cstr_weights)] __device__(i_t idx) { fj_weights[idx] = idx >= old_size ? 1. : new_weights[idx]; + cuopt_assert(isfinite(fj_weights[idx]), "invalid weight"); }); thrust::transform(handle_ptr->get_thrust_policy(), weights.objective_weight.data(), From 9821f038104ca6b3586d1a1118242f841e79c5b4 Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Tue, 19 Aug 2025 05:08:05 -0700 Subject: [PATCH 28/29] handle weight issue on fj with changed size --- cpp/src/mip/diversity/diversity_manager.cu | 2 +- .../mip/feasibility_jump/feasibility_jump.cu | 24 ++++++++++++++----- .../mip/feasibility_jump/feasibility_jump.cuh | 4 +++- cpp/src/mip/local_search/local_search.cu | 8 +++++-- cpp/src/mip/local_search/local_search.cuh | 5 +++- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index ebdad2e993..e0d96d447c 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -387,7 +387,7 @@ template void diversity_manager_t::run_fp_alone(solution_t& solution) { CUOPT_LOG_INFO("Running FP alone!"); - ls.run_fp(solution, timer, false); + ls.run_fp(solution, timer, &population.weights, false); CUOPT_LOG_INFO("FP alone finished!"); } diff --git a/cpp/src/mip/feasibility_jump/feasibility_jump.cu b/cpp/src/mip/feasibility_jump/feasibility_jump.cu index e70dcb090e..8e864dcf20 100644 --- a/cpp/src/mip/feasibility_jump/feasibility_jump.cu +++ b/cpp/src/mip/feasibility_jump/feasibility_jump.cu @@ -239,18 +239,30 @@ void fj_t::populate_climber_views() template void fj_t::copy_weights(const weight_t& weights, - const raft::handle_t* handle_ptr) + const raft::handle_t* handle_ptr, + std::optional new_size) { - i_t old_size = cstr_weights.size(); - cstr_weights.resize(weights.cstr_weights.size(), handle_ptr->get_stream()); + i_t old_size = weights.cstr_weights.size(); + cstr_weights.resize(new_size.value_or(weights.cstr_weights.size()), handle_ptr->get_stream()); + cstr_left_weights.resize(new_size.value_or(weights.cstr_weights.size()), + handle_ptr->get_stream()); + cstr_right_weights.resize(new_size.value_or(weights.cstr_weights.size()), + handle_ptr->get_stream()); thrust::for_each(handle_ptr->get_thrust_policy(), thrust::counting_iterator(0), - thrust::counting_iterator(weights.cstr_weights.size()), + thrust::counting_iterator(new_size.value_or(weights.cstr_weights.size())), [old_size, - fj_weights = make_span(cstr_weights), - new_weights = make_span(weights.cstr_weights)] __device__(i_t idx) { + fj_weights = make_span(cstr_weights), + fj_left_weights = make_span(cstr_left_weights), + fj_right_weights = make_span(cstr_right_weights), + new_weights = make_span(weights.cstr_weights)] __device__(i_t idx) { fj_weights[idx] = idx >= old_size ? 1. : new_weights[idx]; + // TODO: ask Alice how we can manage the previous left,right weights + fj_left_weights[idx] = idx >= old_size ? 1. : new_weights[idx]; + fj_right_weights[idx] = idx >= old_size ? 1. : new_weights[idx]; cuopt_assert(isfinite(fj_weights[idx]), "invalid weight"); + cuopt_assert(isfinite(fj_left_weights[idx]), "invalid left weight"); + cuopt_assert(isfinite(fj_right_weights[idx]), "invalid right weight"); }); thrust::transform(handle_ptr->get_thrust_policy(), weights.objective_weight.data(), diff --git a/cpp/src/mip/feasibility_jump/feasibility_jump.cuh b/cpp/src/mip/feasibility_jump/feasibility_jump.cuh index 028b1c8baf..5d362a3d3d 100644 --- a/cpp/src/mip/feasibility_jump/feasibility_jump.cuh +++ b/cpp/src/mip/feasibility_jump/feasibility_jump.cuh @@ -205,7 +205,9 @@ class fj_t { void set_fj_settings(fj_settings_t settings_); void reset_weights(const rmm::cuda_stream_view& stream, f_t weight = 10.); void randomize_weights(const raft::handle_t* handle_ptr); - void copy_weights(const weight_t& weights, const raft::handle_t* handle_ptr); + void copy_weights(const weight_t& weights, + const raft::handle_t* handle_ptr, + std::optional new_size = std::nullopt); i_t host_loop(solution_t& solution, i_t climber_idx = 0); void run_step_device(i_t climber_idx = 0, bool use_graph = true); void run_step_device(const rmm::cuda_stream_view& stream, diff --git a/cpp/src/mip/local_search/local_search.cu b/cpp/src/mip/local_search/local_search.cu index 5bc153cd47..5e39491264 100644 --- a/cpp/src/mip/local_search/local_search.cu +++ b/cpp/src/mip/local_search/local_search.cu @@ -106,7 +106,6 @@ bool local_search_t::run_local_search(solution_t& solution, fj_settings.update_weights = false; fj_settings.feasibility_run = false; fj.set_fj_settings(fj_settings); - fj.copy_weights(weights, solution.handle_ptr); bool is_feas = false; ls_method_t rd = static_cast(std::uniform_int_distribution( static_cast(ls_method_t::FJ_LINE_SEGMENT), static_cast(ls_method_t::FP_SEARCH))(rng)); @@ -118,11 +117,13 @@ bool local_search_t::run_local_search(solution_t& solution, rd = ls_method_t::FP_SEARCH; } if (rd == ls_method_t::FJ_LINE_SEGMENT && lp_optimal_exists) { + fj.copy_weights(weights, solution.handle_ptr); is_feas = run_fj_line_segment(solution, timer, ls_config); } else if (rd == ls_method_t::FP_SEARCH) { timer = timer_t(std::min(3., timer.remaining_time())); - is_feas = run_fp(solution, timer, false); + is_feas = run_fp(solution, timer, &weights, false); } else { + fj.copy_weights(weights, solution.handle_ptr); is_feas = run_fj_annealing(solution, timer, ls_config); } return is_feas; @@ -367,6 +368,7 @@ void local_search_t::save_solution_and_add_cutting_plane( template bool local_search_t::run_fp(solution_t& solution, timer_t timer, + const weight_t* weights, bool feasibility_run) { const i_t n_fp_iterations = 1000000; @@ -382,6 +384,8 @@ bool local_search_t::run_fp(solution_t& solution, } problem_with_objective_cut.add_cutting_plane_at_objective(solution.get_objective() - OBJECTIVE_EPSILON); + // Do the copy here for proper handling of the added constraints weight + fj.copy_weights(*weights, solution.handle_ptr, problem_with_objective_cut.n_constraints); solution.problem_ptr = &problem_with_objective_cut; solution.resize_to_problem(); resize_vectors(problem_with_objective_cut, solution.handle_ptr); diff --git a/cpp/src/mip/local_search/local_search.cuh b/cpp/src/mip/local_search/local_search.cuh index fc0a398148..a2664e890b 100644 --- a/cpp/src/mip/local_search/local_search.cuh +++ b/cpp/src/mip/local_search/local_search.cuh @@ -73,7 +73,10 @@ class local_search_t { bool run_fj_on_zero(solution_t& solution, timer_t timer); bool check_fj_on_lp_optimal(solution_t& solution, bool perturb, timer_t timer); bool run_staged_fp(solution_t& solution, timer_t timer, bool& early_exit); - bool run_fp(solution_t& solution, timer_t timer, bool feasibility_run = true); + bool run_fp(solution_t& solution, + timer_t timer, + const weight_t* weights = nullptr, + bool feasibility_run = true); void resize_vectors(problem_t& problem, const raft::handle_t* handle_ptr); void save_solution_and_add_cutting_plane(solution_t& solution, rmm::device_uvector& best_solution, From f337b1680e01e4727f5beee6b56684bd4830ecea Mon Sep 17 00:00:00 2001 From: akifcorduk Date: Wed, 20 Aug 2025 05:11:10 -0700 Subject: [PATCH 29/29] fix to_repair queue --- cpp/src/dual_simplex/branch_and_bound.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp/src/dual_simplex/branch_and_bound.cpp b/cpp/src/dual_simplex/branch_and_bound.cpp index 9067040129..ecd7488f19 100644 --- a/cpp/src/dual_simplex/branch_and_bound.cpp +++ b/cpp/src/dual_simplex/branch_and_bound.cpp @@ -422,6 +422,10 @@ branch_and_bound_t::branch_and_bound_t( template mip_status_t branch_and_bound_t::solve(mip_solution_t& solution) { + // TODO remove this after submip PR merge + global_variables::mutex_upper.lock(); + global_variables::repair_queue.clear(); + global_variables::mutex_upper.unlock(); mip_status_t status = mip_status_t::UNSET; mip_solution_t incumbent(original_lp.num_cols); if (guess.size() != 0) {