From c16e22debb9ca097cb8fe3b3dbdc16a33372172f Mon Sep 17 00:00:00 2001 From: JAJHall Date: Sun, 5 Jan 2025 13:33:38 +0000 Subject: [PATCH] Given a basis, now performing presolve unless solver is simplex or choose --- check/TestIpm.cpp | 13 ++++--------- check/TestIpx.cpp | 4 ++-- src/ipm/IpxWrapper.cpp | 13 ++++++------- src/ipm/IpxWrapper.h | 9 ++++----- src/lp_data/Highs.cpp | 12 +++++++++--- src/presolve/ICrashX.cpp | 4 ++-- 6 files changed, 27 insertions(+), 28 deletions(-) diff --git a/check/TestIpm.cpp b/check/TestIpm.cpp index 3fb35dd9ab..dd59b96aea 100644 --- a/check/TestIpm.cpp +++ b/check/TestIpm.cpp @@ -140,21 +140,16 @@ TEST_CASE("test-2087", "[highs_ipm]") { // since optimal basis cannot be used, and ensure that the offset is // used in IPX Highs h; - // h.setOptionValue("output_flag", dev_run); + h.setOptionValue("output_flag", dev_run); // Use shell since it yields an offset after presolve std::string model = "shell.mps"; std::string filename = std::string(HIGHS_DIR) + "/check/instances/" + model; h.readModel(filename); h.setOptionValue("solver", kIpmString); - // if (dev_run) - printf("\nFirst call to Highs::run() with presolve:\n"); h.run(); - - // if (dev_run) - printf("\nSecond call to Highs::run() with presolve:\n"); - h.run(); - - + const HighsInt first_ipm_iteration_count = h.getInfo().ipm_iteration_count; + h.run(); + REQUIRE(first_ipm_iteration_count == h.getInfo().ipm_iteration_count); } diff --git a/check/TestIpx.cpp b/check/TestIpx.cpp index 5d53135d95..a53a199710 100644 --- a/check/TestIpx.cpp +++ b/check/TestIpx.cpp @@ -48,8 +48,8 @@ TEST_CASE("test-ipx", "[highs_ipx]") { lps.SetParameters(parameters); // Solve the LP. - Int load_status = lps.LoadModel(num_var, offset, obj, lb, ub, num_constr, Ap, Ai, Ax, - rhs, constr_type); + Int load_status = lps.LoadModel(num_var, offset, obj, lb, ub, num_constr, Ap, + Ai, Ax, rhs, constr_type); REQUIRE(load_status == 0); highs::parallel::initialize_scheduler(); diff --git a/src/ipm/IpxWrapper.cpp b/src/ipm/IpxWrapper.cpp index 6aea46deeb..7a33b68199 100644 --- a/src/ipm/IpxWrapper.cpp +++ b/src/ipm/IpxWrapper.cpp @@ -154,8 +154,8 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, std::vector Ap, Ai; std::vector objective, col_lb, col_ub, Av, rhs; std::vector constraint_type; - fillInIpxData(lp, num_col, num_row, offset, objective, col_lb, col_ub, Ap, Ai, Av, - rhs, constraint_type); + fillInIpxData(lp, num_col, num_row, offset, objective, col_lb, col_ub, Ap, Ai, + Av, rhs, constraint_type); highsLogUser(options.log_options, HighsLogType::kInfo, "IPX model has %" HIGHSINT_FORMAT " rows, %" HIGHSINT_FORMAT " columns and %" HIGHSINT_FORMAT " nonzeros\n", @@ -388,11 +388,10 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, } void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row, - double& offset, - std::vector& obj, std::vector& col_lb, - std::vector& col_ub, std::vector& Ap, - std::vector& Ai, std::vector& Ax, - std::vector& rhs, + double& offset, std::vector& obj, + std::vector& col_lb, std::vector& col_ub, + std::vector& Ap, std::vector& Ai, + std::vector& Ax, std::vector& rhs, std::vector& constraint_type) { num_col = lp.num_col_; num_row = lp.num_row_; diff --git a/src/ipm/IpxWrapper.h b/src/ipm/IpxWrapper.h index 777afd3d01..99486c2107 100644 --- a/src/ipm/IpxWrapper.h +++ b/src/ipm/IpxWrapper.h @@ -28,11 +28,10 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, HighsCallback& callback); void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row, - double& offset, - std::vector& obj, std::vector& col_lb, - std::vector& col_ub, std::vector& Ap, - std::vector& Ai, std::vector& Ax, - std::vector& rhs, + double& offset, std::vector& obj, + std::vector& col_lb, std::vector& col_ub, + std::vector& Ap, std::vector& Ai, + std::vector& Ax, std::vector& rhs, std::vector& constraint_type); HighsStatus reportIpxSolveStatus(const HighsOptions& options, diff --git a/src/lp_data/Highs.cpp b/src/lp_data/Highs.cpp index 1006ce43a0..61320a1b4a 100644 --- a/src/lp_data/Highs.cpp +++ b/src/lp_data/Highs.cpp @@ -1260,10 +1260,16 @@ HighsStatus Highs::solve() { const bool unconstrained_lp = incumbent_lp.a_matrix_.numNz() == 0; assert(incumbent_lp.num_row_ || unconstrained_lp); - if (basis_.valid || options_.presolve == kHighsOffString || - unconstrained_lp) { + // Even if options_.solver == kHighsChooseString in isolation will, + // untimately lead to a choice between simplex and IPM, if a basis + // is available, simplex should surely be chosen. + const bool solver_will_use_basis = options_.solver == kSimplexString || + options_.solver == kHighsChooseString; + if ((basis_.valid || options_.presolve == kHighsOffString || + unconstrained_lp) && + solver_will_use_basis) { // There is a valid basis for the problem, presolve is off, or LP - // has no constraint matrix + // has no constraint matrix, and the solver will use the basis ekk_instance_.lp_name_ = "LP without presolve, or with basis, or unconstrained"; // If there is a valid HiGHS basis, refine any status values that diff --git a/src/presolve/ICrashX.cpp b/src/presolve/ICrashX.cpp index 1cdec57428..45e0c9cc5e 100644 --- a/src/presolve/ICrashX.cpp +++ b/src/presolve/ICrashX.cpp @@ -25,8 +25,8 @@ HighsStatus callCrossover(const HighsOptions& options, const HighsLp& lp, std::vector objective, col_lb, col_ub, Av, rhs; std::vector constraint_type; - fillInIpxData(lp, num_col, num_row, offset, objective, col_lb, col_ub, Ap, Ai, Av, - rhs, constraint_type); + fillInIpxData(lp, num_col, num_row, offset, objective, col_lb, col_ub, Ap, Ai, + Av, rhs, constraint_type); // if (res != IpxStatus::OK) return HighsStatus::kError; const HighsLogOptions& log_options = options.log_options;