380 lines
13 KiB
Diff
380 lines
13 KiB
Diff
From e9525346e36552686c6f9266c7388791bb27cb0b Mon Sep 17 00:00:00 2001
|
|
From: fwesselm <fwesselm@mathworks.com>
|
|
Date: Wed, 11 Dec 2024 15:55:52 +0100
|
|
Subject: [PATCH 1/7] Fix detection of implied integral (already
|
|
integer-constrained) variables and implicit (continuous) integer variables
|
|
|
|
---
|
|
subprojects/highs/src/presolve/HPresolve.cpp | 24 +++++++++++++-------
|
|
1 file changed, 16 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/subprojects/highs/src/presolve/HPresolve.cpp b/subprojects/highs/src/presolve/HPresolve.cpp
|
|
index 5360c9e..d6dd158 100644
|
|
--- a/subprojects/highs/src/presolve/HPresolve.cpp
|
|
+++ b/subprojects/highs/src/presolve/HPresolve.cpp
|
|
@@ -223,6 +223,7 @@ void HPresolve::dualImpliedFreeGetRhsAndRowType(
|
|
}
|
|
|
|
bool HPresolve::isImpliedIntegral(HighsInt col) {
|
|
+ // check if the integer constraint on a variable is implied by the model
|
|
bool runDualDetection = true;
|
|
|
|
assert(model->integrality_[col] == HighsVarType::kInteger);
|
|
@@ -263,10 +264,15 @@ bool HPresolve::isImpliedIntegral(HighsInt col) {
|
|
|
|
if (!runDualDetection) return false;
|
|
|
|
+ bool impliedIntegral = true;
|
|
for (const HighsSliceNonzero& nz : getColumnVector(col)) {
|
|
double scale = 1.0 / nz.value();
|
|
- if (!rowCoefficientsIntegral(nz.index(), scale)) return false;
|
|
+ // if row coefficients are not integral, variable is not (implied) integral
|
|
+ bool rowIntegral = rowCoefficientsIntegral(nz.index(), scale);
|
|
+ impliedIntegral = impliedIntegral && rowIntegral;
|
|
+ if (!rowIntegral) continue;
|
|
if (model->row_upper_[nz.index()] != kHighsInf) {
|
|
+ // scale, round down and unscale right-hand side again
|
|
double rUpper =
|
|
std::abs(nz.value()) *
|
|
std::floor(model->row_upper_[nz.index()] * std::abs(scale) +
|
|
@@ -276,24 +282,26 @@ bool HPresolve::isImpliedIntegral(HighsInt col) {
|
|
model->row_upper_[nz.index()] = rUpper;
|
|
markChangedRow(nz.index());
|
|
}
|
|
- } else {
|
|
- assert(model->row_lower_[nz.index()] != -kHighsInf);
|
|
+ }
|
|
+ if (model->row_lower_[nz.index()] != -kHighsInf) {
|
|
+ // scale, round up and unscale left-hand side again
|
|
double rLower =
|
|
std::abs(nz.value()) *
|
|
- std::ceil(model->row_upper_[nz.index()] * std::abs(scale) -
|
|
+ std::ceil(model->row_lower_[nz.index()] * std::abs(scale) -
|
|
primal_feastol);
|
|
if (std::abs(model->row_lower_[nz.index()] - rLower) >
|
|
options->small_matrix_value) {
|
|
- model->row_upper_[nz.index()] = rLower;
|
|
+ model->row_lower_[nz.index()] = rLower;
|
|
markChangedRow(nz.index());
|
|
}
|
|
}
|
|
}
|
|
|
|
- return true;
|
|
+ return impliedIntegral;
|
|
}
|
|
|
|
bool HPresolve::isImpliedInteger(HighsInt col) {
|
|
+ // check if a non-integer variable is implied integer
|
|
bool runDualDetection = true;
|
|
|
|
assert(model->integrality_[col] == HighsVarType::kContinuous);
|
|
@@ -345,11 +353,11 @@ bool HPresolve::isImpliedInteger(HighsInt col) {
|
|
for (const HighsSliceNonzero& nz : getColumnVector(col)) {
|
|
double scale = 1.0 / nz.value();
|
|
if (model->row_upper_[nz.index()] != kHighsInf &&
|
|
- fractionality(model->row_upper_[nz.index()]) > primal_feastol)
|
|
+ fractionality(model->row_upper_[nz.index()] * scale) > primal_feastol)
|
|
return false;
|
|
|
|
if (model->row_lower_[nz.index()] != -kHighsInf &&
|
|
- fractionality(model->row_lower_[nz.index()]) > primal_feastol)
|
|
+ fractionality(model->row_lower_[nz.index()] * scale) > primal_feastol)
|
|
return false;
|
|
|
|
if (!rowCoefficientsIntegral(nz.index(), scale)) return false;
|
|
--
|
|
2.53.0
|
|
|
|
|
|
From 7f75cc45101d393b4247e0eec00c59dc2c46f58e Mon Sep 17 00:00:00 2001
|
|
From: Ivet Galabova <galabovaa@gmail.com>
|
|
Date: Mon, 13 Jan 2025 16:57:56 +0000
|
|
Subject: [PATCH 2/7] free gpu memory, localtermination wip
|
|
|
|
---
|
|
subprojects/highs/src/pdlp/CupdlpWrapper.cpp | 55 +++++++++++++------
|
|
.../highs/src/pdlp/cupdlp/cupdlp_linalg.c | 13 +++++
|
|
2 files changed, 51 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/subprojects/highs/src/pdlp/CupdlpWrapper.cpp b/subprojects/highs/src/pdlp/CupdlpWrapper.cpp
|
|
index 31fa31e..8d905da 100644
|
|
--- a/subprojects/highs/src/pdlp/CupdlpWrapper.cpp
|
|
+++ b/subprojects/highs/src/pdlp/CupdlpWrapper.cpp
|
|
@@ -66,8 +66,6 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer,
|
|
0.0; // true objVal = sig * c'x - offset, sig = 1 (min) or -1 (max)
|
|
double sense_origin = 1; // 1 (min) or -1 (max)
|
|
int* constraint_new_idx = NULL;
|
|
- cupdlp_float* x_origin = cupdlp_NULL;
|
|
- cupdlp_float* y_origin = cupdlp_NULL;
|
|
|
|
void* model = NULL;
|
|
void* presolvedmodel = NULL;
|
|
@@ -159,8 +157,6 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer,
|
|
// CUPDLP_CALL(LP_SolvePDHG(prob, ifChangeIntParam, intParam,
|
|
// ifChangeFloatParam, floatParam, fp));
|
|
|
|
- cupdlp_init_double(x_origin, nCols_origin);
|
|
- cupdlp_init_double(y_origin, nRows);
|
|
// Resize the highs_solution so cuPDLP-c can use it internally
|
|
highs_solution.col_value.resize(lp.num_col_);
|
|
highs_solution.row_value.resize(lp.num_row_);
|
|
@@ -208,19 +204,31 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer,
|
|
analysePdlpSolution(options, lp, highs_solution);
|
|
#endif
|
|
|
|
- free(cost);
|
|
- free(lower);
|
|
- free(upper);
|
|
- free(csc_beg);
|
|
- free(csc_idx);
|
|
- free(csc_val);
|
|
- free(rhs);
|
|
+ // free(cost);
|
|
+ // free(lower);
|
|
+ // free(upper);
|
|
+ // free(csc_beg);
|
|
+ // free(csc_idx);
|
|
+ // free(csc_val);
|
|
+ // free(rhs);
|
|
|
|
- free(x_origin);
|
|
- free(y_origin);
|
|
+ // free(constraint_new_idx);
|
|
|
|
- free(constraint_new_idx);
|
|
+ // Scaling
|
|
+#ifdef CUPDLP_CPU
|
|
|
|
+ if (scaling->rowScale != nullptr) free(scaling->rowScale);
|
|
+ if (scaling->colScale != nullptr) free(scaling->colScale);
|
|
+ free(scaling);
|
|
+
|
|
+#else
|
|
+ // free problem
|
|
+ if (scaling) {
|
|
+ scaling_clear(scaling);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+#ifdef CUPDLP_CPU
|
|
free(prob->cost);
|
|
free(prob->lower);
|
|
free(prob->upper);
|
|
@@ -248,10 +256,23 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer,
|
|
free(csc_cpu->colMatElem);
|
|
|
|
free(csc_cpu);
|
|
+#endif
|
|
|
|
- if (scaling->rowScale != nullptr) free(scaling->rowScale);
|
|
- if (scaling->colScale != nullptr) free(scaling->colScale);
|
|
- free(scaling);
|
|
+ if (cost != NULL) cupdlp_free(cost);
|
|
+ if (csc_beg != NULL) cupdlp_free(csc_beg);
|
|
+ if (csc_idx != NULL) cupdlp_free(csc_idx);
|
|
+ if (csc_val != NULL) cupdlp_free(csc_val);
|
|
+ if (rhs != NULL) cupdlp_free(rhs);
|
|
+ if (lower != NULL) cupdlp_free(lower);
|
|
+ if (upper != NULL) cupdlp_free(upper);
|
|
+ if (constraint_new_idx != NULL) cupdlp_free(constraint_new_idx);
|
|
+
|
|
+ // constraint type is std::vector
|
|
+ // if (constraint_type != NULL) cupdlp_free(constraint_type);
|
|
+
|
|
+ // free memory
|
|
+ csc_clear(csc_cpu);
|
|
+ problem_clear(prob);
|
|
|
|
return HighsStatus::kOk;
|
|
}
|
|
diff --git a/subprojects/highs/src/pdlp/cupdlp/cupdlp_linalg.c b/subprojects/highs/src/pdlp/cupdlp/cupdlp_linalg.c
|
|
index 8d28043..bf3e2fe 100644
|
|
--- a/subprojects/highs/src/pdlp/cupdlp/cupdlp_linalg.c
|
|
+++ b/subprojects/highs/src/pdlp/cupdlp/cupdlp_linalg.c
|
|
@@ -801,3 +801,16 @@ void cupdlp_compute_interaction_and_movement(CUPDLPwork *w,
|
|
cupdlp_sub(w->buffer3, iterates->aty->data, iterates->atyUpdate->data, nCols);
|
|
cupdlp_dot(w, nCols, w->buffer2, w->buffer3, dInteraction);
|
|
}
|
|
+
|
|
+double get_fabs_value(double* vec, int index) {
|
|
+#ifdef CUPDLP_CPU
|
|
+ return vec[index];
|
|
+#else
|
|
+ double result = 0;
|
|
+ int status = -1;
|
|
+ get_gpu_vec_element(vec, index, &result, &status);
|
|
+ if (!status)
|
|
+ return 0;
|
|
+ return result;
|
|
+#endif
|
|
+}
|
|
\ No newline at end of file
|
|
--
|
|
2.53.0
|
|
|
|
|
|
From 9efff0fc9ae0eb870ea8f6b5742ea9e17c90de52 Mon Sep 17 00:00:00 2001
|
|
From: Julian Hall <jajhall@ed.ac.uk>
|
|
Date: Thu, 11 Dec 2025 20:23:13 +0000
|
|
Subject: [PATCH 3/7] Modify version and URL for HiGHS release
|
|
|
|
Updated version and URL in CITATION.cff
|
|
---
|
|
subprojects/highs/CITATION.cff | 8 ++------
|
|
1 file changed, 2 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/subprojects/highs/CITATION.cff b/subprojects/highs/CITATION.cff
|
|
index 0987d34..da14abc 100644
|
|
--- a/subprojects/highs/CITATION.cff
|
|
+++ b/subprojects/highs/CITATION.cff
|
|
@@ -6,14 +6,10 @@ authors:
|
|
email: HighsOpt@gmail.com
|
|
- given-names: Ivet
|
|
family-names: Galabova
|
|
-- given-names: Leona
|
|
- family-names: Gottwald
|
|
-- given-names: Michael
|
|
- family-names: Feldmeier
|
|
title: "HiGHS"
|
|
-version: 1.2.2
|
|
+version: 1.12.0
|
|
date-released: 2022-04-18
|
|
-url: "https://github.com/ERGO-Code/HiGHS/releases/tag/v1.2.2"
|
|
+url: "https://github.com/ERGO-Code/HiGHS/releases/tag/v1.12.0"
|
|
preferred-citation:
|
|
type: article
|
|
authors:
|
|
--
|
|
2.53.0
|
|
|
|
|
|
From 7d971de3169912e449b2d2f8ab00f9f7be0968f0 Mon Sep 17 00:00:00 2001
|
|
From: Charalampos Stratakis <cstratak@redhat.com>
|
|
Date: Fri, 19 Dec 2025 17:42:13 +0100
|
|
Subject: [PATCH 4/7] Fix use-after-close in writeSolution when ranging fails
|
|
|
|
Add missing return statement after returnFromWriteSolution() call
|
|
when getRangingInterface() returns an error, preventing fprintf()
|
|
from writing to an already-closed file handle.
|
|
---
|
|
subprojects/highs/src/lp_data/Highs.cpp | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/subprojects/highs/src/lp_data/Highs.cpp b/subprojects/highs/src/lp_data/Highs.cpp
|
|
index c1c3254..a175f1c 100644
|
|
--- a/subprojects/highs/src/lp_data/Highs.cpp
|
|
+++ b/subprojects/highs/src/lp_data/Highs.cpp
|
|
@@ -3272,7 +3272,7 @@ HighsStatus Highs::writeSolution(const std::string& filename,
|
|
interpretCallStatus(options_.log_options, this->getRangingInterface(),
|
|
return_status, "getRangingInterface");
|
|
if (return_status == HighsStatus::kError)
|
|
- returnFromWriteSolution(file, return_status);
|
|
+ return returnFromWriteSolution(file, return_status);
|
|
fprintf(file, "\n# Ranging\n");
|
|
writeRangingFile(file, model_.lp_, info_.objective_function_value, basis_,
|
|
solution_, ranging_, style);
|
|
--
|
|
2.53.0
|
|
|
|
|
|
From d7a19c9fad468ca4b8e094da67ea2d8cc3760e7f Mon Sep 17 00:00:00 2001
|
|
From: Charalampos Stratakis <cstratak@redhat.com>
|
|
Date: Mon, 22 Dec 2025 02:02:25 +0100
|
|
Subject: [PATCH 5/7] mip: Fix use-after-move in HighsLpRelaxation::loadModel
|
|
|
|
Save lpmodel.num_col_ before passing lpmodel via std::move to
|
|
lpsolver.passModel(). After the move, lpmodel is in a valid but
|
|
unspecified state, making access to its members undefined behavior.
|
|
|
|
Found by Coverity static analysis.
|
|
---
|
|
subprojects/highs/src/mip/HighsLpRelaxation.cpp | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/subprojects/highs/src/mip/HighsLpRelaxation.cpp b/subprojects/highs/src/mip/HighsLpRelaxation.cpp
|
|
index 4288f99..58e0e4d 100644
|
|
--- a/subprojects/highs/src/mip/HighsLpRelaxation.cpp
|
|
+++ b/subprojects/highs/src/mip/HighsLpRelaxation.cpp
|
|
@@ -222,11 +222,12 @@ void HighsLpRelaxation::loadModel() {
|
|
for (HighsInt i = 0; i != lpmodel.num_row_; ++i)
|
|
lprows.push_back(LpRow::model(i));
|
|
lpmodel.integrality_.clear();
|
|
+ HighsInt num_col = lpmodel.num_col_;
|
|
lpsolver.clearSolver();
|
|
lpsolver.clearModel();
|
|
lpsolver.passModel(std::move(lpmodel));
|
|
- colLbBuffer.resize(lpmodel.num_col_);
|
|
- colUbBuffer.resize(lpmodel.num_col_);
|
|
+ colLbBuffer.resize(num_col);
|
|
+ colUbBuffer.resize(num_col);
|
|
}
|
|
|
|
void HighsLpRelaxation::resetToGlobalDomain() {
|
|
--
|
|
2.53.0
|
|
|
|
|
|
From cba9eba8aed879bc6335d3f4d43a5cd9f891e854 Mon Sep 17 00:00:00 2001
|
|
From: Charalampos Stratakis <cstratak@redhat.com>
|
|
Date: Wed, 14 Jan 2026 04:50:19 +0100
|
|
Subject: [PATCH 6/7] BUG: initialize save_value field to fix uninitialized
|
|
memory use
|
|
|
|
When a HighsSimplexBadBasisChangeRecord is created, save_value is not
|
|
set until later in applyTabooRowOut/applyTabooVariableIn. Pushing the
|
|
struct with an uninitialized field copies garbage memory.
|
|
|
|
Found via Coverity static analysis
|
|
---
|
|
subprojects/highs/src/simplex/SimplexStruct.h | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/subprojects/highs/src/simplex/SimplexStruct.h b/subprojects/highs/src/simplex/SimplexStruct.h
|
|
index eb49c8c..996dcc4 100644
|
|
--- a/subprojects/highs/src/simplex/SimplexStruct.h
|
|
+++ b/subprojects/highs/src/simplex/SimplexStruct.h
|
|
@@ -258,7 +258,7 @@ struct HighsSimplexBadBasisChangeRecord {
|
|
HighsInt variable_out;
|
|
HighsInt variable_in;
|
|
BadBasisChangeReason reason;
|
|
- double save_value;
|
|
+ double save_value = 0.0;
|
|
};
|
|
|
|
#endif /* SIMPLEX_SIMPLEXSTRUCT_H_ */
|
|
--
|
|
2.53.0
|
|
|
|
|
|
From ee47ee8895c789980a1e90d8e0c17f54a69b4440 Mon Sep 17 00:00:00 2001
|
|
From: Charalampos Stratakis <cstratak@redhat.com>
|
|
Date: Wed, 28 Jan 2026 01:23:57 +0100
|
|
Subject: [PATCH 7/7] Initialize nowactiveatlower in ratiotest_textbook
|
|
|
|
The nowactiveatlower field was only set inside the conditional blocks
|
|
when a limiting constraint was found (alpha_i < result.alpha). If both
|
|
loops completed without finding a limiting constraint, the field remained
|
|
uninitialized.
|
|
|
|
Uncovered by Coverity static analysis
|
|
---
|
|
subprojects/highs/src/qpsolver/ratiotest.cpp | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/subprojects/highs/src/qpsolver/ratiotest.cpp b/subprojects/highs/src/qpsolver/ratiotest.cpp
|
|
index dd313c4..424f695 100644
|
|
--- a/subprojects/highs/src/qpsolver/ratiotest.cpp
|
|
+++ b/subprojects/highs/src/qpsolver/ratiotest.cpp
|
|
@@ -17,6 +17,7 @@ static RatiotestResult ratiotest_textbook(Runtime& rt, const QpVector& p,
|
|
RatiotestResult result;
|
|
result.limitingconstraint = -1;
|
|
result.alpha = alphastart;
|
|
+ result.nowactiveatlower = false;
|
|
|
|
// check ratio towards variable bounds
|
|
for (HighsInt j = 0; j < p.num_nz; j++) {
|
|
--
|
|
2.53.0
|
|
|