diff --git a/check/TestMipSolver.cpp b/check/TestMipSolver.cpp index 47daf516b0..8dc098df34 100644 --- a/check/TestMipSolver.cpp +++ b/check/TestMipSolver.cpp @@ -616,6 +616,43 @@ TEST_CASE("MIP-max-offset-test", "[highs_test_mip_solver]") { dev_run)); } +TEST_CASE("MIP-get-saved-solutions-presolve", "[highs_test_mip_solver]") { + const std::string solution_file = "MipImproving.sol"; + Highs highs; + highs.setOptionValue("output_flag", dev_run); + highs.setOptionValue("mip_improving_solution_save", true); + highs.setOptionValue("mip_improving_solution_report_sparse", true); + highs.setOptionValue("mip_improving_solution_file", solution_file); + // #1724: Add row to the example so that solution is non-zero + HighsLp lp; + lp.num_col_ = 2; + lp.num_row_ = 1; + lp.col_cost_ = {1, 1}; + lp.col_lower_ = {0, 0}; + lp.col_upper_ = {1, 1}; + lp.integrality_ = {HighsVarType::kInteger, HighsVarType::kInteger}; + lp.row_lower_ = {1}; + lp.row_upper_ = {kHighsInf}; + lp.a_matrix_.num_col_ = 2; + lp.a_matrix_.num_row_ = 1; + lp.a_matrix_.start_ = {0, 1, 1}; + lp.a_matrix_.index_ = {0}; + lp.a_matrix_.value_ = {1}; + highs.passModel(lp); + highs.run(); + const std::vector saved_objective_and_solution = + highs.getSavedMipSolutions(); + const HighsInt num_saved_solution = saved_objective_and_solution.size(); + REQUIRE(num_saved_solution == 1); + const HighsInt last_saved_solution = num_saved_solution - 1; + REQUIRE(saved_objective_and_solution[last_saved_solution].objective == + highs.getInfo().objective_function_value); + for (HighsInt iCol = 0; iCol < highs.getLp().num_col_; iCol++) + REQUIRE(saved_objective_and_solution[last_saved_solution].col_value[iCol] == + highs.getSolution().col_value[iCol]); + std::remove(solution_file.c_str()); +} + bool objectiveOk(const double optimal_objective, const double require_optimal_objective, const bool dev_run) { double error = std::fabs(optimal_objective - require_optimal_objective) / diff --git a/src/mip/HighsMipSolver.cpp b/src/mip/HighsMipSolver.cpp index 5357d5b07d..2108729c3e 100644 --- a/src/mip/HighsMipSolver.cpp +++ b/src/mip/HighsMipSolver.cpp @@ -128,6 +128,7 @@ void HighsMipSolver::run() { mipdata_->lower_bound = 0; mipdata_->upper_bound = 0; mipdata_->transformNewIntegerFeasibleSolution(std::vector()); + mipdata_->saveReportMipSolution(); } cleanupSolve(); return; diff --git a/src/mip/HighsMipSolverData.cpp b/src/mip/HighsMipSolverData.cpp index 4dcbbf0a5f..bd2da45224 100644 --- a/src/mip/HighsMipSolverData.cpp +++ b/src/mip/HighsMipSolverData.cpp @@ -1908,16 +1908,6 @@ void HighsMipSolverData::saveReportMipSolution(const double new_upper_limit) { if (mipsolver.submip) return; if (non_improving) return; - /* - printf( - "%7s dimension(%d, %d) " - "%4simproving solution: numImprovingSols = %4d; Limits (%11.4g, " - "%11.4g); Objective = %11.4g\n", - mipsolver.submip ? "Sub-MIP" : "MIP ", mipsolver.model_->num_col_, - mipsolver.model_->num_row_, non_improving ? "non-" : "", - int(numImprovingSols), new_upper_limit, upper_limit, - mipsolver.solution_objective_); - */ if (mipsolver.callback_->user_callback) { if (mipsolver.callback_->active[kCallbackMipImprovingSolution]) { mipsolver.callback_->clearHighsCallbackDataOut(); diff --git a/src/mip/HighsMipSolverData.h b/src/mip/HighsMipSolverData.h index e3ee72f900..07a17e23f6 100644 --- a/src/mip/HighsMipSolverData.h +++ b/src/mip/HighsMipSolverData.h @@ -158,7 +158,7 @@ struct HighsMipSolverData { void checkObjIntegrality(); void runPresolve(const HighsInt presolve_reduction_limit); void setupDomainPropagation(); - void saveReportMipSolution(const double new_upper_limit); + void saveReportMipSolution(const double new_upper_limit = -kHighsInf); void runSetup(); double transformNewIntegerFeasibleSolution( const std::vector& sol,