Skip to content

Commit 024c388

Browse files
committed
Generalise reportPresolveReductions
1 parent b3fee7c commit 024c388

File tree

6 files changed

+66
-36
lines changed

6 files changed

+66
-36
lines changed

highs/lp_data/Highs.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,9 @@ HighsStatus Highs::writeBasis(const std::string& filename) {
841841
}
842842

843843
HighsStatus Highs::presolve() {
844+
const HighsLogOptions& log_options = options_.log_options;
844845
if (model_.needsMods(options_.infinite_cost)) {
845-
highsLogUser(options_.log_options, HighsLogType::kError,
846+
highsLogUser(log_options, HighsLogType::kError,
846847
"Model contains infinite costs or semi-variables, so cannot "
847848
"be presolved independently\n");
848849
return HighsStatus::kError;
@@ -861,7 +862,7 @@ HighsStatus Highs::presolve() {
861862
max_threads = highs::parallel::num_threads();
862863
if (options_.threads != 0 && max_threads != options_.threads) {
863864
highsLogUser(
864-
options_.log_options, HighsLogType::kError,
865+
log_options, HighsLogType::kError,
865866
"Option 'threads' is set to %d but global scheduler has already been "
866867
"initialized to use %d threads. The previous scheduler instance can "
867868
"be destroyed by calling Highs::resetGlobalScheduler().\n",
@@ -873,6 +874,7 @@ HighsStatus Highs::presolve() {
873874
}
874875

875876
bool using_reduced_lp = false;
877+
HighsLp& incumbent_lp = model_.lp_;
876878
switch (model_presolve_status_) {
877879
case HighsPresolveStatus::kNotPresolved: {
878880
// Shouldn't happen
@@ -881,9 +883,12 @@ HighsStatus Highs::presolve() {
881883
break;
882884
}
883885
case HighsPresolveStatus::kNotReduced:
886+
reportPresolveReductions(log_options, incumbent_lp, false);
884887
case HighsPresolveStatus::kInfeasible:
885888
case HighsPresolveStatus::kReduced:
889+
reportPresolveReductions(log_options, incumbent_lp, presolve_.getReducedProblem());
886890
case HighsPresolveStatus::kReducedToEmpty:
891+
reportPresolveReductions(log_options, incumbent_lp, true);
887892
case HighsPresolveStatus::kUnboundedOrInfeasible: {
888893
// All OK
889894
if (model_presolve_status_ == HighsPresolveStatus::kInfeasible) {
@@ -915,7 +920,7 @@ HighsStatus Highs::presolve() {
915920
default: {
916921
// case HighsPresolveStatus::kOutOfMemory
917922
assert(model_presolve_status_ == HighsPresolveStatus::kOutOfMemory);
918-
highsLogUser(options_.log_options, HighsLogType::kError,
923+
highsLogUser(log_options, HighsLogType::kError,
919924
"Presolve fails due to memory allocation error\n");
920925
setHighsModelStatusAndClearSolutionAndBasis(
921926
HighsModelStatus::kPresolveError);
@@ -927,7 +932,7 @@ HighsStatus Highs::presolve() {
927932
presolved_model_.lp_.setMatrixDimensions();
928933
}
929934

930-
highsLogUser(options_.log_options, HighsLogType::kInfo,
935+
highsLogUser(log_options, HighsLogType::kInfo,
931936
"Presolve status: %s\n",
932937
presolveStatusToString(model_presolve_status_).c_str());
933938
return returnFromHighs(return_status);
@@ -1400,6 +1405,7 @@ HighsStatus Highs::optimizeModel() {
14001405
// presolved problem, since the iteration count is reset to zero
14011406
// if PDLP is used to clean up after postsolve
14021407
HighsInt presolved_lp_pdlp_iteration_count = 0;
1408+
// reportPresolveReductions(log_options, model_presolve_status_, incumbent_lp, presolve_.getReducedProblem());
14031409
switch (model_presolve_status_) {
14041410
case HighsPresolveStatus::kNotPresolved: {
14051411
ekk_instance_.lp_name_ = "Original LP";
@@ -3522,8 +3528,8 @@ HighsPresolveStatus Highs::runPresolve(const bool force_lp_presolve,
35223528
// Start the MIP solver's timer so that timeout in presolve can be
35233529
// identified
35243530
solver.timer_.start();
3525-
// Only place that HighsMipSolver::runPresolve is called
3526-
solver.runPresolve(options_.presolve_reduction_limit);
3531+
// Only place that HighsMipSolver::runMipPresolve is called
3532+
solver.runMipPresolve(options_.presolve_reduction_limit);
35273533
presolve_return_status = solver.getPresolveStatus();
35283534
// Assign values to data members of presolve_
35293535
presolve_.data_.reduced_lp_ = solver.getPresolvedModel();

highs/lp_data/HighsLpUtils.cpp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,8 +1808,8 @@ void reportLpDimensions(const HighsLogOptions& log_options, const HighsLp& lp) {
18081808
else
18091809
lp_num_nz = lp.a_matrix_.start_[lp.num_col_];
18101810
highsLogUser(log_options, HighsLogType::kInfo,
1811-
"LP has %" HIGHSINT_FORMAT " columns, %" HIGHSINT_FORMAT " rows",
1812-
lp.num_col_, lp.num_row_);
1811+
"LP has %" HIGHSINT_FORMAT " rows, %" HIGHSINT_FORMAT " columns",
1812+
lp.num_row_, lp.num_col_);
18131813
HighsInt num_int = getNumInt(lp);
18141814
if (num_int) {
18151815
highsLogUser(log_options, HighsLogType::kInfo,
@@ -2962,60 +2962,60 @@ void reportPresolveReductions(const HighsLogOptions& log_options,
29622962
const HighsLp& lp, const HighsLp& presolve_lp) {
29632963
HighsInt num_col_from = lp.num_col_;
29642964
HighsInt num_row_from = lp.num_row_;
2965-
HighsInt num_els_from = lp.a_matrix_.start_[num_col_from];
2965+
HighsInt num_nz_from = lp.a_matrix_.start_[num_col_from];
29662966
HighsInt num_col_to = presolve_lp.num_col_;
29672967
HighsInt num_row_to = presolve_lp.num_row_;
2968-
HighsInt num_els_to;
2968+
HighsInt num_nz_to;
29692969
if (num_col_to) {
2970-
num_els_to = presolve_lp.a_matrix_.start_[num_col_to];
2970+
num_nz_to = presolve_lp.a_matrix_.start_[num_col_to];
29712971
} else {
2972-
num_els_to = 0;
2972+
num_nz_to = 0;
29732973
}
2974-
char elemsignchar = '-';
2975-
HighsInt elemdelta = num_els_from - num_els_to;
2976-
if (num_els_from < num_els_to) {
2977-
elemdelta = -elemdelta;
2978-
elemsignchar = '+';
2974+
char nz_sign_char = '-';
2975+
HighsInt delta_nz = num_nz_from - num_nz_to;
2976+
if (num_nz_from < num_nz_to) {
2977+
delta_nz = -delta_nz;
2978+
nz_sign_char = '+';
29792979
}
29802980
highsLogUser(
29812981
log_options, HighsLogType::kInfo,
2982-
"Presolve : Reductions: rows %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT
2982+
"Presolve reductions: rows %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT
29832983
"); columns %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT
29842984
"); "
2985-
"elements %" HIGHSINT_FORMAT "(%c%" HIGHSINT_FORMAT ")\n",
2985+
"nonzeros %" HIGHSINT_FORMAT "(%c%" HIGHSINT_FORMAT ")\n",
29862986
num_row_to, (num_row_from - num_row_to), num_col_to,
2987-
(num_col_from - num_col_to), num_els_to, elemsignchar, elemdelta);
2987+
(num_col_from - num_col_to), num_nz_to, nz_sign_char, delta_nz);
29882988
}
29892989

29902990
void reportPresolveReductions(const HighsLogOptions& log_options,
29912991
const HighsLp& lp, const bool presolve_to_empty) {
29922992
HighsInt num_col_from = lp.num_col_;
29932993
HighsInt num_row_from = lp.num_row_;
2994-
HighsInt num_els_from = lp.a_matrix_.start_[num_col_from];
2994+
HighsInt num_nz_from = lp.a_matrix_.start_[num_col_from];
29952995
HighsInt num_col_to;
29962996
HighsInt num_row_to;
2997-
HighsInt num_els_to;
2997+
HighsInt num_nz_to;
29982998
std::string message;
29992999
if (presolve_to_empty) {
30003000
num_col_to = 0;
30013001
num_row_to = 0;
3002-
num_els_to = 0;
3002+
num_nz_to = 0;
30033003
message = "- Reduced to empty";
30043004
} else {
30053005
num_col_to = num_col_from;
30063006
num_row_to = num_row_from;
3007-
num_els_to = num_els_from;
3007+
num_nz_to = num_nz_from;
30083008
message = "- Not reduced";
30093009
}
30103010
highsLogUser(log_options, HighsLogType::kInfo,
3011-
"Presolve : Reductions: rows %" HIGHSINT_FORMAT
3011+
"Presolve reductions: rows %" HIGHSINT_FORMAT
30123012
"(-%" HIGHSINT_FORMAT "); columns %" HIGHSINT_FORMAT
30133013
"(-%" HIGHSINT_FORMAT
30143014
"); "
3015-
"elements %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT ") %s\n",
3015+
"nonzeros %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT ") %s\n",
30163016
num_row_to, (num_row_from - num_row_to), num_col_to,
3017-
(num_col_from - num_col_to), num_els_to,
3018-
(num_els_from - num_els_to), message.c_str());
3017+
(num_col_from - num_col_to), num_nz_to,
3018+
(num_nz_from - num_nz_to), message.c_str());
30193019
}
30203020

30213021
bool isLessInfeasibleDSECandidate(const HighsLogOptions& log_options,

highs/mip/HighsMipSolver.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,10 @@ void HighsMipSolver::run() {
9393
std::swap(mipdata_->debugSolution.debugSolActive, debugSolActive);
9494
#endif
9595
analysis_.mipTimerStart(kMipClockRunPresolve);
96-
mipdata_->runPresolve(options_mip_->presolve_reduction_limit);
96+
mipdata_->runMipPresolve(options_mip_->presolve_reduction_limit);
9797
analysis_.mipTimerStop(kMipClockRunPresolve);
9898
analysis_.mipTimerStop(kMipClockPresolve);
99+
99100
if (analysis_.analyse_mip_time && !submip)
100101
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
101102
"MIP-Timing: %11.2g - completed presolve\n", timer_.read());
@@ -865,10 +866,10 @@ void HighsMipSolver::cleanupSolve() {
865866
}
866867

867868
// Only called in Highs::runPresolve
868-
void HighsMipSolver::runPresolve(const HighsInt presolve_reduction_limit) {
869+
void HighsMipSolver::runMipPresolve(const HighsInt presolve_reduction_limit) {
869870
mipdata_ = decltype(mipdata_)(new HighsMipSolverData(*this));
870871
mipdata_->init();
871-
mipdata_->runPresolve(presolve_reduction_limit);
872+
mipdata_->runMipPresolve(presolve_reduction_limit);
872873
}
873874

874875
const HighsLp& HighsMipSolver::getPresolvedModel() const {

highs/mip/HighsMipSolver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class HighsMipSolver {
9797
mutable HighsTimer timer_;
9898
void cleanupSolve();
9999

100-
void runPresolve(const HighsInt presolve_reduction_limit);
100+
void runMipPresolve(const HighsInt presolve_reduction_limit);
101101
const HighsLp& getPresolvedModel() const;
102102
HighsPresolveStatus getPresolveStatus() const;
103103
presolve::HighsPostsolveStack getPostsolveStack() const;

highs/mip/HighsMipSolverData.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#include <random>
1111

12-
// #include "lp_data/HighsLpUtils.h"
1312
#include "../extern/pdqsort/pdqsort.h"
1413
#include "lp_data/HighsModelUtils.h"
1514
#include "mip/HighsPseudocost.h"
@@ -693,7 +692,7 @@ void HighsMipSolverData::init() {
693692
dispfreq = 100;
694693
}
695694

696-
void HighsMipSolverData::runPresolve(const HighsInt presolve_reduction_limit) {
695+
void HighsMipSolverData::runMipPresolve(const HighsInt presolve_reduction_limit) {
697696
mipsolver.timer_.start(mipsolver.timer_.presolve_clock);
698697
presolve::HPresolve presolve;
699698
if (!presolve.okSetInput(mipsolver, presolve_reduction_limit)) {
@@ -704,6 +703,30 @@ void HighsMipSolverData::runPresolve(const HighsInt presolve_reduction_limit) {
704703
presolve_status = presolve.getPresolveStatus();
705704
}
706705
mipsolver.timer_.stop(mipsolver.timer_.presolve_clock);
706+
const HighsLogOptions& log_options = mipsolver.options_mip_->log_options;
707+
const HighsLp& incumbent_lp = *mipsolver.model_;
708+
switch (presolve_status) {
709+
case HighsPresolveStatus::kNotPresolved: {
710+
// Shouldn't happen
711+
assert(presolve_status != HighsPresolveStatus::kNotPresolved);
712+
break;
713+
}
714+
case HighsPresolveStatus::kNotReduced:
715+
reportPresolveReductions(log_options, incumbent_lp, false);
716+
case HighsPresolveStatus::kInfeasible:
717+
case HighsPresolveStatus::kReduced:
718+
reportPresolveReductions(log_options, incumbent_lp, *mipsolver.model_);
719+
case HighsPresolveStatus::kReducedToEmpty:
720+
reportPresolveReductions(log_options, incumbent_lp, true);
721+
case HighsPresolveStatus::kUnboundedOrInfeasible:
722+
case HighsPresolveStatus::kTimeout: {
723+
break;
724+
}
725+
default: {
726+
// case HighsPresolveStatus::kOutOfMemory
727+
assert(presolve_status == HighsPresolveStatus::kOutOfMemory);
728+
}
729+
}
707730
}
708731

709732
void HighsMipSolverData::runSetup() {
@@ -1282,7 +1305,7 @@ void HighsMipSolverData::performRestart() {
12821305
restart_presolve_reduction_limit >= 0
12831306
? num_reductions + restart_presolve_reduction_limit
12841307
: -1;
1285-
runPresolve(further_presolve_reduction_limit);
1308+
runMipPresolve(further_presolve_reduction_limit);
12861309

12871310
if (mipsolver.modelstatus_ != HighsModelStatus::kNotset) {
12881311
// transform the objective limit to the current model

highs/mip/HighsMipSolverData.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ struct HighsMipSolverData {
251251
void init();
252252
void basisTransfer();
253253
void checkObjIntegrality();
254-
void runPresolve(const HighsInt presolve_reduction_limit);
254+
void runMipPresolve(const HighsInt presolve_reduction_limit);
255255
void setupDomainPropagation();
256256
void saveReportMipSolution(const double new_upper_limit = -kHighsInf);
257257
void runSetup();

0 commit comments

Comments
 (0)