Skip to content

Commit f769209

Browse files
committed
Cleaned up HPresolve::removeSlacks but left off by default since not advantageous on average
1 parent d0744ed commit f769209

File tree

5 files changed

+29
-95
lines changed

5 files changed

+29
-95
lines changed

check/TestPresolve.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ TEST_CASE("presolve-slacks", "[highs_test_presolve]") {
616616
lp.a_matrix_.index_ = {0, 0};
617617
lp.a_matrix_.value_ = {1, 1};
618618
Highs h;
619-
h.setOptionValue("output_flag", dev_run);
619+
// h.setOptionValue("output_flag", dev_run);
620620
REQUIRE(h.passModel(lp) == HighsStatus::kOk);
621621
REQUIRE(h.presolve() == HighsStatus::kOk);
622622
REQUIRE(h.getPresolvedLp().num_col_ == 0);

src/lp_data/Highs.cpp

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,46 +1252,6 @@ HighsStatus Highs::run() {
12521252
bool have_optimal_solution = false;
12531253
// ToDo Put solution of presolved problem in a separate method
12541254

1255-
// if (!this->options_.presolve_remove_slacks) {
1256-
HighsLp& reduced_lp = presolve_.getReducedProblem();
1257-
HighsInt num_double_slack = 0;
1258-
HighsInt num_slack = 0;
1259-
HighsInt num_zero_cost_slack = 0;
1260-
HighsInt num_unit_coeff_slack = 0;
1261-
double min_slack_coeff = kHighsInf;
1262-
double max_slack_coeff = -kHighsInf;
1263-
std::vector<bool> found_slack;
1264-
found_slack.assign(reduced_lp.num_row_, false);
1265-
for (HighsInt iCol = 0; iCol < reduced_lp.num_col_; iCol++) {
1266-
HighsInt nnz = reduced_lp.a_matrix_.start_[iCol + 1] -
1267-
reduced_lp.a_matrix_.start_[iCol];
1268-
if (nnz != 1) continue;
1269-
HighsInt iRow =
1270-
reduced_lp.a_matrix_.index_[reduced_lp.a_matrix_.start_[iCol]];
1271-
if (found_slack[iRow]) {
1272-
num_double_slack++;
1273-
continue;
1274-
}
1275-
if (reduced_lp.row_lower_[iRow] != reduced_lp.row_upper_[iRow]) continue;
1276-
num_slack++;
1277-
printf("Column %d is slack\n", int(iCol));
1278-
double coeff = std::fabs(
1279-
reduced_lp.a_matrix_.value_[reduced_lp.a_matrix_.start_[iCol]]);
1280-
if (coeff == 1.0) num_unit_coeff_slack++;
1281-
min_slack_coeff = std::min(coeff, min_slack_coeff);
1282-
max_slack_coeff = std::max(coeff, max_slack_coeff);
1283-
found_slack[iRow] = true;
1284-
if (reduced_lp.col_cost_[iCol] == 0) num_zero_cost_slack++;
1285-
}
1286-
printf(
1287-
"grepSlack,model,col,slack,unit coeff,zero_cost,double,min coeff, "
1288-
"max_coeff\n");
1289-
printf("grepSlack,%s,%d, %d, %d, %d, %d, %g, %g\n",
1290-
this->model_.lp_.model_name_.c_str(), int(reduced_lp.num_col_),
1291-
int(num_slack), int(num_unit_coeff_slack), int(num_zero_cost_slack),
1292-
int(num_double_slack), min_slack_coeff, max_slack_coeff);
1293-
// }
1294-
12951255
switch (model_presolve_status_) {
12961256
case HighsPresolveStatus::kNotPresolved: {
12971257
ekk_instance_.lp_name_ = "Original LP";
@@ -1565,6 +1525,10 @@ HighsStatus Highs::run() {
15651525
options_ = save_options;
15661526
if (return_status == HighsStatus::kError)
15671527
return returnFromRun(return_status, undo_mods);
1528+
if (postsolve_iteration_count > 0)
1529+
highsLogUser(options_.log_options, HighsLogType::kInfo,
1530+
"Required %d simplex iterations after postsolve\n",
1531+
int(postsolve_iteration_count));
15681532
}
15691533
} else {
15701534
highsLogUser(log_options, HighsLogType::kError,

src/presolve/HPresolve.cpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4361,9 +4361,8 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) {
43614361
}
43624362

43634363
// Now consider removing slacks
4364-
if (options->presolve_remove_slacks) {
4364+
if (options->presolve_remove_slacks)
43654365
HPRESOLVE_CHECKED_CALL(removeSlacks(postsolve_stack));
4366-
}
43674366

43684367
report();
43694368
} else {
@@ -4382,10 +4381,8 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) {
43824381

43834382
HPresolve::Result HPresolve::removeSlacks(
43844383
HighsPostsolveStack& postsolve_stack) {
4385-
// singletonColumns data structure appears not to be retained
4384+
// SingletonColumns data structure appears not to be retained
43864385
// throughout presolve
4387-
//
4388-
bool unit_coeff_only = true;
43894386
for (HighsInt iCol = 0; iCol != model->num_col_; ++iCol) {
43904387
if (colDeleted[iCol]) continue;
43914388
if (colsize[iCol] != 1) continue;
@@ -4400,11 +4397,6 @@ HPresolve::Result HPresolve::removeSlacks(
44004397
double cost = model->col_cost_[iCol];
44014398
double rhs = model->row_lower_[iRow];
44024399
double coeff = Avalue[coliter];
4403-
printf(
4404-
"Col %d is continuous and is singleton in equality row %d with cost "
4405-
"%g, bounds [%g, %g], coeff %g and RHS = %g\n",
4406-
int(iCol), int(iRow), cost, lower, upper, coeff, rhs);
4407-
if (unit_coeff_only && std::fabs(coeff) != 1.0) continue;
44084400
assert(coeff);
44094401
// Slack is s = (rhs - a^Tx)/coeff
44104402
//
@@ -4428,10 +4420,7 @@ HPresolve::Result HPresolve::removeSlacks(
44284420
model->offset_ += multiplier * rhs;
44294421
}
44304422
//
4431-
postsolve_stack.slackColSubstitution(iRow, iCol, rhs, cost,
4432-
lower,
4433-
upper,
4434-
getRowVector(iRow));
4423+
postsolve_stack.slackColSubstitution(iRow, iCol, rhs, getRowVector(iRow));
44354424

44364425
markColDeleted(iCol);
44374426

src/presolve/HighsPostsolveStack.cpp

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <numeric>
1414

1515
#include "lp_data/HConst.h"
16-
#include "lp_data/HighsModelUtils.h" // For debugging
16+
#include "lp_data/HighsModelUtils.h" // For debugging #2001
1717
#include "lp_data/HighsOptions.h"
1818
#include "util/HighsCDouble.h"
1919
#include "util/HighsUtils.h"
@@ -1355,10 +1355,7 @@ void HighsPostsolveStack::DuplicateColumn::transformToPresolvedSpace(
13551355
void HighsPostsolveStack::SlackColSubstitution::undo(
13561356
const HighsOptions& options, const std::vector<Nonzero>& rowValues,
13571357
HighsSolution& solution, HighsBasis& basis) {
1358-
// Taken from HighsPostsolveStack::FreeColSubstitution::undo(
1359-
//
1360-
// a (removed) cut may have been used in this reduction.
1361-
//
1358+
bool debug_print = false;
13621359
// May have to determine row dual and basis status unless doing
13631360
// primal-only transformation in MIP solver, in which case row may
13641361
// no longer exist if it corresponds to a removed cut, so have to
@@ -1382,50 +1379,41 @@ void HighsPostsolveStack::SlackColSubstitution::undo(
13821379
double(rowValue + colCoef * solution.col_value[col]);
13831380

13841381
solution.col_value[col] = double((rhs - rowValue) / colCoef);
1385-
double rowLower = colCoef > 0 ? rhs - colCoef * slackUpper : rhs - colCoef * slackLower;
1386-
double rowUpper = colCoef > 0 ? rhs - colCoef * slackLower : rhs - colCoef * slackUpper;
1387-
1388-
printf(
1389-
"\nHighsPostsolveStack::SlackColSubstitution::undo rowValue = %11.5g; "
1390-
"bounds [%11.5g, %11.5g] colCoef = %11.6g\n",
1391-
double(rowValue), rowLower, rowUpper, colCoef);
1392-
printf(
1393-
"HighsPostsolveStack::SlackColSubstitution::undo colValue = %11.5g, bounds [%11.5g, %11.5g]\n",
1394-
solution.col_value[col], slackLower, slackUpper);
13951382

13961383
// If no dual values requested, return here
13971384
if (!solution.dual_valid) return;
13981385

13991386
// Row retains its dual value, and column has this dual value scaled by coeff
1400-
if (isModelRow) {
1401-
solution.col_dual[col] = - solution.row_dual[row] / colCoef;
1402-
printf(
1403-
"HighsPostsolveStack::SlackColSubstitution::undo rowDual = %11.5g; colDual = %11.5g\n",
1404-
solution.row_dual[row], solution.col_dual[col]);
1405-
}
1387+
if (isModelRow) solution.col_dual[col] = -solution.row_dual[row] / colCoef;
14061388

14071389
// Set basis status if necessary
14081390
if (!basis.valid) return;
14091391

1410-
// If row is basic, then slack is basic, otherwise row retains its status
1392+
// If row is basic, then slack is basic, otherwise row retains its status
14111393
if (isModelRow) {
14121394
HighsBasisStatus save_row_basis_status = basis.row_status[row];
14131395
if (basis.row_status[row] == HighsBasisStatus::kBasic) {
14141396
basis.col_status[col] = HighsBasisStatus::kBasic;
1415-
basis.row_status[row] = computeRowStatus(solution.row_dual[row], RowType::kEq);
1397+
basis.row_status[row] =
1398+
computeRowStatus(solution.row_dual[row], RowType::kEq);
14161399
} else if (basis.row_status[row] == HighsBasisStatus::kLower) {
1417-
basis.col_status[col] = colCoef > 0 ? HighsBasisStatus::kUpper : HighsBasisStatus::kLower;
1400+
basis.col_status[col] =
1401+
colCoef > 0 ? HighsBasisStatus::kUpper : HighsBasisStatus::kLower;
14181402
} else {
1419-
basis.col_status[col] = colCoef > 0 ? HighsBasisStatus::kLower : HighsBasisStatus::kUpper;
1403+
basis.col_status[col] =
1404+
colCoef > 0 ? HighsBasisStatus::kLower : HighsBasisStatus::kUpper;
14201405
}
1421-
printf("HighsPostsolveStack::SlackColSubstitution::undo OgRowStatus = %s; "
1422-
"RowStatus = %s; ColStatus = %s\n",
1423-
utilBasisStatusToString(save_row_basis_status).c_str(), utilBasisStatusToString(basis.row_status[row]).c_str(),
1424-
utilBasisStatusToString(basis.col_status[col]).c_str());
1406+
if (debug_print)
1407+
printf(
1408+
"HighsPostsolveStack::SlackColSubstitution::undo OgRowStatus = %s; "
1409+
"RowStatus = %s; ColStatus = %s\n",
1410+
utilBasisStatusToString(save_row_basis_status).c_str(),
1411+
utilBasisStatusToString(basis.row_status[row]).c_str(),
1412+
utilBasisStatusToString(basis.col_status[col]).c_str());
14251413
if (basis.col_status[col] == HighsBasisStatus::kLower) {
1426-
assert(solution.col_dual[col] > 0);
1414+
assert(solution.col_dual[col] > -options.dual_feasibility_tolerance);
14271415
} else if (basis.col_status[col] == HighsBasisStatus::kUpper) {
1428-
assert(solution.col_dual[col] < 0);
1416+
assert(solution.col_dual[col] < options.dual_feasibility_tolerance);
14291417
}
14301418
} else {
14311419
basis.col_status[col] = HighsBasisStatus::kNonbasic;

src/presolve/HighsPostsolveStack.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,6 @@ class HighsPostsolveStack {
221221

222222
struct SlackColSubstitution {
223223
double rhs;
224-
double colCost;
225-
double slackLower;
226-
double slackUpper;
227224
HighsInt row;
228225
HighsInt col;
229226

@@ -339,17 +336,13 @@ class HighsPostsolveStack {
339336

340337
template <typename RowStorageFormat>
341338
void slackColSubstitution(HighsInt row, HighsInt col, double rhs,
342-
double colCost,
343-
double slackLower, double slackUpper,
344339
const HighsMatrixSlice<RowStorageFormat>& rowVec) {
345340
rowValues.clear();
346341
for (const HighsSliceNonzero& rowVal : rowVec)
347342
rowValues.emplace_back(origColIndex[rowVal.index()], rowVal.value());
348343

349-
reductionValues.push(SlackColSubstitution{rhs, colCost,
350-
slackLower, slackUpper,
351-
origRowIndex[row],
352-
origColIndex[col]});
344+
reductionValues.push(
345+
SlackColSubstitution{rhs, origRowIndex[row], origColIndex[col]});
353346
reductionValues.push(rowValues);
354347
reductionAdded(ReductionType::kSlackColSubstitution);
355348
}

0 commit comments

Comments
 (0)