@@ -4468,6 +4468,35 @@ HPresolve::Result HPresolve::detectDominatedCol(
44684468 return Result::kOk ;
44694469}
44704470
4471+ void HPresolve::computeLocks (
4472+ HighsInt col, bool considerObjective,
4473+ std::function<bool (HighsInt, bool )> lockCallback) const {
4474+ // if the callback returns true, we stop examining the locks
4475+ if (considerObjective) {
4476+ // consider objective function
4477+ if (model->col_cost_ [col] < 0 ) {
4478+ // downlock
4479+ if (lockCallback (-1 , false )) return ;
4480+ } else if (model->col_cost_ [col] > 0 ) {
4481+ // uplock
4482+ if (lockCallback (-1 , true )) return ;
4483+ }
4484+ }
4485+
4486+ // check coefficients
4487+ for (const auto & nz : getColumnVector (col)) {
4488+ // implied lower bound -> downlock
4489+ if (yieldsImpliedLowerBound (nz.index (), nz.value ()) &&
4490+ lockCallback (nz.index (), false ))
4491+ break ;
4492+
4493+ // implied upper bound -> uplock
4494+ if (yieldsImpliedUpperBound (nz.index (), nz.value ()) &&
4495+ lockCallback (nz.index (), true ))
4496+ break ;
4497+ }
4498+ }
4499+
44714500HPresolve::Result HPresolve::dualFixing (HighsPostsolveStack& postsolve_stack,
44724501 HighsInt col) {
44734502 // fix variables or tighten bounds using dual arguments
@@ -4479,43 +4508,6 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
44794508 // return if variable is already fixed
44804509 if (model->col_lower_ [col] == model->col_upper_ [col]) return Result::kOk ;
44814510
4482- // lambda for computing locks
4483- auto computeLocks = [&](HighsInt col, HighsInt& numDownLocks,
4484- HighsInt& numUpLocks, HighsInt& downLockRow,
4485- HighsInt& upLockRow) {
4486- // initialise
4487- numDownLocks = 0 ;
4488- numUpLocks = 0 ;
4489- downLockRow = -1 ;
4490- upLockRow = -1 ;
4491-
4492- // consider objective function
4493- if (model->col_cost_ [col] > 0 )
4494- numUpLocks++;
4495- else if (model->col_cost_ [col] < 0 )
4496- numDownLocks++;
4497-
4498- // check coefficients
4499- for (const auto & nz : getColumnVector (col)) {
4500- // update number of locks
4501- if (yieldsImpliedLowerBound (nz.index (), nz.value ())) {
4502- // implied lower bound -> downlock
4503- numDownLocks++;
4504- downLockRow = nz.index ();
4505- }
4506-
4507- if (yieldsImpliedUpperBound (nz.index (), nz.value ())) {
4508- // implied upper bound -> uplock
4509- numUpLocks++;
4510- upLockRow = nz.index ();
4511- }
4512-
4513- // stop early if there are locks in both directions, since the variable
4514- // cannot be fixed in this case.
4515- if (numDownLocks > 1 && numUpLocks > 1 ) break ;
4516- }
4517- };
4518-
45194511 // lambda for variable substitution
45204512 auto substituteCol = [&](HighsInt col, HighsInt row, HighsInt direction,
45214513 double colBound, double otherColBound) {
@@ -4604,12 +4596,26 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
46044596 return true ;
46054597 };
46064598
4607- // compute locks
4599+ // lambda callback for lock computation
46084600 HighsInt numDownLocks = 0 ;
46094601 HighsInt numUpLocks = 0 ;
46104602 HighsInt downLockRow = -1 ;
46114603 HighsInt upLockRow = -1 ;
4612- computeLocks (col, numDownLocks, numUpLocks, downLockRow, upLockRow);
4604+ auto lockCallback = [&](HighsInt row, bool isUpLock) {
4605+ // count locks and remember row index
4606+ if (isUpLock) {
4607+ numUpLocks++;
4608+ upLockRow = row;
4609+ } else {
4610+ numDownLocks++;
4611+ downLockRow = row;
4612+ }
4613+ // stop early if there are locks in both directions, since the variable
4614+ // cannot be fixed in this case.
4615+ return numDownLocks > 1 && numUpLocks > 1 ;
4616+ };
4617+ // compute locks
4618+ computeLocks (col, true , lockCallback);
46134619
46144620 // check if variable can be fixed
46154621 if (numDownLocks == 0 || numUpLocks == 0 ) {
0 commit comments