-
Notifications
You must be signed in to change notification settings - Fork 85
Concurrent LP in get_relaxed_lp (used in FP) and lay foundations for future PDLP warm start #173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: branch-25.08
Are you sure you want to change the base?
Changes from all commits
0e5889a
90e2482
39c8e76
3cbfd91
f8b1c91
364a4d0
f682adf
85d2362
1469558
1a206a0
be08696
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,11 @@ | |
|
||
namespace cuopt::linear_programming { | ||
|
||
namespace detail { | ||
template <typename i_t, typename f_t> | ||
class problem_t; | ||
} | ||
|
||
/** | ||
* @brief Linear programming solve function. | ||
* @note Both primal and dual solutions are zero-initialized. For custom initialization, see | ||
|
@@ -54,7 +59,33 @@ optimization_problem_solution_t<i_t, f_t> solve_lp( | |
bool use_pdlp_solver_mode = true); | ||
|
||
/** | ||
* @brief Linear programming solve function. | ||
* @brief Linear programming solve function. Used in the context of a MIP when the input is a | ||
* detail::problem_t. | ||
* @note Both primal and dual solutions are zero-initialized. For custom initialization, see | ||
* op_problem.initial_primal/dual_solution | ||
* | ||
* @tparam i_t Data type of indexes | ||
* @tparam f_t Data type of the variables and their weights in the equations | ||
* | ||
* @param[in] op_problem An optimization_problem_t<i_t, f_t> object with a | ||
* representation of a linear program | ||
* @param[in] settings A pdlp_solver_settings_t<i_t, f_t> object with the settings for the PDLP | ||
* solver. | ||
* @param[in] use_pdlp_solver_modes If true, the PDLP hyperparameters coming from the | ||
* pdlp_solver_mode are used (instead of the ones comming from a potential hyper-params file). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. syntax: Typo: 'comming' should be 'coming' Prompt To Fix With AIThis is a comment left during a code review.
Path: cpp/include/cuopt/linear_programming/solve.hpp
Line: 75:75
Comment:
**syntax:** Typo: 'comming' should be 'coming'
How can I resolve this? If you propose a fix, please make it concise. |
||
* @param[in] inside_mip If true, the problem is being solved in the context of a MIP. | ||
* @return optimization_problem_solution_t<i_t, f_t> owning container for the solver solution | ||
*/ | ||
template <typename i_t, typename f_t> | ||
optimization_problem_solution_t<i_t, f_t> solve_lp( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is used purely in MIP context. It is cleaner to rename this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that for now this is just used in the context of MIP but some people might want to solve an LP using the detail::problem representation instead of the optimization_problem one. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @akifcorduk do you have an opinion there? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think renaming it kind of pins it to MIP use-cases, I agree with Nicolas that it is just another LP interface that accepts |
||
detail::problem_t<i_t, f_t>& problem, | ||
pdlp_solver_settings_t<i_t, f_t> const& settings = pdlp_solver_settings_t<i_t, f_t>{}, | ||
bool use_pdlp_solver_mode = true, | ||
bool inside_mip = false); | ||
|
||
/** | ||
* @brief Linear programming solve function. This is a wrapper around the solve_lp function taking a | ||
* detail::problem_t as input. | ||
* @note Both primal and dual solutions are zero-initialized. For custom initialization, see | ||
* op_problem.initial_primal/dual_solution | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -128,56 +128,65 @@ pdlp_solver_t<i_t, f_t>::pdlp_solver_t(problem_t<i_t, f_t>& op_problem, | |
set_initial_dual_solution(dual_sol); | ||
} | ||
|
||
if (settings.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_.size() != 0) { | ||
set_initial_primal_solution(settings.get_pdlp_warm_start_data().current_primal_solution_); | ||
set_initial_dual_solution(settings.get_pdlp_warm_start_data().current_dual_solution_); | ||
initial_step_size_ = settings.get_pdlp_warm_start_data().initial_step_size_; | ||
initial_primal_weight_ = settings.get_pdlp_warm_start_data().initial_primal_weight_; | ||
total_pdlp_iterations_ = settings.get_pdlp_warm_start_data().total_pdlp_iterations_; | ||
pdhg_solver_.total_pdhg_iterations_ = | ||
settings.get_pdlp_warm_start_data().total_pdhg_iterations_; | ||
pdhg_solver_.get_d_total_pdhg_iterations().set_value_async( | ||
settings.get_pdlp_warm_start_data().total_pdhg_iterations_, stream_view_); | ||
restart_strategy_.last_candidate_kkt_score = | ||
settings.get_pdlp_warm_start_data().last_candidate_kkt_score_; | ||
restart_strategy_.last_restart_kkt_score = | ||
settings.get_pdlp_warm_start_data().last_restart_kkt_score_; | ||
raft::copy(restart_strategy_.weighted_average_solution_.sum_primal_solutions_.data(), | ||
settings.get_pdlp_warm_start_data().sum_primal_solutions_.data(), | ||
settings.get_pdlp_warm_start_data().sum_primal_solutions_.size(), | ||
stream_view_); | ||
raft::copy(restart_strategy_.weighted_average_solution_.sum_dual_solutions_.data(), | ||
settings.get_pdlp_warm_start_data().sum_dual_solutions_.data(), | ||
settings.get_pdlp_warm_start_data().sum_dual_solutions_.size(), | ||
stream_view_); | ||
raft::copy(unscaled_primal_avg_solution_.data(), | ||
settings.get_pdlp_warm_start_data().initial_primal_average_.data(), | ||
settings.get_pdlp_warm_start_data().initial_primal_average_.size(), | ||
stream_view_); | ||
raft::copy(unscaled_dual_avg_solution_.data(), | ||
settings.get_pdlp_warm_start_data().initial_dual_average_.data(), | ||
settings.get_pdlp_warm_start_data().initial_dual_average_.size(), | ||
stream_view_); | ||
raft::copy(pdhg_solver_.get_saddle_point_state().get_current_AtY().data(), | ||
settings.get_pdlp_warm_start_data().current_ATY_.data(), | ||
settings.get_pdlp_warm_start_data().current_ATY_.size(), | ||
stream_view_); | ||
raft::copy(restart_strategy_.last_restart_duality_gap_.primal_solution_.data(), | ||
settings.get_pdlp_warm_start_data().last_restart_duality_gap_primal_solution_.data(), | ||
settings.get_pdlp_warm_start_data().last_restart_duality_gap_primal_solution_.size(), | ||
stream_view_); | ||
raft::copy(restart_strategy_.last_restart_duality_gap_.dual_solution_.data(), | ||
settings.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_.data(), | ||
settings.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_.size(), | ||
stream_view_); | ||
if (settings.has_pdlp_warm_start_data()) { | ||
const auto& warm_start_data = settings.get_pdlp_warm_start_data(); | ||
if (!warm_start_data.solved_by_pdlp_) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Should verify the logic: warm start data from non-PDLP solvers might still be partially useful for initialization Prompt To Fix With AIThis is a comment left during a code review.
Path: cpp/src/linear_programming/pdlp.cu
Line: 133:133
Comment:
**style:** Should verify the logic: warm start data from non-PDLP solvers might still be partially useful for initialization
How can I resolve this? If you propose a fix, please make it concise. |
||
CUOPT_LOG_DEBUG( | ||
"Warm start data coming from a solution which was not solved by PDLP, skipping warm start"); | ||
} else if (pdlp_hyper_params::restart_strategy == | ||
static_cast<int>( | ||
pdlp_restart_strategy_t<i_t, f_t>::restart_strategy_t::TRUST_REGION_RESTART)) { | ||
CUOPT_LOG_DEBUG( | ||
"Trying to use warm start with trust region restart (neither Stable nor Fast1), skipping " | ||
"warm start"); | ||
} else { | ||
set_initial_primal_solution(warm_start_data.current_primal_solution_); | ||
set_initial_dual_solution(warm_start_data.current_dual_solution_); | ||
initial_step_size_ = warm_start_data.initial_step_size_; | ||
initial_primal_weight_ = warm_start_data.initial_primal_weight_; | ||
total_pdlp_iterations_ = warm_start_data.total_pdlp_iterations_; | ||
pdhg_solver_.total_pdhg_iterations_ = warm_start_data.total_pdhg_iterations_; | ||
pdhg_solver_.get_d_total_pdhg_iterations().set_value_async( | ||
warm_start_data.total_pdhg_iterations_, stream_view_); | ||
restart_strategy_.last_candidate_kkt_score = warm_start_data.last_candidate_kkt_score_; | ||
restart_strategy_.last_restart_kkt_score = warm_start_data.last_restart_kkt_score_; | ||
raft::copy(restart_strategy_.weighted_average_solution_.sum_primal_solutions_.data(), | ||
warm_start_data.sum_primal_solutions_.data(), | ||
warm_start_data.sum_primal_solutions_.size(), | ||
stream_view_); | ||
raft::copy(restart_strategy_.weighted_average_solution_.sum_dual_solutions_.data(), | ||
warm_start_data.sum_dual_solutions_.data(), | ||
warm_start_data.sum_dual_solutions_.size(), | ||
stream_view_); | ||
raft::copy(unscaled_primal_avg_solution_.data(), | ||
warm_start_data.initial_primal_average_.data(), | ||
warm_start_data.initial_primal_average_.size(), | ||
stream_view_); | ||
raft::copy(unscaled_dual_avg_solution_.data(), | ||
warm_start_data.initial_dual_average_.data(), | ||
warm_start_data.initial_dual_average_.size(), | ||
stream_view_); | ||
raft::copy(pdhg_solver_.get_saddle_point_state().get_current_AtY().data(), | ||
warm_start_data.current_ATY_.data(), | ||
warm_start_data.current_ATY_.size(), | ||
stream_view_); | ||
raft::copy(restart_strategy_.last_restart_duality_gap_.primal_solution_.data(), | ||
warm_start_data.last_restart_duality_gap_primal_solution_.data(), | ||
warm_start_data.last_restart_duality_gap_primal_solution_.size(), | ||
stream_view_); | ||
raft::copy(restart_strategy_.last_restart_duality_gap_.dual_solution_.data(), | ||
warm_start_data.last_restart_duality_gap_dual_solution_.data(), | ||
warm_start_data.last_restart_duality_gap_dual_solution_.size(), | ||
stream_view_); | ||
|
||
const auto value = settings.get_pdlp_warm_start_data().sum_solution_weight_; | ||
restart_strategy_.weighted_average_solution_.sum_primal_solution_weights_.set_value_async( | ||
value, stream_view_); | ||
restart_strategy_.weighted_average_solution_.sum_dual_solution_weights_.set_value_async( | ||
value, stream_view_); | ||
restart_strategy_.weighted_average_solution_.iterations_since_last_restart_ = | ||
settings.get_pdlp_warm_start_data().iterations_since_last_restart_; | ||
const auto value = warm_start_data.sum_solution_weight_; | ||
restart_strategy_.weighted_average_solution_.sum_primal_solution_weights_.set_value_async( | ||
value, stream_view_); | ||
restart_strategy_.weighted_average_solution_.sum_dual_solution_weights_.set_value_async( | ||
value, stream_view_); | ||
restart_strategy_.weighted_average_solution_.iterations_since_last_restart_ = | ||
warm_start_data.iterations_since_last_restart_; | ||
} | ||
} | ||
// Checks performed below are assert only | ||
best_primal_quality_so_far_.primal_objective = (op_problem_scaled_.maximize) | ||
|
@@ -323,7 +332,7 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_t> | |
pdhg_solver_, | ||
pdhg_solver_.get_primal_solution(), | ||
pdhg_solver_.get_dual_solution(), | ||
get_filled_warmed_start_data(), | ||
get_filled_warmed_start_data(false), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: Missing the Prompt To Fix With AIThis is a comment left during a code review.
Path: cpp/src/linear_programming/pdlp.cu
Line: 335:335
Comment:
**logic:** Missing the `true` parameter that was added in other calls to `get_filled_warmed_start_data`
How can I resolve this? If you propose a fix, please make it concise. |
||
pdlp_termination_status_t::ConcurrentLimit); | ||
} | ||
|
||
|
@@ -466,7 +475,8 @@ void pdlp_solver_t<i_t, f_t>::record_best_primal_so_far( | |
} | ||
|
||
template <typename i_t, typename f_t> | ||
pdlp_warm_start_data_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::get_filled_warmed_start_data() | ||
pdlp_warm_start_data_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::get_filled_warmed_start_data( | ||
bool solved_by_pdlp) | ||
{ | ||
return pdlp_warm_start_data_t<i_t, f_t>( | ||
pdhg_solver_.get_primal_solution(), | ||
|
@@ -485,7 +495,8 @@ pdlp_warm_start_data_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::get_filled_warmed_star | |
restart_strategy_.last_candidate_kkt_score, | ||
restart_strategy_.last_restart_kkt_score, | ||
restart_strategy_.weighted_average_solution_.sum_primal_solution_weights_.value(stream_view_), | ||
restart_strategy_.weighted_average_solution_.iterations_since_last_restart_); | ||
restart_strategy_.weighted_average_solution_.iterations_since_last_restart_, | ||
solved_by_pdlp); | ||
} | ||
|
||
template <typename i_t, typename f_t> | ||
|
@@ -545,9 +556,14 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_t> | |
#ifdef PDLP_VERBOSE_MODE | ||
RAFT_CUDA_TRY(cudaDeviceSynchronize()); | ||
printf("Termination criteria current\n"); | ||
current_termination_strategy_.print_termination_criteria(); | ||
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; | ||
current_termination_strategy_.print_termination_criteria(total_pdlp_iterations_, elapsed); | ||
RAFT_CUDA_TRY(cudaDeviceSynchronize()); | ||
#endif | ||
|
||
pdlp_termination_status_t termination_current = | ||
current_termination_strategy_.evaluate_termination_criteria( | ||
pdhg_solver_, | ||
|
@@ -559,7 +575,7 @@ std::optional<optimization_problem_solution_t<i_t, f_t>> pdlp_solver_t<i_t, f_t> | |
#ifdef PDLP_VERBOSE_MODE | ||
RAFT_CUDA_TRY(cudaDeviceSynchronize()); | ||
std::cout << "Termination criteria average:" << std::endl; | ||
average_termination_strategy_.print_termination_criteria(); | ||
average_termination_strategy_.print_termination_criteria(total_pdlp_iterations_, elapsed); | ||
RAFT_CUDA_TRY(cudaDeviceSynchronize()); | ||
#endif | ||
|
||
|
@@ -984,6 +1000,8 @@ 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) | ||
{ | ||
raft::common::nvtx::range fun_scope("Run PDLP Solver"); | ||
|
||
bool verbose; | ||
#ifdef PDLP_VERBOSE_MODE | ||
verbose = true; | ||
|
@@ -1071,8 +1089,7 @@ optimization_problem_solution_t<i_t, f_t> pdlp_solver_t<i_t, f_t>::run_solver( | |
raft::print_device_vector("Initial dual_step_size", dual_step_size_.data(), 1, std::cout); | ||
} | ||
|
||
bool warm_start_was_given = | ||
settings_.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_.size() != 0; | ||
bool warm_start_was_given = settings_.has_pdlp_warm_start_data(); | ||
|
||
if (!inside_mip_) { | ||
CUOPT_LOG_INFO( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
syntax: Parameter documentation refers to 'op_problem' but the actual parameter is 'problem' - should be consistent
Prompt To Fix With AI