From 9df7ca0c4d17c09edba1607a50db3a84051f2bed Mon Sep 17 00:00:00 2001 From: JAJHall Date: Wed, 17 Jan 2024 20:40:53 +0000 Subject: [PATCH] Applied fix-1584 mods to update master --- check/TestLpModification.cpp | 56 +++++++++++++++++++++++++++++++++++- check/TestLpSolvers.cpp | 4 +-- src/lp_data/HighsLpUtils.cpp | 15 ++++++++-- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/check/TestLpModification.cpp b/check/TestLpModification.cpp index 429bfecea0..f9b8e85df8 100644 --- a/check/TestLpModification.cpp +++ b/check/TestLpModification.cpp @@ -1,13 +1,14 @@ #include "Avgas.h" #include "HCheckConfig.h" #include "Highs.h" +#include "SpecialLps.h" #include "catch.hpp" #include "lp_data/HighsLpUtils.h" #include "util/HighsRandom.h" #include "util/HighsUtils.h" const bool dev_run = false; -const double inf = kHighsInf; +// const double inf = kHighsInf; const double double_equal_tolerance = 1e-5; void HighsStatusReport(const HighsLogOptions& log_options, std::string message, HighsStatus status); @@ -1874,3 +1875,56 @@ TEST_CASE("mod-duplicate-indices", "[highs_data]") { REQUIRE(objective0 < objective1); REQUIRE(objective0 == -7.75); } + +TEST_CASE("resize-integrality", "[highs_data]") { + Highs highs; + highs.setOptionValue("output_flag", dev_run); + SpecialLps special_lps; + HighsLp lp; + HighsModelStatus require_model_status; + double optimal_objective; + special_lps.distillationLp(lp, require_model_status, optimal_objective); + HighsInt original_num_col = lp.num_col_; + for (HighsInt k = 0; k < 4; k++) { + // k = 0: Add continuous column to LP, so final integrality.size() should be + // 0 + // + // k = 1: Add continuous column to IP, so final integrality.size() should be + // full + // + // k = 2: Add integer column to LP, so final integrality.size() should be + // full + // + // k = 3: Add integer column to IP, so final integrality.size() should be + // full + if (k == 1 || k == 3) { + lp.integrality_.assign(original_num_col, HighsVarType::kInteger); + } else { + lp.integrality_.clear(); + } + REQUIRE(highs.passModel(lp) == HighsStatus::kOk); + REQUIRE(highs.getNumCol() == original_num_col); + double cost = 0.0; + double lower = 0.0; + double upper = 1.0; + highs.addCols(1, &cost, &lower, &upper, 0, nullptr, nullptr, nullptr); + const std::vector& integrality = highs.getLp().integrality_; + if (k == 0 || k == 2) { + // Model is LP + REQUIRE(int(integrality.size()) == 0); + } else { + // Model is MIP + REQUIRE(int(integrality.size()) == int(original_num_col + 1)); + } + if (k >= 2) + REQUIRE(highs.changeColIntegrality(2, HighsVarType::kInteger) == + HighsStatus::kOk); + if (k == 0) { + // Model is LP + REQUIRE(int(integrality.size()) == 0); + } else { + // Model is MIP + REQUIRE(int(integrality.size()) == int(original_num_col + 1)); + } + } +} diff --git a/check/TestLpSolvers.cpp b/check/TestLpSolvers.cpp index e0aa7fab61..35e34cb022 100644 --- a/check/TestLpSolvers.cpp +++ b/check/TestLpSolvers.cpp @@ -279,7 +279,7 @@ TEST_CASE("LP-solver", "[highs_lp_solver]") { const HighsInfo& info = highs.getInfo(); REQUIRE(info.num_dual_infeasibilities == 0); - REQUIRE(info.simplex_iteration_count == 472); //476); // 444); + REQUIRE(info.simplex_iteration_count == 472); // 476); // 444); HighsModelStatus model_status = highs.getModelStatus(); REQUIRE(model_status == HighsModelStatus::kOptimal); @@ -292,7 +292,7 @@ TEST_CASE("LP-solver", "[highs_lp_solver]") { return_status = highs.run(); REQUIRE(return_status == HighsStatus::kOk); - REQUIRE(info.simplex_iteration_count == 592); //621); // 584); // + REQUIRE(info.simplex_iteration_count == 592); // 621); // 584); // } TEST_CASE("mip-with-lp-solver", "[highs_lp_solver]") { diff --git a/src/lp_data/HighsLpUtils.cpp b/src/lp_data/HighsLpUtils.cpp index 5d147cddca..cd9a4a97b2 100644 --- a/src/lp_data/HighsLpUtils.cpp +++ b/src/lp_data/HighsLpUtils.cpp @@ -1419,6 +1419,11 @@ void appendColsToLpVectors(HighsLp& lp, const HighsInt num_new_col, lp.col_cost_.resize(new_num_col); lp.col_lower_.resize(new_num_col); lp.col_upper_.resize(new_num_col); + const bool have_integrality = (lp.integrality_.size() != 0); + if (have_integrality) { + assert(HighsInt(lp.integrality_.size()) == lp.num_col_); + lp.integrality_.resize(new_num_col); + } bool have_names = (lp.col_names_.size() != 0); if (have_names) lp.col_names_.resize(new_num_col); for (HighsInt new_col = 0; new_col < num_new_col; new_col++) { @@ -1428,6 +1433,7 @@ void appendColsToLpVectors(HighsLp& lp, const HighsInt num_new_col, lp.col_upper_[iCol] = colUpper[new_col]; // Cannot guarantee to create unique names, so name is blank if (have_names) lp.col_names_[iCol] = ""; + if (have_integrality) lp.integrality_[iCol] = HighsVarType::kContinuous; } } @@ -1647,9 +1653,12 @@ void changeLpIntegrality(HighsLp& lp, // technique HighsInt lp_col; HighsInt usr_col = -1; - // May be adding integrality to a pure LP for which lp.integrality_ - // is of size 0. - lp.integrality_.resize(lp.num_col_); + // If changing integrality for a problem without an integrality + // vector (ie an LP), have to create it for the incumbent columns - + // which are naturally continuous + if (lp.integrality_.size() == 0) + lp.integrality_.assign(lp.num_col_, HighsVarType::kContinuous); + assert(HighsInt(lp.integrality_.size()) == lp.num_col_); for (HighsInt k = from_k; k < to_k + 1; k++) { if (interval || mask) { lp_col = k;