@@ -4558,6 +4558,13 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
45584558 std::vector<nonZeros> nzs;
45594559 nzs.reserve (colsize[col]);
45604560
4561+ // lambda for checking whether a row provides an implied lower bound
4562+ // (direction = 1) or implied upper bound (direction = -1)
4563+ auto hasImpliedBound = [&](HighsInt row, HighsInt direction, double val) {
4564+ return ((direction * val < 0 && model->row_upper_ [row] != kHighsInf ) ||
4565+ (direction * val > 0 && model->row_lower_ [row] != -kHighsInf ));
4566+ };
4567+
45614568 // lambda for computing locks
45624569 auto computeLocks = [&](HighsInt col, HighsInt& numDownLocks,
45634570 HighsInt& numUpLocks, HighsInt& downLockRow,
@@ -4576,36 +4583,16 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
45764583
45774584 // check coefficients
45784585 for (const auto & nz : getColumnVector (col)) {
4579- // get row index and coefficient
4580- HighsInt row = nz.index ();
4581- double val = nz.value ();
4582-
4583- // skip redundant rows
4584- if (isRedundant (row)) continue ;
4585-
4586- // check lhs and rhs for finiteness
4587- bool lhsFinite = model->row_lower_ [row] != -kHighsInf ;
4588- bool rhsFinite = model->row_upper_ [row] != kHighsInf ;
4589-
45904586 // update number of locks
4591- if (val > 0 ) {
4592- if (lhsFinite) {
4593- numDownLocks++;
4594- downLockRow = row;
4595- }
4596- if (rhsFinite) {
4597- numUpLocks++;
4598- upLockRow = row;
4599- }
4600- } else {
4601- if (lhsFinite) {
4602- numUpLocks++;
4603- upLockRow = row;
4604- }
4605- if (rhsFinite) {
4606- numDownLocks++;
4607- downLockRow = row;
4608- }
4587+ if (hasImpliedBound (nz.index (), HighsInt{1 }, nz.value ())) {
4588+ // implied lower bound -> downlock
4589+ numDownLocks++;
4590+ downLockRow = nz.index ();
4591+ }
4592+ if (hasImpliedBound (nz.index (), HighsInt{-1 }, nz.value ())) {
4593+ // implied upper bound -> uplock
4594+ numUpLocks++;
4595+ upLockRow = nz.index ();
46094596 }
46104597
46114598 // stop early if there are locks in both directions, since the variable
@@ -4614,12 +4601,6 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
46144601 }
46154602 };
46164603
4617- // lambda for checking whether a row provides an implied bound
4618- auto hasImpliedBound = [&](HighsInt row, double val) {
4619- return ((val < 0 && model->row_upper_ [row] != kHighsInf ) ||
4620- (val > 0 && model->row_lower_ [row] != -kHighsInf ));
4621- };
4622-
46234604 // lambda for variable substitution
46244605 auto substituteCol = [&](HighsInt col, HighsInt row, HighsInt direction,
46254606 double colBound, double otherColBound) {
@@ -4659,7 +4640,7 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
46594640 if (colsize[col] < colsize[rowNz.index ()]) {
46604641 for (const auto & colNz : getColumnVector (col)) {
46614642 // skip non-zeros that do not yield an implied bound
4662- if (!hasImpliedBound (colNz.index (), direction * colNz.value ()))
4643+ if (!hasImpliedBound (colNz.index (), direction, colNz.value ()))
46634644 continue ;
46644645 HighsInt nzPos = findNonzero (colNz.index (), rowNz.index ());
46654646 if (nzPos == -1 ) continue ;
@@ -4670,7 +4651,7 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
46704651 HighsInt nzPos = findNonzero (colNz.index (), col);
46714652 if (nzPos == -1 ) continue ;
46724653 // skip non-zeros that do not yield an implied bound
4673- if (!hasImpliedBound (colNz.index (), direction * Avalue[nzPos]))
4654+ if (!hasImpliedBound (colNz.index (), direction, Avalue[nzPos]))
46744655 continue ;
46754656 nzs.push_back ({colNz.index (), Avalue[nzPos], colNz.value ()});
46764657 }
0 commit comments