Skip to content

Commit

Permalink
Corrected TEST_CASE("IP-infeasible-unbounded" now that kInfeasible an…
Browse files Browse the repository at this point in the history
…d kUnbounded are distinguished when presolve is off
  • Loading branch information
jajhall committed Nov 5, 2024
1 parent 919774e commit 5e6ec3e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 7 deletions.
13 changes: 11 additions & 2 deletions check/TestMipSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,8 +677,17 @@ TEST_CASE("IP-infeasible-unbounded", "[highs_test_mip_solver]") {
// Solve
highs.passModel(lp);
highs.run();
REQUIRE(highs.getModelStatus() ==
HighsModelStatus::kUnboundedOrInfeasible);
HighsModelStatus required_model_status;
if (k == 0) {
if (l == 0) {
required_model_status = HighsModelStatus::kInfeasible;
} else {
required_model_status = HighsModelStatus::kUnbounded;
}
} else {
required_model_status = HighsModelStatus::kUnboundedOrInfeasible;
}
REQUIRE(highs.getModelStatus() == required_model_status);
}
highs.setOptionValue("presolve", kHighsOnString);
}
Expand Down
9 changes: 8 additions & 1 deletion src/mip/HighsMipSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,14 @@ void HighsMipSolver::run() {
}
// Apply the trivial heuristics
analysis_.mipTimerStart(kMipClockTrivialHeuristics);
mipdata_->trivialHeuristics();
HighsModelStatus model_status = mipdata_->trivialHeuristics();
if (modelstatus_ == HighsModelStatus::kNotset &&
model_status == HighsModelStatus::kInfeasible) {
// trivialHeuristics can spot trivial infeasibility, so act on it
modelstatus_ = model_status;
cleanupSolve();
return;
}
analysis_.mipTimerStop(kMipClockTrivialHeuristics);
if (analysis_.analyse_mip_time & !submip)
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
Expand Down
13 changes: 10 additions & 3 deletions src/mip/HighsMipSolverData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ bool HighsMipSolverData::solutionRowFeasible(
return true;
}

void HighsMipSolverData::trivialHeuristics() {
HighsModelStatus HighsMipSolverData::trivialHeuristics() {
// printf("\nHighsMipSolverData::trivialHeuristics() Number of continuous
// columns is %d\n",
// int(continuous_cols.size()));
Expand All @@ -176,8 +176,8 @@ void HighsMipSolverData::trivialHeuristics() {
kSolutionSourceTrivialZ, kSolutionSourceTrivialL, kSolutionSourceTrivialU,
kSolutionSourceTrivialP};

const std::vector<double>& col_lower = mipsolver.model_->col_lower_;
const std::vector<double>& col_upper = mipsolver.model_->col_upper_;
std::vector<double> col_lower = mipsolver.model_->col_lower_;
std::vector<double> col_upper = mipsolver.model_->col_upper_;
const std::vector<double>& row_lower = mipsolver.model_->row_lower_;
const std::vector<double>& row_upper = mipsolver.model_->row_upper_;
const HighsSparseMatrix& matrix = mipsolver.model_->a_matrix_;
Expand All @@ -189,6 +189,12 @@ void HighsMipSolverData::trivialHeuristics() {
bool all_integer_upper_finite = true;
for (HighsInt integer_col = 0; integer_col < numintegercols; integer_col++) {
HighsInt iCol = integer_cols[integer_col];
// Round bounds in to nearest integer
col_lower[iCol] = std::ceil(col_lower[iCol]);
col_upper[iCol] = std::floor(col_upper[iCol]);
// If bounds are inconsistent then MIP is infeasible
if (col_lower[iCol] > col_upper[iCol]) return HighsModelStatus::kInfeasible;

if (col_lower[iCol] > 0) all_integer_lower_non_positive = false;
if (col_lower[iCol]) all_integer_lower_zero = false;
if (col_lower[iCol] <= -kHighsInf) all_integer_lower_finite = false;
Expand Down Expand Up @@ -288,6 +294,7 @@ void HighsMipSolverData::trivialHeuristics() {
}
}
}
return HighsModelStatus::kNotset;
}

void HighsMipSolverData::startAnalyticCenterComputation(
Expand Down
2 changes: 1 addition & 1 deletion src/mip/HighsMipSolverData.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ struct HighsMipSolverData {
}

bool solutionRowFeasible(const std::vector<double>& solution) const;
void trivialHeuristics();
HighsModelStatus trivialHeuristics();

void startAnalyticCenterComputation(
const highs::parallel::TaskGroup& taskGroup);
Expand Down

0 comments on commit 5e6ec3e

Please sign in to comment.