From d0c5a425ca1cc24f9b4cb984bc0090b6a4c38755 Mon Sep 17 00:00:00 2001 From: Alice Boucher Date: Tue, 24 Feb 2026 16:09:51 +0000 Subject: [PATCH 1/3] fix thrust build + more timer checks --- .../diversity/diversity_manager.cu | 26 ++++++++++--------- cpp/src/mip_heuristics/solve.cu | 5 ++++ cpp/src/mip_heuristics/solver.cu | 16 ++++++++++++ cpp/src/pdlp/swap_and_resize_helper.cuh | 1 + cpp/src/pdlp/utils.cuh | 1 + cpp/src/utilities/copy_helpers.hpp | 1 + cpp/src/utilities/cuda_helpers.cuh | 1 + 7 files changed, 39 insertions(+), 12 deletions(-) diff --git a/cpp/src/mip_heuristics/diversity/diversity_manager.cu b/cpp/src/mip_heuristics/diversity/diversity_manager.cu index 25b021ac35..4fa0d3f4ab 100644 --- a/cpp/src/mip_heuristics/diversity/diversity_manager.cu +++ b/cpp/src/mip_heuristics/diversity/diversity_manager.cu @@ -201,18 +201,20 @@ bool diversity_manager_t::run_presolve(f_t time_limit) compute_probing_cache(ls.constraint_prop.bounds_update, *problem_ptr, probing_timer); if (problem_is_infeasible) { return false; } } - const bool remap_cache_ids = true; - trivial_presolve(*problem_ptr, remap_cache_ids); - if (!problem_ptr->empty && !check_bounds_sanity(*problem_ptr)) { return false; } - // May overconstrain if Papilo presolve has been run before - if (context.settings.presolver == presolver_t::None) { - if (!problem_ptr->empty) { - // do the resizing no-matter what, bounds presolve might not change the bounds but initial - // trivial presolve might have - ls.constraint_prop.bounds_update.resize(*problem_ptr); - ls.constraint_prop.conditional_bounds_update.update_constraint_bounds( - *problem_ptr, ls.constraint_prop.bounds_update); - if (!check_bounds_sanity(*problem_ptr)) { return false; } + if (!presolve_timer.check_time_limit()) { + const bool remap_cache_ids = true; + trivial_presolve(*problem_ptr, remap_cache_ids); + if (!problem_ptr->empty && !check_bounds_sanity(*problem_ptr)) { return false; } + // May overconstrain if Papilo presolve has been run before + if (context.settings.presolver == presolver_t::None) { + if (!problem_ptr->empty) { + // do the resizing no-matter what, bounds presolve might not change the bounds but initial + // trivial presolve might have + ls.constraint_prop.bounds_update.resize(*problem_ptr); + ls.constraint_prop.conditional_bounds_update.update_constraint_bounds( + *problem_ptr, ls.constraint_prop.bounds_update); + if (!check_bounds_sanity(*problem_ptr)) { return false; } + } } } stats.presolve_time = presolve_timer.elapsed_time(); diff --git a/cpp/src/mip_heuristics/solve.cu b/cpp/src/mip_heuristics/solve.cu index 41e2729927..3c6ee21a42 100644 --- a/cpp/src/mip_heuristics/solve.cu +++ b/cpp/src/mip_heuristics/solve.cu @@ -153,6 +153,11 @@ mip_solution_t run_mip(detail::problem_t& problem, detail::trivial_presolve(scaled_problem); detail::mip_solver_t solver(scaled_problem, settings, scaling, timer); + if (timer.check_time_limit()) { + CUOPT_LOG_INFO("Time limit reached before main solve"); + detail::solution_t sol(problem); + return sol.get_solution(false, solver.get_solver_stats(), false); + } auto scaled_sol = solver.run_solver(); bool is_feasible_before_scaling = scaled_sol.get_feasible(); scaled_sol.problem_ptr = &problem; diff --git a/cpp/src/mip_heuristics/solver.cu b/cpp/src/mip_heuristics/solver.cu index 3e22511714..235d4500d2 100644 --- a/cpp/src/mip_heuristics/solver.cu +++ b/cpp/src/mip_heuristics/solver.cu @@ -134,6 +134,14 @@ solution_t mip_solver_t::run_solver() return sol; } + if (timer_.check_time_limit()) { + CUOPT_LOG_INFO("Time limit reached after presolve"); + solution_t sol(*context.problem_ptr); + context.stats.total_solve_time = timer_.elapsed_time(); + context.problem_ptr->post_process_solution(sol); + return sol; + } + // if the problem was reduced to a LP: run concurrent LP if (run_presolve && context.problem_ptr->n_integer_vars == 0) { CUOPT_LOG_INFO("Problem reduced to a LP, running concurrent LP"); @@ -285,6 +293,14 @@ solution_t mip_solver_t::run_solver() std::placeholders::_5, std::placeholders::_6); + if (timer_.check_time_limit()) { + CUOPT_LOG_INFO("Time limit reached during B&B setup"); + solution_t sol(*context.problem_ptr); + context.stats.total_solve_time = timer_.elapsed_time(); + context.problem_ptr->post_process_solution(sol); + return sol; + } + // Fork a thread for branch and bound // std::async and std::future allow us to get the return value of bb::solve() // without having to manually manage the thread diff --git a/cpp/src/pdlp/swap_and_resize_helper.cuh b/cpp/src/pdlp/swap_and_resize_helper.cuh index 0d4e2a6d01..6ed05df241 100644 --- a/cpp/src/pdlp/swap_and_resize_helper.cuh +++ b/cpp/src/pdlp/swap_and_resize_helper.cuh @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/cpp/src/pdlp/utils.cuh b/cpp/src/pdlp/utils.cuh index 33625f7680..138c9c2ab9 100644 --- a/cpp/src/pdlp/utils.cuh +++ b/cpp/src/pdlp/utils.cuh @@ -25,6 +25,7 @@ #include #include #include +#include namespace cuopt::linear_programming::detail { diff --git a/cpp/src/utilities/copy_helpers.hpp b/cpp/src/utilities/copy_helpers.hpp index 943ce463a7..36a4659059 100644 --- a/cpp/src/utilities/copy_helpers.hpp +++ b/cpp/src/utilities/copy_helpers.hpp @@ -15,6 +15,7 @@ #include #include +#include #include #include diff --git a/cpp/src/utilities/cuda_helpers.cuh b/cpp/src/utilities/cuda_helpers.cuh index ae50e9967b..946099648d 100644 --- a/cpp/src/utilities/cuda_helpers.cuh +++ b/cpp/src/utilities/cuda_helpers.cuh @@ -10,6 +10,7 @@ #include #include +#include #include #include #include From 67240f57035bde789b1e5512c116c00fd46c5baf Mon Sep 17 00:00:00 2001 From: Alice Boucher Date: Tue, 24 Feb 2026 16:51:09 +0000 Subject: [PATCH 2/3] review comment --- cpp/src/mip_heuristics/solve.cu | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/src/mip_heuristics/solve.cu b/cpp/src/mip_heuristics/solve.cu index 3c6ee21a42..44f0e7468d 100644 --- a/cpp/src/mip_heuristics/solve.cu +++ b/cpp/src/mip_heuristics/solve.cu @@ -156,7 +156,9 @@ mip_solution_t run_mip(detail::problem_t& problem, if (timer.check_time_limit()) { CUOPT_LOG_INFO("Time limit reached before main solve"); detail::solution_t sol(problem); - return sol.get_solution(false, solver.get_solver_stats(), false); + auto stats = solver.get_solver_stats(); + stats.total_solve_time = timer.elapsed_time(); + return sol.get_solution(false, stats, false); } auto scaled_sol = solver.run_solver(); bool is_feasible_before_scaling = scaled_sol.get_feasible(); From a15424fc250b6e649b8b0b0015641d9771c9b426 Mon Sep 17 00:00:00 2001 From: Alice Boucher Date: Tue, 24 Feb 2026 17:02:33 +0000 Subject: [PATCH 3/3] fix thrust solve --- cpp/src/routing/utilities/check_input.cu | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/src/routing/utilities/check_input.cu b/cpp/src/routing/utilities/check_input.cu index b2f035ee5c..e902f2d460 100644 --- a/cpp/src/routing/utilities/check_input.cu +++ b/cpp/src/routing/utilities/check_input.cu @@ -1,6 +1,6 @@ /* clang-format off */ /* - * SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ /* clang-format on */ @@ -17,6 +17,7 @@ #include #include #include +#include #include #include