Skip to content

Commit

Permalink
Merge pull request #1750 from ERGO-Code/fix-1691
Browse files Browse the repository at this point in the history
Fix 1691
  • Loading branch information
jajhall committed May 6, 2024
2 parents ae25abb + 3642900 commit b29d344
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
24 changes: 23 additions & 1 deletion check/TestBasis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ TEST_CASE("set-pathological-basis", "[highs_basis_data]") {
// Set up a basis with everything nonbasic. This will lead to
// basic_index being empty when passed to
// HFactor::setupGeneral. Previously this led to the creation of
// pointer &basic_index[0] that caused Windows faiure referenced in
// pointer &basic_index[0] that caused Windows failure referenced in
// #1129, and reported in #1166. However, now that
// basic_index.data() is used to create the pointer, there is no
// Windows failure. Within HFactor::setupGeneral and
Expand Down Expand Up @@ -156,6 +156,28 @@ TEST_CASE("Basis-no-basic", "[highs_basis_data]") {
REQUIRE(highs.getModelStatus() == HighsModelStatus::kOptimal);
}

TEST_CASE("Basis-singular", "[highs_basis_data]") {
Highs highs;
highs.setOptionValue("output_flag", dev_run);
HighsLp lp;
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {1, 1};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {1, 1};
lp.row_lower_ = {1, 1};
lp.row_upper_ = {2, 2};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {1, 2, 2, 4};
highs.passModel(lp);
HighsBasis basis;
REQUIRE(highs.setBasis(basis) == HighsStatus::kError);
basis.col_status = {HighsBasisStatus::kBasic, HighsBasisStatus::kBasic};
basis.row_status = {HighsBasisStatus::kLower, HighsBasisStatus::kLower};
REQUIRE(highs.setBasis(basis) == HighsStatus::kOk);
}

// No commas in test case name.
void testBasisReloadModel(Highs& highs, const bool from_file) {
// Checks that no simplex iterations are required if a saved optimal
Expand Down
14 changes: 14 additions & 0 deletions check/TestCheckSolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,20 @@ TEST_CASE("check-set-mip-solution-extra-row", "[highs_check_solution]") {
std::remove(solution_file_name.c_str());
}

TEST_CASE("check-set-illegal-solution", "[highs_check_solution]") {
HighsStatus return_status;
std::string model_file =
std::string(HIGHS_DIR) + "/check/instances/avgas.mps";
Highs highs;
highs.setOptionValue("output_flag", dev_run);
highs.readModel(model_file);
const HighsLp& lp = highs.getLp();
HighsSolution solution;
REQUIRE(highs.setSolution(solution) == HighsStatus::kError);
solution.col_value.assign(lp.num_col_, 0);
REQUIRE(highs.setSolution(solution) == HighsStatus::kOk);
}

void runWriteReadCheckSolution(Highs& highs, const std::string model,
const HighsModelStatus require_model_status,
const HighsInt write_solution_style) {
Expand Down
26 changes: 25 additions & 1 deletion src/lp_data/Highs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,20 @@ HighsStatus Highs::setSolution(const HighsSolution& solution) {
solution.row_dual.size() >= static_cast<size_t>(model_.lp_.num_row_);
const bool new_solution = new_primal_solution || new_dual_solution;

if (new_solution) invalidateUserSolverData();
if (new_solution) {
invalidateUserSolverData();
} else {
// Solution is rejected, so give a logging message and error
// return
highsLogUser(
options_.log_options, HighsLogType::kError,
"setSolution: User solution is rejected due to mismatch between "
"size of col_value and row_dual vectors (%d, %d) and number "
"of columns and rows in the model (%d, %d)\n",
int(solution.col_value.size()), int(solution.row_dual.size()),
int(model_.lp_.num_col_), int(model_.lp_.num_row_));
return_status = HighsStatus::kError;
}

if (new_primal_solution) {
solution_.col_value = solution.col_value;
Expand Down Expand Up @@ -2052,6 +2065,17 @@ HighsStatus Highs::setBasis(const HighsBasis& basis,
: basis.col_status[iCol];
basis_.alien = false;
} else {
// Check whether a new basis can be defined
if (!isBasisRightSize(model_.lp_, basis)) {
highsLogUser(
options_.log_options, HighsLogType::kError,
"setBasis: User basis is rejected due to mismatch between "
"size of column and row status vectors (%d, %d) and number "
"of columns and rows in the model (%d, %d)\n",
int(basis_.col_status.size()), int(basis_.row_status.size()),
int(model_.lp_.num_col_), int(model_.lp_.num_row_));
return HighsStatus::kError;
}
HighsBasis modifiable_basis = basis;
modifiable_basis.was_alien = true;
HighsLpSolverObject solver_object(model_.lp_, modifiable_basis, solution_,
Expand Down

0 comments on commit b29d344

Please sign in to comment.