diff --git a/cpp/src/linear_programming/pdlp.cu b/cpp/src/linear_programming/pdlp.cu index 824539e0ca..9f2de16f00 100644 --- a/cpp/src/linear_programming/pdlp.cu +++ b/cpp/src/linear_programming/pdlp.cu @@ -253,22 +253,14 @@ void pdlp_solver_t::set_initial_dual_solution( initial_dual_.data(), initial_dual_solution.data(), initial_dual_solution.size(), stream_view_); } -static bool time_limit_reached(const std::chrono::high_resolution_clock::time_point& start_time, - double seconds) -{ - auto current_time = std::chrono::high_resolution_clock::now(); - auto elapsed = - std::chrono::duration_cast(current_time - start_time).count(); - - return elapsed >= (seconds * 1000.0); -} +static bool time_limit_reached(const timer_t& timer) { return timer.check_time_limit(); } template std::optional> pdlp_solver_t::check_limits( - const std::chrono::high_resolution_clock::time_point& start_time) + const timer_t& timer) { // Check for time limit - if (time_limit_reached(start_time, settings_.time_limit)) { + if (time_limit_reached(timer)) { if (settings_.save_best_primal_so_far) { #ifdef PDLP_VERBOSE_MODE RAFT_CUDA_TRY(cudaDeviceSynchronize()); @@ -491,14 +483,10 @@ pdlp_warm_start_data_t pdlp_solver_t::get_filled_warmed_star } template -void pdlp_solver_t::print_termination_criteria( - const std::chrono::high_resolution_clock::time_point& start_time, bool is_average) +void pdlp_solver_t::print_termination_criteria(const timer_t& timer, bool is_average) { if (!inside_mip_) { - const auto current_time = std::chrono::high_resolution_clock::now(); - const f_t elapsed = - std::chrono::duration_cast(current_time - start_time).count() / - 1000.0; + auto elapsed = timer.elapsed_time(); if (is_average) { average_termination_strategy_.print_termination_criteria(total_pdlp_iterations_, elapsed); } else { @@ -509,13 +497,13 @@ void pdlp_solver_t::print_termination_criteria( template void pdlp_solver_t::print_final_termination_criteria( - const std::chrono::high_resolution_clock::time_point& start_time, + const timer_t& timer, const convergence_information_t& convergence_information, const pdlp_termination_status_t& termination_status, bool is_average) { if (!inside_mip_) { - print_termination_criteria(start_time, is_average); + print_termination_criteria(timer, is_average); CUOPT_LOG_INFO( "LP Solver status: %s", optimization_problem_solution_t::get_termination_status_string(termination_status) @@ -538,7 +526,7 @@ void pdlp_solver_t::print_final_termination_criteria( template std::optional> pdlp_solver_t::check_termination( - const std::chrono::high_resolution_clock::time_point& start_time) + const timer_t& timer) { raft::common::nvtx::range fun_scope("Check termination"); @@ -580,8 +568,8 @@ std::optional> pdlp_solver_t // enough) We still need to check iteration and time limit prior without breaking the logic below // of first checking termination before the limit if (total_pdlp_iterations_ <= 1) { - print_termination_criteria(start_time); - return check_limits(start_time); + print_termination_criteria(timer); + return check_limits(timer); } // First check for pdlp_termination_reason_t::Optimality and handle the first primal feasible case @@ -654,9 +642,8 @@ std::optional> pdlp_solver_t std::cout << "Optimal. End total number of iteration current=" << internal_solver_iterations_ << std::endl; #endif - print_final_termination_criteria(start_time, - current_termination_strategy_.get_convergence_information(), - termination_current); + print_final_termination_criteria( + timer, current_termination_strategy_.get_convergence_information(), termination_current); return current_termination_strategy_.fill_return_problem_solution( internal_solver_iterations_, pdhg_solver_, @@ -669,7 +656,7 @@ std::optional> pdlp_solver_t std::cout << "Optimal. End total number of iteration average=" << internal_solver_iterations_ << std::endl; #endif - print_final_termination_criteria(start_time, + print_final_termination_criteria(timer, average_termination_strategy_.get_convergence_information(), termination_average, true); @@ -689,7 +676,7 @@ std::optional> pdlp_solver_t std::cout << "Optimal. End total number of iteration average=" << internal_solver_iterations_ << std::endl; #endif - print_final_termination_criteria(start_time, + print_final_termination_criteria(timer, average_termination_strategy_.get_convergence_information(), termination_average, true); @@ -707,7 +694,7 @@ std::optional> pdlp_solver_t << std::endl; #endif print_final_termination_criteria( - start_time, current_termination_strategy_.get_convergence_information(), termination_current); + timer, current_termination_strategy_.get_convergence_information(), termination_current); return current_termination_strategy_.fill_return_problem_solution( internal_solver_iterations_, pdhg_solver_, @@ -729,9 +716,8 @@ std::optional> pdlp_solver_t std::cout << "Current Infeasible. End total number of iteration current=" << internal_solver_iterations_ << std::endl; #endif - print_final_termination_criteria(start_time, - current_termination_strategy_.get_convergence_information(), - termination_current); + print_final_termination_criteria( + timer, current_termination_strategy_.get_convergence_information(), termination_current); return current_termination_strategy_.fill_return_problem_solution( internal_solver_iterations_, pdhg_solver_, @@ -745,7 +731,7 @@ std::optional> pdlp_solver_t std::cout << "Average Infeasible. End total number of iteration current=" << internal_solver_iterations_ << std::endl; #endif - print_final_termination_criteria(start_time, + print_final_termination_criteria(timer, average_termination_strategy_.get_convergence_information(), termination_average, true); @@ -765,9 +751,8 @@ std::optional> pdlp_solver_t std::cout << "Infeasible. End total number of iteration current=" << internal_solver_iterations_ << std::endl; #endif - print_final_termination_criteria(start_time, - current_termination_strategy_.get_convergence_information(), - termination_current); + print_final_termination_criteria( + timer, current_termination_strategy_.get_convergence_information(), termination_current); return current_termination_strategy_.fill_return_problem_solution( internal_solver_iterations_, pdhg_solver_, @@ -785,7 +770,7 @@ std::optional> pdlp_solver_t << internal_solver_iterations_ << std::endl; #endif print_final_termination_criteria( - start_time, current_termination_strategy_.get_convergence_information(), termination_current); + timer, current_termination_strategy_.get_convergence_information(), termination_current); return optimization_problem_solution_t{pdlp_termination_status_t::NumericalError, stream_view_}; } @@ -797,10 +782,10 @@ std::optional> pdlp_solver_t average_termination_strategy_, termination_current, termination_average); - if (total_pdlp_iterations_ % 1000 == 0) { print_termination_criteria(start_time); } + if (total_pdlp_iterations_ % 1000 == 0) { print_termination_criteria(timer); } // No reason to terminate - return check_limits(start_time); + return check_limits(timer); } template @@ -983,8 +968,7 @@ void pdlp_solver_t::update_primal_dual_solutions( } template -optimization_problem_solution_t pdlp_solver_t::run_solver( - const std::chrono::high_resolution_clock::time_point& start_time) +optimization_problem_solution_t pdlp_solver_t::run_solver(const timer_t& timer) { bool verbose; #ifdef PDLP_VERBOSE_MODE @@ -1139,8 +1123,7 @@ optimization_problem_solution_t pdlp_solver_t::run_solver( pdhg_solver_.get_dual_solution()); // Check for termination - std::optional> solution = - check_termination(start_time); + std::optional> solution = check_termination(timer); if (solution.has_value()) { return std::move(solution.value()); } diff --git a/cpp/src/linear_programming/pdlp.cuh b/cpp/src/linear_programming/pdlp.cuh index 24db449726..ae75505abe 100644 --- a/cpp/src/linear_programming/pdlp.cuh +++ b/cpp/src/linear_programming/pdlp.cuh @@ -29,6 +29,8 @@ #include +#include + #include #include @@ -68,8 +70,7 @@ class pdlp_solver_t { pdlp_solver_settings_t const& settings = pdlp_solver_settings_t{}, bool is_batch_mode = false); - optimization_problem_solution_t run_solver( - const std::chrono::high_resolution_clock::time_point& start_time); + optimization_problem_solution_t run_solver(const timer_t& timer); f_t get_primal_weight_h() const; f_t get_step_size_h() const; @@ -99,19 +100,16 @@ class pdlp_solver_t { void set_inside_mip(bool inside_mip); private: - void print_termination_criteria(const std::chrono::high_resolution_clock::time_point& start_time, - bool is_average = false); + void print_termination_criteria(const timer_t& timer, bool is_average = false); void print_final_termination_criteria( - const std::chrono::high_resolution_clock::time_point& start_time, + const timer_t& timer, const convergence_information_t& convergence_information, const pdlp_termination_status_t& termination_status, bool is_average = false); void compute_initial_step_size(); void compute_initial_primal_weight(); - std::optional> check_termination( - const std::chrono::high_resolution_clock::time_point& start_time); - std::optional> check_limits( - const std::chrono::high_resolution_clock::time_point& start_time); + std::optional> check_termination(const timer_t& timer); + std::optional> check_limits(const timer_t& timer); void record_best_primal_so_far(const detail::pdlp_termination_strategy_t& current, const detail::pdlp_termination_strategy_t& average, const pdlp_termination_status_t& termination_current, @@ -212,7 +210,6 @@ class pdlp_solver_t { // Only used if save_best_primal_so_far is toggeled optimization_problem_solution_t best_primal_solution_so_far; primal_quality_adapter_t best_primal_quality_so_far_; - // Flag to indicate if solver is being called from MIP. No logging is done in this case. bool inside_mip_{false}; }; diff --git a/cpp/src/linear_programming/solve.cu b/cpp/src/linear_programming/solve.cu index e90312067b..95a62df2a6 100644 --- a/cpp/src/linear_programming/solve.cu +++ b/cpp/src/linear_programming/solve.cu @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -298,15 +297,15 @@ optimization_problem_solution_t convert_dual_simplex_sol( template std::tuple, dual_simplex::lp_status_t, f_t, f_t, f_t> run_dual_simplex(dual_simplex::user_problem_t& user_problem, - pdlp_solver_settings_t const& settings) + pdlp_solver_settings_t const& settings, + const timer_t& timer) { - auto start_solver = std::chrono::high_resolution_clock::now(); - + timer_t timer_dual_simplex(timer.remaining_time()); f_t norm_user_objective = dual_simplex::vector_norm2(user_problem.objective); f_t norm_rhs = dual_simplex::vector_norm2(user_problem.rhs); dual_simplex::simplex_solver_settings_t dual_simplex_settings; - dual_simplex_settings.time_limit = settings.time_limit; + dual_simplex_settings.time_limit = timer.remaining_time(); dual_simplex_settings.iteration_limit = settings.iteration_limit; dual_simplex_settings.concurrent_halt = settings.concurrent_halt; if (dual_simplex_settings.concurrent_halt != nullptr) { @@ -318,10 +317,9 @@ run_dual_simplex(dual_simplex::user_problem_t& user_problem, auto status = dual_simplex::solve_linear_program(user_problem, dual_simplex_settings, solution); - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(end - start_solver); - - CUOPT_LOG_INFO("Dual simplex finished in %.2f seconds", duration.count() / 1000.0); + CUOPT_LOG_INFO("Dual simplex finished in %.2f seconds, total time %.2f", + timer_dual_simplex.elapsed_time(), + timer.elapsed_time()); if (settings.concurrent_halt != nullptr && (status == dual_simplex::lp_status_t::OPTIMAL || status == dual_simplex::lp_status_t::UNBOUNDED || @@ -330,17 +328,19 @@ run_dual_simplex(dual_simplex::user_problem_t& user_problem, settings.concurrent_halt->store(1, std::memory_order_release); } - return {std::move(solution), status, duration.count() / 1000.0, norm_user_objective, norm_rhs}; + return {std::move(solution), status, timer.elapsed_time(), norm_user_objective, norm_rhs}; } template optimization_problem_solution_t run_dual_simplex( - detail::problem_t& problem, pdlp_solver_settings_t const& settings) + detail::problem_t& problem, + pdlp_solver_settings_t const& settings, + const timer_t& timer) { // Convert data structures to dual simplex format and back dual_simplex::user_problem_t dual_simplex_problem = cuopt_problem_to_simplex_problem(problem); - auto sol_dual_simplex = run_dual_simplex(dual_simplex_problem, settings); + auto sol_dual_simplex = run_dual_simplex(dual_simplex_problem, settings, timer); return convert_dual_simplex_sol(problem, std::get<0>(sol_dual_simplex), std::get<1>(sol_dual_simplex), @@ -353,7 +353,7 @@ template static optimization_problem_solution_t run_pdlp_solver( detail::problem_t& problem, pdlp_solver_settings_t const& settings, - const std::chrono::high_resolution_clock::time_point& start_time, + const timer_t& timer, bool is_batch_mode) { if (problem.n_constraints == 0) { @@ -362,26 +362,28 @@ static optimization_problem_solution_t run_pdlp_solver( problem.handle_ptr->get_stream()}; } detail::pdlp_solver_t solver(problem, settings, is_batch_mode); - return solver.run_solver(start_time); + return solver.run_solver(timer); } template optimization_problem_solution_t run_pdlp(detail::problem_t& problem, pdlp_solver_settings_t const& settings, + const timer_t& timer, bool is_batch_mode) { auto start_solver = std::chrono::high_resolution_clock::now(); f_t start_time = dual_simplex::tic(); - auto sol = run_pdlp_solver(problem, settings, start_solver, is_batch_mode); - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(end - start_solver); - sol.set_solve_time(duration.count() / 1000.0); + timer_t timer_pdlp(timer.remaining_time()); + auto sol = run_pdlp_solver(problem, settings, timer, is_batch_mode); + auto pdlp_solve_time = timer_pdlp.elapsed_time(); + sol.set_solve_time(timer.elapsed_time()); CUOPT_LOG_INFO("PDLP finished"); if (sol.get_termination_status() != pdlp_termination_status_t::ConcurrentLimit) { - CUOPT_LOG_INFO("Status: %s Objective: %.8e Iterations: %d Time: %.3fs", + CUOPT_LOG_INFO("Status: %s Objective: %.8e Iterations: %d Time: %.3fs, Total time %.3fs", sol.get_termination_status_string().c_str(), sol.get_objective_value(), sol.get_additional_termination_information().number_of_steps_taken, + pdlp_solve_time, sol.get_solve_time()); } @@ -394,7 +396,7 @@ optimization_problem_solution_t run_pdlp(detail::problem_t& dual_simplex::lp_solution_t initial_solution(1, 1); translate_to_crossover_problem(problem, sol, lp, initial_solution); dual_simplex::simplex_solver_settings_t dual_simplex_settings; - dual_simplex_settings.time_limit = settings.time_limit; + dual_simplex_settings.time_limit = timer.remaining_time(); dual_simplex_settings.iteration_limit = settings.iteration_limit; dual_simplex_settings.concurrent_halt = settings.concurrent_halt; dual_simplex::lp_solution_t vertex_solution(lp.num_rows, lp.num_cols); @@ -460,12 +462,13 @@ void run_dual_simplex_thread( pdlp_solver_settings_t const& settings, std::unique_ptr< std::tuple, dual_simplex::lp_status_t, f_t, f_t, f_t>>& - sol_ptr) + sol_ptr, + const timer_t& timer) { // We will return the solution from the thread as a unique_ptr sol_ptr = std::make_unique< std::tuple, dual_simplex::lp_status_t, f_t, f_t, f_t>>( - run_dual_simplex(problem, settings)); + run_dual_simplex(problem, settings, timer)); } template @@ -473,10 +476,11 @@ optimization_problem_solution_t run_concurrent( const optimization_problem_t& op_problem, detail::problem_t& problem, pdlp_solver_settings_t const& settings, + const timer_t& timer, bool is_batch_mode) { CUOPT_LOG_INFO("Running concurrent\n"); - f_t start_time = dual_simplex::tic(); + timer_t timer_concurrent(timer.remaining_time()); // Copy the settings so that we can set the concurrent halt pointer pdlp_solver_settings_t settings_pdlp(settings, @@ -498,10 +502,11 @@ optimization_problem_solution_t run_concurrent( std::thread dual_simplex_thread(run_dual_simplex_thread, std::ref(dual_simplex_problem), std::ref(settings_pdlp), - std::ref(sol_dual_simplex_ptr)); + std::ref(sol_dual_simplex_ptr), + std::ref(timer)); // Run pdlp in the main thread - auto sol_pdlp = run_pdlp(problem, settings_pdlp, is_batch_mode); + auto sol_pdlp = run_pdlp(problem, settings_pdlp, timer, is_batch_mode); // Wait for dual simplex thread to finish dual_simplex_thread.join(); @@ -514,8 +519,9 @@ optimization_problem_solution_t run_concurrent( std::get<3>(*sol_dual_simplex_ptr), std::get<4>(*sol_dual_simplex_ptr)); - f_t end_time = dual_simplex::toc(start_time); - CUOPT_LOG_INFO("Concurrent time: %.3fs", end_time); + f_t end_time = timer.elapsed_time(); + CUOPT_LOG_INFO( + "Concurrent time: %.3fs, total time %.3fs", timer_concurrent.elapsed_time(), end_time); // Check status to see if we should return the pdlp solution or the dual simplex solution if (sol_dual_simplex.get_termination_status() == pdlp_termination_status_t::Optimal || sol_dual_simplex.get_termination_status() == pdlp_termination_status_t::PrimalInfeasible || @@ -546,14 +552,15 @@ optimization_problem_solution_t solve_lp_with_method( const optimization_problem_t& op_problem, detail::problem_t& problem, pdlp_solver_settings_t const& settings, + const timer_t& timer, bool is_batch_mode) { if (settings.method == method_t::DualSimplex) { - return run_dual_simplex(problem, settings); + return run_dual_simplex(problem, settings, timer); } else if (settings.method == method_t::Concurrent) { - return run_concurrent(op_problem, problem, settings, is_batch_mode); + return run_concurrent(op_problem, problem, settings, timer, is_batch_mode); } else { - return run_pdlp(problem, settings, is_batch_mode); + return run_pdlp(problem, settings, timer, is_batch_mode); } } @@ -583,7 +590,7 @@ optimization_problem_solution_t solve_lp(optimization_problem_t::check_initial_solution_representation(op_problem, settings); } - auto presolve_timer = cuopt::timer_t(settings.time_limit); + auto lp_timer = cuopt::timer_t(settings.time_limit); detail::problem_t problem(op_problem); double presolve_time = 0.0; @@ -595,7 +602,7 @@ optimization_problem_solution_t solve_lp(optimization_problem_t>(); auto [reduced_problem, feasible] = presolver->apply(op_problem, @@ -608,7 +615,7 @@ optimization_problem_solution_t solve_lp(optimization_problem_tget_stream()); } problem = detail::problem_t(reduced_problem); - presolve_time = presolve_timer.elapsed_time(); + presolve_time = lp_timer.elapsed_time(); CUOPT_LOG_INFO("Third party presolve time: %f", presolve_time); } @@ -632,7 +639,7 @@ optimization_problem_solution_t solve_lp(optimization_problem_tget_stream()); - auto solution = solve_lp_with_method(op_problem, problem, settings, is_batch_mode); + auto solution = solve_lp_with_method(op_problem, problem, settings, lp_timer, is_batch_mode); if (run_presolve) { auto primal_solution = cuopt::device_copy(solution.get_primal_solution(), @@ -660,8 +667,6 @@ optimization_problem_solution_t solve_lp(optimization_problem_t::signaling_NaN()); auto full_stats = solution.get_additional_termination_information(); - // add third party presolve time to cuopt presolve time - full_stats.solve_time += presolve_time; // Create a new solution with the full problem solution solution = optimization_problem_solution_t(primal_solution, @@ -793,6 +798,7 @@ optimization_problem_solution_t solve_lp( const optimization_problem_t& op_problem, \ detail::problem_t& problem, \ pdlp_solver_settings_t const& settings, \ + const timer_t& timer, \ bool is_batch_mode); \ \ template optimization_problem_t mps_data_model_to_optimization_problem( \ diff --git a/cpp/src/linear_programming/solve.cuh b/cpp/src/linear_programming/solve.cuh index 3024d6774b..3098fd1b96 100644 --- a/cpp/src/linear_programming/solve.cuh +++ b/cpp/src/linear_programming/solve.cuh @@ -35,6 +35,7 @@ cuopt::linear_programming::optimization_problem_solution_t solve_lp_wi const optimization_problem_t& op_problem, detail::problem_t& problem, pdlp_solver_settings_t const& settings, + const timer_t& timer, bool is_batch_mode = false); } // namespace cuopt::linear_programming diff --git a/cpp/src/mip/presolve/third_party_presolve.cpp b/cpp/src/mip/presolve/third_party_presolve.cpp index 4c9dcb5743..211db4605e 100644 --- a/cpp/src/mip/presolve/third_party_presolve.cpp +++ b/cpp/src/mip/presolve/third_party_presolve.cpp @@ -344,6 +344,7 @@ void set_presolve_options(papilo::Presolve& presolver, { presolver.getPresolveOptions().tlim = time_limit; presolver.getPresolveOptions().threads = num_cpu_threads; // user setting or 0 (automatic) + presolver.getPresolveOptions().feastol = 1e-5; } template diff --git a/cpp/src/mip/relaxed_lp/relaxed_lp.cu b/cpp/src/mip/relaxed_lp/relaxed_lp.cu index d7a337dd28..790c50b179 100644 --- a/cpp/src/mip/relaxed_lp/relaxed_lp.cu +++ b/cpp/src/mip/relaxed_lp/relaxed_lp.cu @@ -87,7 +87,7 @@ optimization_problem_solution_t get_relaxed_lp_solution( // before LP flush the logs as it takes quite some time cuopt::default_logger().flush(); // temporarily add timer - auto start_time = std::chrono::high_resolution_clock::now(); + auto start_time = timer_t(pdlp_settings.time_limit); lp_solver.set_inside_mip(true); auto solver_response = lp_solver.run_solver(start_time); diff --git a/cpp/src/mip/solver.cu b/cpp/src/mip/solver.cu index 0f2117991f..5e27a65eaf 100644 --- a/cpp/src/mip/solver.cu +++ b/cpp/src/mip/solver.cu @@ -132,10 +132,11 @@ solution_t mip_solver_t::run_solver() CUOPT_LOG_INFO("Problem reduced to a LP, running concurrent LP"); pdlp_solver_settings_t settings{}; settings.time_limit = timer_.remaining_time(); + auto lp_timer = timer_t(settings.time_limit); settings.method = method_t::Concurrent; auto opt_sol = solve_lp_with_method( - *context.problem_ptr->original_problem_ptr, *context.problem_ptr, settings); + *context.problem_ptr->original_problem_ptr, *context.problem_ptr, settings, lp_timer); solution_t sol(*context.problem_ptr); sol.copy_new_assignment(host_copy(opt_sol.get_primal_solution())); diff --git a/cpp/tests/linear_programming/pdlp_test.cu b/cpp/tests/linear_programming/pdlp_test.cu index 2598561211..de40d8d322 100644 --- a/cpp/tests/linear_programming/pdlp_test.cu +++ b/cpp/tests/linear_programming/pdlp_test.cu @@ -279,8 +279,8 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); - solver.run_solver(start_solver); + auto pdlp_timer = timer_t(solver_settings.time_limit); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); @@ -290,36 +290,36 @@ TEST(pdlp_class, initial_solution_test) // scale on initial option is not toggled { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); } { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); } { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); @@ -328,9 +328,9 @@ TEST(pdlp_class, initial_solution_test) // Toggle the scale on initial solution while not providing should yield the same { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); @@ -338,9 +338,9 @@ TEST(pdlp_class, initial_solution_test) } { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); @@ -348,10 +348,10 @@ TEST(pdlp_class, initial_solution_test) } { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); @@ -364,11 +364,11 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); @@ -377,11 +377,11 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); @@ -393,11 +393,11 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = false; @@ -405,11 +405,11 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = false; @@ -420,14 +420,14 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 0); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); std::vector initial_dual(op_problem.get_n_constraints(), 0); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = false; @@ -438,11 +438,11 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 0); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = false; @@ -450,11 +450,11 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_dual(op_problem.get_n_constraints(), 0); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = false; @@ -462,14 +462,14 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 0); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); std::vector initial_dual(op_problem.get_n_constraints(), 0); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = false; @@ -480,14 +480,14 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NOT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = false; @@ -495,14 +495,14 @@ TEST(pdlp_class, initial_solution_test) { cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NOT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = false; @@ -511,14 +511,14 @@ TEST(pdlp_class, initial_solution_test) cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); EXPECT_NOT_NEAR(initial_step_size_afiro, solver.get_step_size_h(), factor_tolerance); EXPECT_NOT_NEAR(initial_primal_weight_afiro, solver.get_primal_weight_h(), factor_tolerance); cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = false; @@ -551,12 +551,12 @@ TEST(pdlp_class, initial_primal_weight_step_size_test) // Check setting an initial primal weight and step size { cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); constexpr double test_initial_step_size = 1.0; constexpr double test_initial_primal_weight = 2.0; solver.set_initial_primal_weight(test_initial_primal_weight); solver.set_initial_step_size(test_initial_step_size); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_EQ(test_initial_step_size, solver.get_step_size_h()); EXPECT_EQ(test_initial_primal_weight, solver.get_primal_weight_h()); @@ -569,27 +569,27 @@ TEST(pdlp_class, initial_primal_weight_step_size_test) cuopt::linear_programming::pdlp_hyper_params::update_primal_weight_on_initial_solution = true; cuopt::linear_programming::pdlp_hyper_params::update_step_size_on_initial_solution = true; cuopt::linear_programming::detail::pdlp_solver_t solver(problem, solver_settings); - auto start_solver = std::chrono::high_resolution_clock::now(); + auto pdlp_timer = timer_t(solver_settings.time_limit); std::vector initial_primal(op_problem.get_n_variables(), 1); auto d_initial_primal = device_copy(initial_primal, handle_.get_stream()); solver.set_initial_primal_solution(d_initial_primal); std::vector initial_dual(op_problem.get_n_constraints(), 1); auto d_initial_dual = device_copy(initial_dual, handle_.get_stream()); solver.set_initial_dual_solution(d_initial_dual); - solver.run_solver(start_solver); + solver.run_solver(pdlp_timer); const double previous_step_size = solver.get_step_size_h(); const double previous_primal_weight = solver.get_primal_weight_h(); // Start again but with an initial and check the impact cuopt::linear_programming::detail::pdlp_solver_t solver2(problem, solver_settings); - start_solver = std::chrono::high_resolution_clock::now(); + pdlp_timer = timer_t(solver_settings.time_limit); constexpr double test_initial_step_size = 1.0; constexpr double test_initial_primal_weight = 2.0; solver2.set_initial_primal_weight(test_initial_primal_weight); solver2.set_initial_step_size(test_initial_step_size); solver2.set_initial_primal_solution(d_initial_primal); solver2.set_initial_dual_solution(d_initial_dual); - solver2.run_solver(start_solver); + solver2.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); const double sovler2_step_size = solver2.get_step_size_h(); const double sovler2_primal_weight = solver2.get_primal_weight_h(); @@ -598,14 +598,14 @@ TEST(pdlp_class, initial_primal_weight_step_size_test) // Again but with an initial k which should change the step size only, not the primal weight cuopt::linear_programming::detail::pdlp_solver_t solver3(problem, solver_settings); - start_solver = std::chrono::high_resolution_clock::now(); + pdlp_timer = timer_t(solver_settings.time_limit); solver3.set_initial_primal_weight(test_initial_primal_weight); solver3.set_initial_step_size(test_initial_step_size); solver3.set_initial_primal_solution(d_initial_primal); solver3.set_initial_k(10000); solver3.set_initial_dual_solution(d_initial_dual); solver3.set_initial_dual_solution(d_initial_dual); - solver3.run_solver(start_solver); + solver3.run_solver(pdlp_timer); RAFT_CUDA_TRY(cudaStreamSynchronize(handle_.get_stream())); EXPECT_NOT_NEAR(sovler2_step_size, solver3.get_step_size_h(), factor_tolerance); EXPECT_NEAR(sovler2_primal_weight, solver3.get_primal_weight_h(), factor_tolerance);