Repository: ERGO-Code/HiGHS (language: python)

Issue:
WARNING: LP matrix packed vector contains 2 |values| in [0, 0] less than or equal to 1e-09: ignore
With the `latest` branch (not with 1.7.2), I get lots of the following warnings:
`WARNING: LP matrix packed vector contains 2 |values| in [0, 0] less than or equal to 1e-09: ignore`

I guess that's because I'm adding constraints (using highspy) with a coefficient of `0` for some variables. There is some code that computes these coefficients and some end up as `0`. Is that a problem? Is there a way to silence these warnings?


Discussion / hints:
If my memory serves me correctly, this was added because someone wanted to know the reason why they were getting a warning back from methods like `addRow`. 

Since there's no loss of data if explicit zeros are ignored, I could suppress the warning and return `HighsStatus::kOk` in this case. 

Fix patch:
diff --git a/FEATURES.md b/FEATURES.md
index f0a52fcf7f..170a933885 100644
--- a/FEATURES.md
+++ b/FEATURES.md
@@ -16,6 +16,13 @@ Added `Highs::feasibilityRelaxation` to solve the problem of minimizing a (possi
 
 Added Python utility `examples/plot_highs_log.py` (due to @Thell) to visualise progress of the MIP solver.
 
+Added minimal documentation of solvers and how simplex variants can be run
+
+Methods receiving matrix data where only small values are explicit zeros (so removed internally) are now silent and return HighsStatus::kOk (since internal matrix is exact)
+
+
+
+
 
 
 
diff --git a/check/TestLpModification.cpp b/check/TestLpModification.cpp
index b34cf18cae..ea55d16264 100644
--- a/check/TestLpModification.cpp
+++ b/check/TestLpModification.cpp
@@ -1937,3 +1937,20 @@ TEST_CASE("modify-empty-model", "[highs_data]") {
   REQUIRE(highs.changeColBounds(0, 1, 1) == HighsStatus::kError);
   REQUIRE(highs.changeRowBounds(0, 1, 1) == HighsStatus::kError);
 }
+
+TEST_CASE("zero-matrix-entries", "[highs_data]") {
+  Highs highs;
+  highs.setOptionValue("output_flag", dev_run);
+  HighsLp lp;
+  lp.num_col_ = 2;
+  lp.num_row_ = 2;
+  lp.col_cost_ = {0, 0};
+  lp.col_lower_ = {0, 0};
+  lp.col_upper_ = {1, 1};
+  lp.row_lower_ = {-kHighsInf, -kHighsInf};
+  lp.row_upper_ = {5, 8};
+  lp.a_matrix_.start_ = {0, 2, 4};
+  lp.a_matrix_.index_ = {0, 1, 0, 1};
+  lp.a_matrix_.value_ = {1, 0, 0, 1};
+  REQUIRE(highs.passModel(lp) == HighsStatus::kOk);
+}
diff --git a/check/TestLpValidation.cpp b/check/TestLpValidation.cpp
index bb0f71c1db..473fdeb681 100644
--- a/check/TestLpValidation.cpp
+++ b/check/TestLpValidation.cpp
@@ -94,7 +94,7 @@ TEST_CASE("LP-dimension-validation", "[highs_data]") {
   // Yields duplicate index, but values are still zero, so both are
   // discarded and a warning is returned
   lp.a_matrix_.index_[0] = 0;
-  REQUIRE(highs.passModel(lp) == HighsStatus::kWarning);
+  REQUIRE(highs.passModel(lp) == HighsStatus::kOk);
 
   if (dev_run)
     printf("Give nonzero a_matrix_.value_[0] and a_matrix_.value_[1]\n");
diff --git a/check/TestRays.cpp b/check/TestRays.cpp
index 0b9f6ecfbf..5a42d19bc5 100644
--- a/check/TestRays.cpp
+++ b/check/TestRays.cpp
@@ -303,6 +303,8 @@ void testUnboundedMpsLp(const std::string model,
   // Test dual ray for unbounded LP
   model_file = std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps";
   require_model_status = HighsModelStatus::kUnbounded;
+  // gas11 contains small nonzero matrix entries, so readModel yield
+  // HighsStatus::kWarning
   require_status = model == "gas11" ? HighsStatus::kWarning : HighsStatus::kOk;
   REQUIRE(highs.readModel(model_file) == require_status);
   REQUIRE(highs.changeObjectiveSense(sense) == HighsStatus::kOk);
diff --git a/src/util/HighsMatrixUtils.cpp b/src/util/HighsMatrixUtils.cpp
index 42f4375063..b55f4df79a 100644
--- a/src/util/HighsMatrixUtils.cpp
+++ b/src/util/HighsMatrixUtils.cpp
@@ -234,13 +234,18 @@ HighsStatus assessMatrix(
       error_found = true;
       assert(num_small_values == 0);
     }
-    highsLogUser(log_options, HighsLogType::kWarning,
-                 "%s matrix packed vector contains %" HIGHSINT_FORMAT
-                 " |values| in [%g, %g] "
-                 "less than or equal to %g: ignored\n",
-                 matrix_name.c_str(), num_small_values, min_small_value,
-                 max_small_value, small_matrix_value);
-    warning_found = true;
+    // If explicit zeros are ignored, then no model information is
+    // lost, so only report and return a warning if small nonzeros are
+    // ignored
+    if (max_small_value > 0) {
+      highsLogUser(log_options, HighsLogType::kWarning,
+                   "%s matrix packed vector contains %" HIGHSINT_FORMAT
+                   " |values| in [%g, %g] "
+                   "less than or equal to %g: ignored\n",
+                   matrix_name.c_str(), num_small_values, min_small_value,
+                   max_small_value, small_matrix_value);
+      warning_found = true;
+    }
   }
   matrix_start[num_vec] = num_new_nz;
   HighsStatus return_status = HighsStatus::kOk;


Test patch:
diff --git a/src/test/DevKkt.cpp b/src/test/DevKkt.cpp
index de393f7bf1..41f6db6848 100644
--- a/src/test/DevKkt.cpp
+++ b/src/test/DevKkt.cpp
@@ -261,10 +261,12 @@ void checkComplementarySlackness(const State& state,
         if (fabs(state.colDual[i]) > tol &&
             fabs(state.colValue[i] - state.colUpper[i]) > tol) {
           if (dev_print)
+            // clang-format off
             std::cout << "Comp. slackness fail: "
                       << "l[" << i << "]=" << state.colLower[i] << ", x[" << i
                       << "]=" << state.colValue[i] << ", z[" << i
                       << "]=" << state.colDual[i] << std::endl;
+          // clang-format on
           infeas = fabs(state.colDual[i]);
         }
       }