diff --git a/cpp/include/cuopt/linear_programming/constants.h b/cpp/include/cuopt/linear_programming/constants.h index 86becfe06..e1097455f 100644 --- a/cpp/include/cuopt/linear_programming/constants.h +++ b/cpp/include/cuopt/linear_programming/constants.h @@ -74,6 +74,7 @@ #define CUOPT_NUM_CPU_THREADS "num_cpu_threads" #define CUOPT_NUM_GPUS "num_gpus" #define CUOPT_USER_PROBLEM_FILE "user_problem_file" +#define CUOPT_PRESOLVE_FILE "presolve_file" #define CUOPT_RANDOM_SEED "random_seed" #define CUOPT_PDLP_PRECISION "pdlp_precision" diff --git a/cpp/include/cuopt/linear_programming/mip/solver_settings.hpp b/cpp/include/cuopt/linear_programming/mip/solver_settings.hpp index 2c92d2623..8f4a6c1d7 100644 --- a/cpp/include/cuopt/linear_programming/mip/solver_settings.hpp +++ b/cpp/include/cuopt/linear_programming/mip/solver_settings.hpp @@ -105,6 +105,7 @@ class mip_solver_settings_t { std::string log_file; std::string sol_file; std::string user_problem_file; + std::string presolve_file; /** Initial primal solutions */ std::vector>> initial_solutions; diff --git a/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp b/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp index d3f59144c..86ce4d8db 100644 --- a/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp +++ b/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp @@ -245,6 +245,7 @@ class pdlp_solver_settings_t { std::string log_file{""}; std::string sol_file{""}; std::string user_problem_file{""}; + std::string presolve_file{""}; bool per_constraint_residual{false}; bool crossover{false}; bool cudss_deterministic{false}; diff --git a/cpp/src/math_optimization/solver_settings.cu b/cpp/src/math_optimization/solver_settings.cu index a60d508fa..a8bc0ea33 100644 --- a/cpp/src/math_optimization/solver_settings.cu +++ b/cpp/src/math_optimization/solver_settings.cu @@ -131,7 +131,9 @@ solver_settings_t::solver_settings_t() : pdlp_settings(), mip_settings {CUOPT_SOLUTION_FILE, &mip_settings.sol_file, ""}, {CUOPT_SOLUTION_FILE, &pdlp_settings.sol_file, ""}, {CUOPT_USER_PROBLEM_FILE, &mip_settings.user_problem_file, ""}, - {CUOPT_USER_PROBLEM_FILE, &pdlp_settings.user_problem_file, ""} + {CUOPT_USER_PROBLEM_FILE, &pdlp_settings.user_problem_file, ""}, + {CUOPT_PRESOLVE_FILE, &mip_settings.presolve_file, ""}, + {CUOPT_PRESOLVE_FILE, &pdlp_settings.presolve_file, ""} }; // clang-format on } diff --git a/cpp/src/mip_heuristics/solve.cu b/cpp/src/mip_heuristics/solve.cu index f5a2172f2..07f4e7a86 100644 --- a/cpp/src/mip_heuristics/solve.cu +++ b/cpp/src/mip_heuristics/solve.cu @@ -283,6 +283,7 @@ mip_solution_t solve_mip(optimization_problem_t& op_problem, settings.tolerances.relative_tolerance, presolve_time_limit, settings.num_cpu_threads); + if (!result.has_value()) { return mip_solution_t(mip_termination_status_t::Infeasible, solver_stats_t{}, @@ -306,6 +307,10 @@ mip_solution_t solve_mip(optimization_problem_t& op_problem, CUOPT_LOG_INFO("Writing user problem to file: %s", settings.user_problem_file.c_str()); op_problem.write_to_mps(settings.user_problem_file); } + if (run_presolve && settings.presolve_file != "") { + CUOPT_LOG_INFO("Writing presolved problem to file: %s", settings.presolve_file.c_str()); + presolve_result->reduced_problem.write_to_mps(settings.presolve_file); + } auto sol = run_mip(problem, settings, timer); diff --git a/cpp/src/pdlp/solve.cu b/cpp/src/pdlp/solve.cu index 2fc9ec08d..19e0b93a8 100644 --- a/cpp/src/pdlp/solve.cu +++ b/cpp/src/pdlp/solve.cu @@ -1453,6 +1453,10 @@ optimization_problem_solution_t solve_lp( CUOPT_LOG_INFO("Writing user problem to file: %s", settings.user_problem_file.c_str()); op_problem.write_to_mps(settings.user_problem_file); } + if (run_presolve && settings.presolve_file != "") { + CUOPT_LOG_INFO("Writing presolved problem to file: %s", settings.presolve_file.c_str()); + result->reduced_problem.write_to_mps(settings.presolve_file); + } // Set the hyper-parameters based on the solver_settings if (use_pdlp_solver_mode) { set_pdlp_solver_mode(settings); }