Skip to content

Commit

Permalink
Merge pull request #1742 from ERGO-Code/fix-1724
Browse files Browse the repository at this point in the history
Now calling saveReportMipSolution when presolve reduces MIP to empty
  • Loading branch information
jajhall committed May 7, 2024
2 parents 0bd3176 + 053a624 commit d146930
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 11 deletions.
37 changes: 37 additions & 0 deletions check/TestMipSolver.cpp
Expand Up @@ -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<HighsObjectiveSolution> 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) /
Expand Down
1 change: 1 addition & 0 deletions src/mip/HighsMipSolver.cpp
Expand Up @@ -128,6 +128,7 @@ void HighsMipSolver::run() {
mipdata_->lower_bound = 0;
mipdata_->upper_bound = 0;
mipdata_->transformNewIntegerFeasibleSolution(std::vector<double>());
mipdata_->saveReportMipSolution();
}
cleanupSolve();
return;
Expand Down
10 changes: 0 additions & 10 deletions src/mip/HighsMipSolverData.cpp
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/mip/HighsMipSolverData.h
Expand Up @@ -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<double>& sol,
Expand Down

0 comments on commit d146930

Please sign in to comment.