From 5af066f20b824eefb9d56d132ef5ef483bb20652 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 30 Jul 2023 23:10:35 +0000 Subject: [PATCH 1/3] ENH: Add exceptions --- src/util/HighsExceptions.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/util/HighsExceptions.h diff --git a/src/util/HighsExceptions.h b/src/util/HighsExceptions.h new file mode 100644 index 0000000000..412e233f56 --- /dev/null +++ b/src/util/HighsExceptions.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class DataStackOverflow : public std::runtime_error { +public: + explicit DataStackOverflow(const std::string& msg) + : std::runtime_error(msg) {} +}; + +class ProblemTooLargeException : public std::runtime_error { +public: + explicit ProblemTooLargeException(const std::string& msg) + : std::runtime_error(msg) {} +}; + + +class PresolveTooLarge : public std::runtime_error { +public: + explicit PresolveTooLarge(const std::string& msg) + : std::runtime_error(msg) {} +}; From 42568755e0a9b2c91352595194ec639b9a35e378 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 30 Jul 2023 23:10:47 +0000 Subject: [PATCH 2/3] MAINT: Use exceptions to propagate errors --- src/presolve/HPresolve.cpp | 10 +++++++++- src/presolve/HPresolve.h | 1 + src/presolve/HighsPostsolveStack.h | 27 +++++++++++++++++---------- src/util/HighsDataStack.h | 16 +++++++++++++--- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/presolve/HPresolve.cpp b/src/presolve/HPresolve.cpp index 9d9dfbbe18..88be03050b 100644 --- a/src/presolve/HPresolve.cpp +++ b/src/presolve/HPresolve.cpp @@ -18,6 +18,7 @@ #include #include "Highs.h" +#include "HighsExceptions.h" #include "io/HighsIO.h" #include "lp_data/HConst.h" #include "lp_data/HStruct.h" @@ -3993,7 +3994,14 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { } }; - HPRESOLVE_CHECKED_CALL(initialRowAndColPresolve(postsolve_stack)); + try { + HPRESOLVE_CHECKED_CALL(initialRowAndColPresolve(postsolve_stack)); + } catch (const DataStackOverflow& e) { + highsLogUser(options->log_options, HighsLogType::kInfo, + "Problem is too large to be presolved\n"); + // Here we re-throw the error + throw; + } HighsInt numParallelRowColCalls = 0; #if ENABLE_SPARSIFY_FOR_LP diff --git a/src/presolve/HPresolve.h b/src/presolve/HPresolve.h index 7017c1fa21..936d74a2ef 100644 --- a/src/presolve/HPresolve.h +++ b/src/presolve/HPresolve.h @@ -33,6 +33,7 @@ #include "util/HighsHash.h" #include "util/HighsLinearSumBounds.h" #include "util/HighsMatrixSlice.h" +#include "util/HighsExceptions.h" namespace presolve { diff --git a/src/presolve/HighsPostsolveStack.h b/src/presolve/HighsPostsolveStack.h index 3633056f88..6aad96796f 100644 --- a/src/presolve/HighsPostsolveStack.h +++ b/src/presolve/HighsPostsolveStack.h @@ -24,6 +24,7 @@ #include #include +#include "HighsExceptions.h" #include "lp_data/HConst.h" #include "lp_data/HStruct.h" #include "lp_data/HighsOptions.h" @@ -367,17 +368,23 @@ class HighsPostsolveStack { template void fixedColAtLower(HighsInt col, double fixValue, double colCost, const HighsMatrixSlice& colVec) { - assert(std::isfinite(fixValue)); - colValues.clear(); - for (const HighsSliceNonzero& colVal : colVec) - colValues.emplace_back(origRowIndex[colVal.index()], colVal.value()); - - reductionValues.push(FixedCol{fixValue, colCost, origColIndex[col], - HighsBasisStatus::kLower}); - reductionValues.push(colValues); - reductionAdded(ReductionType::kFixedCol); + try { + assert(std::isfinite(fixValue)); + colValues.clear(); + for (const HighsSliceNonzero& colVal : colVec) + colValues.emplace_back(origRowIndex[colVal.index()], colVal.value()); + + reductionValues.push(FixedCol{fixValue, colCost, origColIndex[col], + HighsBasisStatus::kLower}); + reductionValues.push(colValues); + reductionAdded(ReductionType::kFixedCol); + } catch (const DataStackOverflow& e) { + std::cerr << "Memory allocation failed while processing fixedColAtLower: " + << e.what() << std::endl; + // Rethrow. + throw; + } } - template void fixedColAtUpper(HighsInt col, double fixValue, double colCost, const HighsMatrixSlice& colVec) { diff --git a/src/util/HighsDataStack.h b/src/util/HighsDataStack.h index 4a4be05601..d9f15afc45 100644 --- a/src/util/HighsDataStack.h +++ b/src/util/HighsDataStack.h @@ -18,9 +18,11 @@ #define UTIL_HIGHS_DATA_STACK_H_ #include +#include #include #include +#include "util/HighsExceptions.h" #include "util/HighsInt.h" #if __GNUG__ && __GNUC__ < 5 @@ -39,11 +41,19 @@ class HighsDataStack { template ::type = 0> void push(const T& r) { - std::size_t dataSize = data.size(); - data.resize(dataSize + sizeof(T)); + HighsInt dataSize = data.size(); + HighsInt newSize = dataSize + sizeof(T); + try { + data.resize(newSize); + } catch (const std::length_error& e) { + throw DataStackOverflow( + "Failed to resize the vector. Requested new size: " + + std::to_string(newSize) + ". Size to add is " + + std::to_string(sizeof(T)) + "for "+ + ". Current size: " + std::to_string(data.size()) + "."); + } std::memcpy(data.data() + dataSize, &r, sizeof(T)); } - template ::type = 0> void pop(T& r) { From 31d630ffb2871dc24dab6106baf103adb0713b19 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Mon, 31 Jul 2023 02:33:37 +0000 Subject: [PATCH 3/3] MAINT: Cleanup and propagate correct exceptions --- src/Highs.h | 1 + src/presolve/HPresolve.cpp | 4 +--- src/presolve/HighsPostsolveStack.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Highs.h b/src/Highs.h index 4122482286..908471fd19 100644 --- a/src/Highs.h +++ b/src/Highs.h @@ -22,6 +22,7 @@ #include "lp_data/HighsRanging.h" #include "lp_data/HighsSolutionDebug.h" #include "model/HighsModel.h" +#include "util/HighsExceptions.h" #include "presolve/ICrash.h" #include "presolve/PresolveComponent.h" diff --git a/src/presolve/HPresolve.cpp b/src/presolve/HPresolve.cpp index 88be03050b..e5a078401a 100644 --- a/src/presolve/HPresolve.cpp +++ b/src/presolve/HPresolve.cpp @@ -3997,10 +3997,8 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { try { HPRESOLVE_CHECKED_CALL(initialRowAndColPresolve(postsolve_stack)); } catch (const DataStackOverflow& e) { - highsLogUser(options->log_options, HighsLogType::kInfo, - "Problem is too large to be presolved\n"); // Here we re-throw the error - throw; + throw PresolveTooLarge(e.what()); } HighsInt numParallelRowColCalls = 0; diff --git a/src/presolve/HighsPostsolveStack.h b/src/presolve/HighsPostsolveStack.h index 6aad96796f..abd5c84608 100644 --- a/src/presolve/HighsPostsolveStack.h +++ b/src/presolve/HighsPostsolveStack.h @@ -380,7 +380,7 @@ class HighsPostsolveStack { reductionAdded(ReductionType::kFixedCol); } catch (const DataStackOverflow& e) { std::cerr << "Memory allocation failed while processing fixedColAtLower: " - << e.what() << std::endl; + << std::endl; // Rethrow. throw; }