Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 25 additions & 42 deletions cpp/src/linear_programming/pdlp.cu
Original file line number Diff line number Diff line change
Expand Up @@ -253,22 +253,14 @@ void pdlp_solver_t<i_t, f_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<std::chrono::milliseconds>(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 <typename i_t, typename f_t>
std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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());
Expand Down Expand Up @@ -491,14 +483,10 @@ pdlp_warm_start_data_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::get_filled_warmed_star
}

template <typename i_t, typename f_t>
void pdlp_solver_t<i_t, f_t>::print_termination_criteria(
const std::chrono::high_resolution_clock::time_point& start_time, bool is_average)
void pdlp_solver_t<i_t, f_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<std::chrono::milliseconds>(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 {
Expand All @@ -509,13 +497,13 @@ void pdlp_solver_t<i_t, f_t>::print_termination_criteria(

template <typename i_t, typename f_t>
void pdlp_solver_t<i_t, f_t>::print_final_termination_criteria(
const std::chrono::high_resolution_clock::time_point& start_time,
const timer_t& timer,
const convergence_information_t<i_t, f_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<i_t, f_t>::get_termination_status_string(termination_status)
Expand All @@ -538,7 +526,7 @@ void pdlp_solver_t<i_t, f_t>::print_final_termination_criteria(

template <typename i_t, typename f_t>
std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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");

Expand Down Expand Up @@ -580,8 +568,8 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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
Expand Down Expand Up @@ -654,9 +642,8 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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_,
Expand All @@ -669,7 +656,7 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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);
Expand All @@ -689,7 +676,7 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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);
Expand All @@ -707,7 +694,7 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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_,
Expand All @@ -729,9 +716,8 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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_,
Expand All @@ -745,7 +731,7 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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);
Expand All @@ -765,9 +751,8 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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_,
Expand All @@ -785,7 +770,7 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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<i_t, f_t>{pdlp_termination_status_t::NumericalError,
stream_view_};
}
Expand All @@ -797,10 +782,10 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_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 <typename f_t>
Expand Down Expand Up @@ -983,8 +968,7 @@ void pdlp_solver_t<i_t, f_t>::update_primal_dual_solutions(
}

template <typename i_t, typename f_t>
optimization_problem_solution_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::run_solver(
const std::chrono::high_resolution_clock::time_point& start_time)
optimization_problem_solution_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::run_solver(const timer_t& timer)
{
bool verbose;
#ifdef PDLP_VERBOSE_MODE
Expand Down Expand Up @@ -1139,8 +1123,7 @@ optimization_problem_solution_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::run_solver(
pdhg_solver_.get_dual_solution());

// Check for termination
std::optional<optimization_problem_solution_t<i_t, f_t>> solution =
check_termination(start_time);
std::optional<optimization_problem_solution_t<i_t, f_t>> solution = check_termination(timer);

if (solution.has_value()) { return std::move(solution.value()); }

Expand Down
17 changes: 7 additions & 10 deletions cpp/src/linear_programming/pdlp.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

#include <mip/problem/problem.cuh>

#include <utilities/timer.hpp>

#include <raft/core/handle.hpp>

#include <rmm/device_scalar.hpp>
Expand Down Expand Up @@ -68,8 +70,7 @@ class pdlp_solver_t {
pdlp_solver_settings_t<i_t, f_t> const& settings = pdlp_solver_settings_t<i_t, f_t>{},
bool is_batch_mode = false);

optimization_problem_solution_t<i_t, f_t> run_solver(
const std::chrono::high_resolution_clock::time_point& start_time);
optimization_problem_solution_t<i_t, f_t> run_solver(const timer_t& timer);

f_t get_primal_weight_h() const;
f_t get_step_size_h() const;
Expand Down Expand Up @@ -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<i_t, f_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<optimization_problem_solution_t<i_t, f_t>> check_termination(
const std::chrono::high_resolution_clock::time_point& start_time);
std::optional<optimization_problem_solution_t<i_t, f_t>> check_limits(
const std::chrono::high_resolution_clock::time_point& start_time);
std::optional<optimization_problem_solution_t<i_t, f_t>> check_termination(const timer_t& timer);
std::optional<optimization_problem_solution_t<i_t, f_t>> check_limits(const timer_t& timer);
void record_best_primal_so_far(const detail::pdlp_termination_strategy_t<i_t, f_t>& current,
const detail::pdlp_termination_strategy_t<i_t, f_t>& average,
const pdlp_termination_status_t& termination_current,
Expand Down Expand Up @@ -212,7 +210,6 @@ class pdlp_solver_t {
// Only used if save_best_primal_so_far is toggeled
optimization_problem_solution_t<i_t, f_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};
};
Expand Down
Loading