Skip to content

Commit 835b87e

Browse files
committed
Add utilities
1 parent 02aeb70 commit 835b87e

File tree

2 files changed

+49
-45
lines changed

2 files changed

+49
-45
lines changed

src/presolve/HPresolve.cpp

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,26 @@ void HPresolve::dualImpliedFreeGetRhsAndRowType(
222222
}
223223
}
224224

225+
bool HPresolve::isImpliedEquationAtLower(HighsInt row) const {
226+
// if the implied lower bound on a row dual is strictly positive then the row
227+
// is an implied equation (using its lower bound) due to complementary
228+
// slackness
229+
bool isLbndPositive =
230+
implRowDualLower[row] > options->dual_feasibility_tolerance;
231+
assert(!isLbndPositive || model->row_lower_[row] != -kHighsInf);
232+
return isLbndPositive;
233+
}
234+
235+
bool HPresolve::isImpliedEquationAtUpper(HighsInt row) const {
236+
// if the implied upper bound on a row dual is strictly negative then the row
237+
// is an implied equation (using its upper bound) due to complementary
238+
// slackness
239+
bool isUbndNegative =
240+
implRowDualUpper[row] < -options->dual_feasibility_tolerance;
241+
assert(!isUbndNegative || model->row_upper_[row] != kHighsInf);
242+
return isUbndNegative;
243+
}
244+
225245
bool HPresolve::isImpliedIntegral(HighsInt col) {
226246
bool runDualDetection = true;
227247

@@ -236,15 +256,13 @@ bool HPresolve::isImpliedIntegral(HighsInt col) {
236256
continue;
237257
}
238258

239-
double rowLower =
240-
implRowDualUpper[nz.index()] < -options->dual_feasibility_tolerance
241-
? model->row_upper_[nz.index()]
242-
: model->row_lower_[nz.index()];
259+
double rowLower = isImpliedEquationAtUpper(nz.index())
260+
? model->row_upper_[nz.index()]
261+
: model->row_lower_[nz.index()];
243262

244-
double rowUpper =
245-
implRowDualLower[nz.index()] > options->dual_feasibility_tolerance
246-
? model->row_lower_[nz.index()]
247-
: model->row_upper_[nz.index()];
263+
double rowUpper = isImpliedEquationAtLower(nz.index())
264+
? model->row_lower_[nz.index()]
265+
: model->row_upper_[nz.index()];
248266

249267
if (rowUpper == rowLower) {
250268
// if there is an equation the dual detection does not need to be tried
@@ -308,15 +326,13 @@ bool HPresolve::isImpliedInteger(HighsInt col) {
308326
continue;
309327
}
310328

311-
double rowLower =
312-
implRowDualUpper[nz.index()] < -options->dual_feasibility_tolerance
313-
? model->row_upper_[nz.index()]
314-
: model->row_lower_[nz.index()];
329+
double rowLower = isImpliedEquationAtUpper(nz.index())
330+
? model->row_upper_[nz.index()]
331+
: model->row_lower_[nz.index()];
315332

316-
double rowUpper =
317-
implRowDualLower[nz.index()] > options->dual_feasibility_tolerance
318-
? model->row_lower_[nz.index()]
319-
: model->row_upper_[nz.index()];
333+
double rowUpper = isImpliedEquationAtLower(nz.index())
334+
? model->row_lower_[nz.index()]
335+
: model->row_upper_[nz.index()];
320336

321337
if (rowUpper == rowLower) {
322338
// if there is an equation the dual detection does not need to be tried
@@ -564,12 +580,10 @@ void HPresolve::updateRowDualImpliedBounds(HighsInt row, HighsInt col,
564580

565581
void HPresolve::updateColImpliedBounds(HighsInt row, HighsInt col, double val) {
566582
// propagate implied column bound upper bound if row has an upper bound
567-
double rowUpper = implRowDualLower[row] > options->dual_feasibility_tolerance
568-
? model->row_lower_[row]
569-
: model->row_upper_[row];
570-
double rowLower = implRowDualUpper[row] < -options->dual_feasibility_tolerance
571-
? model->row_upper_[row]
572-
: model->row_lower_[row];
583+
double rowUpper = isImpliedEquationAtLower(row) ? model->row_lower_[row]
584+
: model->row_upper_[row];
585+
double rowLower = isImpliedEquationAtUpper(row) ? model->row_upper_[row]
586+
: model->row_lower_[row];
573587

574588
assert(rowLower != kHighsInf);
575589
assert(rowUpper != -kHighsInf);
@@ -3067,7 +3081,7 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack,
30673081
double origRowLower = model->row_lower_[row];
30683082

30693083
if (model->row_lower_[row] != model->row_upper_[row]) {
3070-
if (implRowDualLower[row] > options->dual_feasibility_tolerance) {
3084+
if (isImpliedEquationAtLower(row)) {
30713085
// Convert to equality constraint (note that currently postsolve will not
30723086
// know about this conversion)
30733087
model->row_upper_[row] = model->row_lower_[row];
@@ -3076,7 +3090,7 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack,
30763090
changeRowDualLower(row, -kHighsInf);
30773091
if (mipsolver == nullptr)
30783092
checkRedundantBounds(rowDualLowerSource[row], row);
3079-
} else if (implRowDualUpper[row] < -options->dual_feasibility_tolerance) {
3093+
} else if (isImpliedEquationAtUpper(row)) {
30803094
// Convert to equality constraint (note that currently postsolve will not
30813095
// know about this conversion)
30823096
model->row_lower_[row] = model->row_upper_[row];
@@ -3769,27 +3783,13 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack,
37693783
}
37703784
}
37713785

3772-
bool hasRowUpper =
3773-
model->row_upper_[row] != kHighsInf ||
3774-
implRowDualUpper[row] < -options->dual_feasibility_tolerance;
3775-
// #1711: This looks very dodgy: surely model->row_lower_[row] !=
3776-
// -kHighsInf: dates from before 25/02/21
3777-
//
3778-
// bool hasRowLower =
3779-
// model->row_lower_[row] != kHighsInf ||
3780-
// implRowDualLower[row] > options->dual_feasibility_tolerance;
3781-
//
3782-
// Using this corrected line will reduce the number of calls to
3783-
// updateColImpliedBounds, as model->row_lower_[row] != kHighsInf is
3784-
// never false
3785-
bool hasRowLower =
3786-
model->row_lower_[row] != -kHighsInf ||
3787-
implRowDualLower[row] > options->dual_feasibility_tolerance;
3788-
// #1711: Unsurprisingly, the assert is triggered very frequently
3789-
// assert(true_hasRowLower == hasRowLower);
3790-
3791-
if ((hasRowUpper && impliedRowBounds.getNumInfSumLowerOrig(row) <= 1) ||
3792-
(hasRowLower && impliedRowBounds.getNumInfSumUpperOrig(row) <= 1)) {
3786+
// implied bounds can only be computed when row bounds are available and
3787+
// bounds on activity contain at most one infinite bound
3788+
if (((model->row_upper_[row] != kHighsInf || isImpliedEquationAtLower(row)) &&
3789+
impliedRowBounds.getNumInfSumLowerOrig(row) <= 1) ||
3790+
((model->row_lower_[row] != -kHighsInf ||
3791+
isImpliedEquationAtUpper(row)) &&
3792+
impliedRowBounds.getNumInfSumUpperOrig(row) <= 1)) {
37933793
for (const HighsSliceNonzero& nonzero : getRowVector(row))
37943794
updateColImpliedBounds(row, nonzero.index(), nonzero.value());
37953795
}

src/presolve/HPresolve.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ class HPresolve {
173173
HighsPostsolveStack::RowType& rowType,
174174
bool relaxRowDualBounds = false);
175175

176+
bool isImpliedEquationAtLower(HighsInt row) const;
177+
178+
bool isImpliedEquationAtUpper(HighsInt row) const;
179+
176180
bool isImpliedIntegral(HighsInt col);
177181

178182
bool isImpliedInteger(HighsInt col);

0 commit comments

Comments
 (0)