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
11 changes: 5 additions & 6 deletions cpp/src/linear_programming/solve.cu
Original file line number Diff line number Diff line change
Expand Up @@ -583,15 +583,9 @@ optimization_problem_solution_t<i_t, f_t> solve_lp(optimization_problem_t<i_t, f
auto presolve_timer = cuopt::timer_t(settings.time_limit);
detail::problem_t<i_t, f_t> problem(op_problem);

if (settings.user_problem_file != "") {
CUOPT_LOG_INFO("Writing user problem to file: %s", settings.user_problem_file.c_str());
problem.write_as_mps(settings.user_problem_file);
}

double presolve_time = 0.0;
std::unique_ptr<detail::third_party_presolve_t<i_t, f_t>> presolver;
auto run_presolve = settings.presolve;
run_presolve = run_presolve && op_problem.get_sense() == false;
run_presolve = run_presolve && settings.get_pdlp_warm_start_data().total_pdlp_iterations_ == -1;
if (!run_presolve) { CUOPT_LOG_INFO("Presolve is disabled, skipping"); }

Expand All @@ -615,6 +609,11 @@ optimization_problem_solution_t<i_t, f_t> solve_lp(optimization_problem_t<i_t, f
CUOPT_LOG_INFO("Third party presolve time: %f", presolve_time);
}

if (settings.user_problem_file != "") {
CUOPT_LOG_INFO("Writing user problem to file: %s", settings.user_problem_file.c_str());
problem.write_as_mps(settings.user_problem_file);
}

CUOPT_LOG_INFO(
"Solving a problem with %d constraints %d variables (%d integers) and %d nonzeros",
problem.n_constraints,
Expand Down
30 changes: 20 additions & 10 deletions cpp/src/mip/presolve/third_party_presolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,19 @@
* limitations under the License.
*/

#include <cuopt/error.hpp>
#include <cuopt/logger.hpp>
#include <mip/mip_constants.hpp>
#include <mip/presolve/third_party_presolve.hpp>

#include <papilo/core/Presolve.hpp>
#include <papilo/core/ProblemBuilder.hpp>
// #include <utilities/copy_helpers.hpp>
#include <cuopt/error.hpp>
#include <cuopt/logger.hpp>

namespace cuopt::linear_programming::detail {

static papilo::PostsolveStorage<double> post_solve_storage_;
static int presolve_calls_ = 0;
static bool maximize_ = false;

template <typename i_t, typename f_t>
papilo::Problem<f_t> build_papilo_problem(const optimization_problem_t<i_t, f_t>& op_problem)
Expand All @@ -39,10 +40,6 @@ papilo::Problem<f_t> build_papilo_problem(const optimization_problem_t<i_t, f_t>
const i_t num_rows = op_problem.get_n_constraints();
const i_t nnz = op_problem.get_nnz();

cuopt_expects(op_problem.get_sense() == false,
error_type_t::ValidationError,
"Papilo does not support maximization problems");

builder.reserve(nnz, num_rows, num_cols);

// Get problem data from optimization problem
Expand Down Expand Up @@ -83,6 +80,13 @@ papilo::Problem<f_t> build_papilo_problem(const optimization_problem_t<i_t, f_t>
std::vector<var_t> h_var_types(var_types.size());
raft::copy(h_var_types.data(), var_types.data(), var_types.size(), stream_view);

maximize_ = op_problem.get_sense();
if (maximize_) {
for (size_t i = 0; i < h_obj_coeffs.size(); ++i) {
h_obj_coeffs[i] = -h_obj_coeffs[i];
}
}

auto constr_bounds_empty = h_constr_lb.empty() && h_constr_ub.empty();
if (constr_bounds_empty) {
for (size_t i = 0; i < h_row_types.size(); ++i) {
Expand All @@ -103,7 +107,8 @@ papilo::Problem<f_t> build_papilo_problem(const optimization_problem_t<i_t, f_t>
builder.setNumRows(num_rows);

builder.setObjAll(h_obj_coeffs);
builder.setObjOffset(op_problem.get_objective_offset());
builder.setObjOffset(maximize_ ? -op_problem.get_objective_offset()
: op_problem.get_objective_offset());

if (!h_var_lb.empty() && !h_var_ub.empty()) {
builder.setColLbAll(h_var_lb);
Expand Down Expand Up @@ -149,7 +154,8 @@ optimization_problem_t<i_t, f_t> build_optimization_problem(
optimization_problem_t<i_t, f_t> op_problem(handle_ptr);

auto obj = papilo_problem.getObjective();
op_problem.set_objective_offset(obj.offset);
op_problem.set_objective_offset(maximize_ ? -obj.offset : obj.offset);
op_problem.set_maximize(maximize_);

if (papilo_problem.getNRows() == 0 && papilo_problem.getNCols() == 0) {
// FIXME: Shouldn't need to set offsets
Expand All @@ -165,7 +171,11 @@ optimization_problem_t<i_t, f_t> build_optimization_problem(

return op_problem;
}

if (maximize_) {
for (size_t i = 0; i < obj.coefficients.size(); ++i) {
obj.coefficients[i] = -obj.coefficients[i];
}
}
op_problem.set_objective_coefficients(obj.coefficients.data(), obj.coefficients.size());

auto& constraint_matrix = papilo_problem.getConstraintMatrix();
Expand Down
14 changes: 8 additions & 6 deletions cpp/src/mip/problem/problem_helpers.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,14 @@ static void convert_to_maximization_problem(detail::problem_t<i_t, f_t>& op_prob
{
raft::common::nvtx::range scope("convert_to_maximization_problem");

// Negate objective coefficient
raft::linalg::unaryOp(op_problem.objective_coefficients.data(),
op_problem.objective_coefficients.data(),
op_problem.objective_coefficients.size(),
detail::negate<f_t>(),
op_problem.handle_ptr->get_stream());
if (op_problem.objective_coefficients.size()) {
// Negate objective coefficient
raft::linalg::unaryOp(op_problem.objective_coefficients.data(),
op_problem.objective_coefficients.data(),
op_problem.objective_coefficients.size(),
detail::negate<f_t>(),
op_problem.handle_ptr->get_stream());
}
// Negate objective scaling factor and objective offset so that primal / dual stay same sign after
// negating objective coeffs
op_problem.presolve_data.objective_scaling_factor =
Expand Down
1 change: 0 additions & 1 deletion cpp/src/mip/solve.cu
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ mip_solution_t<i_t, f_t> solve_mip(optimization_problem_t<i_t, f_t>& op_problem,
detail::problem_t<i_t, f_t> problem(op_problem, settings.get_tolerances());

auto run_presolve = settings.presolve;
run_presolve = run_presolve && op_problem.get_sense() == false;
run_presolve = run_presolve && settings.get_mip_callbacks().empty();

if (!run_presolve) { CUOPT_LOG_INFO("Presolve is disabled, skipping"); }
Expand Down
1 change: 1 addition & 0 deletions cpp/tests/mip/doc_example_test.cu
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ TEST(docs, user_problem_file)

settings.time_limit = test_time_limit;
settings.user_problem_file = user_problem_path;
settings.presolve = false;
EXPECT_EQ(solve_mip(&handle_, problem, settings).get_termination_status(),
mip_termination_status_t::Optimal);

Expand Down