Skip to content

Commit 22aebcf

Browse files
committed
Now using single method to report final presolve reductions
1 parent 024c388 commit 22aebcf

File tree

7 files changed

+71
-92
lines changed

7 files changed

+71
-92
lines changed

check/TestPresolve.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,4 +837,5 @@ TEST_CASE("presolve-egout-ac", "[highs_test_presolve]") {
837837
lp_presolve_requires_basis_postsolve);
838838

839839
h.resetGlobalScheduler(true);
840-
}
840+
}
841+

check/TestSemiVariables.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ TEST_CASE("semi-variable-model", "[highs_test_semi_variables]") {
1717
const HighsInfo& info = highs.getInfo();
1818
HighsStatus return_status;
1919
double optimal_objective_function_value;
20-
if (!dev_run) highs.setOptionValue("output_flag", false);
20+
highs.setOptionValue("output_flag", dev_run);
2121
HighsModel model;
2222
HighsLp& lp = model.lp_;
2323
semiModel0(lp);

highs/lp_data/Highs.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,7 @@ HighsStatus Highs::presolve() {
874874
}
875875

876876
bool using_reduced_lp = false;
877-
HighsLp& incumbent_lp = model_.lp_;
877+
reportPresolveReductions(log_options, model_presolve_status_, model_.lp_, presolve_.getReducedProblem());
878878
switch (model_presolve_status_) {
879879
case HighsPresolveStatus::kNotPresolved: {
880880
// Shouldn't happen
@@ -883,12 +883,9 @@ HighsStatus Highs::presolve() {
883883
break;
884884
}
885885
case HighsPresolveStatus::kNotReduced:
886-
reportPresolveReductions(log_options, incumbent_lp, false);
887886
case HighsPresolveStatus::kInfeasible:
888887
case HighsPresolveStatus::kReduced:
889-
reportPresolveReductions(log_options, incumbent_lp, presolve_.getReducedProblem());
890888
case HighsPresolveStatus::kReducedToEmpty:
891-
reportPresolveReductions(log_options, incumbent_lp, true);
892889
case HighsPresolveStatus::kUnboundedOrInfeasible: {
893890
// All OK
894891
if (model_presolve_status_ == HighsPresolveStatus::kInfeasible) {
@@ -1405,7 +1402,9 @@ HighsStatus Highs::optimizeModel() {
14051402
// presolved problem, since the iteration count is reset to zero
14061403
// if PDLP is used to clean up after postsolve
14071404
HighsInt presolved_lp_pdlp_iteration_count = 0;
1408-
// reportPresolveReductions(log_options, model_presolve_status_, incumbent_lp, presolve_.getReducedProblem());
1405+
// Log the presolve reductions
1406+
reportPresolveReductions(log_options, model_presolve_status_,
1407+
incumbent_lp, presolve_.getReducedProblem());
14091408
switch (model_presolve_status_) {
14101409
case HighsPresolveStatus::kNotPresolved: {
14111410
ekk_instance_.lp_name_ = "Original LP";
@@ -1420,7 +1419,6 @@ HighsStatus Highs::optimizeModel() {
14201419
case HighsPresolveStatus::kNotReduced: {
14211420
ekk_instance_.lp_name_ = "Unreduced LP";
14221421
// Log the presolve reductions
1423-
reportPresolveReductions(log_options, incumbent_lp, false);
14241422
solveLp(incumbent_lp, "Problem not reduced by presolve: solving the LP",
14251423
this_solve_original_lp_time);
14261424
return_status = interpretCallStatus(options_.log_options, call_status,
@@ -1460,8 +1458,6 @@ HighsStatus Highs::optimizeModel() {
14601458
return_status,
14611459
"cleanBounds") == HighsStatus::kError)
14621460
return HighsStatus::kError;
1463-
// Log the presolve reductions
1464-
reportPresolveReductions(log_options, incumbent_lp, reduced_lp);
14651461
// Solving the presolved LP with strictly reduced dimensions
14661462
// so ensure that the Ekk instance is cleared
14671463
ekk_instance_.clear();
@@ -1501,7 +1497,6 @@ HighsStatus Highs::optimizeModel() {
15011497
break;
15021498
}
15031499
case HighsPresolveStatus::kReducedToEmpty: {
1504-
reportPresolveReductions(log_options, incumbent_lp, true);
15051500
// Create a trivial optimal solution for postsolve to use
15061501
solution_.clear();
15071502
basis_.clear();

highs/lp_data/HighsLpUtils.cpp

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,21 +2959,52 @@ bool isMatrixDataNull(const HighsLogOptions& log_options,
29592959
}
29602960

29612961
void reportPresolveReductions(const HighsLogOptions& log_options,
2962-
const HighsLp& lp, const HighsLp& presolve_lp) {
2963-
HighsInt num_col_from = lp.num_col_;
2964-
HighsInt num_row_from = lp.num_row_;
2965-
HighsInt num_nz_from = lp.a_matrix_.start_[num_col_from];
2966-
HighsInt num_col_to = presolve_lp.num_col_;
2967-
HighsInt num_row_to = presolve_lp.num_row_;
2968-
HighsInt num_nz_to;
2969-
if (num_col_to) {
2970-
num_nz_to = presolve_lp.a_matrix_.start_[num_col_to];
2971-
} else {
2972-
num_nz_to = 0;
2962+
HighsPresolveStatus presolve_status,
2963+
const HighsLp& lp,
2964+
const HighsLp& presolved_lp) {
2965+
const HighsInt num_col_from = lp.num_col_;
2966+
const HighsInt num_row_from = lp.num_row_;
2967+
const HighsInt num_nz_from = lp.a_matrix_.numNz();
2968+
HighsInt num_col_to = 0;
2969+
HighsInt num_row_to = 0;
2970+
HighsInt num_nz_to = 0;
2971+
std::string message = "";
2972+
2973+
switch (presolve_status) {
2974+
case HighsPresolveStatus::kNotPresolved:
2975+
case HighsPresolveStatus::kInfeasible:
2976+
case HighsPresolveStatus::kUnboundedOrInfeasible: return;
2977+
case HighsPresolveStatus::kNotReduced: {
2978+
num_col_to = num_col_from;
2979+
num_row_to = num_row_from;
2980+
num_nz_to = num_nz_from;
2981+
message = "- Not reduced";
2982+
break;
2983+
}
2984+
case HighsPresolveStatus::kReduced:
2985+
case HighsPresolveStatus::kTimeout: {
2986+
num_col_to = presolved_lp.num_col_;
2987+
num_row_to = presolved_lp.num_row_;
2988+
num_nz_to = presolved_lp.a_matrix_.numNz();
2989+
message = presolve_status == HighsPresolveStatus::kTimeout ? "- Timeout" : "";
2990+
break;
2991+
}
2992+
case HighsPresolveStatus::kReducedToEmpty: {
2993+
num_col_to = 0;
2994+
num_row_to = 0;
2995+
num_nz_to = 0;
2996+
message = "- Reduced to empty";
2997+
break;
2998+
}
2999+
default: {
3000+
// case HighsPresolveStatus::kOutOfMemory
3001+
assert(presolve_status == HighsPresolveStatus::kOutOfMemory);
3002+
return;
3003+
}
29733004
}
29743005
char nz_sign_char = '-';
29753006
HighsInt delta_nz = num_nz_from - num_nz_to;
2976-
if (num_nz_from < num_nz_to) {
3007+
if (num_nz_to > num_nz_from) {
29773008
delta_nz = -delta_nz;
29783009
nz_sign_char = '+';
29793010
}
@@ -2982,40 +3013,9 @@ void reportPresolveReductions(const HighsLogOptions& log_options,
29823013
"Presolve reductions: rows %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT
29833014
"); columns %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT
29843015
"); "
2985-
"nonzeros %" HIGHSINT_FORMAT "(%c%" HIGHSINT_FORMAT ")\n",
3016+
"nonzeros %" HIGHSINT_FORMAT "(%c%" HIGHSINT_FORMAT ") %s\n",
29863017
num_row_to, (num_row_from - num_row_to), num_col_to,
2987-
(num_col_from - num_col_to), num_nz_to, nz_sign_char, delta_nz);
2988-
}
2989-
2990-
void reportPresolveReductions(const HighsLogOptions& log_options,
2991-
const HighsLp& lp, const bool presolve_to_empty) {
2992-
HighsInt num_col_from = lp.num_col_;
2993-
HighsInt num_row_from = lp.num_row_;
2994-
HighsInt num_nz_from = lp.a_matrix_.start_[num_col_from];
2995-
HighsInt num_col_to;
2996-
HighsInt num_row_to;
2997-
HighsInt num_nz_to;
2998-
std::string message;
2999-
if (presolve_to_empty) {
3000-
num_col_to = 0;
3001-
num_row_to = 0;
3002-
num_nz_to = 0;
3003-
message = "- Reduced to empty";
3004-
} else {
3005-
num_col_to = num_col_from;
3006-
num_row_to = num_row_from;
3007-
num_nz_to = num_nz_from;
3008-
message = "- Not reduced";
3009-
}
3010-
highsLogUser(log_options, HighsLogType::kInfo,
3011-
"Presolve reductions: rows %" HIGHSINT_FORMAT
3012-
"(-%" HIGHSINT_FORMAT "); columns %" HIGHSINT_FORMAT
3013-
"(-%" HIGHSINT_FORMAT
3014-
"); "
3015-
"nonzeros %" HIGHSINT_FORMAT "(-%" HIGHSINT_FORMAT ") %s\n",
3016-
num_row_to, (num_row_from - num_row_to), num_col_to,
3017-
(num_col_from - num_col_to), num_nz_to,
3018-
(num_nz_from - num_nz_to), message.c_str());
3018+
(num_col_from - num_col_to), num_nz_to, nz_sign_char, delta_nz, message.c_str());
30193019
}
30203020

30213021
bool isLessInfeasibleDSECandidate(const HighsLogOptions& log_options,
@@ -3212,6 +3212,10 @@ HighsLp withoutSemiVariables(const HighsLp& lp_, HighsSolution& solution,
32123212
lp.num_col_ += num_semi_variables;
32133213
lp.num_row_ += 2 * num_semi_variables;
32143214
assert((HighsInt)index.size() == new_num_nz);
3215+
// Ensure that the matrix dimensions are consistent with the LP
3216+
// dimensions
3217+
lp.a_matrix_.num_col_ = lp.num_col_;
3218+
lp.a_matrix_.num_row_ = lp.num_row_;
32153219
// Clear any modifications inherited from lp_
32163220
lp.mods_.clear();
32173221
return lp;

highs/lp_data/HighsLpUtils.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,9 @@ bool isMatrixDataNull(const HighsLogOptions& log_options,
260260
const double* usr_matrix_value);
261261

262262
void reportPresolveReductions(const HighsLogOptions& log_options,
263-
const HighsLp& lp, const HighsLp& presolve_lp);
264-
265-
void reportPresolveReductions(const HighsLogOptions& log_options,
266-
const HighsLp& lp, const bool presolve_to_empty);
263+
HighsPresolveStatus presolve_status,
264+
const HighsLp& lp,
265+
const HighsLp& presolved_lp);
267266

268267
bool isLessInfeasibleDSECandidate(const HighsLogOptions& log_options,
269268
const HighsLp& lp);

highs/mip/HighsMipSolverData.cpp

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -703,30 +703,11 @@ void HighsMipSolverData::runMipPresolve(const HighsInt presolve_reduction_limit)
703703
presolve_status = presolve.getPresolveStatus();
704704
}
705705
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-
}
706+
707+
reportPresolveReductions(mipsolver.options_mip_->log_options,
708+
presolve_status,
709+
*mipsolver.orig_model_,
710+
*mipsolver.model_);
730711
}
731712

732713
void HighsMipSolverData::runSetup() {

highs/presolve/HPresolve.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4879,20 +4879,19 @@ HighsModelStatus HPresolve::run(HighsPostsolveStack& postsolve_stack) {
48794879
mipsolver->mipdata_->lower_bound = 0;
48804880
} else {
48814881
// An LP with no columns must have no rows, unless the reduction
4882-
// limit has been reached
4883-
assert(model->num_row_ == 0 ||
4884-
postsolve_stack.numReductions() >= reductionLimit);
4885-
if (model->num_row_ != 0) {
4882+
// limit has been reached. As exposed when studying 2326
4883+
const bool num_row_ok = model->num_row_ == 0 ||
4884+
postsolve_stack.numReductions() >= reductionLimit;
4885+
assert(num_row_ok);
4886+
if (!num_row_ok) {
48864887
presolve_status_ = HighsPresolveStatus::kNotPresolved;
48874888
return HighsModelStatus::kNotset;
48884889
}
48894890
}
48904891
presolve_status_ = HighsPresolveStatus::kReducedToEmpty;
4891-
// Make sure that zero row activity from the column-less model is
4892+
// Make sure that zero row activity from the columnless model is
48924893
// consistent with the bounds
4893-
return model->num_row_ == 0 || zeroRowActivityFeasible()
4894-
? HighsModelStatus::kOptimal
4895-
: HighsModelStatus::kInfeasible;
4894+
return zeroRowActivityFeasible() ? HighsModelStatus::kOptimal : HighsModelStatus::kInfeasible;
48964895
} else if (postsolve_stack.numReductions() > 0) {
48974896
// Reductions performed
48984897
presolve_status_ = HighsPresolveStatus::kReduced;

0 commit comments

Comments
 (0)