Skip to content

Commit 43e55c2

Browse files
Merge branch 'main' into update_doc_and_cusparse_check
2 parents ac3dcc8 + 3be4325 commit 43e55c2

File tree

5 files changed

+54
-14
lines changed

5 files changed

+54
-14
lines changed

cpp/src/linear_programming/solve.cu

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -924,17 +924,9 @@ optimization_problem_solution_t<i_t, f_t> solve_lp(
924924
reduced_costs,
925925
cuopt::linear_programming::problem_category_t::LP,
926926
status_to_skip,
927+
settings.dual_postsolve,
927928
op_problem.get_handle_ptr()->get_stream());
928929

929-
thrust::fill(rmm::exec_policy(op_problem.get_handle_ptr()->get_stream()),
930-
dual_solution.data(),
931-
dual_solution.data() + dual_solution.size(),
932-
std::numeric_limits<f_t>::signaling_NaN());
933-
thrust::fill(rmm::exec_policy(op_problem.get_handle_ptr()->get_stream()),
934-
reduced_costs.data(),
935-
reduced_costs.data() + reduced_costs.size(),
936-
std::numeric_limits<f_t>::signaling_NaN());
937-
938930
auto full_stats = solution.get_additional_termination_information();
939931

940932
// Create a new solution with the full problem solution

cpp/src/mip/presolve/third_party_presolve.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,16 @@ void set_presolve_options(papilo::Presolve<f_t>& presolver,
356356
f_t absolute_tolerance,
357357
f_t relative_tolerance,
358358
double time_limit,
359+
bool dual_postsolve,
359360
i_t num_cpu_threads)
360361
{
361362
presolver.getPresolveOptions().tlim = time_limit;
362363
presolver.getPresolveOptions().threads = num_cpu_threads; // user setting or 0 (automatic)
363364
presolver.getPresolveOptions().feastol = 1e-5;
365+
if (dual_postsolve) {
366+
presolver.getPresolveOptions().componentsmaxint = -1;
367+
presolver.getPresolveOptions().detectlindep = 0;
368+
}
364369
}
365370

366371
template <typename f_t>
@@ -404,8 +409,13 @@ std::optional<third_party_presolve_result_t<i_t, f_t>> third_party_presolve_t<i_
404409
if (category == problem_category_t::MIP) { dual_postsolve = false; }
405410
papilo::Presolve<f_t> presolver;
406411
set_presolve_methods<f_t>(presolver, category, dual_postsolve);
407-
set_presolve_options<i_t, f_t>(
408-
presolver, category, absolute_tolerance, relative_tolerance, time_limit, num_cpu_threads);
412+
set_presolve_options<i_t, f_t>(presolver,
413+
category,
414+
absolute_tolerance,
415+
relative_tolerance,
416+
time_limit,
417+
dual_postsolve,
418+
num_cpu_threads);
409419
set_presolve_parameters<f_t>(
410420
presolver, category, op_problem.get_n_constraints(), op_problem.get_n_variables());
411421

@@ -446,6 +456,7 @@ void third_party_presolve_t<i_t, f_t>::undo(rmm::device_uvector<f_t>& primal_sol
446456
rmm::device_uvector<f_t>& reduced_costs,
447457
problem_category_t category,
448458
bool status_to_skip,
459+
bool dual_postsolve,
449460
rmm::cuda_stream_view stream_view)
450461
{
451462
if (status_to_skip) { return; }
@@ -455,8 +466,12 @@ void third_party_presolve_t<i_t, f_t>::undo(rmm::device_uvector<f_t>& primal_sol
455466
raft::copy(dual_sol_vec_h.data(), dual_solution.data(), dual_solution.size(), stream_view);
456467
std::vector<f_t> reduced_costs_vec_h(reduced_costs.size());
457468
raft::copy(reduced_costs_vec_h.data(), reduced_costs.data(), reduced_costs.size(), stream_view);
458-
459469
papilo::Solution<f_t> reduced_sol(primal_sol_vec_h);
470+
if (dual_postsolve) {
471+
reduced_sol.dual = dual_sol_vec_h;
472+
reduced_sol.reducedCosts = reduced_costs_vec_h;
473+
reduced_sol.type = papilo::SolutionType::kPrimalDual;
474+
}
460475
papilo::Solution<f_t> full_sol;
461476

462477
papilo::Message Msg{};

cpp/src/mip/presolve/third_party_presolve.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class third_party_presolve_t {
3939
rmm::device_uvector<f_t>& reduced_costs,
4040
problem_category_t category,
4141
bool status_to_skip,
42+
bool dual_postsolve,
4243
rmm::cuda_stream_view stream_view);
4344
};
4445

cpp/src/mip/solve.cu

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ mip_solution_t<i_t, f_t> solve_mip(optimization_problem_t<i_t, f_t>& op_problem,
195195

196196
if (!run_presolve) { CUOPT_LOG_INFO("Presolve is disabled, skipping"); }
197197

198+
auto constexpr const dual_postsolve = false;
198199
if (run_presolve) {
199200
detail::sort_csr(op_problem);
200201
// allocate not more than 10% of the time limit to presolve.
201202
// Note that this is not the presolve time, but the time limit for presolve.
202203
const double presolve_time_limit = std::min(0.1 * time_limit, 60.0);
203-
const bool dual_postsolve = false;
204204
presolver = std::make_unique<detail::third_party_presolve_t<i_t, f_t>>();
205205
auto result = presolver->apply(op_problem,
206206
cuopt::linear_programming::problem_category_t::MIP,
@@ -246,6 +246,7 @@ mip_solution_t<i_t, f_t> solve_mip(optimization_problem_t<i_t, f_t>& op_problem,
246246
reduced_costs,
247247
cuopt::linear_programming::problem_category_t::MIP,
248248
status_to_skip,
249+
dual_postsolve,
249250
op_problem.get_handle_ptr()->get_stream());
250251
if (!status_to_skip) {
251252
thrust::fill(rmm::exec_policy(op_problem.get_handle_ptr()->get_stream()),

cpp/tests/linear_programming/pdlp_test.cu

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,15 @@ TEST(pdlp_class, run_sub_mittleman)
210210
for (auto solver_mode : solver_mode_list) {
211211
auto settings = pdlp_solver_settings_t<int, double>{};
212212
settings.pdlp_solver_mode = solver_mode;
213+
settings.dual_postsolve = false;
213214
for (auto [presolve, epsilon] : {std::pair{true, 1e-1}, std::pair{false, 1e-6}}) {
214215
settings.presolve = presolve;
215216
settings.method = cuopt::linear_programming::method_t::PDLP;
216217
const raft::handle_t handle_{};
217218
optimization_problem_solution_t<int, double> solution =
218219
solve_lp(&handle_, op_problem, settings);
219-
printf("running %s mode %d presolve? %d\n", name.c_str(), (int)solver_mode, presolve);
220+
printf(
221+
"running %s mode %d presolve? %d\n", name.c_str(), (int)solver_mode, settings.presolve);
220222
EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL);
221223
EXPECT_FALSE(is_incorrect_objective(
222224
expected_objective_value,
@@ -857,6 +859,35 @@ TEST(pdlp_class, warm_start)
857859
}
858860
}
859861

862+
TEST(pdlp_class, dual_postsolve_size)
863+
{
864+
const raft::handle_t handle_{};
865+
866+
auto path = make_path_absolute("linear_programming/afiro_original.mps");
867+
cuopt::mps_parser::mps_data_model_t<int, double> op_problem =
868+
cuopt::mps_parser::parse_mps<int, double>(path, true);
869+
870+
auto solver_settings = pdlp_solver_settings_t<int, double>{};
871+
solver_settings.method = cuopt::linear_programming::method_t::PDLP;
872+
solver_settings.presolve = true;
873+
874+
{
875+
solver_settings.dual_postsolve = true;
876+
optimization_problem_solution_t<int, double> solution =
877+
solve_lp(&handle_, op_problem, solver_settings);
878+
EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL);
879+
EXPECT_EQ(solution.get_dual_solution().size(), op_problem.get_n_constraints());
880+
}
881+
882+
{
883+
solver_settings.dual_postsolve = false;
884+
optimization_problem_solution_t<int, double> solution =
885+
solve_lp(&handle_, op_problem, solver_settings);
886+
EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL);
887+
EXPECT_EQ(solution.get_dual_solution().size(), 0);
888+
}
889+
}
890+
860891
TEST(dual_simplex, afiro)
861892
{
862893
cuopt::linear_programming::pdlp_solver_settings_t<int, double> settings =

0 commit comments

Comments
 (0)